From 51e049cff6a3110504b67644bf02a037dc8b1c5c Mon Sep 17 00:00:00 2001 From: Balasubramanian Kandasamy Date: Mon, 27 Nov 2017 15:33:02 +0530 Subject: [PATCH 01/77] 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/77] 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/77] 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/77] 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/77] 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/77] From 20e75a3efdd12540bf0078e27c62e0daad034cb7 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Thu, 11 Jan 2018 09:31:36 +0100 Subject: [PATCH 07/77] 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/77] 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 4f96b401d9dd9f876c2d3e6e266e8670d30ca2c8 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Thu, 18 Jan 2018 09:20:55 -0800 Subject: [PATCH 09/77] Fixed mdev-14960 [ERROR] mysqld got signal 11 with join_buffer and join_cache In the function JOIN::shrink_join_buffers the iteration over joined tables was organized in a wrong way. This could cause a crash if the optimizer chose to materialize a semi-join that used join caches for which the sizes must be adjusted. --- mysql-test/r/join_cache.result | 58 ++++++++++++++++++++++++++++++++++ mysql-test/t/join_cache.test | 45 ++++++++++++++++++++++++++ sql/sql_select.cc | 5 ++- 3 files changed, 107 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/join_cache.result b/mysql-test/r/join_cache.result index cc64393f975..386f7119bc8 100644 --- a/mysql-test/r/join_cache.result +++ b/mysql-test/r/join_cache.result @@ -5813,4 +5813,62 @@ id select_type table type possible_keys key key_len ref rows Extra set join_buffer_size=default; set join_cache_level = default; DROP TABLE t1,t2; +# +# MDEV-14960: BNLH used for materialized semi-join +# +CREATE TABLE t1 (i1 int); +CREATE TABLE t2 (e1 int); +CREATE TABLE t4 (e1 int); +CREATE TABLE t5 (e1 int); +INSERT INTO t1 VALUES +(1),(2),(3),(4),(5),(6),(7),(8); +INSERT INTO t1 SELECT i1+8 FROM t1; +INSERT INTO t1 SELECT i1+16 FROM t1; +INSERT INTO t1 SELECT i1+32 FROM t1; +INSERT INTO t1 SELECT i1+64 FROM t1; +INSERT INTO t2 SELECT * FROM t1; +INSERT INTO t4 SELECT * FROM t1; +INSERT INTO t5 SELECT * FROM t1; +set @save_optimizer_switch= @@optimizer_switch; +SET join_cache_level = 6; +SET join_buffer_size=4096; +SET join_buffer_space_limit=4096; +SET optimizer_switch = 'join_cache_hashed=on,optimize_join_buffer_size=on'; +EXPLAIN SELECT * FROM t1 +WHERE +i1 < 10 AND +i1 IN +(SELECT i1 FROM +(SELECT (t4.e1) i1 FROM t4 +LEFT JOIN t5 ON t4.e1 = t5.e1 +LEFT JOIN (SELECT e1 FROM t2 ) AS d ON t4.e1 = d.e1) a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 128 Using where +1 PRIMARY eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED t4 ALL NULL NULL NULL NULL 128 +2 MATERIALIZED t5 hash_ALL NULL #hash#$hj 5 test.t4.e1 128 Using where; Using join buffer (flat, BNLH join) +2 MATERIALIZED t2 hash_ALL NULL #hash#$hj 5 test.t4.e1 128 Using where; Using join buffer (incremental, BNLH join) +SELECT * FROM t1 +WHERE +i1 < 10 AND +i1 IN +(SELECT i1 FROM +(SELECT (t4.e1) i1 FROM t4 +LEFT JOIN t5 ON t4.e1 = t5.e1 +LEFT JOIN (SELECT e1 FROM t2 ) AS d ON t4.e1 = d.e1) a); +i1 +1 +2 +3 +4 +5 +6 +7 +8 +9 +SET join_cache_level = default; +SET join_buffer_size = default; +SET join_buffer_space_limit= default; +set optimizer_switch=@save_optimizer_switch; +DROP TABLE t1,t4,t5,t2; set @@optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/t/join_cache.test b/mysql-test/t/join_cache.test index 77e8fce0d27..58a7b885356 100644 --- a/mysql-test/t/join_cache.test +++ b/mysql-test/t/join_cache.test @@ -3791,5 +3791,50 @@ set join_cache_level = default; DROP TABLE t1,t2; +--echo # +--echo # MDEV-14960: BNLH used for materialized semi-join +--echo # + +CREATE TABLE t1 (i1 int); +CREATE TABLE t2 (e1 int); +CREATE TABLE t4 (e1 int); +CREATE TABLE t5 (e1 int); + +INSERT INTO t1 VALUES + (1),(2),(3),(4),(5),(6),(7),(8); +INSERT INTO t1 SELECT i1+8 FROM t1; +INSERT INTO t1 SELECT i1+16 FROM t1; +INSERT INTO t1 SELECT i1+32 FROM t1; +INSERT INTO t1 SELECT i1+64 FROM t1; +INSERT INTO t2 SELECT * FROM t1; +INSERT INTO t4 SELECT * FROM t1; +INSERT INTO t5 SELECT * FROM t1; + +set @save_optimizer_switch= @@optimizer_switch; +SET join_cache_level = 6; +SET join_buffer_size=4096; +SET join_buffer_space_limit=4096; +SET optimizer_switch = 'join_cache_hashed=on,optimize_join_buffer_size=on'; + +let $q= +SELECT * FROM t1 +WHERE + i1 < 10 AND + i1 IN + (SELECT i1 FROM + (SELECT (t4.e1) i1 FROM t4 + LEFT JOIN t5 ON t4.e1 = t5.e1 + LEFT JOIN (SELECT e1 FROM t2 ) AS d ON t4.e1 = d.e1) a); + +eval EXPLAIN $q; +eval $q; + +SET join_cache_level = default; +SET join_buffer_size = default; +SET join_buffer_space_limit= default; +set optimizer_switch=@save_optimizer_switch; + +DROP TABLE t1,t4,t5,t2; + # this must be the last command in the file set @@optimizer_switch=@save_optimizer_switch; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 9f89a261540..42b3420a9b6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2085,8 +2085,11 @@ bool JOIN::shrink_join_buffers(JOIN_TAB *jt, ulonglong curr_space, ulonglong needed_space) { + JOIN_TAB *tab; JOIN_CACHE *cache; - for (JOIN_TAB *tab= join_tab+const_tables; tab < jt; tab++) + for (tab= first_linear_tab(this, WITHOUT_BUSH_ROOTS, WITHOUT_CONST_TABLES); + tab != jt; + tab= next_linear_tab(this, tab, WITHOUT_BUSH_ROOTS)) { cache= tab->cache; if (cache) From a7a4519a40c58947796c6d9b2e4e58acc18aeef8 Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Fri, 19 Jan 2018 13:29:31 +0530 Subject: [PATCH 10/77] MDEV-14241: Server crash in key_copy / get_matching_chain_by_join_key or valgrind warnings In this case we were using the optimization derived_with_keys but we could not create a key because the length of the key was greater than the max allowed(MI_MAX_KEY_LENGTH). To do the join we needed to create a hash join key instead, but in the explain output it showed that we were still referring to derived keys which were created but not used. --- mysql-test/r/derived.result | 25 +++++++++++++++++++++++++ mysql-test/t/derived.test | 23 +++++++++++++++++++++++ sql/sql_select.cc | 2 +- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index 33af7c61613..763dbe264fb 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -1011,4 +1011,29 @@ id id data 2 2 yes 1 NULL NULL drop table t1; +# +# MDEV-14241: Server crash in key_copy / get_matching_chain_by_join_key +# or valgrind warnings +# +CREATE TABLE t1 (a VARCHAR(10)) ENGINE=MyISAM; +CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES ('foo'),('bar'); +CREATE TABLE t2 (b integer auto_increment primary key) ENGINE=MyISAM; +INSERT INTO t2 VALUES (NULL),(NULL); +CREATE TABLE t3 (c VARCHAR(1024) CHARACTER SET utf8, d INT) ENGINE=MyISAM; +CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v3 AS SELECT * FROM t3; +INSERT INTO t3 VALUES ('abc',NULL),('def',4); +SET join_cache_level= 8; +explain +SELECT * FROM v1, t2, v3 WHERE a = c AND b = d; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 2 +1 PRIMARY hash_ALL NULL #hash#$hj 3075 func 2 Using where; Using join buffer (flat, BNLH join) +1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 v3.d 1 Using index +3 DERIVED t3 ALL NULL NULL NULL NULL 2 +2 DERIVED t1 ALL NULL NULL NULL NULL 2 +SELECT * FROM v1, t2, v3 WHERE a = c AND b = d; +a b c d +DROP VIEW v1, v3; +DROP TABLE t1, t2, t3; # end of 5.5 diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index f8ba87ac1f5..eb6e502b029 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -864,5 +864,28 @@ select distinct t1.id, tt.id, tt.data drop table t1; +--echo # +--echo # MDEV-14241: Server crash in key_copy / get_matching_chain_by_join_key +--echo # or valgrind warnings +--echo # + +CREATE TABLE t1 (a VARCHAR(10)) ENGINE=MyISAM; +CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES ('foo'),('bar'); + +CREATE TABLE t2 (b integer auto_increment primary key) ENGINE=MyISAM; +INSERT INTO t2 VALUES (NULL),(NULL); + +CREATE TABLE t3 (c VARCHAR(1024) CHARACTER SET utf8, d INT) ENGINE=MyISAM; +CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v3 AS SELECT * FROM t3; +INSERT INTO t3 VALUES ('abc',NULL),('def',4); + +SET join_cache_level= 8; +explain +SELECT * FROM v1, t2, v3 WHERE a = c AND b = d; +SELECT * FROM v1, t2, v3 WHERE a = c AND b = d; + +DROP VIEW v1, v3; +DROP TABLE t1, t2, t3; --echo # end of 5.5 diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 42b3420a9b6..d35a5a8094c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9513,7 +9513,7 @@ void JOIN::drop_unused_derived_keys() table->use_index(tab->ref.key); if (table->s->keys) { - if (tab->ref.key >= 0) + if (tab->ref.key >= 0 && tab->ref.key < MAX_KEY) tab->ref.key= 0; else table->s->keys= 0; From 26e5f9dda13efad33e867742ea4e42e479b51b2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 16 Jan 2018 22:57:52 +0200 Subject: [PATCH 11/77] MDEV-14229: Stack trace is not resolved for shared objects Resolving a stacktrace including functions in dynamic libraries requires us to look inside the libraries for the symbols. Addr2line needs to be started with the correct binary for each address on the stack. To do this, figure out which library it is using dladdr, then if the addr2line binary was started with a different binary, fork it again with the correct one. We only have one addr2line process running at any point during the stacktrace resolving step. The maximum number of forks for addr2line should generally be around 6. One for server stacktrace code, one for plugin code, one when going back into server code, one for pthread library, one for libc, one for the _start function in the server. More can come up if plugin calls server function which goes back to a plugin, etc. --- config.h.cmake | 1 + configure.cmake | 1 + include/my_global.h | 4 ++ mysys/CMakeLists.txt | 2 +- mysys/my_addr_resolve.c | 97 ++++++++++++++++++++++++++++------------- 5 files changed, 73 insertions(+), 32 deletions(-) diff --git a/config.h.cmake b/config.h.cmake index dfdd4215e4a..99a2ebdd093 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -148,6 +148,7 @@ #cmakedefine HAVE_CUSERID 1 #cmakedefine HAVE_CXX_NEW 1 #cmakedefine HAVE_DIRECTIO 1 +#cmakedefine HAVE_DLADDR 1 #cmakedefine HAVE_DLERROR 1 #cmakedefine HAVE_DLOPEN 1 #cmakedefine HAVE_DOPRNT 1 diff --git a/configure.cmake b/configure.cmake index 470fb719fb8..43f8f71390d 100644 --- a/configure.cmake +++ b/configure.cmake @@ -346,6 +346,7 @@ CHECK_FUNCTION_EXISTS (ftruncate HAVE_FTRUNCATE) CHECK_FUNCTION_EXISTS (getline HAVE_GETLINE) CHECK_FUNCTION_EXISTS (compress HAVE_COMPRESS) CHECK_FUNCTION_EXISTS (crypt HAVE_CRYPT) +CHECK_FUNCTION_EXISTS (dladdr HAVE_DLADDR) CHECK_FUNCTION_EXISTS (dlerror HAVE_DLERROR) CHECK_FUNCTION_EXISTS (dlopen HAVE_DLOPEN) CHECK_FUNCTION_EXISTS (fchmod HAVE_FCHMOD) diff --git a/include/my_global.h b/include/my_global.h index cf140cf54ce..767ac3e459e 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -1373,11 +1373,15 @@ static inline char *dlerror(void) #ifndef HAVE_DLERROR #define dlerror() "" #endif +#ifndef HAVE_DLADDR +#define dladdr(A, B) 0 +#endif #else #define dlerror() "No support for dynamic loading (static build?)" #define dlopen(A,B) 0 #define dlsym(A,B) 0 #define dlclose(A) 0 +#define dladdr(A, B) 0 #endif /* diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index cb86850c2de..15f3fbad9bf 100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -67,7 +67,7 @@ ENDIF() ADD_CONVENIENCE_LIBRARY(mysys ${MYSYS_SOURCES}) TARGET_LINK_LIBRARIES(mysys dbug strings ${ZLIB_LIBRARY} - ${LIBNSL} ${LIBM} ${LIBRT} ${LIBSOCKET} ${LIBEXECINFO}) + ${LIBNSL} ${LIBM} ${LIBRT} ${LIBSOCKET} ${LIBEXECINFO} ${LIBDL}) DTRACE_INSTRUMENT(mysys) IF(HAVE_BFD_H) diff --git a/mysys/my_addr_resolve.c b/mysys/my_addr_resolve.c index 90e6f43f390..f831ad5121f 100644 --- a/mysys/my_addr_resolve.c +++ b/mysys/my_addr_resolve.c @@ -132,15 +132,79 @@ err: #include #include + +#include + static int in[2], out[2]; -static int initialized= 0; +static pid_t pid; +static char addr2line_binary[1024]; static char output[1024]; + +int start_addr2line_fork(const char *binary_path) +{ + + if (pid > 0) + { + /* Don't leak FDs */ + close(in[1]); + close(out[0]); + /* Don't create zombie processes. */ + waitpid(pid, NULL, 0); + } + + if (pipe(in) < 0) + return 1; + if (pipe(out) < 0) + return 1; + + pid = fork(); + if (pid == -1) + return 1; + + if (!pid) /* child */ + { + dup2(in[0], 0); + dup2(out[1], 1); + close(in[0]); + close(in[1]); + close(out[0]); + close(out[1]); + execlp("addr2line", "addr2line", "-C", "-f", "-e", binary_path, NULL); + exit(1); + } + + close(in[0]); + close(out[1]); + + return 0; +} + int my_addr_resolve(void *ptr, my_addr_loc *loc) { char input[32], *s; size_t len; - len= my_snprintf(input, sizeof(input), "%p\n", ptr); + Dl_info info; + void *offset; + + if (!dladdr(ptr, &info)) + return 1; + + if (strcmp(addr2line_binary, info.dli_fname)) + { + /* We use dli_fname in case the path is longer than the length of our static + string. We don't want to allocate anything dynamicaly here as we are in + a "crashed" state. */ + if (start_addr2line_fork(info.dli_fname)) + { + addr2line_binary[0] = '\0'; + return 1; + } + /* Save result for future comparisons. */ + strnmov(addr2line_binary, info.dli_fname, sizeof(addr2line_binary)); + } + offset = info.dli_fbase; + len= my_snprintf(input, sizeof(input), "%p\n", ptr - offset); if (write(in[1], input, len) <= 0) return 1; if (read(out[0], output, sizeof(output)) <= 0) @@ -168,35 +232,6 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) const char *my_addr_resolve_init() { - if (!initialized) - { - pid_t pid; - - if (pipe(in) < 0) - return "pipe(in)"; - if (pipe(out) < 0) - return "pipe(out)"; - - pid = fork(); - if (pid == -1) - return "fork"; - - if (!pid) /* child */ - { - dup2(in[0], 0); - dup2(out[1], 1); - close(in[0]); - close(in[1]); - close(out[0]); - close(out[1]); - execlp("addr2line", "addr2line", "-C", "-f", "-e", my_progname, NULL); - exit(1); - } - - close(in[0]); - close(out[1]); - initialized= 1; - } return 0; } #endif From 17f64b362a3d7de430070e8535eaeb7b68a67a97 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Fri, 19 Jan 2018 11:01:32 -0500 Subject: [PATCH 12/77] bump the VERSION --- 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 6c60c809bb90e229f6f6c09ea2dbb9c87e2759ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Fri, 19 Jan 2018 18:04:51 +0200 Subject: [PATCH 13/77] Add dummy defintion for Dl_info in case we're missing dladdr --- include/my_global.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/my_global.h b/include/my_global.h index 767ac3e459e..ab7e485a1a0 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -1375,6 +1375,8 @@ static inline char *dlerror(void) #endif #ifndef HAVE_DLADDR #define dladdr(A, B) 0 +/* Dummy definition in case we're missing dladdr() */ +typedef int Dl_info; #endif #else #define dlerror() "No support for dynamic loading (static build?)" @@ -1382,6 +1384,8 @@ static inline char *dlerror(void) #define dlsym(A,B) 0 #define dlclose(A) 0 #define dladdr(A, B) 0 +/* Dummy definition in case we're missing dladdr() */ +typedef int Dl_info; #endif /* From 906ce0962d12731eafed6f5ad64c5d50aeac8ce4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 22 Jan 2018 11:18:10 +0200 Subject: [PATCH 14/77] MDEV-7049 MySQL#74585 - InnoDB: Failing assertion: *mbmaxlen < 5 in file ha_innodb.cc line 1904 InnoDB limited the maximum number of bytes per character to 4. But, the filename character set that was introduced in MySQL 5.1 uses up to 5 bytes per character. To allow InnoDB tables to be created with wider characters, let us split the mbminmaxlen fields into mbminlen, mbmaxlen, and increase the limit to 7 bytes per character. This will increase the payload size of dtype_t and dict_col_t by one bit. The storage size will be unchanged (54 bits and 77 bits will use the same number of bytes as the previous sizes 53 and 76 bits). --- mysql-test/suite/innodb/r/innodb.result | 2 + mysql-test/suite/innodb/t/innodb.test | 33 ++------------ storage/innobase/data/data0type.c | 10 ++--- storage/innobase/dict/dict0mem.c | 4 +- storage/innobase/handler/handler0alter.cc | 4 +- storage/innobase/include/data0type.h | 50 +++++++-------------- storage/innobase/include/data0type.ic | 55 +++++++---------------- storage/innobase/include/dict0dict.h | 12 +---- storage/innobase/include/dict0dict.ic | 33 ++++---------- storage/innobase/include/dict0mem.h | 10 ++--- storage/innobase/rem/rem0rec.c | 18 +++----- storage/innobase/row/row0ins.c | 6 ++- storage/innobase/row/row0merge.c | 13 +++--- storage/innobase/row/row0row.c | 9 ++-- storage/innobase/row/row0sel.c | 13 +++--- storage/innobase/row/row0upd.c | 3 +- storage/xtradb/data/data0type.c | 10 ++--- storage/xtradb/dict/dict0mem.c | 4 +- storage/xtradb/handler/ha_innodb.cc | 4 +- storage/xtradb/handler/handler0alter.cc | 4 +- storage/xtradb/include/data0type.h | 50 +++++++-------------- storage/xtradb/include/data0type.ic | 55 +++++++---------------- storage/xtradb/include/dict0dict.h | 12 +---- storage/xtradb/include/dict0dict.ic | 33 ++++---------- storage/xtradb/include/dict0mem.h | 10 ++--- storage/xtradb/rem/rem0rec.c | 18 +++----- storage/xtradb/row/row0ins.c | 6 ++- storage/xtradb/row/row0merge.c | 13 +++--- storage/xtradb/row/row0row.c | 9 ++-- storage/xtradb/row/row0sel.c | 13 +++--- storage/xtradb/row/row0upd.c | 3 +- 31 files changed, 181 insertions(+), 338 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result index a7db250d8c7..c427038e8a1 100644 --- a/mysql-test/suite/innodb/r/innodb.result +++ b/mysql-test/suite/innodb/r/innodb.result @@ -1,3 +1,5 @@ +create temporary table t (a char(1) character set filename) engine=innodb; +drop temporary table t; set optimizer_switch = 'mrr=on,mrr_sort_keys=on,index_condition_pushdown=on'; drop table if exists t1,t2,t3,t4; drop database if exists mysqltest; diff --git a/mysql-test/suite/innodb/t/innodb.test b/mysql-test/suite/innodb/t/innodb.test index c36dc1c5f95..b91fbe13718 100644 --- a/mysql-test/suite/innodb/t/innodb.test +++ b/mysql-test/suite/innodb/t/innodb.test @@ -1,23 +1,11 @@ -####################################################################### -# # -# Please, DO NOT TOUCH this file as well as the innodb.result file. # -# These files are to be modified ONLY BY INNOBASE guys. # -# # -# Use innodb_mysql.[test|result] files instead. # -# # -# If nevertheless you need to make some changes here, please, forward # -# your commit message # -# To: innodb_dev_ww@oracle.com # -# Cc: dev-innodb@mysql.com # -# (otherwise your changes may be erased). # -# # -####################################################################### - -- source include/have_innodb.inc let $MYSQLD_DATADIR= `select @@datadir`; let collation=utf8_unicode_ci; --source include/have_collation.inc +create temporary table t (a char(1) character set filename) engine=innodb; +drop temporary table t; + set optimizer_switch = 'mrr=on,mrr_sort_keys=on,index_condition_pushdown=on'; # Save the original values of some variables in order to be able to @@ -2546,18 +2534,3 @@ show status like "handler_read_key"; select f1 from t1; show status like "handler_read_key"; drop table t1; - -####################################################################### -# # -# Please, DO NOT TOUCH this file as well as the innodb.result file. # -# These files are to be modified ONLY BY INNOBASE guys. # -# # -# Use innodb_mysql.[test|result] files instead. # -# # -# If nevertheless you need to make some changes here, please, forward # -# your commit message # -# To: innodb_dev_ww@oracle.com # -# Cc: dev-innodb@mysql.com # -# (otherwise your changes may be erased). # -# # -####################################################################### diff --git a/storage/innobase/data/data0type.c b/storage/innobase/data/data0type.c index 9f855d58adf..c278cc8821e 100644 --- a/storage/innobase/data/data0type.c +++ b/storage/innobase/data/data0type.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2009, Innobase Oy. 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 @@ -49,8 +50,10 @@ ulint dtype_get_at_most_n_mbchars( /*========================*/ ulint prtype, /*!< in: precise type */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of - a multi-byte character */ + ulint mbminlen, /*!< in: minimum length of + a multi-byte character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of + a multi-byte character, in bytes */ ulint prefix_len, /*!< in: length of the requested prefix, in characters, multiplied by dtype_get_mbmaxlen(dtype) */ @@ -58,9 +61,6 @@ dtype_get_at_most_n_mbchars( const char* str) /*!< in: the string whose prefix length is being determined */ { - ulint mbminlen = DATA_MBMINLEN(mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN(mbminmaxlen); - ut_a(data_len != UNIV_SQL_NULL); ut_ad(!mbmaxlen || !(prefix_len % mbmaxlen)); diff --git a/storage/innobase/dict/dict0mem.c b/storage/innobase/dict/dict0mem.c index 87d03eff3c2..e3056df53a5 100644 --- a/storage/innobase/dict/dict0mem.c +++ b/storage/innobase/dict/dict0mem.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2010, Innobase Oy. 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 @@ -251,7 +252,8 @@ dict_mem_fill_column_struct( column->len = (unsigned int) col_len; #ifndef UNIV_HOTBACKUP dtype_get_mblen(mtype, prtype, &mbminlen, &mbmaxlen); - dict_col_set_mbminmaxlen(column, mbminlen, mbmaxlen); + column->mbminlen = mbminlen; + column->mbmaxlen = mbmaxlen; #endif /* !UNIV_HOTBACKUP */ } diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index ecfda6d6264..0ccbb2c3942 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2013, 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 @@ -99,8 +100,7 @@ innobase_col_to_mysql( #ifdef UNIV_DEBUG case DATA_MYSQL: ut_ad(flen >= len); - ut_ad(DATA_MBMAXLEN(col->mbminmaxlen) - >= DATA_MBMINLEN(col->mbminmaxlen)); + ut_ad(col->mbmaxlen >= col->mbminlen); memcpy(dest, data, len); break; diff --git a/storage/innobase/include/data0type.h b/storage/innobase/include/data0type.h index 25d68de6646..852e18153c2 100644 --- a/storage/innobase/include/data0type.h +++ b/storage/innobase/include/data0type.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2009, Innobase Oy. 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 @@ -169,18 +170,7 @@ store the charset-collation number; one byte is left unused, though */ #define DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE 6 /* Maximum multi-byte character length in bytes, plus 1 */ -#define DATA_MBMAX 5 - -/* Pack mbminlen, mbmaxlen to mbminmaxlen. */ -#define DATA_MBMINMAXLEN(mbminlen, mbmaxlen) \ - ((mbmaxlen) * DATA_MBMAX + (mbminlen)) -/* Get mbminlen from mbminmaxlen. Cast the result of UNIV_EXPECT to ulint -because in GCC it returns a long. */ -#define DATA_MBMINLEN(mbminmaxlen) ((ulint) \ - UNIV_EXPECT(((mbminmaxlen) % DATA_MBMAX), \ - 1)) -/* Get mbmaxlen from mbminmaxlen. */ -#define DATA_MBMAXLEN(mbminmaxlen) ((ulint) ((mbminmaxlen) / DATA_MBMAX)) +#define DATA_MBMAX 8 #ifndef UNIV_HOTBACKUP /*********************************************************************//** @@ -201,8 +191,10 @@ ulint dtype_get_at_most_n_mbchars( /*========================*/ ulint prtype, /*!< in: precise type */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of - a multi-byte character */ + ulint mbminlen, /*!< in: minimum length of + a multi-byte character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of + a multi-byte character, in bytes */ ulint prefix_len, /*!< in: length of the requested prefix, in characters, multiplied by dtype_get_mbmaxlen(dtype) */ @@ -347,19 +339,6 @@ dtype_get_mbmaxlen( /*===============*/ const dtype_t* type); /*!< in: type */ /*********************************************************************//** -Sets the minimum and maximum length of a character, in bytes. */ -UNIV_INLINE -void -dtype_set_mbminmaxlen( -/*==================*/ - dtype_t* type, /*!< in/out: type */ - ulint mbminlen, /*!< in: minimum length of a char, - in bytes, or 0 if this is not - a character type */ - ulint mbmaxlen); /*!< in: maximum length of a char, - in bytes, or 0 if this is not - a character type */ -/*********************************************************************//** Gets the padding character code for the type. @return padding character code, or ULINT_UNDEFINED if no padding specified */ UNIV_INLINE @@ -379,7 +358,9 @@ dtype_get_fixed_size_low( ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ ulint len, /*!< in: length */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of a + ulint mbminlen, /*!< in: minimum length of a + multibyte character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of a multibyte character, in bytes */ ulint comp); /*!< in: nonzero=ROW_FORMAT=COMPACT */ #ifndef UNIV_HOTBACKUP @@ -393,8 +374,8 @@ dtype_get_min_size_low( ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ ulint len, /*!< in: length */ - ulint mbminmaxlen); /*!< in: minimum and maximum length of a - multibyte character */ + ulint mbminlen, /*!< in: minimum length of a character */ + ulint mbmaxlen); /*!< in: maximum length of a character */ /***********************************************************************//** Returns the maximum size of a data type. Note: types in system tables may be incomplete and return incorrect information. @@ -497,11 +478,10 @@ struct dtype_struct{ the string, MySQL uses 1 or 2 bytes to store the string length) */ #ifndef UNIV_HOTBACKUP - unsigned mbminmaxlen:5; /*!< minimum and maximum length of a - character, in bytes; - DATA_MBMINMAXLEN(mbminlen,mbmaxlen); - mbminlen=DATA_MBMINLEN(mbminmaxlen); - mbmaxlen=DATA_MBMINLEN(mbminmaxlen) */ + unsigned mbminlen:3; /*!< minimum length of a character, + in bytes */ + unsigned mbmaxlen:3; /*!< maximum length of a character, + in bytes */ #endif /* !UNIV_HOTBACKUP */ }; diff --git a/storage/innobase/include/data0type.ic b/storage/innobase/include/data0type.ic index 515b6b249ef..2b4ae7bcf54 100644 --- a/storage/innobase/include/data0type.ic +++ b/storage/innobase/include/data0type.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2012, 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 @@ -100,27 +101,6 @@ dtype_get_mblen( } } -/*********************************************************************//** -Sets the minimum and maximum length of a character, in bytes. */ -UNIV_INLINE -void -dtype_set_mbminmaxlen( -/*==================*/ - dtype_t* type, /*!< in/out: type */ - ulint mbminlen, /*!< in: minimum length of a char, - in bytes, or 0 if this is not - a character type */ - ulint mbmaxlen) /*!< in: maximum length of a char, - in bytes, or 0 if this is not - a character type */ -{ - ut_ad(mbminlen < DATA_MBMAX); - ut_ad(mbmaxlen < DATA_MBMAX); - ut_ad(mbminlen <= mbmaxlen); - - type->mbminmaxlen = DATA_MBMINMAXLEN(mbminlen, mbmaxlen); -} - /*********************************************************************//** Compute the mbminlen and mbmaxlen members of a data type structure. */ UNIV_INLINE @@ -133,7 +113,8 @@ dtype_set_mblen( ulint mbmaxlen; dtype_get_mblen(type->mtype, type->prtype, &mbminlen, &mbmaxlen); - dtype_set_mbminmaxlen(type, mbminlen, mbmaxlen); + type->mbminlen = mbminlen; + type->mbmaxlen = mbmaxlen; ut_ad(dtype_validate(type)); } @@ -229,8 +210,7 @@ dtype_get_mbminlen( /*===============*/ const dtype_t* type) /*!< in: type */ { - ut_ad(type); - return(DATA_MBMINLEN(type->mbminmaxlen)); + return type->mbminlen; } /*********************************************************************//** Gets the maximum length of a character, in bytes. @@ -242,8 +222,7 @@ dtype_get_mbmaxlen( /*===============*/ const dtype_t* type) /*!< in: type */ { - ut_ad(type); - return(DATA_MBMAXLEN(type->mbminmaxlen)); + return type->mbmaxlen; } /*********************************************************************//** @@ -424,8 +403,10 @@ dtype_get_fixed_size_low( ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ ulint len, /*!< in: length */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of - a multibyte character, in bytes */ + ulint mbminlen, /*!< in: minimum length of a + multibyte character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of a + multibyte character, in bytes */ ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ { switch (mtype) { @@ -466,11 +447,10 @@ dtype_get_fixed_size_low( dtype_get_charset_coll(prtype), &i_mbminlen, &i_mbmaxlen); - ut_ad(DATA_MBMINMAXLEN(i_mbminlen, i_mbmaxlen) - == mbminmaxlen); + ut_ad(i_mbminlen == mbminlen); + ut_ad(i_mbmaxlen == mbmaxlen); #endif /* UNIV_DEBUG */ - if (DATA_MBMINLEN(mbminmaxlen) - == DATA_MBMAXLEN(mbminmaxlen)) { + if (mbminlen == mbmaxlen) { return(len); } } @@ -502,8 +482,8 @@ dtype_get_min_size_low( ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ ulint len, /*!< in: length */ - ulint mbminmaxlen) /*!< in: minimum and maximum length of a - multi-byte character */ + ulint mbminlen, /*!< in: minimum length of a character */ + ulint mbmaxlen) /*!< in: maximum length of a character */ { switch (mtype) { case DATA_SYS: @@ -533,9 +513,6 @@ dtype_get_min_size_low( if (prtype & DATA_BINARY_TYPE) { return(len); } else { - ulint mbminlen = DATA_MBMINLEN(mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN(mbminmaxlen); - if (mbminlen == mbmaxlen) { return(len); } @@ -606,9 +583,9 @@ dtype_get_sql_null_size( { #ifndef UNIV_HOTBACKUP return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len, - type->mbminmaxlen, comp)); + type->mbminlen, type->mbmaxlen, comp)); #else /* !UNIV_HOTBACKUP */ return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len, - 0, 0)); + 0, 0, 0)); #endif /* !UNIV_HOTBACKUP */ } diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index bb1119b3c19..4d6fd4a9b1e 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2014, 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 @@ -119,17 +120,6 @@ dict_col_get_mbmaxlen( /*==================*/ const dict_col_t* col); /*!< in: column */ /*********************************************************************//** -Sets the minimum and maximum number of bytes per character. */ -UNIV_INLINE -void -dict_col_set_mbminmaxlen( -/*=====================*/ - dict_col_t* col, /*!< in/out: column */ - ulint mbminlen, /*!< in: minimum multi-byte - character size, in bytes */ - ulint mbmaxlen); /*!< in: minimum multi-byte - character size, in bytes */ -/*********************************************************************//** Gets the column data type. */ UNIV_INLINE void diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index dbc3ce99ab0..c17826548e4 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2014, 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 @@ -38,7 +39,7 @@ dict_col_get_mbminlen( /*==================*/ const dict_col_t* col) /*!< in: column */ { - return(DATA_MBMINLEN(col->mbminmaxlen)); + return col->mbminlen; } /*********************************************************************//** Gets the maximum number of bytes per character. @@ -49,25 +50,7 @@ dict_col_get_mbmaxlen( /*==================*/ const dict_col_t* col) /*!< in: column */ { - return(DATA_MBMAXLEN(col->mbminmaxlen)); -} -/*********************************************************************//** -Sets the minimum and maximum number of bytes per character. */ -UNIV_INLINE -void -dict_col_set_mbminmaxlen( -/*=====================*/ - dict_col_t* col, /*!< in/out: column */ - ulint mbminlen, /*!< in: minimum multi-byte - character size, in bytes */ - ulint mbmaxlen) /*!< in: minimum multi-byte - character size, in bytes */ -{ - ut_ad(mbminlen < DATA_MBMAX); - ut_ad(mbmaxlen < DATA_MBMAX); - ut_ad(mbminlen <= mbmaxlen); - - col->mbminmaxlen = DATA_MBMINMAXLEN(mbminlen, mbmaxlen); + return col->mbmaxlen; } /*********************************************************************//** Gets the column data type. */ @@ -83,7 +66,8 @@ dict_col_copy_type( type->mtype = col->mtype; type->prtype = col->prtype; type->len = col->len; - type->mbminmaxlen = col->mbminmaxlen; + type->mbminlen = col->mbminlen; + type->mbmaxlen = col->mbmaxlen; } #endif /* !UNIV_HOTBACKUP */ @@ -105,7 +89,8 @@ dict_col_type_assert_equal( ut_ad(col->prtype == type->prtype); ut_ad(col->len == type->len); # ifndef UNIV_HOTBACKUP - ut_ad(col->mbminmaxlen == type->mbminmaxlen); + ut_ad(col->mbminlen == type->mbminlen); + ut_ad(col->mbmaxlen == type->mbmaxlen); # endif /* !UNIV_HOTBACKUP */ return(TRUE); @@ -123,7 +108,7 @@ dict_col_get_min_size( const dict_col_t* col) /*!< in: column */ { return(dtype_get_min_size_low(col->mtype, col->prtype, col->len, - col->mbminmaxlen)); + col->mbminlen, col->mbmaxlen)); } /***********************************************************************//** Returns the maximum size of the column. @@ -148,7 +133,7 @@ dict_col_get_fixed_size( ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ { return(dtype_get_fixed_size_low(col->mtype, col->prtype, col->len, - col->mbminmaxlen, comp)); + col->mbminlen, col->mbmaxlen, comp)); } /***********************************************************************//** Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column. diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 1b12c8303bb..e807d0fcbea 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2014, 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 @@ -294,11 +295,10 @@ struct dict_col_struct{ the string, MySQL uses 1 or 2 bytes to store the string length) */ - unsigned mbminmaxlen:5; /*!< minimum and maximum length of a - character, in bytes; - DATA_MBMINMAXLEN(mbminlen,mbmaxlen); - mbminlen=DATA_MBMINLEN(mbminmaxlen); - mbmaxlen=DATA_MBMINLEN(mbminmaxlen) */ + unsigned mbminlen:3; /*!< minimum length of a + character, in bytes */ + unsigned mbmaxlen:3; /*!< maximum length of a + character, in bytes */ /*----------------------*/ /* End of definitions copied from dtype_t */ /* @} */ diff --git a/storage/innobase/rem/rem0rec.c b/storage/innobase/rem/rem0rec.c index 7f435a92489..779a2a0867d 100644 --- a/storage/innobase/rem/rem0rec.c +++ b/storage/innobase/rem/rem0rec.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2011, 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 @@ -845,13 +846,10 @@ rec_get_converted_size_comp_prefix_low( if (fixed_len) { #ifdef UNIV_DEBUG - ulint mbminlen = DATA_MBMINLEN(col->mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN(col->mbminmaxlen); - ut_ad(len <= fixed_len); - ut_ad(!mbmaxlen || len >= mbminlen - * (fixed_len / mbmaxlen)); + ut_ad(!col->mbmaxlen || len >= col->mbminlen + * (fixed_len / col->mbmaxlen)); /* dict_index_add_col() should guarantee this */ ut_ad(!field->prefix_len @@ -1237,14 +1235,10 @@ rec_convert_dtuple_to_rec_comp( it is 128 or more, or when the field is stored externally. */ if (fixed_len) { #ifdef UNIV_DEBUG - ulint mbminlen = DATA_MBMINLEN( - ifield->col->mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN( - ifield->col->mbminmaxlen); - ut_ad(len <= fixed_len); - ut_ad(!mbmaxlen || len >= mbminlen - * (fixed_len / mbmaxlen)); + ut_ad(!ifield->col->mbmaxlen + || len >= ifield->col->mbminlen + * (fixed_len / ifield->col->mbmaxlen)); ut_ad(!dfield_is_ext(field)); #endif /* UNIV_DEBUG */ } else if (dfield_is_ext(field)) { diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index ec3815ed8cd..93628d9261c 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2014, 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 @@ -527,7 +528,8 @@ row_ins_cascade_calc_update_vec( if (!dfield_is_null(&ufield->new_val) && dtype_get_at_most_n_mbchars( - col->prtype, col->mbminmaxlen, + col->prtype, + col->mbminlen, col->mbmaxlen, col->len, ufield_len, dfield_get_data(&ufield->new_val)) @@ -2312,7 +2314,7 @@ row_ins_index_entry_set_vals( = dict_field_get_col(ind_field); len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminmaxlen, + col->prtype, col->mbminlen, col->mbmaxlen, ind_field->prefix_len, len, dfield_get_data(row_field)); diff --git a/storage/innobase/row/row0merge.c b/storage/innobase/row/row0merge.c index a393254d145..22ba78a1ef3 100644 --- a/storage/innobase/row/row0merge.c +++ b/storage/innobase/row/row0merge.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2013, 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 @@ -339,7 +340,7 @@ row_merge_buf_add( if (ifield->prefix_len) { len = dtype_get_at_most_n_mbchars( col->prtype, - col->mbminmaxlen, + col->mbminlen, col->mbmaxlen, ifield->prefix_len, len, dfield_get_data(field)); dfield_set_len(field, len); @@ -349,8 +350,7 @@ row_merge_buf_add( fixed_len = ifield->fixed_len; if (fixed_len && !dict_table_is_comp(index->table) - && DATA_MBMINLEN(col->mbminmaxlen) - != DATA_MBMAXLEN(col->mbminmaxlen)) { + && col->mbminlen != col->mbmaxlen) { /* CHAR in ROW_FORMAT=REDUNDANT is always fixed-length, but in the temporary file it is variable-length for variable-length character @@ -360,14 +360,11 @@ row_merge_buf_add( if (fixed_len) { #ifdef UNIV_DEBUG - ulint mbminlen = DATA_MBMINLEN(col->mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN(col->mbminmaxlen); - /* len should be between size calcualted base on mbmaxlen and mbminlen */ ut_ad(len <= fixed_len); - ut_ad(!mbmaxlen || len >= mbminlen - * (fixed_len / mbmaxlen)); + ut_ad(!col->mbmaxlen || len >= col->mbminlen + * (fixed_len / col->mbmaxlen)); ut_ad(!dfield_is_ext(field)); #endif /* UNIV_DEBUG */ diff --git a/storage/innobase/row/row0row.c b/storage/innobase/row/row0row.c index c15e2bbf739..bacdcbfaac0 100644 --- a/storage/innobase/row/row0row.c +++ b/storage/innobase/row/row0row.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2012, 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 @@ -164,7 +165,7 @@ row_build_index_entry( /* If a column prefix index, take only the prefix. */ if (ind_field->prefix_len) { len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminmaxlen, + col->prtype, col->mbminlen, col->mbmaxlen, ind_field->prefix_len, len, dfield_get_data(dfield)); dfield_set_len(dfield, len); @@ -546,7 +547,8 @@ row_build_row_ref( dfield_set_len(dfield, dtype_get_at_most_n_mbchars( dtype->prtype, - dtype->mbminmaxlen, + dtype->mbminlen, + dtype->mbmaxlen, clust_col_prefix_len, len, (char*) field)); } @@ -660,7 +662,8 @@ notfound: dfield_set_len(dfield, dtype_get_at_most_n_mbchars( dtype->prtype, - dtype->mbminmaxlen, + dtype->mbminlen, + dtype->mbmaxlen, clust_col_prefix_len, len, (char*) field)); } diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index d697fef3f52..e6525489a52 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -2,6 +2,7 @@ Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. +Copyright (c) 2018, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -90,8 +91,10 @@ row_sel_sec_rec_is_for_blob( /*========================*/ ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of - a multi-byte character */ + ulint mbminlen, /*!< in: minimum length of + a character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of + a character, in bytes */ const byte* clust_field, /*!< in: the locally stored part of the clustered index column, including the BLOB pointer; the clustered @@ -141,7 +144,7 @@ row_sel_sec_rec_is_for_blob( return(FALSE); } - len = dtype_get_at_most_n_mbchars(prtype, mbminmaxlen, + len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen, prefix_len, len, (const char*) buf); return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len)); @@ -225,14 +228,14 @@ row_sel_sec_rec_is_for_clust_rec( } len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminmaxlen, + col->prtype, col->mbminlen, col->mbmaxlen, ifield->prefix_len, len, (char*) clust_field); if (rec_offs_nth_extern(clust_offs, clust_pos) && len < sec_len) { if (!row_sel_sec_rec_is_for_blob( col->mtype, col->prtype, - col->mbminmaxlen, + col->mbminlen, col->mbmaxlen, clust_field, clust_len, sec_field, sec_len, ifield->prefix_len, diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c index 25fe6f09c4e..35a989a75c4 100644 --- a/storage/innobase/row/row0upd.c +++ b/storage/innobase/row/row0upd.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2014, 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 @@ -990,7 +991,7 @@ row_upd_index_replace_new_col_val( } len = dtype_get_at_most_n_mbchars(col->prtype, - col->mbminmaxlen, + col->mbminlen, col->mbmaxlen, field->prefix_len, len, (const char*) data); diff --git a/storage/xtradb/data/data0type.c b/storage/xtradb/data/data0type.c index 9f855d58adf..c278cc8821e 100644 --- a/storage/xtradb/data/data0type.c +++ b/storage/xtradb/data/data0type.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2009, Innobase Oy. 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 @@ -49,8 +50,10 @@ ulint dtype_get_at_most_n_mbchars( /*========================*/ ulint prtype, /*!< in: precise type */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of - a multi-byte character */ + ulint mbminlen, /*!< in: minimum length of + a multi-byte character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of + a multi-byte character, in bytes */ ulint prefix_len, /*!< in: length of the requested prefix, in characters, multiplied by dtype_get_mbmaxlen(dtype) */ @@ -58,9 +61,6 @@ dtype_get_at_most_n_mbchars( const char* str) /*!< in: the string whose prefix length is being determined */ { - ulint mbminlen = DATA_MBMINLEN(mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN(mbminmaxlen); - ut_a(data_len != UNIV_SQL_NULL); ut_ad(!mbmaxlen || !(prefix_len % mbmaxlen)); diff --git a/storage/xtradb/dict/dict0mem.c b/storage/xtradb/dict/dict0mem.c index 18917a30ff6..253d766d5b3 100644 --- a/storage/xtradb/dict/dict0mem.c +++ b/storage/xtradb/dict/dict0mem.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2010, Innobase Oy. 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 @@ -254,7 +255,8 @@ dict_mem_fill_column_struct( column->len = (unsigned int) col_len; #ifndef UNIV_HOTBACKUP dtype_get_mblen(mtype, prtype, &mbminlen, &mbmaxlen); - dict_col_set_mbminmaxlen(column, mbminlen, mbmaxlen); + column->mbminlen = mbminlen; + column->mbmaxlen = mbmaxlen; #endif /* !UNIV_HOTBACKUP */ } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 00f345d4bc1..a17ab44f49d 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -5800,8 +5800,8 @@ build_template_field( } templ->charset = dtype_get_charset_coll(col->prtype); - templ->mbminlen = DATA_MBMINLEN(col->mbminmaxlen); - templ->mbmaxlen = DATA_MBMAXLEN(col->mbminmaxlen); + templ->mbminlen = col->mbminlen; + templ->mbmaxlen = col->mbmaxlen; templ->is_unsigned = col->prtype & DATA_UNSIGNED; if (!dict_index_is_clust(index) diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index 82902db8412..70ff556e98d 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2013, 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 @@ -100,8 +101,7 @@ innobase_col_to_mysql( #ifdef UNIV_DEBUG case DATA_MYSQL: ut_ad(flen >= len); - ut_ad(DATA_MBMAXLEN(col->mbminmaxlen) - >= DATA_MBMINLEN(col->mbminmaxlen)); + ut_ad(col->mbmaxlen >= col->mbminlen); memcpy(dest, data, len); break; diff --git a/storage/xtradb/include/data0type.h b/storage/xtradb/include/data0type.h index 25d68de6646..852e18153c2 100644 --- a/storage/xtradb/include/data0type.h +++ b/storage/xtradb/include/data0type.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2009, Innobase Oy. 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 @@ -169,18 +170,7 @@ store the charset-collation number; one byte is left unused, though */ #define DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE 6 /* Maximum multi-byte character length in bytes, plus 1 */ -#define DATA_MBMAX 5 - -/* Pack mbminlen, mbmaxlen to mbminmaxlen. */ -#define DATA_MBMINMAXLEN(mbminlen, mbmaxlen) \ - ((mbmaxlen) * DATA_MBMAX + (mbminlen)) -/* Get mbminlen from mbminmaxlen. Cast the result of UNIV_EXPECT to ulint -because in GCC it returns a long. */ -#define DATA_MBMINLEN(mbminmaxlen) ((ulint) \ - UNIV_EXPECT(((mbminmaxlen) % DATA_MBMAX), \ - 1)) -/* Get mbmaxlen from mbminmaxlen. */ -#define DATA_MBMAXLEN(mbminmaxlen) ((ulint) ((mbminmaxlen) / DATA_MBMAX)) +#define DATA_MBMAX 8 #ifndef UNIV_HOTBACKUP /*********************************************************************//** @@ -201,8 +191,10 @@ ulint dtype_get_at_most_n_mbchars( /*========================*/ ulint prtype, /*!< in: precise type */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of - a multi-byte character */ + ulint mbminlen, /*!< in: minimum length of + a multi-byte character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of + a multi-byte character, in bytes */ ulint prefix_len, /*!< in: length of the requested prefix, in characters, multiplied by dtype_get_mbmaxlen(dtype) */ @@ -347,19 +339,6 @@ dtype_get_mbmaxlen( /*===============*/ const dtype_t* type); /*!< in: type */ /*********************************************************************//** -Sets the minimum and maximum length of a character, in bytes. */ -UNIV_INLINE -void -dtype_set_mbminmaxlen( -/*==================*/ - dtype_t* type, /*!< in/out: type */ - ulint mbminlen, /*!< in: minimum length of a char, - in bytes, or 0 if this is not - a character type */ - ulint mbmaxlen); /*!< in: maximum length of a char, - in bytes, or 0 if this is not - a character type */ -/*********************************************************************//** Gets the padding character code for the type. @return padding character code, or ULINT_UNDEFINED if no padding specified */ UNIV_INLINE @@ -379,7 +358,9 @@ dtype_get_fixed_size_low( ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ ulint len, /*!< in: length */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of a + ulint mbminlen, /*!< in: minimum length of a + multibyte character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of a multibyte character, in bytes */ ulint comp); /*!< in: nonzero=ROW_FORMAT=COMPACT */ #ifndef UNIV_HOTBACKUP @@ -393,8 +374,8 @@ dtype_get_min_size_low( ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ ulint len, /*!< in: length */ - ulint mbminmaxlen); /*!< in: minimum and maximum length of a - multibyte character */ + ulint mbminlen, /*!< in: minimum length of a character */ + ulint mbmaxlen); /*!< in: maximum length of a character */ /***********************************************************************//** Returns the maximum size of a data type. Note: types in system tables may be incomplete and return incorrect information. @@ -497,11 +478,10 @@ struct dtype_struct{ the string, MySQL uses 1 or 2 bytes to store the string length) */ #ifndef UNIV_HOTBACKUP - unsigned mbminmaxlen:5; /*!< minimum and maximum length of a - character, in bytes; - DATA_MBMINMAXLEN(mbminlen,mbmaxlen); - mbminlen=DATA_MBMINLEN(mbminmaxlen); - mbmaxlen=DATA_MBMINLEN(mbminmaxlen) */ + unsigned mbminlen:3; /*!< minimum length of a character, + in bytes */ + unsigned mbmaxlen:3; /*!< maximum length of a character, + in bytes */ #endif /* !UNIV_HOTBACKUP */ }; diff --git a/storage/xtradb/include/data0type.ic b/storage/xtradb/include/data0type.ic index 5848e5d6548..0688b162387 100644 --- a/storage/xtradb/include/data0type.ic +++ b/storage/xtradb/include/data0type.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2012, 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 @@ -100,27 +101,6 @@ dtype_get_mblen( } } -/*********************************************************************//** -Sets the minimum and maximum length of a character, in bytes. */ -UNIV_INLINE -void -dtype_set_mbminmaxlen( -/*==================*/ - dtype_t* type, /*!< in/out: type */ - ulint mbminlen, /*!< in: minimum length of a char, - in bytes, or 0 if this is not - a character type */ - ulint mbmaxlen) /*!< in: maximum length of a char, - in bytes, or 0 if this is not - a character type */ -{ - ut_ad(mbminlen < DATA_MBMAX); - ut_ad(mbmaxlen < DATA_MBMAX); - ut_ad(mbminlen <= mbmaxlen); - - type->mbminmaxlen = DATA_MBMINMAXLEN(mbminlen, mbmaxlen); -} - /*********************************************************************//** Compute the mbminlen and mbmaxlen members of a data type structure. */ UNIV_INLINE @@ -133,7 +113,8 @@ dtype_set_mblen( ulint mbmaxlen; dtype_get_mblen(type->mtype, type->prtype, &mbminlen, &mbmaxlen); - dtype_set_mbminmaxlen(type, mbminlen, mbmaxlen); + type->mbminlen = mbminlen; + type->mbmaxlen = mbmaxlen; ut_ad(dtype_validate(type)); } @@ -229,8 +210,7 @@ dtype_get_mbminlen( /*===============*/ const dtype_t* type) /*!< in: type */ { - ut_ad(type); - return(DATA_MBMINLEN(type->mbminmaxlen)); + return type->mbminlen; } /*********************************************************************//** Gets the maximum length of a character, in bytes. @@ -242,8 +222,7 @@ dtype_get_mbmaxlen( /*===============*/ const dtype_t* type) /*!< in: type */ { - ut_ad(type); - return(DATA_MBMAXLEN(type->mbminmaxlen)); + return type->mbmaxlen; } /*********************************************************************//** @@ -424,8 +403,10 @@ dtype_get_fixed_size_low( ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ ulint len, /*!< in: length */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of - a multibyte character, in bytes */ + ulint mbminlen, /*!< in: minimum length of a + multibyte character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of a + multibyte character, in bytes */ ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ { switch (mtype) { @@ -466,11 +447,10 @@ dtype_get_fixed_size_low( dtype_get_charset_coll(prtype), &i_mbminlen, &i_mbmaxlen); - ut_ad(DATA_MBMINMAXLEN(i_mbminlen, i_mbmaxlen) - == mbminmaxlen); + ut_ad(i_mbminlen == mbminlen); + ut_ad(i_mbmaxlen == mbmaxlen); #endif /* UNIV_DEBUG */ - if (DATA_MBMINLEN(mbminmaxlen) - == DATA_MBMAXLEN(mbminmaxlen)) { + if (mbminlen == mbmaxlen) { return(len); } } @@ -502,8 +482,8 @@ dtype_get_min_size_low( ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ ulint len, /*!< in: length */ - ulint mbminmaxlen) /*!< in: minimum and maximum length of a - multi-byte character */ + ulint mbminlen, /*!< in: minimum length of a character */ + ulint mbmaxlen) /*!< in: maximum length of a character */ { switch (mtype) { case DATA_SYS: @@ -533,9 +513,6 @@ dtype_get_min_size_low( if (prtype & DATA_BINARY_TYPE) { return(len); } else { - ulint mbminlen = DATA_MBMINLEN(mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN(mbminmaxlen); - if (mbminlen == mbmaxlen) { return(len); } @@ -606,9 +583,9 @@ dtype_get_sql_null_size( { #ifndef UNIV_HOTBACKUP return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len, - type->mbminmaxlen, comp)); + type->mbminlen, type->mbmaxlen, comp)); #else /* !UNIV_HOTBACKUP */ return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len, - 0, 0)); + 0, 0, 0)); #endif /* !UNIV_HOTBACKUP */ } diff --git a/storage/xtradb/include/dict0dict.h b/storage/xtradb/include/dict0dict.h index d8c8e39b1bf..9f39a0b3e05 100644 --- a/storage/xtradb/include/dict0dict.h +++ b/storage/xtradb/include/dict0dict.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2014, 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 @@ -119,17 +120,6 @@ dict_col_get_mbmaxlen( /*==================*/ const dict_col_t* col); /*!< in: column */ /*********************************************************************//** -Sets the minimum and maximum number of bytes per character. */ -UNIV_INLINE -void -dict_col_set_mbminmaxlen( -/*=====================*/ - dict_col_t* col, /*!< in/out: column */ - ulint mbminlen, /*!< in: minimum multi-byte - character size, in bytes */ - ulint mbmaxlen); /*!< in: minimum multi-byte - character size, in bytes */ -/*********************************************************************//** Gets the column data type. */ UNIV_INLINE void diff --git a/storage/xtradb/include/dict0dict.ic b/storage/xtradb/include/dict0dict.ic index 3410c945a80..3631dc38d81 100644 --- a/storage/xtradb/include/dict0dict.ic +++ b/storage/xtradb/include/dict0dict.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2014, 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 @@ -38,7 +39,7 @@ dict_col_get_mbminlen( /*==================*/ const dict_col_t* col) /*!< in: column */ { - return(DATA_MBMINLEN(col->mbminmaxlen)); + return col->mbminlen; } /*********************************************************************//** Gets the maximum number of bytes per character. @@ -49,25 +50,7 @@ dict_col_get_mbmaxlen( /*==================*/ const dict_col_t* col) /*!< in: column */ { - return(DATA_MBMAXLEN(col->mbminmaxlen)); -} -/*********************************************************************//** -Sets the minimum and maximum number of bytes per character. */ -UNIV_INLINE -void -dict_col_set_mbminmaxlen( -/*=====================*/ - dict_col_t* col, /*!< in/out: column */ - ulint mbminlen, /*!< in: minimum multi-byte - character size, in bytes */ - ulint mbmaxlen) /*!< in: minimum multi-byte - character size, in bytes */ -{ - ut_ad(mbminlen < DATA_MBMAX); - ut_ad(mbmaxlen < DATA_MBMAX); - ut_ad(mbminlen <= mbmaxlen); - - col->mbminmaxlen = DATA_MBMINMAXLEN(mbminlen, mbmaxlen); + return col->mbmaxlen; } /*********************************************************************//** Gets the column data type. */ @@ -83,7 +66,8 @@ dict_col_copy_type( type->mtype = col->mtype; type->prtype = col->prtype; type->len = col->len; - type->mbminmaxlen = col->mbminmaxlen; + type->mbminlen = col->mbminlen; + type->mbmaxlen = col->mbmaxlen; } #endif /* !UNIV_HOTBACKUP */ @@ -105,7 +89,8 @@ dict_col_type_assert_equal( ut_ad(col->prtype == type->prtype); ut_ad(col->len == type->len); # ifndef UNIV_HOTBACKUP - ut_ad(col->mbminmaxlen == type->mbminmaxlen); + ut_ad(col->mbminlen == type->mbminlen); + ut_ad(col->mbmaxlen == type->mbmaxlen); # endif /* !UNIV_HOTBACKUP */ return(TRUE); @@ -123,7 +108,7 @@ dict_col_get_min_size( const dict_col_t* col) /*!< in: column */ { return(dtype_get_min_size_low(col->mtype, col->prtype, col->len, - col->mbminmaxlen)); + col->mbminlen, col->mbmaxlen)); } /***********************************************************************//** Returns the maximum size of the column. @@ -148,7 +133,7 @@ dict_col_get_fixed_size( ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ { return(dtype_get_fixed_size_low(col->mtype, col->prtype, col->len, - col->mbminmaxlen, comp)); + col->mbminlen, col->mbmaxlen, comp)); } /***********************************************************************//** Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column. diff --git a/storage/xtradb/include/dict0mem.h b/storage/xtradb/include/dict0mem.h index 07ecc42f045..bd4cbddd591 100644 --- a/storage/xtradb/include/dict0mem.h +++ b/storage/xtradb/include/dict0mem.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2014, 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 @@ -294,11 +295,10 @@ struct dict_col_struct{ the string, MySQL uses 1 or 2 bytes to store the string length) */ - unsigned mbminmaxlen:5; /*!< minimum and maximum length of a - character, in bytes; - DATA_MBMINMAXLEN(mbminlen,mbmaxlen); - mbminlen=DATA_MBMINLEN(mbminmaxlen); - mbmaxlen=DATA_MBMINLEN(mbminmaxlen) */ + unsigned mbminlen:3; /*!< minimum length of a + character, in bytes */ + unsigned mbmaxlen:3; /*!< maximum length of a + character, in bytes */ /*----------------------*/ /* End of definitions copied from dtype_t */ /* @} */ diff --git a/storage/xtradb/rem/rem0rec.c b/storage/xtradb/rem/rem0rec.c index a43085fe89e..a7126f526e8 100644 --- a/storage/xtradb/rem/rem0rec.c +++ b/storage/xtradb/rem/rem0rec.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2011, 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 @@ -845,13 +846,10 @@ rec_get_converted_size_comp_prefix_low( if (fixed_len) { #ifdef UNIV_DEBUG - ulint mbminlen = DATA_MBMINLEN(col->mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN(col->mbminmaxlen); - ut_ad(len <= fixed_len); - ut_ad(!mbmaxlen || len >= mbminlen - * (fixed_len / mbmaxlen)); + ut_ad(!col->mbmaxlen || len >= col->mbminlen + * (fixed_len / col->mbmaxlen)); /* dict_index_add_col() should guarantee this */ ut_ad(!field->prefix_len @@ -1237,14 +1235,10 @@ rec_convert_dtuple_to_rec_comp( it is 128 or more, or when the field is stored externally. */ if (fixed_len) { #ifdef UNIV_DEBUG - ulint mbminlen = DATA_MBMINLEN( - ifield->col->mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN( - ifield->col->mbminmaxlen); - ut_ad(len <= fixed_len); - ut_ad(!mbmaxlen || len >= mbminlen - * (fixed_len / mbmaxlen)); + ut_ad(!ifield->col->mbmaxlen + || len >= ifield->col->mbminlen + * (fixed_len / ifield->col->mbmaxlen)); ut_ad(!dfield_is_ext(field)); #endif /* UNIV_DEBUG */ } else if (dfield_is_ext(field)) { diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c index e6c92080e41..0e3c1d38897 100644 --- a/storage/xtradb/row/row0ins.c +++ b/storage/xtradb/row/row0ins.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2014, 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 @@ -528,7 +529,8 @@ row_ins_cascade_calc_update_vec( if (!dfield_is_null(&ufield->new_val) && dtype_get_at_most_n_mbchars( - col->prtype, col->mbminmaxlen, + col->prtype, + col->mbminlen, col->mbmaxlen, col->len, ufield_len, dfield_get_data(&ufield->new_val)) @@ -2353,7 +2355,7 @@ row_ins_index_entry_set_vals( = dict_field_get_col(ind_field); len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminmaxlen, + col->prtype, col->mbminlen, col->mbmaxlen, ind_field->prefix_len, len, dfield_get_data(row_field)); diff --git a/storage/xtradb/row/row0merge.c b/storage/xtradb/row/row0merge.c index 00a7decdce6..0d0b0e402d3 100644 --- a/storage/xtradb/row/row0merge.c +++ b/storage/xtradb/row/row0merge.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2013, 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 @@ -350,7 +351,7 @@ row_merge_buf_add( if (ifield->prefix_len) { len = dtype_get_at_most_n_mbchars( col->prtype, - col->mbminmaxlen, + col->mbminlen, col->mbmaxlen, ifield->prefix_len, len, dfield_get_data(field)); dfield_set_len(field, len); @@ -360,8 +361,7 @@ row_merge_buf_add( fixed_len = ifield->fixed_len; if (fixed_len && !dict_table_is_comp(index->table) - && DATA_MBMINLEN(col->mbminmaxlen) - != DATA_MBMAXLEN(col->mbminmaxlen)) { + && col->mbminlen != col->mbmaxlen) { /* CHAR in ROW_FORMAT=REDUNDANT is always fixed-length, but in the temporary file it is variable-length for variable-length character @@ -371,14 +371,11 @@ row_merge_buf_add( if (fixed_len) { #ifdef UNIV_DEBUG - ulint mbminlen = DATA_MBMINLEN(col->mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN(col->mbminmaxlen); - /* len should be between size calcualted base on mbmaxlen and mbminlen */ ut_ad(len <= fixed_len); - ut_ad(!mbmaxlen || len >= mbminlen - * (fixed_len / mbmaxlen)); + ut_ad(!col->mbmaxlen || len >= col->mbminlen + * (fixed_len / col->mbmaxlen)); ut_ad(!dfield_is_ext(field)); #endif /* UNIV_DEBUG */ diff --git a/storage/xtradb/row/row0row.c b/storage/xtradb/row/row0row.c index 2c33bdc4b15..0c1c1da3b2b 100644 --- a/storage/xtradb/row/row0row.c +++ b/storage/xtradb/row/row0row.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2012, 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 @@ -164,7 +165,7 @@ row_build_index_entry( /* If a column prefix index, take only the prefix. */ if (ind_field->prefix_len) { len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminmaxlen, + col->prtype, col->mbminlen, col->mbmaxlen, ind_field->prefix_len, len, dfield_get_data(dfield)); dfield_set_len(dfield, len); @@ -562,7 +563,8 @@ row_build_row_ref( dfield_set_len(dfield, dtype_get_at_most_n_mbchars( dtype->prtype, - dtype->mbminmaxlen, + dtype->mbminlen, + dtype->mbmaxlen, clust_col_prefix_len, len, (char*) field)); } @@ -676,7 +678,8 @@ notfound: dfield_set_len(dfield, dtype_get_at_most_n_mbchars( dtype->prtype, - dtype->mbminmaxlen, + dtype->mbminlen, + dtype->mbmaxlen, clust_col_prefix_len, len, (char*) field)); } diff --git a/storage/xtradb/row/row0sel.c b/storage/xtradb/row/row0sel.c index 69b364600b2..54a76ca06c6 100644 --- a/storage/xtradb/row/row0sel.c +++ b/storage/xtradb/row/row0sel.c @@ -2,6 +2,7 @@ Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. +Copyright (c) 2018, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -92,8 +93,10 @@ row_sel_sec_rec_is_for_blob( /*========================*/ ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of - a multi-byte character */ + ulint mbminlen, /*!< in: minimum length of + a character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of + a character, in bytes */ const byte* clust_field, /*!< in: the locally stored part of the clustered index column, including the BLOB pointer; the clustered @@ -143,7 +146,7 @@ row_sel_sec_rec_is_for_blob( return(FALSE); } - len = dtype_get_at_most_n_mbchars(prtype, mbminmaxlen, + len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen, prefix_len, len, (const char*) buf); return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len)); @@ -227,14 +230,14 @@ row_sel_sec_rec_is_for_clust_rec( } len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminmaxlen, + col->prtype, col->mbminlen, col->mbmaxlen, ifield->prefix_len, len, (char*) clust_field); if (rec_offs_nth_extern(clust_offs, clust_pos) && len < sec_len) { if (!row_sel_sec_rec_is_for_blob( col->mtype, col->prtype, - col->mbminmaxlen, + col->mbminlen, col->mbmaxlen, clust_field, clust_len, sec_field, sec_len, ifield->prefix_len, diff --git a/storage/xtradb/row/row0upd.c b/storage/xtradb/row/row0upd.c index c5c2ca5ee8a..c829a5a6744 100644 --- a/storage/xtradb/row/row0upd.c +++ b/storage/xtradb/row/row0upd.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2014, 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 @@ -1008,7 +1009,7 @@ row_upd_index_replace_new_col_val( } len = dtype_get_at_most_n_mbchars(col->prtype, - col->mbminmaxlen, + col->mbminlen, col->mbmaxlen, field->prefix_len, len, (const char*) data); From 204cb85aab3e6326e9f7a51c478efd6fad44801a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 20 Jan 2018 11:45:23 +0100 Subject: [PATCH 15/77] Fix compilation without dlopen --- include/my_global.h | 4 ++-- sql/item_func.cc | 2 ++ sql/sql_plugin.cc | 5 +++++ storage/tokudb/CMakeLists.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index ab7e485a1a0..194e1039c60 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -1376,7 +1376,7 @@ static inline char *dlerror(void) #ifndef HAVE_DLADDR #define dladdr(A, B) 0 /* Dummy definition in case we're missing dladdr() */ -typedef int Dl_info; +typedef struct { const char *dli_fname, dli_fbase; } Dl_info; #endif #else #define dlerror() "No support for dynamic loading (static build?)" @@ -1385,7 +1385,7 @@ typedef int Dl_info; #define dlclose(A) 0 #define dladdr(A, B) 0 /* Dummy definition in case we're missing dladdr() */ -typedef int Dl_info; +typedef struct { const char *dli_fname, dli_fbase; } Dl_info; #endif /* diff --git a/sql/item_func.cc b/sql/item_func.cc index 00006a25a8d..9e4edfc14de 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -595,6 +595,7 @@ my_decimal *Item_real_func::val_decimal(my_decimal *decimal_value) } +#ifdef HAVE_DLOPEN void Item_udf_func::fix_num_length_and_dec() { uint fl_length= 0; @@ -611,6 +612,7 @@ void Item_udf_func::fix_num_length_and_dec() max_length= float_length(NOT_FIXED_DEC); } } +#endif /** diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index d1e855e272e..ccefb04451c 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -477,6 +477,11 @@ static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl) sizeof(struct st_plugin_dl)); DBUG_RETURN(tmp); } +#else +static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *) +{ + return 0; +} #endif /* HAVE_DLOPEN */ diff --git a/storage/tokudb/CMakeLists.txt b/storage/tokudb/CMakeLists.txt index ab6bb0a8504..1e48260b618 100644 --- a/storage/tokudb/CMakeLists.txt +++ b/storage/tokudb/CMakeLists.txt @@ -1,6 +1,6 @@ # ft-index only supports x86-64 and cmake-2.8.9+ IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND - NOT CMAKE_VERSION VERSION_LESS "2.8.9") + NOT CMAKE_VERSION VERSION_LESS "2.8.9" AND HAVE_DLSYM) CHECK_CXX_SOURCE_COMPILES( " struct a {int b; int c; }; From 22ae3843db6c8b2a84ca5d16cd99025abb52cc27 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 20 Jan 2018 17:59:11 +0100 Subject: [PATCH 16/77] Correct TRASH() macro usage TRASH was mapped to TRASH_FREE and was supposed to be used for memory that should not be accessed anymore, while TRASH_ALLOC() is to be used for uninitialized but to-be-used memory. But sometimes TRASH() was used in the latter sense. Remove TRASH() macro, always use explicit TRASH_ALLOC() or TRASH_FREE(). --- include/my_valgrind.h | 1 - mysys/my_alloc.c | 2 +- mysys/my_thr_init.c | 2 -- sql/field.h | 2 +- sql/item.h | 2 +- sql/opt_range.cc | 2 +- sql/sql_cursor.cc | 2 +- sql/sql_lex.h | 4 ++-- sql/sql_lifo_buffer.h | 4 ++-- sql/sql_list.h | 4 ++-- sql/sql_plugin.cc | 2 +- sql/sql_select.cc | 2 +- sql/sql_show.cc | 2 +- sql/sql_string.h | 2 +- sql/sql_union.cc | 16 ---------------- sql/table.cc | 2 +- storage/federatedx/ha_federatedx.h | 2 +- 17 files changed, 17 insertions(+), 36 deletions(-) diff --git a/include/my_valgrind.h b/include/my_valgrind.h index a9dba1cb06c..6fcc4dfa54a 100644 --- a/include/my_valgrind.h +++ b/include/my_valgrind.h @@ -45,4 +45,3 @@ #endif #define TRASH_ALLOC(A,B) TRASH_FILL(A,B,0xA5) #define TRASH_FREE(A,B) TRASH_FILL(A,B,0x8F) -#define TRASH(A,B) TRASH_FREE(A,B) diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index 1054db6cee4..d7bc4247556 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -293,7 +293,7 @@ void *multi_alloc_root(MEM_ROOT *root, ...) DBUG_RETURN((void*) start); } -#define TRASH_MEM(X) TRASH(((char*)(X) + ((X)->size-(X)->left)), (X)->left) +#define TRASH_MEM(X) TRASH_FREE(((char*)(X) + ((X)->size-(X)->left)), (X)->left) /* Mark all data in blocks free for reusage */ diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index aefd3564185..55ee1db657e 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -423,8 +423,6 @@ void my_thread_end(void) if (--THR_thread_count == 0) mysql_cond_signal(&THR_COND_threads); mysql_mutex_unlock(&THR_LOCK_threads); - - TRASH(tmp, sizeof(*tmp)); free(tmp); } } diff --git a/sql/field.h b/sql/field.h index f8fc7427618..d484b31d682 100644 --- a/sql/field.h +++ b/sql/field.h @@ -208,7 +208,7 @@ class Field public: static void *operator new(size_t size) throw () { return sql_alloc(size); } - static void operator delete(void *ptr_arg, size_t size) { TRASH(ptr_arg, size); } + static void operator delete(void *ptr_arg, size_t size) { TRASH_FREE(ptr_arg, size); } uchar *ptr; // Position to field in record /** diff --git a/sql/item.h b/sql/item.h index e01cf5384b9..4daca60f68e 100644 --- a/sql/item.h +++ b/sql/item.h @@ -580,7 +580,7 @@ public: { return sql_alloc(size); } static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return alloc_root(mem_root, size); } - static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } + static void operator delete(void *ptr,size_t size) { TRASH_FREE(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) {} enum Type {FIELD_ITEM= 0, FUNC_ITEM, SUM_FUNC_ITEM, STRING_ITEM, diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 25a9e729a8b..04ab8415dfe 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2651,7 +2651,7 @@ public: /* Table read plans are allocated on MEM_ROOT and are never deleted */ static void *operator new(size_t size, MEM_ROOT *mem_root) { return (void*) alloc_root(mem_root, (uint) size); } - static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } + static void operator delete(void *ptr,size_t size) { TRASH_FREE(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) { /* Never called */ } virtual ~TABLE_READ_PLAN() {} /* Remove gcc warning */ diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc index 230a8b2c802..f7ffd86fe83 100644 --- a/sql/sql_cursor.cc +++ b/sql/sql_cursor.cc @@ -187,7 +187,7 @@ void Server_side_cursor::operator delete(void *ptr, size_t size) MEM_ROOT own_root= *cursor->mem_root; DBUG_ENTER("Server_side_cursor::operator delete"); - TRASH(ptr, size); + TRASH_FREE(ptr, size); /* If this cursor has never been opened mem_root is empty. Otherwise mem_root points to the memory the cursor object was allocated in. diff --git a/sql/sql_lex.h b/sql/sql_lex.h index cf34c567626..57129cfedc7 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -548,7 +548,7 @@ public: } static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return (void*) alloc_root(mem_root, (uint) size); } - static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } + static void operator delete(void *ptr,size_t size) { TRASH_FREE(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) {} // Ensures that at least all members used during cleanup() are initialized. @@ -2949,7 +2949,7 @@ struct st_lex_local: public LEX return (void*) alloc_root(mem_root, (uint) size); } static void operator delete(void *ptr,size_t size) - { TRASH(ptr, size); } + { TRASH_FREE(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) { /* Never called */ } }; diff --git a/sql/sql_lifo_buffer.h b/sql/sql_lifo_buffer.h index feec4aeb4c2..f551cc48c23 100644 --- a/sql/sql_lifo_buffer.h +++ b/sql/sql_lifo_buffer.h @@ -84,7 +84,7 @@ public: start= start_arg; end= end_arg; if (end != start) - TRASH(start, end - start); + TRASH_ALLOC(start, end - start); reset(); } @@ -224,7 +224,7 @@ public: { DBUG_ASSERT(unused_end >= unused_start); DBUG_ASSERT(end == unused_start); - TRASH(unused_start, unused_end - unused_start); + TRASH_ALLOC(unused_start, unused_end - unused_start); end= unused_end; } /* Return pointer to start of the memory area that is occupied by the data */ diff --git a/sql/sql_list.h b/sql/sql_list.h index 7538f69766d..08667bed02a 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -41,12 +41,12 @@ public: { return alloc_root(mem_root, size); } static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return alloc_root(mem_root, size); } - static void operator delete(void *ptr, size_t size) { TRASH(ptr, size); } + static void operator delete(void *ptr, size_t size) { TRASH_FREE(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) { /* never called */ } static void operator delete[](void *ptr, MEM_ROOT *mem_root) { /* never called */ } - static void operator delete[](void *ptr, size_t size) { TRASH(ptr, size); } + static void operator delete[](void *ptr, size_t size) { TRASH_FREE(ptr, size); } #ifdef HAVE_valgrind bool dummy; inline Sql_alloc() :dummy(0) {} diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index ccefb04451c..e616b0a09e4 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -267,7 +267,7 @@ public: static void *operator new(size_t size, MEM_ROOT *mem_root) { return (void*) alloc_root(mem_root, size); } static void operator delete(void *ptr_arg,size_t size) - { TRASH(ptr_arg, size); } + { TRASH_FREE(ptr_arg, size); } sys_var_pluginvar(sys_var_chain *chain, const char *name_arg, struct st_mysql_sys_var *plugin_var_arg, diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d35a5a8094c..f7624b2b56c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11530,7 +11530,7 @@ public: } static void operator delete(void *ptr __attribute__((unused)), size_t size __attribute__((unused))) - { TRASH(ptr, size); } + { TRASH_FREE(ptr, size); } Item *and_level; Item_func *cmp_func; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 8789f0c9f24..06d5a6f570a 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2111,7 +2111,7 @@ public: } static void operator delete(void *ptr __attribute__((unused)), size_t size __attribute__((unused))) - { TRASH(ptr, size); } + { TRASH_FREE(ptr, size); } ulong thread_id; time_t start_time; diff --git a/sql/sql_string.h b/sql/sql_string.h index 1fce3ae6c6f..3175a6616bf 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -102,7 +102,7 @@ public: { (void) ptr_arg; (void) size; - TRASH(ptr_arg, size); + TRASH_FREE(ptr_arg, size); } static void operator delete(void *, MEM_ROOT *) { /* never called */ } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 2d816e0309d..bbb4133417e 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -935,22 +935,6 @@ bool st_select_lex_unit::cleanup() void st_select_lex_unit::reinit_exec_mechanism() { prepared= optimized= executed= 0; -#ifndef DBUG_OFF - if (is_union()) - { - List_iterator_fast it(item_list); - Item *field; - while ((field= it++)) - { - /* - we can't cleanup here, because it broke link to temporary table field, - but have to drop fixed flag to allow next fix_field of this field - during re-executing - */ - field->fixed= 0; - } - } -#endif } diff --git a/sql/table.cc b/sql/table.cc index 9cade76cb78..6795621b719 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3991,7 +3991,7 @@ void TABLE::init(THD *thd, TABLE_LIST *tl) DBUG_ASSERT(key_read == 0); /* mark the record[0] uninitialized */ - TRASH(record[0], s->reclength); + TRASH_ALLOC(record[0], s->reclength); /* Initialize the null marker bits, to ensure that if we are doing a read diff --git a/storage/federatedx/ha_federatedx.h b/storage/federatedx/ha_federatedx.h index 1c64892418e..9529cb126e7 100644 --- a/storage/federatedx/ha_federatedx.h +++ b/storage/federatedx/ha_federatedx.h @@ -169,7 +169,7 @@ public: static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return alloc_root(mem_root, size); } static void operator delete(void *ptr, size_t size) - { TRASH(ptr, size); } + { TRASH_FREE(ptr, size); } virtual int query(const char *buffer, uint length)=0; virtual FEDERATEDX_IO_RESULT *store_result()=0; From a966d422ca56d1772b9f975a8ef48442ae528f0a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 20 Jan 2018 12:50:28 +0100 Subject: [PATCH 17/77] improve ASAN instrumentation: TRASH mark freed memory as not accessible, not merely undefined --- include/my_valgrind.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/my_valgrind.h b/include/my_valgrind.h index 6fcc4dfa54a..9baed2e01d6 100644 --- a/include/my_valgrind.h +++ b/include/my_valgrind.h @@ -39,9 +39,9 @@ #endif /* HAVE_VALGRIND */ #ifndef DBUG_OFF -#define TRASH_FILL(A,B,C) do { memset(A, C, B); MEM_UNDEFINED(A, B); } while (0) +#define TRASH_FILL(A,B,C) do { MEM_UNDEFINED(A,B); memset(A,C,B); } while(0) #else -#define TRASH_FILL(A,B,C) do { MEM_CHECK_ADDRESSABLE(A,B);MEM_UNDEFINED(A,B);} while (0) +#define TRASH_FILL(A,B,C) do { MEM_UNDEFINED(A,B); } while(0) #endif -#define TRASH_ALLOC(A,B) TRASH_FILL(A,B,0xA5) -#define TRASH_FREE(A,B) TRASH_FILL(A,B,0x8F) +#define TRASH_ALLOC(A,B) do { TRASH_FILL(A,B,0xA5); MEM_UNDEFINED(A,B); } while(0) +#define TRASH_FREE(A,B) do { TRASH_FILL(A,B,0x8F); MEM_NOACCESS(A,B); } while(0) From dc28b6d180a00658debf65b1258bd5fdf0d0c26e Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 21 Jan 2018 12:53:17 +0100 Subject: [PATCH 18/77] improve ASAN instrumentation: MEM_ROOT more complete TRASH-ing of memroots --- mysys/my_alloc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index d7bc4247556..24e95d2c69c 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -22,6 +22,8 @@ #undef EXTRA_DEBUG #define EXTRA_DEBUG +#define TRASH_MEM(X) TRASH_FREE(((char*)(X) + ((X)->size-(X)->left)), (X)->left) + /* Initialize memory root @@ -60,12 +62,13 @@ void init_alloc_root(MEM_ROOT *mem_root, size_t block_size, if (pre_alloc_size) { if ((mem_root->free= mem_root->pre_alloc= - (USED_MEM*) my_malloc(pre_alloc_size+ ALIGN_SIZE(sizeof(USED_MEM)), + (USED_MEM*) my_malloc(pre_alloc_size + ALIGN_SIZE(sizeof(USED_MEM)), MYF(0)))) { mem_root->free->size= pre_alloc_size+ALIGN_SIZE(sizeof(USED_MEM)); mem_root->free->left= pre_alloc_size; mem_root->free->next= 0; + TRASH_MEM(mem_root->free); } } #endif @@ -132,6 +135,7 @@ void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size, mem->left= pre_alloc_size; mem->next= *prev; *prev= mem_root->pre_alloc= mem; + TRASH_MEM(mem); } else { @@ -225,6 +229,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) next->size= get_size; next->left= get_size-ALIGN_SIZE(sizeof(USED_MEM)); *prev=next; + TRASH_MEM(next); } point= (uchar*) ((char*) next+ (next->size-next->left)); @@ -293,8 +298,6 @@ void *multi_alloc_root(MEM_ROOT *root, ...) DBUG_RETURN((void*) start); } -#define TRASH_MEM(X) TRASH_FREE(((char*)(X) + ((X)->size-(X)->left)), (X)->left) - /* Mark all data in blocks free for reusage */ static inline void mark_blocks_free(MEM_ROOT* root) From fa331acefd6b5907b06d394ae0ae096749129601 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 21 Jan 2018 11:30:02 +0100 Subject: [PATCH 19/77] improve ASAN instrumentation: mtr --- mysql-test/mysql-test-run.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 7bd86e66575..37e5d486988 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1605,6 +1605,7 @@ sub command_line_setup { $opt_manual_debug || $opt_dbx || $opt_client_dbx || $opt_manual_dbx || $opt_debugger || $opt_client_debugger ) { + $ENV{ASAN_OPTIONS}= 'abort_on_error=1:'.($ENV{ASAN_OPTIONS} || ''); if ( using_extern() ) { mtr_error("Can't use --extern when using debugger"); From 36eb0b7a558542689ad654a770c3f1ce8f18dd87 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 21 Jan 2018 12:50:49 +0100 Subject: [PATCH 20/77] improve ASAN instrumentation: table->record[0] instrument table->record[0], table->record[1] and share->default_values. One should not access record image beyond share->reclength, even if table->record[0] has some unused space after it (functions that work with records, might get a copy of the record as an argument, and that copy - not being record[0] - might not have this buffer space at the end). See b80fa4000d6 and 444587d8a3c --- sql/table.cc | 8 ++++++-- storage/heap/ha_heap.cc | 10 +++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/sql/table.cc b/sql/table.cc index 6795621b719..5d73d7dffd2 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1269,9 +1269,10 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, extra_rec_buf_length= uint2korr(head+59); rec_buff_length= ALIGN_SIZE(share->reclength + 1 + extra_rec_buf_length); share->rec_buff_length= rec_buff_length; - if (!(record= (uchar *) alloc_root(&share->mem_root, - rec_buff_length))) + if (!(record= (uchar *) alloc_root(&share->mem_root, rec_buff_length))) goto err; /* purecov: inspected */ + MEM_NOACCESS(record, rec_buff_length); + MEM_UNDEFINED(record, share->reclength); share->default_values= record; if (mysql_file_pread(file, record, (size_t) share->reclength, record_offset, MYF(MY_NABP))) @@ -2430,6 +2431,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, if (!(record= (uchar*) alloc_root(&outparam->mem_root, share->rec_buff_length * records))) goto err; /* purecov: inspected */ + MEM_NOACCESS(record, share->rec_buff_length * records); if (records == 0) { @@ -2444,6 +2446,8 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, else outparam->record[1]= outparam->record[0]; // Safety } + MEM_UNDEFINED(outparam->record[0], share->reclength); + MEM_UNDEFINED(outparam->record[1], share->reclength); if (!(field_ptr = (Field **) alloc_root(&outparam->mem_root, (uint) ((share->fields+1)* diff --git a/storage/heap/ha_heap.cc b/storage/heap/ha_heap.cc index 345ebb8419f..259e54bfc59 100644 --- a/storage/heap/ha_heap.cc +++ b/storage/heap/ha_heap.cc @@ -100,7 +100,15 @@ const char **ha_heap::bas_ext() const int ha_heap::open(const char *name, int mode, uint test_if_locked) { - set_if_bigger(table->s->reclength, sizeof (uchar*)); + if (table->s->reclength < sizeof (char*)) + { + MEM_UNDEFINED(table->s->default_values + table->s->reclength, + sizeof(char*) - table->s->reclength); + table->s->reclength= sizeof(char*); + MEM_UNDEFINED(table->record[0], table->s->reclength); + MEM_UNDEFINED(table->record[1], table->s->reclength); + } + internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE); if (internal_table || (!(file= heap_open(name, mode)) && my_errno == ENOENT)) { From f2408e7e6a39a8544b34e2407a02a084e38e49ba Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 20 Jan 2018 17:59:37 +0100 Subject: [PATCH 21/77] Free memory in unit tests. Makes ASAN happier. --- storage/maria/unittest/ma_test_loghandler_multigroup-t.c | 4 +++- storage/maria/unittest/ma_test_loghandler_nologs-t.c | 1 + unittest/mysys/base64-t.c | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/storage/maria/unittest/ma_test_loghandler_multigroup-t.c b/storage/maria/unittest/ma_test_loghandler_multigroup-t.c index 56329a18d7d..779128830dc 100644 --- a/storage/maria/unittest/ma_test_loghandler_multigroup-t.c +++ b/storage/maria/unittest/ma_test_loghandler_multigroup-t.c @@ -234,7 +234,7 @@ int main(int argc __attribute__((unused)), char *argv[]) 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 }; - uchar *long_buffer= malloc(LONG_BUFFER_SIZE + LSN_STORE_SIZE * 2 + 2); + uchar *long_buffer; char **default_argv; PAGECACHE pagecache; LSN lsn, lsn_base, first_lsn; @@ -255,6 +255,7 @@ int main(int argc __attribute__((unused)), char *argv[]) } #endif + long_buffer= malloc(LONG_BUFFER_SIZE + LSN_STORE_SIZE * 2 + 2); load_defaults("my", load_default_groups, &argc, &argv); get_options(&argc, &argv); default_argv= argv; @@ -758,6 +759,7 @@ err: if (maria_log_remove(maria_data_root)) exit(1); + free(long_buffer); return (test(exit_status())); } diff --git a/storage/maria/unittest/ma_test_loghandler_nologs-t.c b/storage/maria/unittest/ma_test_loghandler_nologs-t.c index 24c93e428e1..06529066305 100644 --- a/storage/maria/unittest/ma_test_loghandler_nologs-t.c +++ b/storage/maria/unittest/ma_test_loghandler_nologs-t.c @@ -191,6 +191,7 @@ int main(int argc __attribute__((unused)), char *argv[]) if (maria_log_remove(maria_data_root)) exit(1); + free(long_buffer); exit(0); } diff --git a/unittest/mysys/base64-t.c b/unittest/mysys/base64-t.c index ed19c4de851..f4496f570f9 100644 --- a/unittest/mysys/base64-t.c +++ b/unittest/mysys/base64-t.c @@ -91,6 +91,9 @@ main(int argc __attribute__((unused)),char *argv[]) diag("src length: %.8x, dst length: %.8x\n", (uint) src_len, (uint) dst_len); } + free(dst); + free(str); + free(src); } my_end(0); return exit_status(); From d9c460b84e6dd603d0101369ee3d6f935213827c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 21 Jan 2018 15:08:33 +0100 Subject: [PATCH 22/77] Finally! Make './mtr --valgrind-mysqld --gdb' to work. It has its limitations, e.g. it assumes that there's only one gdb and only one valgrind process is running. And a hard-coded one-second delay might be too short for slow machines. Still, it's better than "doesn't work at all" --- mysql-test/lib/My/SafeProcess.pm | 2 +- mysql-test/mysql-test-run.pl | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/mysql-test/lib/My/SafeProcess.pm b/mysql-test/lib/My/SafeProcess.pm index e7917f8fb16..7059ceebdad 100644 --- a/mysql-test/lib/My/SafeProcess.pm +++ b/mysql-test/lib/My/SafeProcess.pm @@ -84,7 +84,7 @@ sub is_child { } -my @safe_process_cmd; +our @safe_process_cmd; my $safe_kill; my $bindir; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 37e5d486988..61ad87cc21c 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -5378,7 +5378,7 @@ sub mysqld_start ($$) { my $args; mtr_init_args(\$args); - if ( $opt_valgrind_mysqld ) + if ( $opt_valgrind_mysqld and not $opt_gdb and not $opt_manual_gdb ) { valgrind_arguments($args, \$exe); } @@ -5981,11 +5981,20 @@ sub gdb_arguments { unlink($gdb_init_file); # Put $args into a single string - my $str= join(" ", @$$args); $input = $input ? "< $input" : ""; - # write init file for mysqld or client - mtr_tofile($gdb_init_file, "set args $str $input\n"); + if ($type ne 'client' and $opt_valgrind_mysqld) { + my $v = $$exe; + my $vargs = []; + valgrind_arguments($vargs, \$v); + mtr_tofile($gdb_init_file, < Date: Sun, 21 Jan 2018 20:48:59 +0100 Subject: [PATCH 23/77] improve ASAN instrumentation: InnoDB/XtraDB --- storage/innobase/include/univ.i | 17 ++++++++++------- storage/xtradb/include/univ.i | 16 +++++++++------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index a9d75955550..35c32d6bc1b 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -162,7 +162,7 @@ command. Not tested on Windows. */ #define UNIV_COMPILE_TEST_FUNCS */ -#if defined(HAVE_valgrind)&& defined(HAVE_VALGRIND_MEMCHECK_H) +#if defined(HAVE_VALGRIND) && defined(HAVE_valgrind) # define UNIV_DEBUG_VALGRIND #endif /* HAVE_VALGRIND */ #if 0 @@ -497,12 +497,17 @@ typedef void* os_thread_ret_t; #include "ut0dbg.h" #include "ut0ut.h" #include "db0err.h" + +#include +/* define UNIV macros in terms of my_valgrind.h */ +# define UNIV_MEM_INVALID(addr, size) MEM_UNDEFINED(addr, size) +# define UNIV_MEM_FREE(addr, size) MEM_NOACCESS(addr, size) +# define UNIV_MEM_ALLOC(addr, size) UNIV_MEM_INVALID(addr, size) + +/* macros below cannot be defined in terms of my_valgrind.h */ #ifdef UNIV_DEBUG_VALGRIND # include # define UNIV_MEM_VALID(addr, size) VALGRIND_MAKE_MEM_DEFINED(addr, size) -# define UNIV_MEM_INVALID(addr, size) VALGRIND_MAKE_MEM_UNDEFINED(addr, size) -# define UNIV_MEM_FREE(addr, size) VALGRIND_MAKE_MEM_NOACCESS(addr, size) -# define UNIV_MEM_ALLOC(addr, size) VALGRIND_MAKE_MEM_UNDEFINED(addr, size) # define UNIV_MEM_DESC(addr, size, b) VALGRIND_CREATE_BLOCK(addr, size, b) # define UNIV_MEM_UNDESC(b) VALGRIND_DISCARD(b) # define UNIV_MEM_ASSERT_RW(addr, size) do { \ @@ -525,14 +530,12 @@ typedef void* os_thread_ret_t; } while (0) #else # define UNIV_MEM_VALID(addr, size) do {} while(0) -# define UNIV_MEM_INVALID(addr, size) do {} while(0) -# define UNIV_MEM_FREE(addr, size) do {} while(0) -# define UNIV_MEM_ALLOC(addr, size) do {} while(0) # define UNIV_MEM_DESC(addr, size, b) do {} while(0) # define UNIV_MEM_UNDESC(b) do {} while(0) # define UNIV_MEM_ASSERT_RW(addr, size) do {} while(0) # define UNIV_MEM_ASSERT_W(addr, size) do {} while(0) #endif + #define UNIV_MEM_ASSERT_AND_FREE(addr, size) do { \ UNIV_MEM_ASSERT_W(addr, size); \ UNIV_MEM_FREE(addr, size); \ diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index 6cc424ad0ba..d76350b7715 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -170,7 +170,7 @@ command. Not tested on Windows. */ #define UNIV_COMPILE_TEST_FUNCS */ -#if defined(HAVE_valgrind)&& defined(HAVE_VALGRIND_MEMCHECK_H) +#if defined(HAVE_VALGRIND) && defined(HAVE_valgrind) # define UNIV_DEBUG_VALGRIND #endif #if 0 @@ -511,12 +511,17 @@ typedef void* os_thread_ret_t; #include "ut0dbg.h" #include "ut0ut.h" #include "db0err.h" + +#include +/* define UNIV macros in terms of my_valgrind.h */ +# define UNIV_MEM_INVALID(addr, size) MEM_UNDEFINED(addr, size) +# define UNIV_MEM_FREE(addr, size) MEM_NOACCESS(addr, size) +# define UNIV_MEM_ALLOC(addr, size) UNIV_MEM_INVALID(addr, size) + +/* macros below cannot be defined in terms of my_valgrind.h */ #ifdef UNIV_DEBUG_VALGRIND # include # define UNIV_MEM_VALID(addr, size) VALGRIND_MAKE_MEM_DEFINED(addr, size) -# define UNIV_MEM_INVALID(addr, size) VALGRIND_MAKE_MEM_UNDEFINED(addr, size) -# define UNIV_MEM_FREE(addr, size) VALGRIND_MAKE_MEM_NOACCESS(addr, size) -# define UNIV_MEM_ALLOC(addr, size) VALGRIND_MAKE_MEM_UNDEFINED(addr, size) # define UNIV_MEM_DESC(addr, size, b) VALGRIND_CREATE_BLOCK(addr, size, b) # define UNIV_MEM_UNDESC(b) VALGRIND_DISCARD(b) # define UNIV_MEM_ASSERT_RW(addr, size) do { \ @@ -539,9 +544,6 @@ typedef void* os_thread_ret_t; } while (0) #else # define UNIV_MEM_VALID(addr, size) do {} while(0) -# define UNIV_MEM_INVALID(addr, size) do {} while(0) -# define UNIV_MEM_FREE(addr, size) do {} while(0) -# define UNIV_MEM_ALLOC(addr, size) do {} while(0) # define UNIV_MEM_DESC(addr, size, b) do {} while(0) # define UNIV_MEM_UNDESC(b) do {} while(0) # define UNIV_MEM_ASSERT_RW(addr, size) do {} while(0) From 6d826e3d7ee9af0af2b81d96b69edd6cf8d00423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Sun, 21 Jan 2018 13:12:33 +0200 Subject: [PATCH 24/77] Remove commented out code post merge fix in 2011 --- sql/sql_select.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f7624b2b56c..02a3f0590ac 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -696,12 +696,11 @@ JOIN::prepare(Item ***rref_pointer_array, } table_count= select_lex->leaf_tables.elements; - + TABLE_LIST *tbl; List_iterator_fast li(select_lex->leaf_tables); while ((tbl= li++)) { - //table_count++; /* Count the number of tables in the join. */ /* If the query uses implicit grouping where the select list contains both aggregate functions and non-aggregate fields, any non-aggregated field From b20c3dc664314a3045fa31e2245d4613e9efa508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Sun, 21 Jan 2018 21:18:57 +0200 Subject: [PATCH 25/77] MDEV-14715: Assertion `!table || (!table->read_set... failed in Field_num::val_decimal The assertion failure was caused by an incorrectly set read_set for functions in the ORDER BY clause in part of a union, when we are using a mergeable view and the order by clause can be skipped (removed). An order by clause can be skipped if it's part of one part of the UNION as the result set is not meaningful when multiple SELECT queries are UNIONed. The server is aware of this optimization and tries to remove the order by clause before JOIN::prepare. The problem is that we need to throw an error when the ORDER BY clause contains invalid columns. To do this, we attempt resolving the ORDER BY expressions, then subsequently drop them if resolution succeeded. However, ORDER BY resolution had the side effect of adding the expressions to the all_fields list, which is used to construct temporary tables to store the result. We may be ignoring the ORDER BY statement, but the tmp table still tried to compute the values for the expressions, even if the columns are never used. The assertion only shows itself if the order by clause contains members which were not previously in the select list, and are part of a function. There is an additional question as to why this only manifests when using VIEWS and not when using a regular table. The difference lies with the "reset" of the read_set for the temporary table during SELECT_LEX::update_used_tables() in JOIN::optimize(). The changes introduced in fdf789a7eadf864ecc0e617f25f795fafda55026 cleared the read_set when a mergeable view is encountered in the TABLE_LIST defintion. Upon initial order_list resolution, the table's read_set is updated correctly. JOIN::optimize() will only reset the read_set if it encounters a VIEW. Since we no longer have ORDER BY clause in JOIN::optimize() we never get to correctly update the read_set again. Other relevant commit by Timour, which first introduced the order resolution when we "can_skip_sort_order": 883af99e7dac91e3f258135a2053e6b8e3c05fc3 Solution: Don't add the resolved ORDER BY elements to all_fields. We only resolve them to check if an error should be returned for the query. Ignore them completely otherwise. --- mysql-test/r/union.result | 37 +++++++++++++++++++++++++++++++++++++ mysql-test/t/union.test | 37 +++++++++++++++++++++++++++++++++++++ sql/sql_select.cc | 32 ++++++++++++++++++++++++-------- sql/sql_select.h | 2 +- 4 files changed, 99 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index fe2339db471..83d889b7b73 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1995,4 +1995,41 @@ avg(f) sub 31.5000 0 1.5000 1 drop table t1,t2,t3; +# +# MDEV-14715 Assertion `!table || (!table->read_set || +# bitmap_is_set(table->read_set, field_index))' +# failed in Field_num::val_decimal +# +CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM; +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (1, NULL),(3, 4); +(SELECT a, sum(a) AS f FROM v1 group by a ORDER BY b + sum(a)) +UNION +(SELECT 2, 2); +ERROR HY000: Invalid use of group function +(SELECT a, sum(a) AS f FROM v1 group by a ORDER BY b + 1) +UNION +(SELECT 2, 2); +a f +1 1 +3 3 +2 2 +SELECT a, b FROM t1 +UNION +(SELECT a, VAR_POP(a) AS f FROM v1 GROUP BY a ORDER BY b/a ); +a b +1 NULL +3 4 +1 0 +3 0 +DROP TABLE t1; +(SELECT a, sum(a) AS f FROM v1 group by a ORDER BY b + 1) +UNION +(SELECT 2, 2); +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +DROP VIEW v1; +(SELECT a, sum(a) AS f FROM v1 group by a ORDER BY b + 1) +UNION +(SELECT 2, 2); +ERROR 42S02: Table 'test.v1' doesn't exist End of 5.5 tests diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 4a3c19b49ab..55d09a7d5ac 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -1384,4 +1384,41 @@ select e,f, (e , f) in (select e,b from t1 union select c,d from t2) as sub from select avg(f), (e , f) in (select e,b from t1 union select c,d from t2) as sub from t3 group by sub; drop table t1,t2,t3; +--echo # +--echo # MDEV-14715 Assertion `!table || (!table->read_set || +--echo # bitmap_is_set(table->read_set, field_index))' +--echo # failed in Field_num::val_decimal +--echo # + +CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM; +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (1, NULL),(3, 4); + +--error ER_INVALID_GROUP_FUNC_USE +(SELECT a, sum(a) AS f FROM v1 group by a ORDER BY b + sum(a)) +UNION +(SELECT 2, 2); + +(SELECT a, sum(a) AS f FROM v1 group by a ORDER BY b + 1) +UNION +(SELECT 2, 2); + +SELECT a, b FROM t1 +UNION +(SELECT a, VAR_POP(a) AS f FROM v1 GROUP BY a ORDER BY b/a ); + +DROP TABLE t1; + +--error ER_VIEW_INVALID +(SELECT a, sum(a) AS f FROM v1 group by a ORDER BY b + 1) +UNION +(SELECT 2, 2); + +DROP VIEW v1; + +--error ER_NO_SUCH_TABLE +(SELECT a, sum(a) AS f FROM v1 group by a ORDER BY b + 1) +UNION +(SELECT 2, 2); + --echo End of 5.5 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 02a3f0590ac..5db503cd266 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -279,6 +279,10 @@ enum enum_exec_or_opt {WALK_OPTIMIZATION_TABS , WALK_EXECUTION_TABS}; JOIN_TAB *first_breadth_first_tab(JOIN *join, enum enum_exec_or_opt tabs_kind); JOIN_TAB *next_breadth_first_tab(JOIN *join, enum enum_exec_or_opt tabs_kind, JOIN_TAB *tab); +static bool +find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, + ORDER *order, List &fields, List &all_fields, + bool is_group_field, bool add_to_all_fields); /** This handles SELECT with and without UNION. @@ -735,9 +739,15 @@ JOIN::prepare(Item ***rref_pointer_array, /* Resolve the ORDER BY that was skipped, then remove it. */ if (skip_order_by && select_lex != select_lex->master_unit()->global_parameters) { - if (setup_order(thd, (*rref_pointer_array), tables_list, fields_list, - all_fields, select_lex->order_list.first)) - DBUG_RETURN(-1); + thd->where= "order clause"; + for (ORDER *order= select_lex->order_list.first; order; order= order->next) + { + /* Don't add the order items to all fields. Just resolve them to ensure + the query is valid, we'll drop them immediately after. */ + if (find_order_in_list(thd, *rref_pointer_array, tables_list, order, + fields_list, all_fields, false, false)) + DBUG_RETURN(-1); + } select_lex->order_list.empty(); } @@ -20625,7 +20635,10 @@ cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref) SELECT list) @param[in,out] all_fields All select, group and order by fields @param[in] is_group_field True if order is a GROUP field, false if - ORDER by field + ORDER by field + @param[in] add_to_all_fields If the item is to be added to all_fields and + ref_pointer_array, this flag can be set to + false to stop the automatic insertion. @retval FALSE if OK @@ -20636,7 +20649,7 @@ cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref) static bool find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, ORDER *order, List &fields, List &all_fields, - bool is_group_field) + bool is_group_field, bool add_to_all_fields) { Item *order_item= *order->item; /* The item from the GROUP/ORDER caluse. */ Item::Type order_item_type; @@ -20755,6 +20768,9 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, thd->is_error())) return TRUE; /* Wrong field. */ + if (!add_to_all_fields) + return FALSE; + uint el= all_fields.elements; DBUG_ASSERT(all_fields.elements <= thd->lex->current_select->ref_pointer_array_size); @@ -20784,13 +20800,13 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, */ int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, - List &fields, List &all_fields, ORDER *order) + List &fields, List &all_fields, ORDER *order) { thd->where="order clause"; for (; order; order=order->next) { if (find_order_in_list(thd, ref_pointer_array, tables, order, fields, - all_fields, FALSE)) + all_fields, FALSE, true)) return 1; } return 0; @@ -20842,7 +20858,7 @@ setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, for (ord= order; ord; ord= ord->next) { if (find_order_in_list(thd, ref_pointer_array, tables, ord, fields, - all_fields, TRUE)) + all_fields, TRUE, true)) return 1; (*ord->item)->marker= UNDEF_POS; /* Mark found */ if ((*ord->item)->with_sum_func) diff --git a/sql/sql_select.h b/sql/sql_select.h index 1bc1e4c2b7a..e208377e275 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1757,7 +1757,7 @@ int get_quick_record(SQL_SELECT *select); SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length, SORT_FIELD *sortorder); int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, - List &fields, List &all_fields, ORDER *order); + List &fields, List &all_fields, ORDER *order); int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, List &fields, List &all_fields, ORDER *order, bool *hidden_group_fields); From 8539e4b1b609f8060677fcb3e27b6b6224d582d6 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 22 Jan 2018 13:39:59 +0100 Subject: [PATCH 26/77] improve ASAN instrumentation: clang translate clang __has_feature to gcc macros --- include/my_valgrind.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/my_valgrind.h b/include/my_valgrind.h index 9baed2e01d6..b76f5607bb5 100644 --- a/include/my_valgrind.h +++ b/include/my_valgrind.h @@ -13,6 +13,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* clang -> gcc */ +#ifndef __has_feature +# define __has_feature(x) 0 +#endif +#if __has_feature(address_sanitizer) +# define __SANITIZE_ADDRESS__ 1 +#endif + #ifdef HAVE_valgrind #define IF_VALGRIND(A,B) A #else From a04b07eb342fa00f952e8fd60216ea781bc7c5d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Mon, 22 Jan 2018 23:51:32 +0200 Subject: [PATCH 27/77] Fix TokuDB Not building We don't check for DLSYM in CMake, check for DLOPEN instead. --- storage/tokudb/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/tokudb/CMakeLists.txt b/storage/tokudb/CMakeLists.txt index 1e48260b618..903471b097c 100644 --- a/storage/tokudb/CMakeLists.txt +++ b/storage/tokudb/CMakeLists.txt @@ -1,6 +1,6 @@ # ft-index only supports x86-64 and cmake-2.8.9+ IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND - NOT CMAKE_VERSION VERSION_LESS "2.8.9" AND HAVE_DLSYM) + NOT CMAKE_VERSION VERSION_LESS "2.8.9" AND HAVE_DLOPEN) CHECK_CXX_SOURCE_COMPILES( " struct a {int b; int c; }; From 3532a421f6e272c739f4c435e80a354ba13da824 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Tue, 23 Jan 2018 11:57:54 +0300 Subject: [PATCH 28/77] fix build for recent clang /home/kevg/work/mariadb/sql/sql_partition.cc:286:47: error: cannot initialize a parameter of type 'HA_CREATE_INFO *' (aka 'st_ha_create_information *') with an rvalue of type 'ulonglong' (aka 'unsigned long long') (ulonglong)0, (uint)0); ^~~~~~~~~~~~ /home/kevg/work/mariadb/sql/partition_info.h:281:72: note: passing argument to parameter 'info' here bool set_up_defaults_for_partitioning(handler *file, HA_CREATE_INFO *info, ^ --- sql/sql_partition.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 01dcc7cc2ac..8e58c34162f 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -283,7 +283,7 @@ bool partition_default_handling(TABLE *table, partition_info *part_info, } } part_info->set_up_defaults_for_partitioning(table->file, - (ulonglong)0, (uint)0); + NULL, (uint)0); DBUG_RETURN(FALSE); } From c98906e4fe779430e1392d70ba71fb7ac41eb6ff Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Tue, 23 Jan 2018 07:35:38 +1100 Subject: [PATCH 29/77] mysql_install_db: correct --skip-grant-tables help --- scripts/mysql_install_db.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 7d644e835da..b437108d041 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -448,7 +448,7 @@ else echo echo "You can also try to start the mysqld daemon with:" echo - echo " shell> $mysqld --skip-grant --general-log &" + echo " shell> $mysqld --skip-grant-tables --general-log &" echo echo "and use the command line tool $bindir/mysql" echo "to connect to the mysql database and look at the grant tables:" From 9ee372736faf999e9c6189019ac3faa5063e7777 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Tue, 23 Jan 2018 07:37:00 +1100 Subject: [PATCH 30/77] mysql_install_db: correct hosting/source/maillist information --- scripts/mysql_install_db.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index b437108d041..2c5f8d7082d 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -459,8 +459,8 @@ else echo "Try 'mysqld --help' if you have problems with paths. Using" echo "--general-log gives you a log in $ldata that may be helpful." link_to_help - echo "MariaDB is hosted on launchpad; You can find the latest source and" - echo "email lists at http://launchpad.net/maria" + echo "You can find the latest source at https://downloads.mariadb.org and" + echo "the maria-discuss email list at https://launchpad.net/~maria-discuss" echo echo "Please check all of the above before submitting a bug report" echo "at http://mariadb.org/jira" From 701c7e777ff707085337c01f0a49d0daa8635c06 Mon Sep 17 00:00:00 2001 From: Karim Geiger Date: Tue, 23 Jan 2018 11:56:52 +0100 Subject: [PATCH 31/77] Fix error message typo --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3d2de3126ff..c78f2ffd94f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3461,7 +3461,7 @@ static int init_common_variables() /* TODO: remove this when my_time_t is 64 bit compatible */ if (!IS_TIME_T_VALID_FOR_TIMESTAMP(server_start_time)) { - sql_print_error("This MySQL server doesn't support dates later then 2038"); + sql_print_error("This MySQL server doesn't support dates later than 2038"); return 1; } From cc3155415ec1c1c7143fbab51b30e52575bbc36f Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Fri, 19 Jan 2018 19:52:01 +1100 Subject: [PATCH 32/77] MDEV-5510: Replace MySQL -> MariaDB in init scripts --- support-files/mysql.server.sh | 48 +++++++++++++++++------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index 7a6154a1af5..1776919e950 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -2,7 +2,7 @@ # Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB # This file is public domain and comes with NO WARRANTY of any kind -# MySQL daemon start/stop script. +# MariaDB daemon start/stop script. # Usually this is put in /etc/init.d (at least on machines SYSV R4 based # systems) and linked to /etc/rc3.d/S99mysql and /etc/rc0.d/K01mysql. @@ -21,14 +21,14 @@ # Required-Stop: $local_fs $network $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 -# Short-Description: start and stop MySQL -# Description: MySQL is a very fast and reliable SQL database engine. +# Short-Description: start and stop MariaDB +# Description: MariaDB is a very fast and reliable SQL database engine. ### END INIT INFO - -# If you install MySQL on some other places than @prefix@, then you + +# If you install MariaDB on some other places than @prefix@, then you # have to do one of the following things for this script to work: # -# - Run this script from within the MySQL installation directory +# - Run this script from within the MariaDB installation directory # - Create a /etc/my.cnf file with the following information: # [mysqld] # basedir= @@ -37,11 +37,11 @@ # - Add the path to the mysql-installation-directory to the basedir variable # below. # -# If you want to affect other MySQL variables, you should make your changes -# in the /etc/my.cnf, ~/.my.cnf or other MySQL configuration files. +# If you want to affect other MariaDB variables, you should make your changes +# in the /etc/my.cnf, ~/.my.cnf or other MariaDB configuration files. # If you change base dir, you must also change datadir. These may get -# overwritten by settings in the MySQL configuration files. +# overwritten by settings in the MariaDB configuration files. basedir= datadir= @@ -291,7 +291,7 @@ case "$mode" in # Safeguard (relative paths, core dumps..) cd $basedir - echo $echo_n "Starting MySQL" + echo $echo_n "Starting MariaDB" if test -x $bindir/mysqld_safe then # Give extra arguments to mysqld with the my.cnf file. This script @@ -307,7 +307,7 @@ case "$mode" in exit $return_value else - log_failure_msg "Couldn't find MySQL server ($bindir/mysqld_safe)" + log_failure_msg "Couldn't find MariaDB server ($bindir/mysqld_safe)" fi ;; @@ -321,12 +321,12 @@ case "$mode" in if (kill -0 $mysqld_pid 2>/dev/null) then - echo $echo_n "Shutting down MySQL" + echo $echo_n "Shutting down MariaDB" kill $mysqld_pid # mysqld should remove the pid file when it exits, so wait for it. wait_for_gone $mysqld_pid "$mysqld_pid_file_path"; return_value=$? else - log_failure_msg "MySQL server process #$mysqld_pid is not running!" + log_failure_msg "MariaDB server process #$mysqld_pid is not running!" rm "$mysqld_pid_file_path" fi @@ -337,7 +337,7 @@ case "$mode" in fi exit $return_value else - log_failure_msg "MySQL server PID file could not be found!" + log_failure_msg "MariaDB server PID file could not be found!" fi ;; @@ -355,10 +355,10 @@ case "$mode" in 'reload'|'force-reload') if test -s "$mysqld_pid_file_path" ; then read mysqld_pid < "$mysqld_pid_file_path" - kill -HUP $mysqld_pid && log_success_msg "Reloading service MySQL" + kill -HUP $mysqld_pid && log_success_msg "Reloading service MariaDB" touch "$mysqld_pid_file_path" else - log_failure_msg "MySQL PID file could not be found!" + log_failure_msg "MariaDB PID file could not be found!" exit 1 fi ;; @@ -367,10 +367,10 @@ case "$mode" in if test -s "$mysqld_pid_file_path" ; then read mysqld_pid < "$mysqld_pid_file_path" if kill -0 $mysqld_pid 2>/dev/null ; then - log_success_msg "MySQL running ($mysqld_pid)" + log_success_msg "MariaDB running ($mysqld_pid)" exit 0 else - log_failure_msg "MySQL is not running, but PID file exists" + log_failure_msg "MariaDB is not running, but PID file exists" exit 1 fi else @@ -380,17 +380,17 @@ case "$mode" in # test if multiple pids exist pid_count=`echo $mysqld_pid | wc -w` if test $pid_count -gt 1 ; then - log_failure_msg "Multiple MySQL running but PID file could not be found ($mysqld_pid)" + log_failure_msg "Multiple MariaDB running but PID file could not be found ($mysqld_pid)" exit 5 elif test -z $mysqld_pid ; then if test -f "$lock_file_path" ; then - log_failure_msg "MySQL is not running, but lock file ($lock_file_path) exists" + log_failure_msg "MariaDB is not running, but lock file ($lock_file_path) exists" exit 2 fi - log_failure_msg "MySQL is not running" + log_failure_msg "MariaDB is not running" exit 3 else - log_failure_msg "MySQL is running but PID file could not be found" + log_failure_msg "MariaDB is running but PID file could not be found" exit 4 fi fi @@ -398,7 +398,7 @@ case "$mode" in 'configtest') # Safeguard (relative paths, core dumps..) cd $basedir - echo $echo_n "Testing MySQL configuration syntax" + echo $echo_n "Testing MariaDB configuration syntax" daemon=$bindir/mysqld if test -x $libexecdir/mysqld then @@ -425,7 +425,7 @@ case "$mode" in *) # usage basename=`basename "$0"` - echo "Usage: $basename {start|stop|restart|reload|force-reload|status|configtest} [ MySQL server options ]" + echo "Usage: $basename {start|stop|restart|reload|force-reload|status|configtest} [ MariaDB server options ]" exit 1 ;; esac From 94da1cb4a67ecb2e2590748381eebac072308ce6 Mon Sep 17 00:00:00 2001 From: Sachin Setiya Date: Tue, 23 Jan 2018 15:47:54 +0530 Subject: [PATCH 33/77] MDEV-14586 Assertion `0' failed in retrieve_auto_increment ... Problem:- If we create table using myisam/aria then this crashes the server. CREATE TABLE t1(a bit(1), b int auto_increment , index(a,b)); insert into t1 values(1,1); Or this query CREATE TABLE t1 (b BIT(1), pk INTEGER AUTO_INCREMENT PRIMARY KEY); ALTER TABLE t1 ADD INDEX(b,pk); INSERT INTO t1 VALUES (1,b'1'); ALTER TABLE t1 DROP PRIMARY KEY; Reason:- The reason for this is 1st- find_ref_key() finds what key an auto_increment field belongs to by comparing key_part->offset and field->ptr. But BIT fields might have zero length in the record, so a key might have many key parts with the same offset. That is, comparing offsets cannot uniquely identify the correct key part. 2nd- Since next_number_key_offset is zero it myisam/aria will think that auto_increment is in first part of key. 3nd- myisam/aria will call retrieve_auto_key which will see first key_part field as a bit field and call assert(0) Solution:- Many key parts might have the same offset, but BIT fields do not support auto_increment. So, we can skip all key parts over BIT fields, and then comparing offsets will be unambiguous. --- mysql-test/r/mdev_14586.result | 44 ++++++++++++++++++++++++++++++++++ mysql-test/t/mdev_14586.test | 27 +++++++++++++++++++++ sql/key.cc | 6 +++-- 3 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 mysql-test/r/mdev_14586.result create mode 100644 mysql-test/t/mdev_14586.test diff --git a/mysql-test/r/mdev_14586.result b/mysql-test/r/mdev_14586.result new file mode 100644 index 00000000000..f6c2095d3cd --- /dev/null +++ b/mysql-test/r/mdev_14586.result @@ -0,0 +1,44 @@ +create table t1(a bit(1), b int auto_increment ,id int, index(a,b)); +insert into t1 values(1,null,1); +insert into t1 values(1,null,2); +insert into t1 values(0,null,3); +insert into t1 values(0,null,4); +select a+0, b as auto_increment , id from t1 order by id; +a+0 auto_increment id +1 1 1 +1 2 2 +0 1 3 +0 2 4 +drop table t1; +create table t1(a int auto_increment, b bit(5) ,id int, index (b,a)); +insert into t1 values(null,b'1',1); +insert into t1 values(null,b'1',2); +insert into t1 values(null,b'11',3); +insert into t1 values(null,b'11',4); +select a as auto_increment, b+0, id from t1 order by id; +auto_increment b+0 id +1 1 1 +2 1 2 +1 3 3 +2 3 4 +drop table t1; +create table t1(a bit(1), b int auto_increment , c bit(1) , d bit(1), id int,index(a,c,b,d)); +insert into t1 values(1,null,1,1,1); +insert into t1 values(1,null,1,1,2); +insert into t1 values(0,null,1,1,3); +insert into t1 values(1,null,0,1,4); +select a+0, b as auto_increment, c+0, d+0, id from t1 order by id; +a+0 auto_increment c+0 d+0 id +1 1 1 1 1 +1 2 1 1 2 +0 1 1 1 3 +1 1 0 1 4 +drop table t1; +CREATE TABLE t1 (b BIT(1), pk INTEGER AUTO_INCREMENT PRIMARY KEY); +ALTER TABLE t1 ADD INDEX(b,pk); +INSERT INTO t1 VALUES (1,b'1'); +ALTER TABLE t1 DROP PRIMARY KEY; +select b+0, pk as auto_increment from t1; +b+0 auto_increment +1 1 +DROP TABLE t1; diff --git a/mysql-test/t/mdev_14586.test b/mysql-test/t/mdev_14586.test new file mode 100644 index 00000000000..8b3d3780151 --- /dev/null +++ b/mysql-test/t/mdev_14586.test @@ -0,0 +1,27 @@ +create table t1(a bit(1), b int auto_increment ,id int, index(a,b)); +insert into t1 values(1,null,1); +insert into t1 values(1,null,2); +insert into t1 values(0,null,3); +insert into t1 values(0,null,4); +select a+0, b as auto_increment , id from t1 order by id; +drop table t1; +create table t1(a int auto_increment, b bit(5) ,id int, index (b,a)); +insert into t1 values(null,b'1',1); +insert into t1 values(null,b'1',2); +insert into t1 values(null,b'11',3); +insert into t1 values(null,b'11',4); +select a as auto_increment, b+0, id from t1 order by id; +drop table t1; +create table t1(a bit(1), b int auto_increment , c bit(1) , d bit(1), id int,index(a,c,b,d)); +insert into t1 values(1,null,1,1,1); +insert into t1 values(1,null,1,1,2); +insert into t1 values(0,null,1,1,3); +insert into t1 values(1,null,0,1,4); +select a+0, b as auto_increment, c+0, d+0, id from t1 order by id; +drop table t1; +CREATE TABLE t1 (b BIT(1), pk INTEGER AUTO_INCREMENT PRIMARY KEY); +ALTER TABLE t1 ADD INDEX(b,pk); +INSERT INTO t1 VALUES (1,b'1'); +ALTER TABLE t1 DROP PRIMARY KEY; +select b+0, pk as auto_increment from t1; +DROP TABLE t1; diff --git a/sql/key.cc b/sql/key.cc index 110b13000ed..700bf6a05a6 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -62,7 +62,8 @@ int find_ref_key(KEY *key, uint key_count, uchar *record, Field *field, i < (int) key_count ; i++, key_info++) { - if (key_info->key_part[0].offset == fieldpos) + if (key_info->key_part[0].offset == fieldpos && + key_info->key_part[0].field->type() != MYSQL_TYPE_BIT) { /* Found key. Calc keylength */ *key_length= *keypart= 0; return i; /* Use this key */ @@ -81,7 +82,8 @@ int find_ref_key(KEY *key, uint key_count, uchar *record, Field *field, j < key_info->key_parts ; j++, key_part++) { - if (key_part->offset == fieldpos) + if (key_part->offset == fieldpos && + key_part->field->type() != MYSQL_TYPE_BIT) { *keypart= j; return i; /* Use this key */ From 11408a69adc6749c855a9867fc4db3e3d45236c3 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Sun, 21 Jan 2018 23:44:31 +0100 Subject: [PATCH 34/77] Fix Item tree changes/rollback debug print --- sql/sql_class.cc | 8 ++++---- sql/sql_class.h | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index b007729494e..c88c13b9524 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2234,6 +2234,9 @@ void THD::check_and_register_item_tree_change(Item **place, Item **new_value, MEM_ROOT *runtime_memroot) { Item_change_record *change; + DBUG_ENTER("THD::check_and_register_item_tree_change"); + DBUG_PRINT("enter", ("Register: %p (%p) <- %p (%p)", + *place, place, *new_value, new_value)); I_List_iterator it(change_list); while ((change= it++)) { @@ -2243,6 +2246,7 @@ void THD::check_and_register_item_tree_change(Item **place, Item **new_value, if (change) nocheck_register_item_tree_change(place, change->old_value, runtime_memroot); + DBUG_VOID_RETURN; } @@ -2250,17 +2254,13 @@ void THD::rollback_item_tree_changes() { I_List_iterator it(change_list); Item_change_record *change; - DBUG_ENTER("rollback_item_tree_changes"); while ((change= it++)) { - DBUG_PRINT("info", ("revert %p -> %p", - change->old_value, (*change->place))); *change->place= change->old_value; } /* We can forget about changes memory: it's allocated in runtime memroot */ change_list.empty(); - DBUG_VOID_RETURN; } diff --git a/sql/sql_class.h b/sql/sql_class.h index e8f50f13ebc..bff7492ffec 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2725,10 +2725,14 @@ public: void change_item_tree(Item **place, Item *new_value) { + DBUG_ENTER("THD::change_item_tree"); + DBUG_PRINT("enter", ("Register: %p (%p) <- %p", + *place, place, new_value)); /* TODO: check for OOM condition here */ if (!stmt_arena->is_conventional()) nocheck_register_item_tree_change(place, *place, mem_root); *place= new_value; + DBUG_VOID_RETURN; } /** Make change in item tree after checking whether it needs registering From ba8d0fa700a73893979793785ed53f7bbd950df8 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 15 Jan 2018 14:50:35 +0100 Subject: [PATCH 35/77] MDEV-14786: Server crashes in Item_cond::transform on 2nd execution of SP querying from a view MDEV-14957: JOIN::prepare gets unusable "conds" as argument Do not touch merged derived (it is irreversible) Fix first argument of in_optimizer for calls possible before fix_fields() --- mysql-test/r/derived.result | 16 ++++++++++++++++ mysql-test/t/derived.test | 15 +++++++++++++++ sql/item.cc | 2 +- sql/item.h | 6 ++++++ sql/item_cmpfunc.cc | 34 ++++++++++++++++++++++++++++++++++ sql/item_cmpfunc.h | 2 ++ sql/sql_derived.cc | 20 ++++++++++++++++++++ sql/sql_select.cc | 3 +++ 8 files changed, 97 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index 763dbe264fb..54c78dc9f6f 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -1036,4 +1036,20 @@ SELECT * FROM v1, t2, v3 WHERE a = c AND b = d; a b c d DROP VIEW v1, v3; DROP TABLE t1, t2, t3; +# +# MDEV-14786: Server crashes in Item_cond::transform on 2nd +# execution of SP querying from a view +# +create table t1 (i int, row_start timestamp(6) not null default now(), +row_end timestamp(6) not null default '2030-01-01 0:0:0'); +create view v1 as select i from t1 where i < 5 and (row_end = +TIMESTAMP'2030-01-01 0:0:0' or row_end is null); +create procedure pr(x int) select i from v1; +call pr(1); +i +call pr(2); +i +drop procedure pr; +drop view v1; +drop table t1; # end of 5.5 diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index eb6e502b029..c5b792c8d4d 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -888,4 +888,19 @@ SELECT * FROM v1, t2, v3 WHERE a = c AND b = d; DROP VIEW v1, v3; DROP TABLE t1, t2, t3; +--echo # +--echo # MDEV-14786: Server crashes in Item_cond::transform on 2nd +--echo # execution of SP querying from a view +--echo # +create table t1 (i int, row_start timestamp(6) not null default now(), + row_end timestamp(6) not null default '2030-01-01 0:0:0'); +create view v1 as select i from t1 where i < 5 and (row_end = +TIMESTAMP'2030-01-01 0:0:0' or row_end is null); +create procedure pr(x int) select i from v1; +call pr(1); +call pr(2); +drop procedure pr; +drop view v1; +drop table t1; + --echo # end of 5.5 diff --git a/sql/item.cc b/sql/item.cc index 576dce78299..08a00615c0c 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -10010,7 +10010,7 @@ const char *dbug_print_item(Item *item) if (!item) return "(Item*)NULL"; item->print(&str ,QT_ORDINARY); - if (str.c_ptr() == buf) + if (str.c_ptr_safe() == buf) return buf; else return "Couldn't fit into buffer"; diff --git a/sql/item.h b/sql/item.h index 4daca60f68e..830f8bf14a4 100644 --- a/sql/item.h +++ b/sql/item.h @@ -50,6 +50,12 @@ bool trace_unsupported_by_check_vcol_func_processor(const char *where) return trace_unsupported_func(where, "check_vcol_func_processor"); } +#ifdef DBUG_OFF +static inline const char *dbug_print_item(Item *item) { return NULL; } +#else +extern const char *dbug_print_item(Item *item); +#endif + class Protocol; struct TABLE_LIST; void item_init(void); /* Init item functions */ diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 62e76922c0e..a77443f40ef 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1420,6 +1420,7 @@ bool Item_in_optimizer::is_top_level_item() void Item_in_optimizer::fix_after_pullout(st_select_lex *new_parent, Item **ref) { + DBUG_ASSERT(fixed); /* This will re-calculate attributes of our Item_in_subselect: */ Item_bool_func::fix_after_pullout(new_parent, ref); @@ -1443,6 +1444,33 @@ bool Item_in_optimizer::eval_not_null_tables(uchar *opt_arg) } +void Item_in_optimizer::print(String *str, enum_query_type query_type) +{ + restore_first_argumet(); + Item_func::print(str, query_type); +} + + +/** + "Restore" first argument before fix_fields() call (after it is harmless). + + @Note: Main pointer to left part of IN/ALL/ANY subselect is subselect's + lest_expr (see Item_in_optimizer::fix_left) so changes made during + fix_fields will be rolled back there which can make + Item_in_optimizer::args[0] unusable on second execution before fix_left() + call. This call fix the pointer. +*/ + +void Item_in_optimizer::restore_first_argumet() +{ + if (args[1]->type() == Item::SUBSELECT_ITEM && + ((Item_subselect *)args[1])->is_in_predicate()) + { + args[0]= ((Item_in_subselect *)args[1])->left_expr; + } +} + + bool Item_in_optimizer::fix_left(THD *thd, Item **ref) { DBUG_ENTER("Item_in_optimizer::fix_left"); @@ -1588,6 +1616,8 @@ Item *Item_in_optimizer::expr_cache_insert_transformer(uchar *thd_arg) { THD *thd= (THD*) thd_arg; DBUG_ENTER("Item_in_optimizer::expr_cache_insert_transformer"); + DBUG_ASSERT(fixed); + if (args[1]->type() != Item::SUBSELECT_ITEM) DBUG_RETURN(this); // MAX/MIN transformed => do nothing @@ -1611,6 +1641,7 @@ Item *Item_in_optimizer::expr_cache_insert_transformer(uchar *thd_arg) void Item_in_optimizer::get_cache_parameters(List ¶meters) { + DBUG_ASSERT(fixed); /* Add left expression to the list of the parameters of the subquery */ if (args[0]->cols() == 1) parameters.add_unique(args[0], &cmp_items); @@ -1842,6 +1873,7 @@ Item *Item_in_optimizer::transform(Item_transformer transformer, uchar *argument { Item *new_item; + DBUG_ASSERT(fixed); DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare()); DBUG_ASSERT(arg_count == 2); @@ -1893,6 +1925,7 @@ Item *Item_in_optimizer::transform(Item_transformer transformer, uchar *argument bool Item_in_optimizer::is_expensive_processor(uchar *arg) { + DBUG_ASSERT(fixed); return args[0]->is_expensive_processor(arg) || args[1]->is_expensive_processor(arg); } @@ -1900,6 +1933,7 @@ bool Item_in_optimizer::is_expensive_processor(uchar *arg) bool Item_in_optimizer::is_expensive() { + DBUG_ASSERT(fixed); return args[0]->is_expensive() || args[1]->is_expensive(); } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 7b7ca9223fd..c0e97be20c4 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -268,6 +268,8 @@ public: bool is_top_level_item(); bool eval_not_null_tables(uchar *opt_arg); void fix_after_pullout(st_select_lex *new_parent, Item **ref); + virtual void print(String *str, enum_query_type query_type); + void restore_first_argumet(); }; class Comp_creator diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 2a6d82c161a..2e947ecba16 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -366,7 +366,11 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) derived->get_unit())); if (derived->merged) + { + + DBUG_PRINT("info", ("Irreversibly merged: exit")); DBUG_RETURN(FALSE); + } if (dt_select->uncacheable & UNCACHEABLE_RAND) { @@ -667,6 +671,17 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) unit->derived= derived; + /* + Above cascade call of prepare is important for PS protocol, but after it + is called we can check if we really need prepare for this derived + */ + if (derived->merged) + { + DBUG_PRINT("info", ("Irreversibly merged: exit")); + DBUG_RETURN(FALSE); + } + + derived->fill_me= FALSE; if (!(derived->derived_result= new select_union)) @@ -795,6 +810,11 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived) DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", (derived->alias ? derived->alias : ""), derived->get_unit())); + if (derived->merged) + { + DBUG_PRINT("info", ("Irreversibly merged: exit")); + DBUG_RETURN(FALSE); + } if (unit->optimized) DBUG_RETURN(FALSE); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 5db503cd266..90bb536c0e2 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -638,6 +638,9 @@ JOIN::prepare(Item ***rref_pointer_array, join_list= &select_lex->top_join_list; union_part= unit_arg->is_union(); + // simple check that we got usable conds + dbug_print_item(conds); + if (select_lex->handle_derived(thd->lex, DT_PREPARE)) DBUG_RETURN(1); From 70a9b12de90d25d9348c87a71c742fecbdb07c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 23 Jan 2018 18:08:55 +0200 Subject: [PATCH 36/77] Silence -Wimplicit-fallthrough --- storage/innobase/row/row0sel.c | 1 + storage/xtradb/row/row0sel.c | 1 + 2 files changed, 2 insertions(+) diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index e6525489a52..9d163158b10 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -4276,6 +4276,7 @@ no_gap_lock: prebuilt->new_rec_locks = 1; } err = DB_SUCCESS; + /* fall through */ case DB_SUCCESS: break; case DB_LOCK_WAIT: diff --git a/storage/xtradb/row/row0sel.c b/storage/xtradb/row/row0sel.c index 54a76ca06c6..67a9dfcae90 100644 --- a/storage/xtradb/row/row0sel.c +++ b/storage/xtradb/row/row0sel.c @@ -4434,6 +4434,7 @@ no_gap_lock: prebuilt->new_rec_locks = 1; } err = DB_SUCCESS; + /* fall through */ case DB_SUCCESS: break; case DB_LOCK_WAIT: From 8637931f118b53ff6fdadf6006ccdb8dedd6f732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 23 Jan 2018 19:29:12 +0200 Subject: [PATCH 37/77] Add ASAN instrumentation (and more strict Valgrind) to InnoDB mem_heap_free_heap_top(): Remove UNIV_MEM_ASSERT_W() and unpoison the memory region first, because part of it may have been poisoned by an earlier mem_heap_free_top() call. Poison the address range at the end. mem_heap_block_free(): Poison the address range at the end. UNIV_MEM_ASSERT_AND_ALLOC(): Replace with UNIV_MEM_ALLOC(). We want to keep the address ranges poisoned (unaccessible) as long as possible. UNIV_MEM_ASSERT_AND_FREE(): Replace with UNIV_MEM_FREE(). --- storage/innobase/buf/buf0buddy.c | 3 ++- storage/innobase/buf/buf0lru.c | 4 ++-- storage/innobase/include/mem0mem.ic | 13 ++++--------- storage/innobase/include/rem0rec.ic | 3 ++- storage/innobase/include/univ.i | 9 --------- storage/innobase/mem/mem0mem.c | 9 +++++---- storage/xtradb/buf/buf0buddy.c | 3 ++- storage/xtradb/buf/buf0lru.c | 3 ++- storage/xtradb/include/mem0mem.ic | 13 ++++--------- storage/xtradb/include/rem0rec.ic | 3 ++- storage/xtradb/include/univ.i | 8 -------- storage/xtradb/mem/mem0mem.c | 9 +++++---- 12 files changed, 30 insertions(+), 50 deletions(-) diff --git a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c index fa2515eddc2..6382cf534e1 100644 --- a/storage/innobase/buf/buf0buddy.c +++ b/storage/innobase/buf/buf0buddy.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2006, 2011, 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 @@ -438,7 +439,7 @@ buf_buddy_free_low( buf_pool->buddy_stat[i].used--; recombine: - UNIV_MEM_ASSERT_AND_ALLOC(buf, BUF_BUDDY_LOW << i); + UNIV_MEM_ALLOC(buf, BUF_BUDDY_LOW << i); ((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE; if (i == BUF_BUDDY_SIZES) { diff --git a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c index 09a136bfa59..c3911c255ad 100644 --- a/storage/innobase/buf/buf0lru.c +++ b/storage/innobase/buf/buf0lru.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2011, 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 @@ -1953,8 +1954,7 @@ buf_LRU_block_free_non_file_page( UT_LIST_ADD_FIRST(list, buf_pool->free, (&block->page)); ut_d(block->page.in_free_list = TRUE); - - UNIV_MEM_ASSERT_AND_FREE(block->frame, UNIV_PAGE_SIZE); + UNIV_MEM_FREE(block->frame, UNIV_PAGE_SIZE); } /******************************************************************//** diff --git a/storage/innobase/include/mem0mem.ic b/storage/innobase/include/mem0mem.ic index 6b2e35d7387..b0b24526031 100644 --- a/storage/innobase/include/mem0mem.ic +++ b/storage/innobase/include/mem0mem.ic @@ -297,6 +297,7 @@ mem_heap_free_heap_top( #ifdef UNIV_MEM_DEBUG ut_ad(mem_block_get_start(block) <= mem_block_get_free(block)); + UNIV_MEM_ALLOC(old_top, (byte*)block + block->len - old_top); /* In the debug version erase block from top up */ mem_erase_buf(old_top, (byte*)block + block->len - old_top); @@ -304,10 +305,8 @@ mem_heap_free_heap_top( mutex_enter(&mem_hash_mutex); mem_current_allocated_memory -= (total_size - size); mutex_exit(&mem_hash_mutex); -#else /* UNIV_MEM_DEBUG */ - UNIV_MEM_ASSERT_W(old_top, (byte*)block + block->len - old_top); #endif /* UNIV_MEM_DEBUG */ - UNIV_MEM_ALLOC(old_top, (byte*)block + block->len - old_top); + UNIV_MEM_FREE(old_top, (byte*)block + block->len - old_top); /* If free == start, we may free the block if it is not the first one */ @@ -388,11 +387,11 @@ mem_heap_free_top( /* Subtract the free field of block */ mem_block_set_free(block, mem_block_get_free(block) - MEM_SPACE_NEEDED(n)); - UNIV_MEM_ASSERT_W((byte*) block + mem_block_get_free(block), n); #ifdef UNIV_MEM_DEBUG ut_ad(mem_block_get_start(block) <= mem_block_get_free(block)); + UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n); /* In the debug version check the consistency, and erase field */ mem_field_erase((byte*)block + mem_block_get_free(block), n); #endif @@ -404,11 +403,7 @@ mem_heap_free_top( == mem_block_get_start(block))) { mem_heap_block_free(heap, block); } else { - /* Avoid a bogus UNIV_MEM_ASSERT_W() warning in a - subsequent invocation of mem_heap_free_top(). - Originally, this was UNIV_MEM_FREE(), to catch writes - to freed memory. */ - UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n); + UNIV_MEM_FREE((byte*) block + mem_block_get_free(block), n); } } diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic index c81388391d7..8138552d095 100644 --- a/storage/innobase/include/rem0rec.ic +++ b/storage/innobase/include/rem0rec.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2011, 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 @@ -923,7 +924,7 @@ rec_offs_set_n_alloc( { ut_ad(offsets); ut_ad(n_alloc > REC_OFFS_HEADER_SIZE); - UNIV_MEM_ASSERT_AND_ALLOC(offsets, n_alloc * sizeof *offsets); + UNIV_MEM_ALLOC(offsets, n_alloc * sizeof *offsets); offsets[0] = n_alloc; } diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index 35c32d6bc1b..25287a57b35 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -536,13 +536,4 @@ typedef void* os_thread_ret_t; # define UNIV_MEM_ASSERT_W(addr, size) do {} while(0) #endif -#define UNIV_MEM_ASSERT_AND_FREE(addr, size) do { \ - UNIV_MEM_ASSERT_W(addr, size); \ - UNIV_MEM_FREE(addr, size); \ -} while (0) -#define UNIV_MEM_ASSERT_AND_ALLOC(addr, size) do { \ - UNIV_MEM_ASSERT_W(addr, size); \ - UNIV_MEM_ALLOC(addr, size); \ -} while (0) - #endif diff --git a/storage/innobase/mem/mem0mem.c b/storage/innobase/mem/mem0mem.c index 159e9fc6b3c..6e9a39d329f 100644 --- a/storage/innobase/mem/mem0mem.c +++ b/storage/innobase/mem/mem0mem.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2010, Innobase Oy. 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 @@ -502,13 +503,13 @@ mem_heap_block_free( #ifndef UNIV_HOTBACKUP if (!srv_use_sys_malloc) { #ifdef UNIV_MEM_DEBUG + UNIV_MEM_ALLOC(block, len); /* In the debug version we set the memory to a random combination of hex 0xDE and 0xAD. */ mem_erase_buf((byte*)block, len); -#else /* UNIV_MEM_DEBUG */ - UNIV_MEM_ASSERT_AND_FREE(block, len); #endif /* UNIV_MEM_DEBUG */ + UNIV_MEM_FREE(block, len); } if (type == MEM_HEAP_DYNAMIC || len < UNIV_PAGE_SIZE / 2) { @@ -522,13 +523,13 @@ mem_heap_block_free( } #else /* !UNIV_HOTBACKUP */ #ifdef UNIV_MEM_DEBUG + UNIV_MEM_ALLOC(block, len); /* In the debug version we set the memory to a random combination of hex 0xDE and 0xAD. */ mem_erase_buf((byte*)block, len); -#else /* UNIV_MEM_DEBUG */ - UNIV_MEM_ASSERT_AND_FREE(block, len); #endif /* UNIV_MEM_DEBUG */ + UNIV_MEM_FREE(block, len); ut_free(block); #endif /* !UNIV_HOTBACKUP */ } diff --git a/storage/xtradb/buf/buf0buddy.c b/storage/xtradb/buf/buf0buddy.c index 493d0d2d41c..9e37ad2a7cb 100644 --- a/storage/xtradb/buf/buf0buddy.c +++ b/storage/xtradb/buf/buf0buddy.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2006, 2011, 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 @@ -500,7 +501,7 @@ buf_buddy_free_low( buf_pool->buddy_stat[i].used--; recombine: - UNIV_MEM_ASSERT_AND_ALLOC(buf, BUF_BUDDY_LOW << i); + UNIV_MEM_ALLOC(buf, BUF_BUDDY_LOW << i); ((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE; if (i == BUF_BUDDY_SIZES) { diff --git a/storage/xtradb/buf/buf0lru.c b/storage/xtradb/buf/buf0lru.c index 8b74fd10c3d..9c0b171d3f6 100644 --- a/storage/xtradb/buf/buf0lru.c +++ b/storage/xtradb/buf/buf0lru.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2011, 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 @@ -2146,7 +2147,7 @@ buf_LRU_block_free_non_file_page( ut_d(block->page.in_free_list = TRUE); mutex_exit(&buf_pool->free_list_mutex); - UNIV_MEM_ASSERT_AND_FREE(block->frame, UNIV_PAGE_SIZE); + UNIV_MEM_FREE(block->frame, UNIV_PAGE_SIZE); } /******************************************************************//** diff --git a/storage/xtradb/include/mem0mem.ic b/storage/xtradb/include/mem0mem.ic index 6b2e35d7387..b0b24526031 100644 --- a/storage/xtradb/include/mem0mem.ic +++ b/storage/xtradb/include/mem0mem.ic @@ -297,6 +297,7 @@ mem_heap_free_heap_top( #ifdef UNIV_MEM_DEBUG ut_ad(mem_block_get_start(block) <= mem_block_get_free(block)); + UNIV_MEM_ALLOC(old_top, (byte*)block + block->len - old_top); /* In the debug version erase block from top up */ mem_erase_buf(old_top, (byte*)block + block->len - old_top); @@ -304,10 +305,8 @@ mem_heap_free_heap_top( mutex_enter(&mem_hash_mutex); mem_current_allocated_memory -= (total_size - size); mutex_exit(&mem_hash_mutex); -#else /* UNIV_MEM_DEBUG */ - UNIV_MEM_ASSERT_W(old_top, (byte*)block + block->len - old_top); #endif /* UNIV_MEM_DEBUG */ - UNIV_MEM_ALLOC(old_top, (byte*)block + block->len - old_top); + UNIV_MEM_FREE(old_top, (byte*)block + block->len - old_top); /* If free == start, we may free the block if it is not the first one */ @@ -388,11 +387,11 @@ mem_heap_free_top( /* Subtract the free field of block */ mem_block_set_free(block, mem_block_get_free(block) - MEM_SPACE_NEEDED(n)); - UNIV_MEM_ASSERT_W((byte*) block + mem_block_get_free(block), n); #ifdef UNIV_MEM_DEBUG ut_ad(mem_block_get_start(block) <= mem_block_get_free(block)); + UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n); /* In the debug version check the consistency, and erase field */ mem_field_erase((byte*)block + mem_block_get_free(block), n); #endif @@ -404,11 +403,7 @@ mem_heap_free_top( == mem_block_get_start(block))) { mem_heap_block_free(heap, block); } else { - /* Avoid a bogus UNIV_MEM_ASSERT_W() warning in a - subsequent invocation of mem_heap_free_top(). - Originally, this was UNIV_MEM_FREE(), to catch writes - to freed memory. */ - UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n); + UNIV_MEM_FREE((byte*) block + mem_block_get_free(block), n); } } diff --git a/storage/xtradb/include/rem0rec.ic b/storage/xtradb/include/rem0rec.ic index b99d076b500..b727523e1aa 100644 --- a/storage/xtradb/include/rem0rec.ic +++ b/storage/xtradb/include/rem0rec.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2011, 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 @@ -923,7 +924,7 @@ rec_offs_set_n_alloc( { ut_ad(offsets); ut_ad(n_alloc > REC_OFFS_HEADER_SIZE); - UNIV_MEM_ASSERT_AND_ALLOC(offsets, n_alloc * sizeof *offsets); + UNIV_MEM_ALLOC(offsets, n_alloc * sizeof *offsets); offsets[0] = n_alloc; } diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index d76350b7715..ddada668f79 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -549,14 +549,6 @@ typedef void* os_thread_ret_t; # define UNIV_MEM_ASSERT_RW(addr, size) do {} while(0) # define UNIV_MEM_ASSERT_W(addr, size) do {} while(0) #endif -#define UNIV_MEM_ASSERT_AND_FREE(addr, size) do { \ - UNIV_MEM_ASSERT_W(addr, size); \ - UNIV_MEM_FREE(addr, size); \ -} while (0) -#define UNIV_MEM_ASSERT_AND_ALLOC(addr, size) do { \ - UNIV_MEM_ASSERT_W(addr, size); \ - UNIV_MEM_ALLOC(addr, size); \ -} while (0) extern ulint srv_page_size_shift; extern ulint srv_page_size; diff --git a/storage/xtradb/mem/mem0mem.c b/storage/xtradb/mem/mem0mem.c index 159e9fc6b3c..6e9a39d329f 100644 --- a/storage/xtradb/mem/mem0mem.c +++ b/storage/xtradb/mem/mem0mem.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2010, Innobase Oy. 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 @@ -502,13 +503,13 @@ mem_heap_block_free( #ifndef UNIV_HOTBACKUP if (!srv_use_sys_malloc) { #ifdef UNIV_MEM_DEBUG + UNIV_MEM_ALLOC(block, len); /* In the debug version we set the memory to a random combination of hex 0xDE and 0xAD. */ mem_erase_buf((byte*)block, len); -#else /* UNIV_MEM_DEBUG */ - UNIV_MEM_ASSERT_AND_FREE(block, len); #endif /* UNIV_MEM_DEBUG */ + UNIV_MEM_FREE(block, len); } if (type == MEM_HEAP_DYNAMIC || len < UNIV_PAGE_SIZE / 2) { @@ -522,13 +523,13 @@ mem_heap_block_free( } #else /* !UNIV_HOTBACKUP */ #ifdef UNIV_MEM_DEBUG + UNIV_MEM_ALLOC(block, len); /* In the debug version we set the memory to a random combination of hex 0xDE and 0xAD. */ mem_erase_buf((byte*)block, len); -#else /* UNIV_MEM_DEBUG */ - UNIV_MEM_ASSERT_AND_FREE(block, len); #endif /* UNIV_MEM_DEBUG */ + UNIV_MEM_FREE(block, len); ut_free(block); #endif /* !UNIV_HOTBACKUP */ } From e2da680c5119d78eb152394d521b898337ea5836 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 23 Jan 2018 23:19:09 +0100 Subject: [PATCH 38/77] MDEV-13187 incorrect backslash parsing in clients also cover USE and other built-in commands --- client/mysql.cc | 7 ++++-- mysql-test/r/mysqldump-nl.result | 43 ++++++++++++++++++++++++++++++++ mysql-test/t/mysqldump-nl.test | 20 +++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 3521896c3b1..bc306c55880 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -4559,8 +4559,11 @@ static char *get_arg(char *line, get_arg_mode mode) } for (start=ptr ; *ptr; ptr++) { - if ((*ptr == '\\' && ptr[1]) || // escaped character - (!short_cmd && qtype && *ptr == qtype && ptr[1] == qtype)) // quote + /* if short_cmd use historical rules (only backslash) otherwise SQL rules */ + if (short_cmd + ? (*ptr == '\\' && ptr[1]) // escaped character + : (*ptr == '\\' && ptr[1] && qtype != '`') || // escaped character + (qtype && *ptr == qtype && ptr[1] == qtype)) // quote { // Remove (or skip) the backslash (or a second quote) if (mode != CHECK) diff --git a/mysql-test/r/mysqldump-nl.result b/mysql-test/r/mysqldump-nl.result index 6de439bdf3c..bca199dc46a 100644 --- a/mysql-test/r/mysqldump-nl.result +++ b/mysql-test/r/mysqldump-nl.result @@ -124,3 +124,46 @@ v1 1v drop database `mysqltest1 1tsetlqsym`; +create database `test```; +create database `test\`` +\! ls +#`; +show databases like 'test%'; +Database (test%) +test +test\` +\! ls +# +test` + +-- +-- Current Database: `test``` +-- + +/*!40000 DROP DATABASE IF EXISTS `test```*/; + +CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test``` /*!40100 DEFAULT CHARACTER SET latin1 */; + +USE `test```; + +-- +-- Current Database: `test\`` +-- \! ls +-- #` +-- + +/*!40000 DROP DATABASE IF EXISTS `test\`` +\! ls +#`*/; + +CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test\`` +\! ls +#` /*!40100 DEFAULT CHARACTER SET latin1 */; + +USE `test\`` +\! ls +#`; +drop database `test```; +drop database `test\`` +\! ls +#`; diff --git a/mysql-test/t/mysqldump-nl.test b/mysql-test/t/mysqldump-nl.test index 311996e77c3..4513fb2c637 100644 --- a/mysql-test/t/mysqldump-nl.test +++ b/mysql-test/t/mysqldump-nl.test @@ -36,3 +36,23 @@ show tables from `mysqltest1 drop database `mysqltest1 1tsetlqsym`; + +create database `test```; +create database `test\`` +\! ls +#`; + +show databases like 'test%'; + +exec $MYSQL_DUMP --compact --comment --add-drop-database --databases 'test`' 'test\` +\! ls +#'; + +exec $MYSQL_DUMP --compact --comment --add-drop-database --databases 'test`' 'test\` +\! ls +#' | $MYSQL; + +drop database `test```; +drop database `test\`` +\! ls +#`; From 76577e1e2602f3c30859a176808c433a263e1b0a Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 24 Jan 2018 10:58:27 +0100 Subject: [PATCH 39/77] typo fix --- sql/item_cmpfunc.cc | 4 ++-- sql/item_cmpfunc.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index a77443f40ef..39f497e3828 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1446,7 +1446,7 @@ bool Item_in_optimizer::eval_not_null_tables(uchar *opt_arg) void Item_in_optimizer::print(String *str, enum_query_type query_type) { - restore_first_argumet(); + restore_first_argument(); Item_func::print(str, query_type); } @@ -1461,7 +1461,7 @@ void Item_in_optimizer::print(String *str, enum_query_type query_type) call. This call fix the pointer. */ -void Item_in_optimizer::restore_first_argumet() +void Item_in_optimizer::restore_first_argument() { if (args[1]->type() == Item::SUBSELECT_ITEM && ((Item_subselect *)args[1])->is_in_predicate()) diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index c0e97be20c4..a045a08e4fd 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -269,7 +269,7 @@ public: bool eval_not_null_tables(uchar *opt_arg); void fix_after_pullout(st_select_lex *new_parent, Item **ref); virtual void print(String *str, enum_query_type query_type); - void restore_first_argumet(); + void restore_first_argument(); }; class Comp_creator From ee8755e3c51a1da8fcf108ad0257a7e62fc94347 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 24 Jan 2018 14:42:52 +0100 Subject: [PATCH 40/77] MDEV-15012: ASAN: numerous test failures in PS First roll back changes, then free Items which can lead to memory freeing. --- sql/sql_prepare.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index faaeaf51573..a3bf9d6c93c 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -3230,9 +3230,9 @@ void Prepared_statement::cleanup_stmt() DBUG_ENTER("Prepared_statement::cleanup_stmt"); DBUG_PRINT("enter",("stmt: 0x%lx", (long) this)); + thd->rollback_item_tree_changes(); cleanup_items(free_list); thd->cleanup_after_query(); - thd->rollback_item_tree_changes(); DBUG_VOID_RETURN; } From 547ec8ce27c9035e2f0a823866a7e4ed1b02d4c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 29 Jan 2018 16:25:26 +0200 Subject: [PATCH 41/77] Do not SET DEBUG_DBUG=-d,... in tests To disable debug instrumentation, save and restore the original value of the variable DEBUG_DBUG. Assigning -d,... will enable the output of a lot of unrelated DBUG messages to the server error log. --- .../innodb/r/innodb-replace-debug.result | 5 ++- .../suite/innodb/r/innodb_corrupt_bit.result | 45 +++++++++++++++++++ .../suite/innodb/t/innodb-replace-debug.test | 5 ++- .../suite/innodb/t/innodb_corrupt_bit.test | 6 ++- 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-replace-debug.result b/mysql-test/suite/innodb/r/innodb-replace-debug.result index 84bc9dc9769..989fb055cbc 100644 --- a/mysql-test/suite/innodb/r/innodb-replace-debug.result +++ b/mysql-test/suite/innodb/r/innodb-replace-debug.result @@ -4,10 +4,11 @@ create table t1 (f1 int primary key, f2 int, f3 int, unique key k1(f2), key k2(f3)) engine=innodb; insert into t1 values (14, 24, 34); -set @@debug_dbug = '+d,row_ins_sec_index_entry_timeout'; +set @old_dbug= @@session.debug_dbug; +set debug_dbug = '+d,row_ins_sec_index_entry_timeout'; replace into t1 values (14, 25, 34); select * from t1; f1 f2 f3 14 25 34 drop table t1; -set @@debug_dbug = '-d,row_ins_sec_index_entry_timeout'; +set debug_dbug = @old_dbug; diff --git a/mysql-test/suite/innodb/r/innodb_corrupt_bit.result b/mysql-test/suite/innodb/r/innodb_corrupt_bit.result index bc4334bd219..8acbcf74cf6 100644 --- a/mysql-test/suite/innodb/r/innodb_corrupt_bit.result +++ b/mysql-test/suite/innodb/r/innodb_corrupt_bit.result @@ -1,27 +1,63 @@ +set names utf8; +SET UNIQUE_CHECKS=0; +CREATE TABLE corrupt_bit_test_ā( +a INT AUTO_INCREMENT PRIMARY KEY, +b CHAR(100), +c INT, +z INT, +INDEX idx(b)) +ENGINE=InnoDB; +INSERT INTO corrupt_bit_test_ā VALUES(0,'x',1, 1); +CREATE UNIQUE INDEX idxā ON corrupt_bit_test_ā(c, b); +CREATE UNIQUE INDEX idxē ON corrupt_bit_test_ā(z, b); +SELECT * FROM corrupt_bit_test_ā; a b c z 1 x 1 1 +INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+1,z+1 FROM corrupt_bit_test_ā; +select count(*) from corrupt_bit_test_ā; count(*) 2 +SET @save_dbug = @@SESSION.debug_dbug; +SET debug_dbug = '+d,dict_set_index_corrupted'; +check table corrupt_bit_test_ā; Table Op Msg_type Msg_text test.corrupt_bit_test_ā check Warning InnoDB: Index "idx" is marked as corrupted test.corrupt_bit_test_ā check Warning InnoDB: Index "idxā" is marked as corrupted test.corrupt_bit_test_ā check Warning InnoDB: Index "idxē" is marked as corrupted test.corrupt_bit_test_ā check error Corrupt +SET debug_dbug = @save_dbug; +CREATE INDEX idx3 ON corrupt_bit_test_ā(b, c); ERROR HY000: Index corrupt_bit_test_ā is corrupted +CREATE INDEX idx4 ON corrupt_bit_test_ā(b, z); ERROR HY000: Index corrupt_bit_test_ā is corrupted +select c from corrupt_bit_test_ā; ERROR HY000: Index corrupt_bit_test_ā is corrupted +select z from corrupt_bit_test_ā; ERROR HY000: Index corrupt_bit_test_ā is corrupted +show warnings; Level Code Message Warning 179 InnoDB: Index "idxē" for table "test"."corrupt_bit_test_ā" is marked as corrupted Warning 179 Got error 179 when reading table `test`.`corrupt_bit_test_ā` Error 1712 Index corrupt_bit_test_ā is corrupted +insert into corrupt_bit_test_ā values (10001, "a", 20001, 20001); +select * from corrupt_bit_test_ā use index(primary) where a = 10001; a b c z 10001 a 20001 20001 +begin; +insert into corrupt_bit_test_ā values (10002, "a", 20002, 20002); +delete from corrupt_bit_test_ā where a = 10001; +insert into corrupt_bit_test_ā values (10001, "a", 20001, 20001); +rollback; +drop index idxā on corrupt_bit_test_ā; +check table corrupt_bit_test_ā; Table Op Msg_type Msg_text test.corrupt_bit_test_ā check Warning InnoDB: Index "idx" is marked as corrupted test.corrupt_bit_test_ā check Warning InnoDB: Index "idxē" is marked as corrupted test.corrupt_bit_test_ā check error Corrupt +set names utf8; +select z from corrupt_bit_test_ā; ERROR HY000: Index corrupt_bit_test_ā is corrupted +show create table corrupt_bit_test_ā; Table Create Table corrupt_bit_test_ā CREATE TABLE `corrupt_bit_test_ā` ( `a` int(11) NOT NULL AUTO_INCREMENT, @@ -32,8 +68,12 @@ corrupt_bit_test_ā CREATE TABLE `corrupt_bit_test_ā` ( UNIQUE KEY `idxē` (`z`,`b`), KEY `idx` (`b`) ) ENGINE=InnoDB AUTO_INCREMENT=10003 DEFAULT CHARSET=latin1 +drop index idxē on corrupt_bit_test_ā; +CREATE INDEX idx3 ON corrupt_bit_test_ā(b, c); ERROR HY000: Index corrupt_bit_test_ā is corrupted +CREATE INDEX idx4 ON corrupt_bit_test_ā(b, z); ERROR HY000: Index corrupt_bit_test_ā is corrupted +show create table corrupt_bit_test_ā; Table Create Table corrupt_bit_test_ā CREATE TABLE `corrupt_bit_test_ā` ( `a` int(11) NOT NULL AUTO_INCREMENT, @@ -43,7 +83,12 @@ corrupt_bit_test_ā CREATE TABLE `corrupt_bit_test_ā` ( PRIMARY KEY (`a`), KEY `idx` (`b`) ) ENGINE=InnoDB AUTO_INCREMENT=10003 DEFAULT CHARSET=latin1 +drop index idx on corrupt_bit_test_ā; +CREATE INDEX idx3 ON corrupt_bit_test_ā(b, c); +CREATE INDEX idx4 ON corrupt_bit_test_ā(b, z); +select z from corrupt_bit_test_ā limit 10; z 20001 1 2 +drop table corrupt_bit_test_ā; diff --git a/mysql-test/suite/innodb/t/innodb-replace-debug.test b/mysql-test/suite/innodb/t/innodb-replace-debug.test index 5cec9e1febf..7e710ae154c 100644 --- a/mysql-test/suite/innodb/t/innodb-replace-debug.test +++ b/mysql-test/suite/innodb/t/innodb-replace-debug.test @@ -8,8 +8,9 @@ create table t1 (f1 int primary key, f2 int, f3 int, unique key k1(f2), key k2(f3)) engine=innodb; insert into t1 values (14, 24, 34); -set @@debug_dbug = '+d,row_ins_sec_index_entry_timeout'; +set @old_dbug= @@session.debug_dbug; +set debug_dbug = '+d,row_ins_sec_index_entry_timeout'; replace into t1 values (14, 25, 34); select * from t1; drop table t1; -set @@debug_dbug = '-d,row_ins_sec_index_entry_timeout'; +set debug_dbug = @old_dbug; diff --git a/mysql-test/suite/innodb/t/innodb_corrupt_bit.test b/mysql-test/suite/innodb/t/innodb_corrupt_bit.test index f67e2e7e047..34fe0a7812a 100644 --- a/mysql-test/suite/innodb/t/innodb_corrupt_bit.test +++ b/mysql-test/suite/innodb/t/innodb_corrupt_bit.test @@ -8,6 +8,7 @@ -- disable_query_log call mtr.add_suppression("Flagged corruption of idx.*in CHECK TABLE"); +-- enable_query_log set names utf8; @@ -36,9 +37,10 @@ INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+1,z+1 FROM corrupt_bit_test_ā; select count(*) from corrupt_bit_test_ā; # This will flag all secondary indexes corrupted -SET SESSION debug_dbug="+d,dict_set_index_corrupted"; +SET @save_dbug = @@SESSION.debug_dbug; +SET debug_dbug = '+d,dict_set_index_corrupted'; check table corrupt_bit_test_ā; -SET SESSION debug_dbug="-d,dict_set_index_corrupted"; +SET debug_dbug = @save_dbug; # Cannot create new indexes while corrupted indexes exist --error ER_INDEX_CORRUPT From ded07724eebb6c3afe882884fbad32e8dc907b0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Mon, 29 Jan 2018 19:46:59 +0200 Subject: [PATCH 42/77] MDEV-15014 Assertion `m_cache_lock_status == LOCKED_NO_WAIT || m_cache_status == DISABLE_REQUEST' failed in Query_cache::free_cache on startup The assert guards against not-locked or not-requested query cache disabling. If during startup we disable query cache, we failed to request disabling. --- sql/sql_cache.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 3fc1edfcb56..6effc376a2f 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -2477,6 +2477,7 @@ void Query_cache::init() */ if (global_system_variables.query_cache_type == 0) { + m_cache_status= DISABLE_REQUEST; free_cache(); m_cache_status= DISABLED; } From 5edd129fbf14eb56e793f84963b3b9e5770c4604 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 30 Jan 2018 21:05:27 +0200 Subject: [PATCH 43/77] Fix ASAN failure in main.lock (and others) Whenever one copies an IO_CACHE struct, one must remember to call setup_io_cache, if not, the IO_CACHE's current_pos and end_pos self-references will point to the previous struct's memory, which could go out of scope. Commit 90038693903044bbbf7946ac128c3757ad33d7ba fixes this problem in a more general fashion by removing the self-references altogether, but for 5.5 we'll keep the old behaviour. --- sql/sql_update.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index ede38468513..e42f6a4ff76 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -628,6 +628,8 @@ int mysql_update(THD *thd, if (reinit_io_cache(&tempfile,READ_CACHE,0L,0,0)) error=1; /* purecov: inspected */ select->file=tempfile; // Read row ptrs from this file + // select->file was copied, update self-references. + setup_io_cache(&select->file); if (error >= 0) goto err; } From 7a63ffab71644118223aefe66094366a7b7f115e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Mon, 29 Jan 2018 18:56:08 +0200 Subject: [PATCH 44/77] Fix an out of scope bzero --- mysys/mf_iocache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 31a09e214d2..bd71e2ae527 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -258,7 +258,7 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize, else { /* Clear mutex so that safe_mutex will notice that it's not initialized */ - bzero((char*) &info->append_buffer_lock, sizeof(info)); + bzero((char*) &info->append_buffer_lock, sizeof(info->append_buffer_lock)); } #endif From 3fb2f8db179c2ea9a15fcc2f142c5b98c5aab17a Mon Sep 17 00:00:00 2001 From: Joao Gramacho Date: Fri, 2 Feb 2018 11:45:56 +0000 Subject: [PATCH 45/77] 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 46/77] 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 7c6cf7fefe68a1a3f68e7d6436da4689ec302bca Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 25 Jan 2018 14:25:48 +0100 Subject: [PATCH 47/77] bug: ha_heap was unilaterally increasing reclength proper fix replacing the hack from b80fa4000d6 don't confuse length of the data area (reclength) with the offset to the "deleted" mark. --- include/heap.h | 1 + storage/heap/_check.c | 2 +- storage/heap/ha_heap.cc | 11 +---------- storage/heap/hp_create.c | 8 +++++--- storage/heap/hp_delete.c | 2 +- storage/heap/hp_rrnd.c | 4 ++-- storage/heap/hp_rsame.c | 2 +- storage/heap/hp_scan.c | 2 +- storage/heap/hp_write.c | 4 ++-- 9 files changed, 15 insertions(+), 21 deletions(-) diff --git a/include/heap.h b/include/heap.h index 2b7fd28699d..eecb7084e66 100644 --- a/include/heap.h +++ b/include/heap.h @@ -144,6 +144,7 @@ typedef struct st_heap_share uint key_version; /* Updated on key change */ uint file_version; /* Update on clear */ uint reclength; /* Length of one record */ + uint visible; /* Offset to the visible/deleted mark */ uint changed; uint keys,max_key_length; uint currently_disabled_keys; /* saved value from "keys" when disabled */ diff --git a/storage/heap/_check.c b/storage/heap/_check.c index b64c9ab1831..f2fd8ab94be 100644 --- a/storage/heap/_check.c +++ b/storage/heap/_check.c @@ -79,7 +79,7 @@ int heap_check_heap(HP_INFO *info, my_bool print_status) } hp_find_record(info,pos); - if (!info->current_ptr[share->reclength]) + if (!info->current_ptr[share->visible]) deleted++; else records++; diff --git a/storage/heap/ha_heap.cc b/storage/heap/ha_heap.cc index 259e54bfc59..ec76d08bf97 100644 --- a/storage/heap/ha_heap.cc +++ b/storage/heap/ha_heap.cc @@ -100,15 +100,6 @@ const char **ha_heap::bas_ext() const int ha_heap::open(const char *name, int mode, uint test_if_locked) { - if (table->s->reclength < sizeof (char*)) - { - MEM_UNDEFINED(table->s->default_values + table->s->reclength, - sizeof(char*) - table->s->reclength); - table->s->reclength= sizeof(char*); - MEM_UNDEFINED(table->record[0], table->s->reclength); - MEM_UNDEFINED(table->record[1], table->s->reclength); - } - internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE); if (internal_table || (!(file= heap_open(name, mode)) && my_errno == ENOENT)) { @@ -736,7 +727,7 @@ heap_prepare_hp_create_info(TABLE *table_arg, bool internal_table, } } } - mem_per_row+= MY_ALIGN(share->reclength + 1, sizeof(char*)); + mem_per_row+= MY_ALIGN(max(share->reclength, sizeof(char*)) + 1, sizeof(char*)); if (table_arg->found_next_number_field) { keydef[share->next_number_index].flag|= HA_AUTO_KEY; diff --git a/storage/heap/hp_create.c b/storage/heap/hp_create.c index 0b5dc841ada..1daca0beeb5 100644 --- a/storage/heap/hp_create.c +++ b/storage/heap/hp_create.c @@ -33,6 +33,7 @@ int heap_create(const char *name, HP_CREATE_INFO *create_info, uint keys= create_info->keys; ulong min_records= create_info->min_records; ulong max_records= create_info->max_records; + uint visible_offset; DBUG_ENTER("heap_create"); if (!create_info->internal_table) @@ -58,9 +59,9 @@ int heap_create(const char *name, HP_CREATE_INFO *create_info, /* We have to store sometimes uchar* del_link in records, - so the record length should be at least sizeof(uchar*) + so the visible_offset must be least at sizeof(uchar*) */ - set_if_bigger(reclength, sizeof (uchar*)); + visible_offset= max(reclength, sizeof (char*)); for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++) { @@ -152,7 +153,7 @@ int heap_create(const char *name, HP_CREATE_INFO *create_info, share->keydef= (HP_KEYDEF*) (share + 1); share->key_stat_version= 1; keyseg= (HA_KEYSEG*) (share->keydef + keys); - init_block(&share->block, reclength + 1, min_records, max_records); + init_block(&share->block, visible_offset + 1, min_records, max_records); /* Fix keys */ memcpy(share->keydef, keydef, (size_t) (sizeof(keydef[0]) * keys)); for (i= 0, keyinfo= share->keydef; i < keys; i++, keyinfo++) @@ -192,6 +193,7 @@ int heap_create(const char *name, HP_CREATE_INFO *create_info, share->max_table_size= create_info->max_table_size; share->data_length= share->index_length= 0; share->reclength= reclength; + share->visible= visible_offset; share->blength= 1; share->keys= keys; share->max_key_length= max_length; diff --git a/storage/heap/hp_delete.c b/storage/heap/hp_delete.c index 1cbfe7408d4..eb9749601aa 100644 --- a/storage/heap/hp_delete.c +++ b/storage/heap/hp_delete.c @@ -45,7 +45,7 @@ int heap_delete(HP_INFO *info, const uchar *record) info->update=HA_STATE_DELETED; *((uchar**) pos)=share->del_link; share->del_link=pos; - pos[share->reclength]=0; /* Record deleted */ + pos[share->visible]=0; /* Record deleted */ share->deleted++; share->key_version++; #if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG) diff --git a/storage/heap/hp_rrnd.c b/storage/heap/hp_rrnd.c index 8e0d51a78ca..d105c5c2e13 100644 --- a/storage/heap/hp_rrnd.c +++ b/storage/heap/hp_rrnd.c @@ -37,7 +37,7 @@ int heap_rrnd(register HP_INFO *info, uchar *record, uchar *pos) info->update= 0; DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE); } - if (!info->current_ptr[share->reclength]) + if (!info->current_ptr[share->visible]) { info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND; DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED); @@ -91,7 +91,7 @@ int heap_rrnd_old(register HP_INFO *info, uchar *record, ulong pos) hp_find_record(info, pos); end: - if (!info->current_ptr[share->reclength]) + if (!info->current_ptr[share->visible]) { info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND; DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED); diff --git a/storage/heap/hp_rsame.c b/storage/heap/hp_rsame.c index 40c5a18f974..19767fd752b 100644 --- a/storage/heap/hp_rsame.c +++ b/storage/heap/hp_rsame.c @@ -32,7 +32,7 @@ int heap_rsame(register HP_INFO *info, uchar *record, int inx) DBUG_ENTER("heap_rsame"); test_active(info); - if (info->current_ptr[share->reclength]) + if (info->current_ptr[share->visible]) { if (inx < -1 || inx >= (int) share->keys) { diff --git a/storage/heap/hp_scan.c b/storage/heap/hp_scan.c index 39a6f2082a3..65726c37e1f 100644 --- a/storage/heap/hp_scan.c +++ b/storage/heap/hp_scan.c @@ -62,7 +62,7 @@ int heap_scan(register HP_INFO *info, uchar *record) } hp_find_record(info, pos); } - if (!info->current_ptr[share->reclength]) + if (!info->current_ptr[share->visible]) { DBUG_PRINT("warning",("Found deleted record")); info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND; diff --git a/storage/heap/hp_write.c b/storage/heap/hp_write.c index e45c78b75f1..4a9c1ba59c0 100644 --- a/storage/heap/hp_write.c +++ b/storage/heap/hp_write.c @@ -54,7 +54,7 @@ int heap_write(HP_INFO *info, const uchar *record) } memcpy(pos,record,(size_t) share->reclength); - pos[share->reclength]=1; /* Mark record as not deleted */ + pos[share->visible]= 1; /* Mark record as not deleted */ if (++share->records == share->blength) share->blength+= share->blength; info->s->key_version++; @@ -92,7 +92,7 @@ err: share->deleted++; *((uchar**) pos)=share->del_link; share->del_link=pos; - pos[share->reclength]=0; /* Record deleted */ + pos[share->visible]= 0; /* Record deleted */ DBUG_RETURN(my_errno); } /* heap_write */ From c8afe7daaced3339f24b88d63f6bcf8477dfaf8c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 5 Feb 2018 14:13:26 +0100 Subject: [PATCH 48/77] cleanup: remove a duplicated test case --- mysql-test/r/view.result | 108 ------------------------------------- mysql-test/t/view.test | 112 --------------------------------------- 2 files changed, 220 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 8bc33a8860b..1d12c50954f 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -5236,114 +5236,6 @@ execute stmt1; deallocate prepare stmt1; drop view v1,v2; drop table t1,t2; -# -# MDEV-6251: SIGSEGV in query optimizer (in set_check_materialized -# with MERGE view) -# -CREATE TABLE t1 (a1 INT(11) NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY); -CREATE TABLE t2 (b1 INT(11) NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY); -CREATE TABLE t3 (c1 INT(11) NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY); -CREATE TABLE t4 (d1 INT(11) NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY); -CREATE TABLE t5 (e1 INT(11) NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY); -CREATE TABLE t6 (f1 INT(11) NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY); -CREATE OR REPLACE view v1 AS -SELECT 1 -FROM t1 a_alias_1 -LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 -LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 -LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 -LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 -LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 -LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -; -SELECT 1 -FROM (( SELECT 1 -FROM t1 a_alias_1 -LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 -LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 -LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 -LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 -LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 -LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t1) -LEFT OUTER JOIN (( SELECT 1 -FROM t1 a_alias_1 -LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 -LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 -LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 -LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 -LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 -LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t2) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 -FROM t1 a_alias_1 -LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 -LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 -LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 -LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 -LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 -LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t3) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 -FROM t1 a_alias_1 -LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 -LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 -LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 -LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 -LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 -LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t4) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 -FROM t1 a_alias_1 -LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 -LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 -LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 -LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 -LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 -LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t5) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 -FROM t1 a_alias_1 -LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 -LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 -LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 -LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 -LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 -LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t6) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 -FROM t1 a_alias_1 -LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 -LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 -LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 -LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 -LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 -LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t7) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 -FROM t1 a_alias_1 -LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 -LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 -LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 -LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 -LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 -LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t8) ON 1=1 -; -1 -SELECT 1 -FROM (v1 t1) -LEFT OUTER JOIN (v1 t2) ON 1=1 -LEFT OUTER JOIN (v1 t3) ON 1=1 -LEFT OUTER JOIN (v1 t4) ON 1=1 -LEFT OUTER JOIN (v1 t5) ON 1=1 -LEFT OUTER JOIN (v1 t6) ON 1=1 -LEFT OUTER JOIN (v1 t7) ON 1=1 -LEFT OUTER JOIN (v1 t8) ON 1=1 -; -1 -drop view v1; -drop table t1,t2,t3,t4,t5,t6; # ----------------------------------------------------------------- # -- End of 5.3 tests. # ----------------------------------------------------------------- diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 0fc7cb6adf7..4b3537df2de 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -5169,118 +5169,6 @@ deallocate prepare stmt1; drop view v1,v2; drop table t1,t2; ---echo # ---echo # MDEV-6251: SIGSEGV in query optimizer (in set_check_materialized ---echo # with MERGE view) ---echo # - -CREATE TABLE t1 (a1 INT(11) NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY); -CREATE TABLE t2 (b1 INT(11) NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY); -CREATE TABLE t3 (c1 INT(11) NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY); -CREATE TABLE t4 (d1 INT(11) NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY); -CREATE TABLE t5 (e1 INT(11) NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY); -CREATE TABLE t6 (f1 INT(11) NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY); - -CREATE OR REPLACE view v1 AS - SELECT 1 - FROM t1 a_alias_1 - LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 - LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 - LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 - LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 - LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 - LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -; - -SELECT 1 -FROM (( SELECT 1 - FROM t1 a_alias_1 - LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 - LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 - LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 - LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 - LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 - LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t1) -LEFT OUTER JOIN (( SELECT 1 - FROM t1 a_alias_1 - LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 - LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 - LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 - LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 - LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 - LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t2) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 - FROM t1 a_alias_1 - LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 - LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 - LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 - LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 - LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 - LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t3) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 - FROM t1 a_alias_1 - LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 - LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 - LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 - LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 - LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 - LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t4) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 - FROM t1 a_alias_1 - LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 - LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 - LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 - LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 - LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 - LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t5) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 - FROM t1 a_alias_1 - LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 - LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 - LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 - LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 - LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 - LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t6) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 - FROM t1 a_alias_1 - LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 - LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 - LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 - LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 - LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 - LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t7) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 - FROM t1 a_alias_1 - LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 - LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 - LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 - LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 - LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 - LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t8) ON 1=1 -; - -SELECT 1 -FROM (v1 t1) -LEFT OUTER JOIN (v1 t2) ON 1=1 -LEFT OUTER JOIN (v1 t3) ON 1=1 -LEFT OUTER JOIN (v1 t4) ON 1=1 -LEFT OUTER JOIN (v1 t5) ON 1=1 -LEFT OUTER JOIN (v1 t6) ON 1=1 -LEFT OUTER JOIN (v1 t7) ON 1=1 -LEFT OUTER JOIN (v1 t8) ON 1=1 -; - -drop view v1; -drop table t1,t2,t3,t4,t5,t6; - --echo # ----------------------------------------------------------------- --echo # -- End of 5.3 tests. --echo # ----------------------------------------------------------------- From e4784703ee44d0a0a497a1a411dea20987d501ad Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Mon, 12 Feb 2018 15:19:43 +0530 Subject: [PATCH 49/77] 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 50/77] --- 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 2709380587bbcbc7abda77f11ee0abd207c65027 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 14 Feb 2018 18:14:24 +0100 Subject: [PATCH 51/77] MDEV-13748 Assertion `status_var.local_memory_used == 0 || !debug_assert_on_not_freed_memory' failed in virtual THD::~THD after query with INTERSECT my_safe_alloca()/my_safe_afree() work as alloca() or malloc()/free() depending on the memory size to allocate, that is, depending on reclength here. They only work correctly if reclength doesn't change in the middle. --- mysql-test/suite/maria/dynamic.result | 4 ++++ mysql-test/suite/maria/dynamic.test | 7 +++++++ storage/maria/ma_dynrec.c | 10 +++++----- 3 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 mysql-test/suite/maria/dynamic.result create mode 100644 mysql-test/suite/maria/dynamic.test diff --git a/mysql-test/suite/maria/dynamic.result b/mysql-test/suite/maria/dynamic.result new file mode 100644 index 00000000000..1e87010e9ca --- /dev/null +++ b/mysql-test/suite/maria/dynamic.result @@ -0,0 +1,4 @@ +create table t1 (a blob, b varchar(20000)) engine=aria row_format=dynamic; +insert t1 (b) values (repeat('a', 20000)); +update t1 set b='b'; +drop table t1; diff --git a/mysql-test/suite/maria/dynamic.test b/mysql-test/suite/maria/dynamic.test new file mode 100644 index 00000000000..f8a1e98cd41 --- /dev/null +++ b/mysql-test/suite/maria/dynamic.test @@ -0,0 +1,7 @@ +# +# MDEV-13748 Assertion `status_var.local_memory_used == 0 || !debug_assert_on_not_freed_memory' failed in virtual THD::~THD after query with INTERSECT +# +create table t1 (a blob, b varchar(20000)) engine=aria row_format=dynamic; +insert t1 (b) values (repeat('a', 20000)); +update t1 set b='b'; +drop table t1; diff --git a/storage/maria/ma_dynrec.c b/storage/maria/ma_dynrec.c index c47da42b555..35a5040f09d 100644 --- a/storage/maria/ma_dynrec.c +++ b/storage/maria/ma_dynrec.c @@ -276,7 +276,7 @@ my_bool _ma_update_blob_record(MARIA_HA *info, MARIA_RECORD_POS pos, { uchar *rec_buff; int error; - ulong reclength,extra; + ulong reclength,reclength2,extra; extra= (ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER)+MARIA_SPLIT_LENGTH+ MARIA_DYN_DELETE_BLOCK_HEADER); @@ -289,17 +289,17 @@ my_bool _ma_update_blob_record(MARIA_HA *info, MARIA_RECORD_POS pos, return 1; } #endif - if (!(rec_buff=(uchar*) my_safe_alloca(reclength, - MARIA_MAX_RECORD_ON_STACK))) + if (!(rec_buff=(uchar*) my_safe_alloca(reclength, MARIA_MAX_RECORD_ON_STACK))) { my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */ return(1); } - reclength= _ma_rec_pack(info,rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER), + reclength2= _ma_rec_pack(info,rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER), record); + DBUG_ASSERT(reclength2 <= reclength); error=update_dynamic_record(info,pos, rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER), - reclength); + reclength2); my_safe_afree(rec_buff, reclength, MARIA_MAX_RECORD_ON_STACK); return(error != 0); } From 03de234baf423eaefe3d0b768dccb719b1298ff6 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 14 Feb 2018 19:12:23 +0100 Subject: [PATCH 52/77] MDEV-13982 Server crashes in in ha_partition::engine_name use the correct handlerton when looking for TRANSACTIONAL=1 support --- mysql-test/suite/parts/r/partition_alter_maria.result | 9 +++++++++ mysql-test/suite/parts/t/partition_alter_maria.test | 7 +++++++ sql/sql_table.cc | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/parts/r/partition_alter_maria.result b/mysql-test/suite/parts/r/partition_alter_maria.result index 460d20b9255..d79bc0a41fe 100644 --- a/mysql-test/suite/parts/r/partition_alter_maria.result +++ b/mysql-test/suite/parts/r/partition_alter_maria.result @@ -16,6 +16,15 @@ select * from t1; pk dt 1 2017-09-28 15:12:00 drop table t1; +create table t1 (a int) engine=Aria transactional=1 partition by hash(a) partitions 2; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=Aria DEFAULT CHARSET=latin1 TRANSACTIONAL=1 +/*!50100 PARTITION BY HASH (a) +PARTITIONS 2 */ +drop table t1; # # MDEV-13788 Server crash when issuing bad SQL partition syntax # diff --git a/mysql-test/suite/parts/t/partition_alter_maria.test b/mysql-test/suite/parts/t/partition_alter_maria.test index e21f0dfab82..e0b9256391d 100644 --- a/mysql-test/suite/parts/t/partition_alter_maria.test +++ b/mysql-test/suite/parts/t/partition_alter_maria.test @@ -17,5 +17,12 @@ alter table t1 drop partition p20181231; select * from t1; drop table t1; +# +# MDEV-13982 Server crashes in in ha_partition::engine_name +# +create table t1 (a int) engine=Aria transactional=1 partition by hash(a) partitions 2; +show create table t1; +drop table t1; + --let $engine=Aria --source inc/part_alter_values.inc diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 19093d9b2ca..f56781faf39 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4397,7 +4397,7 @@ bool mysql_create_table_no_lock(THD *thd, /* Give warnings for not supported table options */ #if defined(WITH_ARIA_STORAGE_ENGINE) extern handlerton *maria_hton; - if (file->ht != maria_hton) + if (file->partition_ht() != maria_hton) #endif if (create_info->transactional) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, From 7bd258c44c00f232ecf4ec448179f114b878227b Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 15 Feb 2018 10:06:14 +0100 Subject: [PATCH 53/77] fix plugins.server_audit test for --ps --- mysql-test/suite/plugins/t/server_audit.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/suite/plugins/t/server_audit.test b/mysql-test/suite/plugins/t/server_audit.test index 9be0d5556f0..6c5eaffd9a2 100644 --- a/mysql-test/suite/plugins/t/server_audit.test +++ b/mysql-test/suite/plugins/t/server_audit.test @@ -42,8 +42,10 @@ select 1, 3; insert into t2 values (1), (2); select * from t2; +--disable_ps_protocol --error ER_NO_SUCH_TABLE select * from t_doesnt_exist; +--enable_ps_protocol --error 1064 syntax_error_query; drop table renamed_t1, t2; From 873f8c25b6de24d267cbdedc70de40dc4b5b83aa Mon Sep 17 00:00:00 2001 From: Lars Tangvald Date: Tue, 13 Feb 2018 13:58:43 +0100 Subject: [PATCH 54/77] 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 ac3fd5acac6b3717ce206e3e9ebf78204af06861 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sat, 3 Feb 2018 22:01:30 +1100 Subject: [PATCH 55/77] debian: VCS is on github --- debian/dist/Debian/control | 4 ++-- debian/dist/Ubuntu/control | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/debian/dist/Debian/control b/debian/dist/Debian/control index e83ac1ffa5d..8c1173b8540 100644 --- a/debian/dist/Debian/control +++ b/debian/dist/Debian/control @@ -12,8 +12,8 @@ Build-Depends: procps | hurd, debhelper, libncurses5-dev (>= 5.0-6), ${CMAKE_DEP}libaio-dev, libjemalloc-dev (>= 3.0.0) Standards-Version: 3.8.3 Homepage: http://mariadb.org/ -Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/5.5/files -Vcs-Bzr: bzr://lp:maria +Vcs-Git: https://github.com/MariaDB/server.git +Vcs-Browser: https://github.com/MariaDB/server/ Package: libmariadbclient18 Section: libs diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control index 94424f38db8..037c7bc1454 100644 --- a/debian/dist/Ubuntu/control +++ b/debian/dist/Ubuntu/control @@ -12,8 +12,8 @@ Build-Depends: procps | hurd, debhelper, libncurses5-dev (>= 5.0-6), ${CMAKE_DEP}libaio-dev, libjemalloc-dev (>= 3.0.0) Standards-Version: 3.8.2 Homepage: http://mariadb.org/ -Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/5.5/files -Vcs-Bzr: bzr://lp:maria +Vcs-Git: https://github.com/MariaDB/server.git +Vcs-Browser: https://github.com/MariaDB/server/ Package: libmariadbclient18 Section: libs From c0b4d74b52e7eec9b13af732193f7f8d7abe05de Mon Sep 17 00:00:00 2001 From: Nisha Gopalakrishnan Date: Mon, 26 Feb 2018 14:37:39 +0530 Subject: [PATCH 56/77] 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 926edd48e1e67bf9a315b3602638a76c4c445ef6 Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Tue, 6 Mar 2018 19:59:57 +0530 Subject: [PATCH 57/77] MDEV-15235: Assertion `length > 0' failed in create_ref_for_key The issue is that we are creating a materialised table with key of length 0 which is incorrect, we should disable materialisation for such a case. --- mysql-test/r/subselect_mat.result | 15 +++++++++++++++ mysql-test/t/subselect_mat.test | 13 +++++++++++++ sql/opt_subselect.cc | 4 +++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result index d4dc519227b..00448ac4f91 100644 --- a/mysql-test/r/subselect_mat.result +++ b/mysql-test/r/subselect_mat.result @@ -2642,3 +2642,18 @@ a b sq 4 4 1 4 2 1 drop table t1, t2; +# +# MDEV-15235: Assertion `length > 0' failed in create_ref_for_key +# +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (f CHAR(1)); +INSERT INTO t2 VALUES ('a'),('b'); +explain +SELECT * FROM t2 WHERE f IN ( SELECT LEFT('foo',0) FROM t1 ORDER BY 1 ); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 +SELECT * FROM t2 WHERE f IN ( SELECT LEFT('foo',0) FROM t1 ORDER BY 1 ); +f +DROP TABLE t1, t2; diff --git a/mysql-test/t/subselect_mat.test b/mysql-test/t/subselect_mat.test index 09c6b3e1747..5211f35b48b 100644 --- a/mysql-test/t/subselect_mat.test +++ b/mysql-test/t/subselect_mat.test @@ -254,3 +254,16 @@ SELECT a, b, (a, b) NOT IN (SELECT a, b FROM t2) as sq FROM t1; drop table t1, t2; + +--echo # +--echo # MDEV-15235: Assertion `length > 0' failed in create_ref_for_key +--echo # + +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (f CHAR(1)); +INSERT INTO t2 VALUES ('a'),('b'); +explain +SELECT * FROM t2 WHERE f IN ( SELECT LEFT('foo',0) FROM t1 ORDER BY 1 ); +SELECT * FROM t2 WHERE f IN ( SELECT LEFT('foo',0) FROM t1 ORDER BY 1 ); +DROP TABLE t1, t2; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 028bf44bf79..24f35a0c14c 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -873,8 +873,10 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs) Make sure that create_tmp_table will not fail due to too long keys. See MDEV-7122. This check is performed inside create_tmp_table also and we must do it so that we know the table has keys created. + Make sure that the length of the key for the temp_table is atleast + greater than 0. */ - if (total_key_length > tmp_table_max_key_length() || + if (!total_key_length || total_key_length > tmp_table_max_key_length() || elements > tmp_table_max_key_parts()) DBUG_RETURN(FALSE); From 0943b33de3daa0fcbf58803be8e991941de63218 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 14 Mar 2018 14:35:27 +0000 Subject: [PATCH 58/77] MDEV-12190 YASSL isn't able to negotiate TLS version correctly Backport from 10.2 --- extra/yassl/src/handshake.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp index aa2de39333c..bb8e3791552 100644 --- a/extra/yassl/src/handshake.cpp +++ b/extra/yassl/src/handshake.cpp @@ -787,6 +787,16 @@ int DoProcessReply(SSL& ssl) needHdr = true; else { buffer >> hdr; + /* + According to RFC 4346 (see "7.4.1.3. Server Hello"), the Server Hello + packet needs to specify the highest supported TLS version, but not + higher than what client requests. YaSSL highest supported version is + TLSv1.1 (=3.2) - if the client requests a higher version, downgrade it + here to 3.2. + See also Appendix E of RFC 5246 (TLS 1.2) + */ + if (hdr.version_.major_ == 3 && hdr.version_.minor_ > 2) + hdr.version_.minor_ = 2; ssl.verifyState(hdr); } From 75c76dbb06a99359d867e2a516f3244bf41fde96 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Mon, 19 Mar 2018 16:18:53 +0300 Subject: [PATCH 59/77] MDEV-15030 Add ASAN instrumentation Learn both valgrind and asan to catch this bug: mem_heap_t* heap = mem_heap_create(1024); byte* p = reinterpret_cast(heap) + sizeof(mem_heap_t); *p = 123; Overflows of the last allocation in a block will be catched too. mem_heap_create_block(): poison newly allocated memory --- storage/innobase/mem/mem0mem.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/storage/innobase/mem/mem0mem.c b/storage/innobase/mem/mem0mem.c index 6e9a39d329f..31f235b1960 100644 --- a/storage/innobase/mem/mem0mem.c +++ b/storage/innobase/mem/mem0mem.c @@ -404,6 +404,8 @@ mem_heap_create_block( heap->total_size += len; } + UNIV_MEM_FREE(block + 1, len - MEM_BLOCK_HEADER_SIZE); + ut_ad((ulint)MEM_BLOCK_HEADER_SIZE < len); return(block); From 5a8f8f89d65b75e51048288a49c86a8d974a8543 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Tue, 20 Mar 2018 10:46:57 +0300 Subject: [PATCH 60/77] honor alignment rules and xtradb too --- include/my_valgrind.h | 2 ++ storage/innobase/mem/mem0mem.c | 5 ++++- storage/xtradb/mem/mem0mem.c | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/include/my_valgrind.h b/include/my_valgrind.h index b76f5607bb5..8dde079b976 100644 --- a/include/my_valgrind.h +++ b/include/my_valgrind.h @@ -35,6 +35,8 @@ # define MEM_CHECK_DEFINED(a,len) VALGRIND_CHECK_MEM_IS_DEFINED(a,len) #elif defined(__SANITIZE_ADDRESS__) # include +/* How to do manual poisoning: +https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning */ # define MEM_UNDEFINED(a,len) ASAN_UNPOISON_MEMORY_REGION(a,len) # define MEM_NOACCESS(a,len) ASAN_POISON_MEMORY_REGION(a,len) # define MEM_CHECK_ADDRESSABLE(a,len) ((void) 0) diff --git a/storage/innobase/mem/mem0mem.c b/storage/innobase/mem/mem0mem.c index 31f235b1960..924231470aa 100644 --- a/storage/innobase/mem/mem0mem.c +++ b/storage/innobase/mem/mem0mem.c @@ -404,7 +404,10 @@ mem_heap_create_block( heap->total_size += len; } - UNIV_MEM_FREE(block + 1, len - MEM_BLOCK_HEADER_SIZE); + /* Poison all available memory. Individual chunks will be unpoisoned on + every mem_heap_alloc() call. */ + compile_time_assert(MEM_BLOCK_HEADER_SIZE >= sizeof *block); + UNIV_MEM_FREE(block + 1, len - sizeof *block); ut_ad((ulint)MEM_BLOCK_HEADER_SIZE < len); diff --git a/storage/xtradb/mem/mem0mem.c b/storage/xtradb/mem/mem0mem.c index 6e9a39d329f..924231470aa 100644 --- a/storage/xtradb/mem/mem0mem.c +++ b/storage/xtradb/mem/mem0mem.c @@ -404,6 +404,11 @@ mem_heap_create_block( heap->total_size += len; } + /* Poison all available memory. Individual chunks will be unpoisoned on + every mem_heap_alloc() call. */ + compile_time_assert(MEM_BLOCK_HEADER_SIZE >= sizeof *block); + UNIV_MEM_FREE(block + 1, len - sizeof *block); + ut_ad((ulint)MEM_BLOCK_HEADER_SIZE < len); return(block); From 2dd4e50d5f74451a5f6bf56d1a36bafffcca878c Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Wed, 21 Mar 2018 01:34:45 +0530 Subject: [PATCH 61/77] MDEV-15555: select from DUAL where false yielding wrong result when in a IN For the query having an IN subquery with no tables, we were converting the subquery with an expression between the left part and the select list of the subquery . This can give incorrect results when we have a condition in the subquery with a dual table (as this is treated as a no table). The fix is that we don't do this conversion when we have conds in the subquery with a dual table. --- mysql-test/r/subselect4.result | 11 +++++++++++ mysql-test/t/subselect4.test | 8 ++++++++ sql/item_subselect.cc | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result index d3c63ff9a2f..c20c048b919 100644 --- a/mysql-test/r/subselect4.result +++ b/mysql-test/r/subselect4.result @@ -2498,5 +2498,16 @@ FROM t2 WHERE b <= 'quux' GROUP BY field; field COUNT(DISTINCT c) 0 1 drop table t1,t2; +# +# MDEV-15555: select from DUAL where false yielding wrong result when in a IN +# +explain +SELECT 2 IN (SELECT 2 from DUAL WHERE 1 != 1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +SELECT 2 IN (SELECT 2 from DUAL WHERE 1 != 1); +2 IN (SELECT 2 from DUAL WHERE 1 != 1) +0 SET optimizer_switch= @@global.optimizer_switch; set @@tmp_table_size= @@global.tmp_table_size; diff --git a/mysql-test/t/subselect4.test b/mysql-test/t/subselect4.test index f051c8eaaf2..673dc9be0b4 100644 --- a/mysql-test/t/subselect4.test +++ b/mysql-test/t/subselect4.test @@ -2035,5 +2035,13 @@ SELECT ( SELECT COUNT(*) FROM t1 WHERE a = c ) AS field, COUNT(DISTINCT c) FROM t2 WHERE b <= 'quux' GROUP BY field; drop table t1,t2; +--echo # +--echo # MDEV-15555: select from DUAL where false yielding wrong result when in a IN +--echo # + +explain +SELECT 2 IN (SELECT 2 from DUAL WHERE 1 != 1); +SELECT 2 IN (SELECT 2 from DUAL WHERE 1 != 1); + SET optimizer_switch= @@global.optimizer_switch; set @@tmp_table_size= @@global.tmp_table_size; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 46d41fd61e3..57dcbd4f540 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1746,7 +1746,7 @@ Item_in_subselect::single_value_transformer(JOIN *join) Item* join_having= join->having ? join->having : join->tmp_having; if (!(join_having || select_lex->with_sum_func || select_lex->group_list.elements) && - select_lex->table_list.elements == 0 && + select_lex->table_list.elements == 0 && !join->conds && !select_lex->master_unit()->is_union()) { Item *where_item= (Item*) select_lex->item_list.head(); From f3994b74327eef37fa6010368f7f8db044cf70f8 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 21 Mar 2018 12:13:37 +0100 Subject: [PATCH 62/77] MDEV-15492: Subquery crash similar to MDEV-10050 Detection of first execution of PS fixed. More debug info. --- mysql-test/r/ps_qc_innodb.result | 23 +++++++++++++++++++++ mysql-test/t/ps_qc_innodb.test | 35 ++++++++++++++++++++++++++++++++ sql/sql_class.cc | 4 ++++ sql/sql_prepare.cc | 4 +++- 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 mysql-test/r/ps_qc_innodb.result create mode 100644 mysql-test/t/ps_qc_innodb.test diff --git a/mysql-test/r/ps_qc_innodb.result b/mysql-test/r/ps_qc_innodb.result new file mode 100644 index 00000000000..775055e858f --- /dev/null +++ b/mysql-test/r/ps_qc_innodb.result @@ -0,0 +1,23 @@ +# +# MDEV-15492: Subquery crash similar to MDEV-10050 +# +SET @qcs.save= @@global.query_cache_size, @qct.save= @@global.query_cache_type; +SET GLOBAL query_cache_size= 512*1024*1024, query_cache_type= ON; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (b INT) ENGINE=InnoDB; +CREATE VIEW v AS select a from t1 join t2; +PREPARE stmt1 FROM "SELECT * FROM t1 WHERE a in (SELECT a FROM v)"; +PREPARE stmt2 FROM "SELECT * FROM t1 WHERE a in (SELECT a FROM v)"; +EXECUTE stmt2; +a +EXECUTE stmt1; +a +INSERT INTO t2 VALUES (0); +EXECUTE stmt1; +a +START TRANSACTION; +EXECUTE stmt1; +a +DROP VIEW v; +DROP TABLE t1, t2; +SET GLOBAL query_cache_size= @qcs.save, query_cache_type= @qct.save; diff --git a/mysql-test/t/ps_qc_innodb.test b/mysql-test/t/ps_qc_innodb.test new file mode 100644 index 00000000000..e09a2bf4070 --- /dev/null +++ b/mysql-test/t/ps_qc_innodb.test @@ -0,0 +1,35 @@ +--source include/have_query_cache.inc +--source include/have_innodb.inc + +--echo # +--echo # MDEV-15492: Subquery crash similar to MDEV-10050 +--echo # + +SET @qcs.save= @@global.query_cache_size, @qct.save= @@global.query_cache_type; +SET GLOBAL query_cache_size= 512*1024*1024, query_cache_type= ON; + +--connect (con1,localhost,root,,test) +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (b INT) ENGINE=InnoDB; +CREATE VIEW v AS select a from t1 join t2; + +PREPARE stmt1 FROM "SELECT * FROM t1 WHERE a in (SELECT a FROM v)"; + +--connect (con2,localhost,root,,test) +PREPARE stmt2 FROM "SELECT * FROM t1 WHERE a in (SELECT a FROM v)"; +EXECUTE stmt2; + +--connection con1 +EXECUTE stmt1; +INSERT INTO t2 VALUES (0); +EXECUTE stmt1; +START TRANSACTION; +EXECUTE stmt1; + +# Cleanup +--disconnect con1 +--disconnect con2 +--connection default +DROP VIEW v; +DROP TABLE t1, t2; +SET GLOBAL query_cache_size= @qcs.save, query_cache_type= @qct.save; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index c88c13b9524..ff06b7fb3dc 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2252,15 +2252,19 @@ void THD::check_and_register_item_tree_change(Item **place, Item **new_value, void THD::rollback_item_tree_changes() { + DBUG_ENTER("THD::rollback_item_tree_changes"); I_List_iterator it(change_list); Item_change_record *change; while ((change= it++)) { + DBUG_PRINT("info", ("Rollback: %p (%p) <- %p", + *change->place, change->place, change->old_value)); *change->place= change->old_value; } /* We can forget about changes memory: it's allocated in runtime memroot */ change_list.empty(); + DBUG_VOID_RETURN; } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index a3bf9d6c93c..6aa6aacc504 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -3819,6 +3819,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor) Statement stmt_backup; Query_arena *old_stmt_arena; bool error= TRUE; + bool qc_executed= FALSE; char saved_cur_db_name_buf[SAFE_NAME_LEN+1]; LEX_STRING saved_cur_db_name= @@ -3937,6 +3938,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor) thd->lex->sql_command= SQLCOM_SELECT; status_var_increment(thd->status_var.com_stat[SQLCOM_SELECT]); thd->update_stats(); + qc_executed= TRUE; } } @@ -3960,7 +3962,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor) thd->set_statement(&stmt_backup); thd->stmt_arena= old_stmt_arena; - if (state == Query_arena::STMT_PREPARED) + if (state == Query_arena::STMT_PREPARED && !qc_executed) state= Query_arena::STMT_EXECUTED; if (error == 0 && this->lex->sql_command == SQLCOM_CALL) From ddc5c65333a4add28907ccb82054ecba0ff6b873 Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Thu, 22 Mar 2018 03:01:53 +0530 Subject: [PATCH 63/77] MDEV-14779: using left join causes incorrect results with materialization and derived tables Conversion of a subquery to a semi-join is blocked when we have an IN subquery predicate in the on_expr of an outer join. Currently this scenario is handled but the cases when an IN subquery predicate is wrapped inside a Item_in_optimizer item then this blocking is not done. --- mysql-test/r/join_outer.result | 18 +++++++++++++++++- mysql-test/r/join_outer_jcl6.result | 18 +++++++++++++++++- mysql-test/t/join_outer.test | 18 +++++++++++++++++- sql/item_cmpfunc.h | 5 +++++ sql/item_func.h | 2 +- sql/opt_subselect.cc | 4 ++++ 6 files changed, 61 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 74580e67499..67b22ca86b2 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -2346,11 +2346,27 @@ CREATE TABLE t1 (b1 BIT NOT NULL); INSERT INTO t1 VALUES (0),(1); CREATE TABLE t2 (b2 BIT NOT NULL); INSERT INTO t2 VALUES (0),(1); -SET SESSION JOIN_CACHE_LEVEL = 3; +set @save_join_cache_level= @@join_cache_level; +SET @@join_cache_level = 3; SELECT t1.b1+'0' , t2.b2 + '0' FROM t1 LEFT JOIN t2 ON b1 = b2; t1.b1+'0' t2.b2 + '0' 0 0 1 1 DROP TABLE t1, t2; +set @join_cache_level= @save_join_cache_level; +# +# MDEV-14779: using left join causes incorrect results with materialization and derived tables +# +create table t1(id int); +insert into t1 values (1),(2); +create table t2(sid int, id int); +insert into t2 values (1,1),(2,2); +select * from t1 t +left join (select * from t2 where sid in (select max(sid) from t2 where 0=1 group by id)) r +on t.id=r.id ; +id sid id +1 NULL NULL +2 NULL NULL +drop table t1, t2; # end of 5.5 tests SET optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/r/join_outer_jcl6.result b/mysql-test/r/join_outer_jcl6.result index d46a4ee6c7a..c019da6197b 100644 --- a/mysql-test/r/join_outer_jcl6.result +++ b/mysql-test/r/join_outer_jcl6.result @@ -2357,12 +2357,28 @@ CREATE TABLE t1 (b1 BIT NOT NULL); INSERT INTO t1 VALUES (0),(1); CREATE TABLE t2 (b2 BIT NOT NULL); INSERT INTO t2 VALUES (0),(1); -SET SESSION JOIN_CACHE_LEVEL = 3; +set @save_join_cache_level= @@join_cache_level; +SET @@join_cache_level = 3; SELECT t1.b1+'0' , t2.b2 + '0' FROM t1 LEFT JOIN t2 ON b1 = b2; t1.b1+'0' t2.b2 + '0' 0 0 1 1 DROP TABLE t1, t2; +set @join_cache_level= @save_join_cache_level; +# +# MDEV-14779: using left join causes incorrect results with materialization and derived tables +# +create table t1(id int); +insert into t1 values (1),(2); +create table t2(sid int, id int); +insert into t2 values (1,1),(2,2); +select * from t1 t +left join (select * from t2 where sid in (select max(sid) from t2 where 0=1 group by id)) r +on t.id=r.id ; +id sid id +1 NULL NULL +2 NULL NULL +drop table t1, t2; # end of 5.5 tests SET optimizer_switch=@save_optimizer_switch; set join_cache_level=default; diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test index 896cc137e07..2769aea9969 100644 --- a/mysql-test/t/join_outer.test +++ b/mysql-test/t/join_outer.test @@ -1891,9 +1891,25 @@ INSERT INTO t1 VALUES (0),(1); CREATE TABLE t2 (b2 BIT NOT NULL); INSERT INTO t2 VALUES (0),(1); -SET SESSION JOIN_CACHE_LEVEL = 3; +set @save_join_cache_level= @@join_cache_level; +SET @@join_cache_level = 3; SELECT t1.b1+'0' , t2.b2 + '0' FROM t1 LEFT JOIN t2 ON b1 = b2; DROP TABLE t1, t2; +set @join_cache_level= @save_join_cache_level; + +--echo # +--echo # MDEV-14779: using left join causes incorrect results with materialization and derived tables +--echo # + +create table t1(id int); +insert into t1 values (1),(2); +create table t2(sid int, id int); +insert into t2 values (1,1),(2,2); + +select * from t1 t + left join (select * from t2 where sid in (select max(sid) from t2 where 0=1 group by id)) r + on t.id=r.id ; +drop table t1, t2; --echo # end of 5.5 tests diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index a045a08e4fd..3c8cc71370d 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -255,6 +255,7 @@ public: bool is_null(); longlong val_int(); void cleanup(); + enum Functype functype() const { return IN_OPTIMIZER_FUNC; } const char *func_name() const { return ""; } Item_cache **get_cache() { return &cache; } void keep_top_level_cache(); @@ -270,6 +271,10 @@ public: void fix_after_pullout(st_select_lex *new_parent, Item **ref); virtual void print(String *str, enum_query_type query_type); void restore_first_argument(); + Item* get_wrapped_in_subselect_item() + { + return args[1]; + } }; class Comp_creator diff --git a/sql/item_func.h b/sql/item_func.h index 2157c6b6b6d..60122f03e0b 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -66,7 +66,7 @@ public: NOW_FUNC, TRIG_COND_FUNC, SUSERVAR_FUNC, GUSERVAR_FUNC, COLLATE_FUNC, EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC, - NEG_FUNC, GSYSVAR_FUNC }; + NEG_FUNC, GSYSVAR_FUNC, IN_OPTIMIZER_FUNC }; enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL, OPTIMIZE_EQUAL }; enum Type type() const { return FUNC_ITEM; } diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 24f35a0c14c..c21541c4b97 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1006,6 +1006,10 @@ bool check_for_outer_joins(List *join_list) void find_and_block_conversion_to_sj(Item *to_find, List_iterator_fast &li) { + if (to_find->type() == Item::FUNC_ITEM && + ((Item_func*)to_find)->functype() == Item_func::IN_OPTIMIZER_FUNC) + to_find= ((Item_in_optimizer*)to_find)->get_wrapped_in_subselect_item(); + if (to_find->type() != Item::SUBSELECT_ITEM || ((Item_subselect *) to_find)->substype() != Item_subselect::IN_SUBS) return; From e8c2366bf87a89f87feac16d1cf98551ddb6bd40 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 27 Mar 2018 09:40:10 +0400 Subject: [PATCH 64/77] MDEV-15620 Crash when using "SET @@NEW.a=expr" inside a trigger A simple patch fixing the problem in 5.5. Note, a full patch was previously fixed to 10.3. --- mysql-test/r/parser.result | 7 +++++++ mysql-test/t/parser.test | 9 +++++++++ sql/sql_yacc.yy | 5 +++++ 3 files changed, 21 insertions(+) diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result index 9a14c0e324b..70dc7a4c1cf 100644 --- a/mysql-test/r/parser.result +++ b/mysql-test/r/parser.result @@ -672,3 +672,10 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp PREPARE stmt FROM 'CREATE TRIGGER tr AFTER DELETE ON t1 FOR EACH ROW SET @a = 1\\'; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '\' at line 1 DROP TABLE t1; +# +# MDEV-15620 Crash when using "SET @@NEW.a=expr" inside a trigger +# +CREATE TABLE t1 (a INT); +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET @@NEW.a=0; +ERROR HY000: Unknown system variable 'NEW' +DROP TABLE t1; diff --git a/mysql-test/t/parser.test b/mysql-test/t/parser.test index 1e3458eafdf..06ec3164ad1 100644 --- a/mysql-test/t/parser.test +++ b/mysql-test/t/parser.test @@ -780,3 +780,12 @@ CREATE TRIGGER tr AFTER DELETE ON t1 FOR EACH ROW SET @a = 1\; --error ER_PARSE_ERROR PREPARE stmt FROM 'CREATE TRIGGER tr AFTER DELETE ON t1 FOR EACH ROW SET @a = 1\\'; DROP TABLE t1; + +--echo # +--echo # MDEV-15620 Crash when using "SET @@NEW.a=expr" inside a trigger +--echo # + +CREATE TABLE t1 (a INT); +--error ER_UNKNOWN_SYSTEM_VARIABLE +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET @@NEW.a=0; +DROP TABLE t1; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e1c6b5b6276..bf47153c0c1 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -13567,6 +13567,11 @@ option_value: | '@' '@' opt_var_ident_type internal_variable_name equal set_expr_or_default { struct sys_var_with_base tmp= $4; + if (tmp.var == trg_new_row_fake_var) + { + my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), "NEW"); + MYSQL_YYABORT; + } /* Lookup if necessary: must be a system variable. */ if (tmp.var == NULL) { From bdab8b74ff24a25ecbc7aa96addc54767a6c7146 Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Sat, 24 Mar 2018 03:31:18 +0530 Subject: [PATCH 65/77] MDEV-11274: Executing EXPLAIN of complex query over join limit causes server to crash For this case we have a view that is mergeable but we are not able to merge it in the parent select because that would exceed the maximum tables allowed in the join list, so we materialise this view TABLE_LIST::dervied is NULL for such views, it is only set for views which have ALGORITHM=TEMPTABLE Fixed by making sure TABLE_LIST::derived is set for views that could not be merged --- mysql-test/r/view.result | 197 +++++++++++++++++++++++++++++++++++++++ mysql-test/t/view.test | 196 ++++++++++++++++++++++++++++++++++++++ sql/table.h | 1 + 3 files changed, 394 insertions(+) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 1d12c50954f..7fc3c48c3a0 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -5535,6 +5535,203 @@ View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select group_concat(`t1`.`str` separator '\\') AS `GROUP_CONCAT(str SEPARATOR '\\')` from `t1` latin1 latin1_swedish_ci drop view v1; drop table t1; +CREATE TABLE IF NOT EXISTS t0 (f0 INT); +CREATE TABLE IF NOT EXISTS t1 (f1 INT); +CREATE TABLE IF NOT EXISTS t2 (f2 INT); +CREATE TABLE IF NOT EXISTS t3 (f3 INT); +CREATE TABLE IF NOT EXISTS t4 (f4 INT); +CREATE TABLE IF NOT EXISTS t5 (f5 INT); +CREATE TABLE IF NOT EXISTS t6 (f6 INT); +CREATE TABLE IF NOT EXISTS t7 (f7 INT); +CREATE TABLE IF NOT EXISTS t8 (f8 INT); +CREATE TABLE IF NOT EXISTS t9 (f9 INT); +CREATE TABLE IF NOT EXISTS t10 (f10 INT); +CREATE TABLE IF NOT EXISTS t11 (f11 INT); +CREATE TABLE IF NOT EXISTS t12 (f12 INT); +CREATE TABLE IF NOT EXISTS t13 (f13 INT); +CREATE TABLE IF NOT EXISTS t14 (f14 INT); +CREATE TABLE IF NOT EXISTS t15 (f15 INT); +CREATE TABLE IF NOT EXISTS t16 (f16 INT); +CREATE TABLE IF NOT EXISTS t17 (f17 INT); +CREATE TABLE IF NOT EXISTS t18 (f18 INT); +CREATE TABLE IF NOT EXISTS t19 (f19 INT); +CREATE TABLE IF NOT EXISTS t20 (f20 INT); +CREATE TABLE IF NOT EXISTS t21 (f21 INT); +CREATE TABLE IF NOT EXISTS t22 (f22 INT); +CREATE TABLE IF NOT EXISTS t23 (f23 INT); +CREATE TABLE IF NOT EXISTS t24 (f24 INT); +CREATE TABLE IF NOT EXISTS t25 (f25 INT); +CREATE TABLE IF NOT EXISTS t26 (f26 INT); +CREATE TABLE IF NOT EXISTS t27 (f27 INT); +CREATE TABLE IF NOT EXISTS t28 (f28 INT); +CREATE TABLE IF NOT EXISTS t29 (f29 INT); +CREATE TABLE IF NOT EXISTS t30 (f30 INT); +CREATE TABLE IF NOT EXISTS t31 (f31 INT); +CREATE TABLE IF NOT EXISTS t32 (f32 INT); +CREATE TABLE IF NOT EXISTS t33 (f33 INT); +CREATE TABLE IF NOT EXISTS t34 (f34 INT); +CREATE TABLE IF NOT EXISTS t35 (f35 INT); +CREATE TABLE IF NOT EXISTS t36 (f36 INT); +CREATE TABLE IF NOT EXISTS t37 (f37 INT); +CREATE TABLE IF NOT EXISTS t38 (f38 INT); +CREATE TABLE IF NOT EXISTS t39 (f39 INT); +CREATE TABLE IF NOT EXISTS t40 (f40 INT); +CREATE TABLE IF NOT EXISTS t41 (f41 INT); +CREATE TABLE IF NOT EXISTS t42 (f42 INT); +CREATE TABLE IF NOT EXISTS t43 (f43 INT); +CREATE TABLE IF NOT EXISTS t44 (f44 INT); +CREATE TABLE IF NOT EXISTS t45 (f45 INT); +CREATE TABLE IF NOT EXISTS t46 (f46 INT); +CREATE TABLE IF NOT EXISTS t47 (f47 INT); +CREATE TABLE IF NOT EXISTS t48 (f48 INT); +CREATE TABLE IF NOT EXISTS t49 (f49 INT); +CREATE TABLE IF NOT EXISTS t50 (f50 INT); +CREATE TABLE IF NOT EXISTS t51 (f51 INT); +CREATE TABLE IF NOT EXISTS t52 (f52 INT); +CREATE TABLE IF NOT EXISTS t53 (f53 INT); +CREATE TABLE IF NOT EXISTS t54 (f54 INT); +CREATE TABLE IF NOT EXISTS t55 (f55 INT); +CREATE TABLE IF NOT EXISTS t56 (f56 INT); +CREATE TABLE IF NOT EXISTS t57 (f57 INT); +CREATE TABLE IF NOT EXISTS t58 (f58 INT); +CREATE TABLE IF NOT EXISTS t59 (f59 INT); +CREATE TABLE IF NOT EXISTS t60 (f60 INT); +CREATE OR REPLACE VIEW v60 AS SELECT * FROM t60; +EXPLAIN +SELECT t0.* +FROM t0 +JOIN t1 +ON t1.f1 = t0.f0 +LEFT JOIN t2 +ON t0.f0 = t2.f2 +LEFT JOIN t3 +ON t0.f0 = t3.f3 +LEFT JOIN t4 +ON t0.f0 = t4.f4 +LEFT JOIN t5 +ON t4.f4 = t5.f5 +LEFT JOIN t6 +ON t0.f0 = t6.f6 +LEFT JOIN t7 +ON t0.f0 = t7.f7 +LEFT JOIN t8 +ON t0.f0 = t8.f8 +LEFT JOIN t9 +ON t0.f0 = t9.f9 +LEFT JOIN t10 +ON t0.f0 = t10.f10 +LEFT JOIN t11 +ON t0.f0 = t11.f11 +LEFT JOIN t12 +ON t0.f0 = t12.f12 +LEFT JOIN t13 +ON t0.f0 = t13.f13 +LEFT JOIN t14 +ON t0.f0 = t14.f14 +LEFT JOIN t15 +ON t0.f0 = t15.f15 +LEFT JOIN t16 +ON t0.f0 = t16.f16 +LEFT JOIN t17 +ON t0.f0 = t17.f17 +LEFT JOIN t18 +ON t0.f0 = t18.f18 +LEFT JOIN t19 +ON t18.f18 = t19.f19 +LEFT JOIN t20 +ON t20.f20 = t19.f19 +LEFT JOIN t21 +ON t20.f20 = t21.f21 +LEFT JOIN t22 +ON t19.f19 = t22.f22 +LEFT JOIN t23 +ON t23.f23 = t0.f0 +LEFT JOIN t24 +ON t24.f24 = t23.f23 +LEFT JOIN t25 +ON t0.f0 = t25.f25 +LEFT JOIN t26 +ON t26.f26 = t0.f0 +LEFT JOIN t27 +ON t27.f27 = t0.f0 +LEFT JOIN t28 +ON t0.f0 = t28.f28 +LEFT JOIN t29 +ON t0.f0 = t29.f29 +LEFT JOIN t30 +ON t30.f30 = t0.f0 +LEFT JOIN t31 +ON t0.f0 = t31.f31 +LEFT JOIN t32 +ON t32.f32 = t31.f31 +LEFT JOIN t33 +ON t33.f33 = t0.f0 +LEFT JOIN t34 +ON t33.f33 = t34.f34 +LEFT JOIN t35 +ON t33.f33 = t35.f35 +LEFT JOIN t36 +ON t36.f36 = t0.f0 +LEFT JOIN t37 +ON t32.f32 = t37.f37 +LEFT JOIN t38 +ON t31.f31 = t38.f38 +LEFT JOIN t39 +ON t39.f39 = t0.f0 +LEFT JOIN t40 +ON t40.f40 = t39.f39 +LEFT JOIN t41 +ON t41.f41 = t0.f0 +LEFT JOIN t42 +ON t42.f42 = t41.f41 +LEFT JOIN t43 +ON t43.f43 = t41.f41 +LEFT JOIN t44 +ON t44.f44 = t0.f0 +LEFT JOIN t45 +ON t45.f45 = t0.f0 +LEFT JOIN t46 +ON t46.f46 = t0.f0 +LEFT JOIN t47 +ON t47.f47 = t0.f0 +LEFT JOIN t48 +ON t48.f48 = t0.f0 +LEFT JOIN t49 +ON t0.f0 = t49.f49 +LEFT JOIN t50 +ON t0.f0 = t50.f50 +LEFT JOIN t51 +ON t0.f0 = t51.f51 +LEFT JOIN t52 +ON t52.f52 = t0.f0 +LEFT JOIN t53 +ON t53.f53 = t0.f0 +LEFT JOIN t54 +ON t54.f54 = t0.f0 +LEFT JOIN t55 +ON t55.f55 = t0.f0 +LEFT JOIN t56 +ON t56.f56 = t0.f0 +LEFT JOIN t57 +ON t57.f57 = t0.f0 +LEFT JOIN t58 +ON t58.f58 = t57.f57 +LEFT JOIN t59 +ON t36.f36 = t59.f59 +LEFT JOIN v60 +ON t36.f36 = v60.f60 +; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table +drop table t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, +t10, t11, t12, t13, t14, t15, t16, t17, t18, +t19, t20, t21, t22, t23, t24, t25, t26, t27, +t28, t29, t30, t31, t32, t33, t34, t35, t36, +t37, t38, t39, t40, t41, t42, t43, t44, t45, +t46, t47, t48, t49, t50, t51, t52, t53, t54, +t55, t56, t57, t58, t59,t60; +drop view v60; # ----------------------------------------------------------------- # -- End of 5.5 tests. # ----------------------------------------------------------------- diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 4b3537df2de..835f12957d4 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -5478,6 +5478,202 @@ SHOW CREATE VIEW v1; drop view v1; drop table t1; +CREATE TABLE IF NOT EXISTS t0 (f0 INT); +CREATE TABLE IF NOT EXISTS t1 (f1 INT); +CREATE TABLE IF NOT EXISTS t2 (f2 INT); +CREATE TABLE IF NOT EXISTS t3 (f3 INT); +CREATE TABLE IF NOT EXISTS t4 (f4 INT); +CREATE TABLE IF NOT EXISTS t5 (f5 INT); +CREATE TABLE IF NOT EXISTS t6 (f6 INT); +CREATE TABLE IF NOT EXISTS t7 (f7 INT); +CREATE TABLE IF NOT EXISTS t8 (f8 INT); +CREATE TABLE IF NOT EXISTS t9 (f9 INT); +CREATE TABLE IF NOT EXISTS t10 (f10 INT); +CREATE TABLE IF NOT EXISTS t11 (f11 INT); +CREATE TABLE IF NOT EXISTS t12 (f12 INT); +CREATE TABLE IF NOT EXISTS t13 (f13 INT); +CREATE TABLE IF NOT EXISTS t14 (f14 INT); +CREATE TABLE IF NOT EXISTS t15 (f15 INT); +CREATE TABLE IF NOT EXISTS t16 (f16 INT); +CREATE TABLE IF NOT EXISTS t17 (f17 INT); +CREATE TABLE IF NOT EXISTS t18 (f18 INT); +CREATE TABLE IF NOT EXISTS t19 (f19 INT); +CREATE TABLE IF NOT EXISTS t20 (f20 INT); +CREATE TABLE IF NOT EXISTS t21 (f21 INT); +CREATE TABLE IF NOT EXISTS t22 (f22 INT); +CREATE TABLE IF NOT EXISTS t23 (f23 INT); +CREATE TABLE IF NOT EXISTS t24 (f24 INT); +CREATE TABLE IF NOT EXISTS t25 (f25 INT); +CREATE TABLE IF NOT EXISTS t26 (f26 INT); +CREATE TABLE IF NOT EXISTS t27 (f27 INT); +CREATE TABLE IF NOT EXISTS t28 (f28 INT); +CREATE TABLE IF NOT EXISTS t29 (f29 INT); +CREATE TABLE IF NOT EXISTS t30 (f30 INT); +CREATE TABLE IF NOT EXISTS t31 (f31 INT); +CREATE TABLE IF NOT EXISTS t32 (f32 INT); +CREATE TABLE IF NOT EXISTS t33 (f33 INT); +CREATE TABLE IF NOT EXISTS t34 (f34 INT); +CREATE TABLE IF NOT EXISTS t35 (f35 INT); +CREATE TABLE IF NOT EXISTS t36 (f36 INT); +CREATE TABLE IF NOT EXISTS t37 (f37 INT); +CREATE TABLE IF NOT EXISTS t38 (f38 INT); +CREATE TABLE IF NOT EXISTS t39 (f39 INT); +CREATE TABLE IF NOT EXISTS t40 (f40 INT); +CREATE TABLE IF NOT EXISTS t41 (f41 INT); +CREATE TABLE IF NOT EXISTS t42 (f42 INT); +CREATE TABLE IF NOT EXISTS t43 (f43 INT); +CREATE TABLE IF NOT EXISTS t44 (f44 INT); +CREATE TABLE IF NOT EXISTS t45 (f45 INT); +CREATE TABLE IF NOT EXISTS t46 (f46 INT); +CREATE TABLE IF NOT EXISTS t47 (f47 INT); +CREATE TABLE IF NOT EXISTS t48 (f48 INT); +CREATE TABLE IF NOT EXISTS t49 (f49 INT); +CREATE TABLE IF NOT EXISTS t50 (f50 INT); +CREATE TABLE IF NOT EXISTS t51 (f51 INT); +CREATE TABLE IF NOT EXISTS t52 (f52 INT); +CREATE TABLE IF NOT EXISTS t53 (f53 INT); +CREATE TABLE IF NOT EXISTS t54 (f54 INT); +CREATE TABLE IF NOT EXISTS t55 (f55 INT); +CREATE TABLE IF NOT EXISTS t56 (f56 INT); +CREATE TABLE IF NOT EXISTS t57 (f57 INT); +CREATE TABLE IF NOT EXISTS t58 (f58 INT); +CREATE TABLE IF NOT EXISTS t59 (f59 INT); +CREATE TABLE IF NOT EXISTS t60 (f60 INT); +CREATE OR REPLACE VIEW v60 AS SELECT * FROM t60; + +EXPLAIN + SELECT t0.* +FROM t0 +JOIN t1 + ON t1.f1 = t0.f0 +LEFT JOIN t2 + ON t0.f0 = t2.f2 +LEFT JOIN t3 + ON t0.f0 = t3.f3 +LEFT JOIN t4 + ON t0.f0 = t4.f4 +LEFT JOIN t5 + ON t4.f4 = t5.f5 +LEFT JOIN t6 + ON t0.f0 = t6.f6 +LEFT JOIN t7 + ON t0.f0 = t7.f7 +LEFT JOIN t8 + ON t0.f0 = t8.f8 +LEFT JOIN t9 + ON t0.f0 = t9.f9 +LEFT JOIN t10 + ON t0.f0 = t10.f10 +LEFT JOIN t11 + ON t0.f0 = t11.f11 +LEFT JOIN t12 + ON t0.f0 = t12.f12 +LEFT JOIN t13 + ON t0.f0 = t13.f13 +LEFT JOIN t14 + ON t0.f0 = t14.f14 +LEFT JOIN t15 + ON t0.f0 = t15.f15 +LEFT JOIN t16 + ON t0.f0 = t16.f16 +LEFT JOIN t17 + ON t0.f0 = t17.f17 +LEFT JOIN t18 + ON t0.f0 = t18.f18 +LEFT JOIN t19 + ON t18.f18 = t19.f19 +LEFT JOIN t20 + ON t20.f20 = t19.f19 +LEFT JOIN t21 + ON t20.f20 = t21.f21 +LEFT JOIN t22 + ON t19.f19 = t22.f22 +LEFT JOIN t23 + ON t23.f23 = t0.f0 +LEFT JOIN t24 + ON t24.f24 = t23.f23 +LEFT JOIN t25 + ON t0.f0 = t25.f25 +LEFT JOIN t26 + ON t26.f26 = t0.f0 +LEFT JOIN t27 + ON t27.f27 = t0.f0 +LEFT JOIN t28 + ON t0.f0 = t28.f28 +LEFT JOIN t29 + ON t0.f0 = t29.f29 +LEFT JOIN t30 + ON t30.f30 = t0.f0 +LEFT JOIN t31 + ON t0.f0 = t31.f31 +LEFT JOIN t32 + ON t32.f32 = t31.f31 +LEFT JOIN t33 + ON t33.f33 = t0.f0 +LEFT JOIN t34 + ON t33.f33 = t34.f34 +LEFT JOIN t35 + ON t33.f33 = t35.f35 +LEFT JOIN t36 + ON t36.f36 = t0.f0 +LEFT JOIN t37 + ON t32.f32 = t37.f37 +LEFT JOIN t38 + ON t31.f31 = t38.f38 +LEFT JOIN t39 + ON t39.f39 = t0.f0 +LEFT JOIN t40 + ON t40.f40 = t39.f39 +LEFT JOIN t41 + ON t41.f41 = t0.f0 +LEFT JOIN t42 + ON t42.f42 = t41.f41 +LEFT JOIN t43 + ON t43.f43 = t41.f41 +LEFT JOIN t44 + ON t44.f44 = t0.f0 +LEFT JOIN t45 + ON t45.f45 = t0.f0 +LEFT JOIN t46 + ON t46.f46 = t0.f0 +LEFT JOIN t47 + ON t47.f47 = t0.f0 +LEFT JOIN t48 + ON t48.f48 = t0.f0 +LEFT JOIN t49 + ON t0.f0 = t49.f49 +LEFT JOIN t50 + ON t0.f0 = t50.f50 +LEFT JOIN t51 + ON t0.f0 = t51.f51 +LEFT JOIN t52 + ON t52.f52 = t0.f0 +LEFT JOIN t53 + ON t53.f53 = t0.f0 +LEFT JOIN t54 + ON t54.f54 = t0.f0 +LEFT JOIN t55 + ON t55.f55 = t0.f0 +LEFT JOIN t56 + ON t56.f56 = t0.f0 +LEFT JOIN t57 + ON t57.f57 = t0.f0 +LEFT JOIN t58 + ON t58.f58 = t57.f57 +LEFT JOIN t59 + ON t36.f36 = t59.f59 +LEFT JOIN v60 + ON t36.f36 = v60.f60 +; +drop table t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, +t10, t11, t12, t13, t14, t15, t16, t17, t18, +t19, t20, t21, t22, t23, t24, t25, t26, t27, +t28, t29, t30, t31, t32, t33, t34, t35, t36, +t37, t38, t39, t40, t41, t42, t43, t44, t45, +t46, t47, t48, t49, t50, t51, t52, t53, t54, +t55, t56, t57, t58, t59,t60; +drop view v60; + --echo # ----------------------------------------------------------------- --echo # -- End of 5.5 tests. --echo # ----------------------------------------------------------------- diff --git a/sql/table.h b/sql/table.h index 98f8c7ad73f..fcf214d3582 100644 --- a/sql/table.h +++ b/sql/table.h @@ -2125,6 +2125,7 @@ struct TABLE_LIST DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", (alias ? alias : ""), get_unit())); + derived= get_unit(); derived_type= ((derived_type & (derived ? DTYPE_MASK : DTYPE_VIEW)) | DTYPE_TABLE | DTYPE_MATERIALIZE); set_check_materialized(); From 606e21867c0f5765f61efd2478c9f12cf33da71e Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 3 Apr 2018 16:28:52 +0400 Subject: [PATCH 66/77] MDEV-15630 uuid() function evaluates at wrong time in query --- mysql-test/r/func_misc.result | 11 +++++++++++ mysql-test/t/func_misc.test | 12 ++++++++++++ sql/item_strfunc.h | 1 + 3 files changed, 24 insertions(+) diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index 1c106acf333..66e3cfd4ff4 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -572,6 +572,17 @@ N AVG 0 NULL drop table t1; # +# MDEV-15630 uuid() function evaluates at wrong time in query +# +CREATE TABLE t1 (id INT); +INSERT INTO t1 VALUES (1),(2),(3); +SELECT COUNT(1), UUID() as uid FROM t1 GROUP BY uid; +COUNT(1) uid +1 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +1 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +1 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +DROP TABLE t1; +# # End of 5.5 tests # SELECT NAME_CONST('a', -(1 OR 2)) OR 1; diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index d7eda5ee4e6..c21630c0c7b 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -596,6 +596,18 @@ AND 57813X540X1723 = 'Test'; drop table t1; + +--echo # +--echo # MDEV-15630 uuid() function evaluates at wrong time in query +--echo # + +CREATE TABLE t1 (id INT); +INSERT INTO t1 VALUES (1),(2),(3); +--replace_column 2 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +SELECT COUNT(1), UUID() as uid FROM t1 GROUP BY uid; +DROP TABLE t1; + + --echo # --echo # End of 5.5 tests --echo # diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 00ae60a7fb1..006b1b90081 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); } + table_map used_tables() const { return RAND_TABLE_BIT; } const char *func_name() const{ return "uuid"; } String *val_str(String *); bool check_vcol_func_processor(uchar *int_arg) From df6197c8b93bd686cfc25e72890c28070b22f195 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 23 Feb 2018 18:50:12 +0100 Subject: [PATCH 67/77] compiler warning warning: format '%p' expects argument of type 'void *', but argument 4 has type 'long int' --- mysys/my_addr_resolve.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysys/my_addr_resolve.c b/mysys/my_addr_resolve.c index f831ad5121f..02f71fd72bd 100644 --- a/mysys/my_addr_resolve.c +++ b/mysys/my_addr_resolve.c @@ -204,7 +204,7 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) strnmov(addr2line_binary, info.dli_fname, sizeof(addr2line_binary)); } offset = info.dli_fbase; - len= my_snprintf(input, sizeof(input), "%p\n", ptr - offset); + len= my_snprintf(input, sizeof(input), "%08x\n", (ulonglong)(ptr - offset)); if (write(in[1], input, len) <= 0) return 1; if (read(out[0], output, sizeof(output)) <= 0) From f5369faf5bbfb56b5e945836eb3f7c7ee88b4079 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 29 Mar 2018 15:25:08 +0200 Subject: [PATCH 68/77] don't disable SSL when connecting via libmysqld --- sql-common/client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql-common/client.c b/sql-common/client.c index 7d92f71d69f..fc591e21616 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -2532,10 +2532,10 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, if (mysql->client_flag & CLIENT_MULTI_STATEMENTS) mysql->client_flag|= CLIENT_MULTI_RESULTS; -#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) +#ifdef HAVE_OPENSSL if (mysql->options.use_ssl) mysql->client_flag|= CLIENT_SSL; -#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY*/ +#endif /* HAVE_OPENSSL */ if (mpvio->db) mysql->client_flag|= CLIENT_CONNECT_WITH_DB; From 6beb08c7b67ed7610e95c0350f9f93005db1e055 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 4 Apr 2018 09:12:14 +0400 Subject: [PATCH 69/77] 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 70/77] 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 71/77] 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 88ac368fea2182447284d6bacff4d93ef1acb865 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sat, 13 Jan 2018 14:05:14 +1100 Subject: [PATCH 72/77] 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 73/77] 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 f1258e7cd2c57886e5eb4cf51b4ab3a9c030cbab Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 19 Apr 2018 22:32:27 +0200 Subject: [PATCH 74/77] 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 75/77] 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 76/77] 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 77/77] 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; }