From aec43216c834c2156e9aca7b7dc182fbdd1916de Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 26 Oct 2016 21:38:58 +0000 Subject: [PATCH 01/21] MDEV-9409 Windows - workaround VS2015 CRT bug that makes mysqldump/mysql_install_db.exe fail The bug is described in https://connect.microsoft.com/VisualStudio/Feedback/Details/1902345 When reading from a pipe in text mode, using CRT function such as fread(), some newlines may be lost. Workaround is to use binary mode on reading side and if necessary, replace \r\n with \n. --- client/mysqltest.cc | 28 ++++++++++++++++++++++------ sql/mysqld.cc | 6 ++++++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index acb9e8b1e0c..5daa0e72270 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -1705,11 +1705,11 @@ int cat_file(DYNAMIC_STRING* ds, const char* filename) while((len= my_read(fd, (uchar*)&buff, sizeof(buff)-1, MYF(0))) > 0) { - char *p= buff, *start= buff; - while (p < buff+len) + char *p= buff, *start= buff,*end=buff+len; + while (p < end) { /* Convert cr/lf to lf */ - if (*p == '\r' && *(p+1) && *(p+1)== '\n') + if (*p == '\r' && p+1 < end && *(p+1)== '\n') { /* Add fake newline instead of cr and output the line */ *p= '\n'; @@ -3367,16 +3367,32 @@ void do_exec(struct st_command *command) ds_result= &ds_sorted; } +#ifdef _WIN32 + /* Workaround for CRT bug, MDEV-9409 */ + _setmode(fileno(res_file), O_BINARY); +#endif + while (fgets(buf, sizeof(buf), res_file)) { + int len = (int)strlen(buf); +#ifdef _WIN32 + /* Strip '\r' off newlines. */ + if (len > 1 && buf[len-2] == '\r' && buf[len-1] == '\n') + { + buf[len-2] = '\n'; + buf[len-1] = 0; + len--; + } +#endif if (disable_result_log) { - buf[strlen(buf)-1]=0; + if (len) + buf[len-1] = 0; DBUG_PRINT("exec_result",("%s", buf)); } else { - replace_dynstr_append(ds_result, buf); + replace_dynstr_append_mem(ds_result, buf, len); } } error= pclose(res_file); @@ -5200,7 +5216,7 @@ typedef struct static st_error global_error_names[] = { - { "", -1U, "" }, + { "", ~0U, "" }, #include { 0, 0, 0 } }; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index be9e21d6746..8eb92cafc03 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4949,6 +4949,12 @@ int mysqld_main(int argc, char **argv) setbuf(stderr, NULL); FreeConsole(); // Remove window } + + if (fileno(stdin) >= 0) + { + /* Disable CRLF translation (MDEV-9409). */ + _setmode(fileno(stdin), O_BINARY); + } #endif /* From d8cb6822bc7deecba26021368c2f08fa6bf59e58 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 26 Oct 2016 21:54:41 +0000 Subject: [PATCH 02/21] VS2015 build fixes - new location of signtool - silence a nonsensical warning from stl header (complain about noexcept() function attribute, if /EHsc is not set) --- cmake/install_macros.cmake | 1 + cmake/os/Windows.cmake | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/install_macros.cmake b/cmake/install_macros.cmake index 15e2dc4930b..22a525d7344 100644 --- a/cmake/install_macros.cmake +++ b/cmake/install_macros.cmake @@ -208,6 +208,7 @@ IF(WIN32) FIND_PROGRAM(SIGNTOOL_EXECUTABLE signtool PATHS "$ENV{ProgramFiles}/Microsoft SDKs/Windows/v7.0A/bin" "$ENV{ProgramFiles}/Windows Kits/8.0/bin/x86" + "$ENV{ProgramFiles}/Windows Kits/8.1/bin/x86" ) IF(NOT SIGNTOOL_EXECUTABLE) MESSAGE(FATAL_ERROR diff --git a/cmake/os/Windows.cmake b/cmake/os/Windows.cmake index e1055ab5894..283f79b3b41 100644 --- a/cmake/os/Windows.cmake +++ b/cmake/os/Windows.cmake @@ -120,7 +120,7 @@ IF(MSVC) #TODO: update the code and remove the disabled warnings SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4800 /wd4805 /wd4996") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4800 /wd4805 /wd4996 /wd4291 /we4099") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4800 /wd4805 /wd4996 /wd4291 /wd4577 /we4099") IF(CMAKE_SIZEOF_VOID_P MATCHES 8) # _WIN64 is defined by the compiler itself. From 2a2e79b702b28149c8f9984d24367fe3ad7afa13 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 27 Oct 2016 13:03:49 +0000 Subject: [PATCH 03/21] MDEV-11157 Windows - Upgrade installer to use HeidiSQL 9.4 --- win/packaging/heidisql.cmake | 2 +- win/packaging/heidisql.wxi.in | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/win/packaging/heidisql.cmake b/win/packaging/heidisql.cmake index e2636eb4af8..772834e7c7d 100644 --- a/win/packaging/heidisql.cmake +++ b/win/packaging/heidisql.cmake @@ -1,4 +1,4 @@ -SET(HEIDISQL_BASE_NAME "HeidiSQL_9.3_Portable") +SET(HEIDISQL_BASE_NAME "HeidiSQL_9.4_Portable") SET(HEIDISQL_ZIP "${HEIDISQL_BASE_NAME}.zip") SET(HEIDISQL_URL "http://www.heidisql.com/downloads/releases/${HEIDISQL_ZIP}") SET(HEIDISQL_DOWNLOAD_DIR ${THIRD_PARTY_DOWNLOAD_LOCATION}/${HEIDISQL_BASE_NAME}) diff --git a/win/packaging/heidisql.wxi.in b/win/packaging/heidisql.wxi.in index 4f07a07627c..1d5c4430cd2 100644 --- a/win/packaging/heidisql.wxi.in +++ b/win/packaging/heidisql.wxi.in @@ -45,14 +45,20 @@ - - + + + + + + + + @@ -70,8 +76,10 @@ - + + + From e0f48e5ce9e77711f6d8cc1397bc32e0bd3edc33 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 3 Nov 2016 16:21:48 +0000 Subject: [PATCH 04/21] MDEV-11214 Windows : MSI installation fails, if run by a service user (e.g LocalSystem) Skip permission for data directory for LogonUser, if installation runs by one of the service accounts (determined from their well-known SID). There is no real LogonUser in this case. --- win/packaging/extra.wxs.in | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/win/packaging/extra.wxs.in b/win/packaging/extra.wxs.in index b716bbf7e88..f60c0bb2020 100644 --- a/win/packaging/extra.wxs.in +++ b/win/packaging/extra.wxs.in @@ -463,9 +463,24 @@ + + + + + + + + + "S-1-5-18") AND (UserSID <> "S-1-5-19") AND (UserSID <> "S-1-5-20") ]]> + + - From 10aee66896a127da599a91f389820937cb4ba832 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 10 Nov 2016 23:47:42 +0000 Subject: [PATCH 05/21] MDEV-11248 Fix passing offset parameter to my_file_pread in read_ddl_log_file_entry --- sql/sql_table.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 2cd36ceb4de..1936cbc56f8 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -684,8 +684,8 @@ static bool read_ddl_log_file_entry(uchar *file_entry_buf, DBUG_ENTER("read_ddl_log_file_entry"); DBUG_ASSERT(io_size >= size); - if (mysql_file_pread(file_id, file_entry_buf, size, io_size * entry_no, - MYF(MY_WME)) != size) + if (mysql_file_pread(file_id, file_entry_buf, size, ((my_off_t)io_size) * entry_no, + MYF(MY_FNABP)) != size) error= TRUE; DBUG_RETURN(error); } From 96b62b55149a9297f32c3aad99ece613cc3f788f Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 11 Nov 2016 20:55:03 -0800 Subject: [PATCH 06/21] Fixed bug mdev-11161. The flag TABLE_LIST::fill_me must be reset to false at the prepare phase for any materialized derived table used in the executed query. Otherwise if the optimizer decides to generate a key for such a table it is generated only for the first execution of the query. --- mysql-test/r/derived_view.result | 83 ++++++++++++++++++++++++++++++++ mysql-test/t/derived_view.test | 54 +++++++++++++++++++++ sql/sql_derived.cc | 2 + 3 files changed, 139 insertions(+) diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result index 230660f2fcf..d993086299e 100644 --- a/mysql-test/r/derived_view.result +++ b/mysql-test/r/derived_view.result @@ -2496,5 +2496,88 @@ DROP TABLE t1,t2; # # end of 5.3 tests # +# +# Bug mdev-11161: The second execution of prepared statement +# does not use generated key for materialized +# derived table / view +# (actually this is a 5.3 bug.) +# +create table t1 ( +mat_id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, +matintnum CHAR(6) NOT NULL, +test MEDIUMINT UNSIGNED NULL +); +create table t2 ( +mat_id MEDIUMINT UNSIGNED NOT NULL, +pla_id MEDIUMINT UNSIGNED NOT NULL +); +insert into t1 values +(NULL, 'a', 1), (NULL, 'b', 2), (NULL, 'c', 3), (NULL, 'd', 4), +(NULL, 'e', 5), (NULL, 'f', 6), (NULL, 'g', 7), (NULL, 'h', 8), +(NULL, 'i', 9); +insert into t2 values +(1, 100), (1, 101), (1, 102), (2, 100), (2, 103), (2, 104), +(3, 101), (3, 102), (3, 105); +explain +SELECT STRAIGHT_JOIN d.pla_id, m2.mat_id +FROM t1 m2 +INNER JOIN +(SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum +FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id +GROUP BY mp.pla_id) d +ON d.matintnum=m2.matintnum; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY m2 ALL NULL NULL NULL NULL 9 +1 PRIMARY ref key0 key0 7 test.m2.matintnum 2 +2 DERIVED mp ALL NULL NULL NULL NULL 9 Using temporary; Using filesort +2 DERIVED m1 eq_ref PRIMARY PRIMARY 3 test.mp.mat_id 1 +prepare stmt1 from +"SELECT STRAIGHT_JOIN d.pla_id, m2.mat_id + FROM t1 m2 + INNER JOIN + (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum + FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id + GROUP BY mp.pla_id) d + ON d.matintnum=m2.matintnum"; +flush status; +execute stmt1; +pla_id mat_id +102 1 +101 1 +100 1 +104 2 +103 2 +105 3 +show status like '%Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 21 +Handler_read_last 0 +Handler_read_next 6 +Handler_read_prev 0 +Handler_read_rnd 6 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 27 +flush status; +execute stmt1; +pla_id mat_id +102 1 +101 1 +100 1 +104 2 +103 2 +105 3 +show status like '%Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 21 +Handler_read_last 0 +Handler_read_next 6 +Handler_read_prev 0 +Handler_read_rnd 6 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 27 +deallocate prepare stmt1; +drop table t1,t2; set optimizer_switch=@exit_optimizer_switch; set join_cache_level=@exit_join_cache_level; diff --git a/mysql-test/t/derived_view.test b/mysql-test/t/derived_view.test index 67899837bb2..d017f847af9 100644 --- a/mysql-test/t/derived_view.test +++ b/mysql-test/t/derived_view.test @@ -1827,6 +1827,60 @@ DROP TABLE t1,t2; --echo # end of 5.3 tests --echo # +--echo # +--echo # Bug mdev-11161: The second execution of prepared statement +--echo # does not use generated key for materialized +--echo # derived table / view +--echo # (actually this is a 5.3 bug.) +--echo # + +create table t1 ( + mat_id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + matintnum CHAR(6) NOT NULL, + test MEDIUMINT UNSIGNED NULL +); +create table t2 ( + mat_id MEDIUMINT UNSIGNED NOT NULL, + pla_id MEDIUMINT UNSIGNED NOT NULL +); +insert into t1 values + (NULL, 'a', 1), (NULL, 'b', 2), (NULL, 'c', 3), (NULL, 'd', 4), + (NULL, 'e', 5), (NULL, 'f', 6), (NULL, 'g', 7), (NULL, 'h', 8), + (NULL, 'i', 9); +insert into t2 values + (1, 100), (1, 101), (1, 102), (2, 100), (2, 103), (2, 104), + (3, 101), (3, 102), (3, 105); + +explain + SELECT STRAIGHT_JOIN d.pla_id, m2.mat_id + FROM t1 m2 + INNER JOIN + (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum + FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id + GROUP BY mp.pla_id) d + ON d.matintnum=m2.matintnum; + +prepare stmt1 from +"SELECT STRAIGHT_JOIN d.pla_id, m2.mat_id + FROM t1 m2 + INNER JOIN + (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum + FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id + GROUP BY mp.pla_id) d + ON d.matintnum=m2.matintnum"; + +flush status; +execute stmt1; +show status like '%Handler_read%'; + +flush status; +execute stmt1; +show status like '%Handler_read%'; + +deallocate prepare stmt1; + +drop table t1,t2; + # The following command must be the last one the file set optimizer_switch=@exit_optimizer_switch; set join_cache_level=@exit_join_cache_level; diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index c6865a7116e..44395599961 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -651,6 +651,8 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) unit->derived= derived; + derived->fill_me= FALSE; + if (!(derived->derived_result= new select_union)) DBUG_RETURN(TRUE); // out of memory From adc38ed81140701f89b40b3356b5fb7f9587c2b7 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 14 Nov 2016 08:02:35 +0100 Subject: [PATCH 07/21] Restore MY_WME flag for my_pread in read_ddl_log_entry, fix errors in buildbot --- sql/sql_table.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 1936cbc56f8..7d2e67b5cfd 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -685,7 +685,7 @@ static bool read_ddl_log_file_entry(uchar *file_entry_buf, DBUG_ASSERT(io_size >= size); if (mysql_file_pread(file_id, file_entry_buf, size, ((my_off_t)io_size) * entry_no, - MYF(MY_FNABP)) != size) + MYF(MY_WME)) != size) error= TRUE; DBUG_RETURN(error); } From 9976223c0063944a7fb598b8e22512a35c841f67 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 28 Nov 2016 17:28:37 +0400 Subject: [PATCH 08/21] MDEV-11171 Assertion `m_cpp_buf <= ptr && ptr <= m_cpp_buf + m_buf_length' failed in Lex_input_stream::body_utf8_append(const char*, const char*) --- mysql-test/r/parser.result | 9 +++++++++ mysql-test/t/parser.test | 10 ++++++++++ sql/sql_lex.cc | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result index 25143f97d9a..9a14c0e324b 100644 --- a/mysql-test/r/parser.result +++ b/mysql-test/r/parser.result @@ -663,3 +663,12 @@ select 1<!0, 2 > ! 0; select 0<=!0, 0 <= !0; select 1<yyGet() == 'N') + if (!lip->eof() && lip->yyGet() == 'N') { // Allow \N as shortcut for NULL yylval->lex_str.str=(char*) "\\N"; yylval->lex_str.length=2; From f640527e65cf83b5bfbc09df3c72813c1ca67d8d Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 2 Dec 2016 15:22:11 +0100 Subject: [PATCH 09/21] typo fixed: s/MSYQL/MYSQL/ --- mysql-test/suite/binlog/r/binlog_index.result | 6 +++--- mysql-test/suite/binlog/t/binlog_index.test | 6 +++--- mysql-test/suite/rpl/r/rpl_binlog_errors.result | 4 ++-- mysql-test/suite/rpl/t/rpl_binlog_errors.test | 4 ++-- sql/log.cc | 14 +++++++------- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/mysql-test/suite/binlog/r/binlog_index.result b/mysql-test/suite/binlog/r/binlog_index.result index ca92cc5398b..35a86f479cc 100644 --- a/mysql-test/suite/binlog/r/binlog_index.result +++ b/mysql-test/suite/binlog/r/binlog_index.result @@ -1,9 +1,9 @@ call mtr.add_suppression('Attempting backtrace'); -call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to process registered files that would be purged.'); -call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file'); +call mtr.add_suppression('MYSQL_BIN_LOG::purge_logs failed to process registered files that would be purged.'); +call mtr.add_suppression('MYSQL_BIN_LOG::open failed to sync the index file'); call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.'); call mtr.add_suppression('Could not open .*'); -call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.'); +call mtr.add_suppression('MYSQL_BIN_LOG::purge_logs failed to clean registers before purging logs.'); flush tables; RESET MASTER; flush logs; diff --git a/mysql-test/suite/binlog/t/binlog_index.test b/mysql-test/suite/binlog/t/binlog_index.test index a264549ce17..09e817c0469 100644 --- a/mysql-test/suite/binlog/t/binlog_index.test +++ b/mysql-test/suite/binlog/t/binlog_index.test @@ -9,11 +9,11 @@ source include/have_debug.inc; # Avoid CrashReporter popup on Mac --source include/not_crashrep.inc call mtr.add_suppression('Attempting backtrace'); -call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to process registered files that would be purged.'); -call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file'); +call mtr.add_suppression('MYSQL_BIN_LOG::purge_logs failed to process registered files that would be purged.'); +call mtr.add_suppression('MYSQL_BIN_LOG::open failed to sync the index file'); call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.'); call mtr.add_suppression('Could not open .*'); -call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.'); +call mtr.add_suppression('MYSQL_BIN_LOG::purge_logs failed to clean registers before purging logs.'); flush tables; let $old=`select @@debug`; diff --git a/mysql-test/suite/rpl/r/rpl_binlog_errors.result b/mysql-test/suite/rpl/r/rpl_binlog_errors.result index ddafbca0672..a71dcdfb1be 100644 --- a/mysql-test/suite/rpl/r/rpl_binlog_errors.result +++ b/mysql-test/suite/rpl/r/rpl_binlog_errors.result @@ -169,7 +169,7 @@ count(*) SET SQL_LOG_BIN=1; SET GLOBAL debug_dbug="-d,error_unique_log_filename"; ###################### TEST #10 -call mtr.add_suppression("MSYQL_BIN_LOG::open failed to sync the index file."); +call mtr.add_suppression("MYSQL_BIN_LOG::open failed to sync the index file."); call mtr.add_suppression("Could not open .*"); RESET MASTER; SHOW WARNINGS; @@ -226,7 +226,7 @@ include/rpl_reset.inc call mtr.add_suppression("Slave I/O: Relay log write failure: could not queue event from master.*"); call mtr.add_suppression("Error writing file .*"); call mtr.add_suppression("Could not open .*"); -call mtr.add_suppression("MSYQL_BIN_LOG::open failed to sync the index file."); +call mtr.add_suppression("MYSQL_BIN_LOG::open failed to sync the index file."); call mtr.add_suppression("Can't generate a unique log-filename .*"); ###################### TEST #13 SET @old_debug=@@global.debug; diff --git a/mysql-test/suite/rpl/t/rpl_binlog_errors.test b/mysql-test/suite/rpl/t/rpl_binlog_errors.test index 9e4a106a5b5..fb3b39fac9d 100644 --- a/mysql-test/suite/rpl/t/rpl_binlog_errors.test +++ b/mysql-test/suite/rpl/t/rpl_binlog_errors.test @@ -256,7 +256,7 @@ SET GLOBAL debug_dbug="-d,error_unique_log_filename"; ### while registering the index file and the binary log ### file or failure to write the rotate event. -call mtr.add_suppression("MSYQL_BIN_LOG::open failed to sync the index file."); +call mtr.add_suppression("MYSQL_BIN_LOG::open failed to sync the index file."); call mtr.add_suppression("Could not open .*"); RESET MASTER; @@ -362,7 +362,7 @@ RESET MASTER; call mtr.add_suppression("Slave I/O: Relay log write failure: could not queue event from master.*"); call mtr.add_suppression("Error writing file .*"); call mtr.add_suppression("Could not open .*"); -call mtr.add_suppression("MSYQL_BIN_LOG::open failed to sync the index file."); +call mtr.add_suppression("MYSQL_BIN_LOG::open failed to sync the index file."); call mtr.add_suppression("Can't generate a unique log-filename .*"); -- echo ###################### TEST #13 diff --git a/sql/log.cc b/sql/log.cc index bb8f06c80f7..077bbf5e711 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -3059,7 +3059,7 @@ bool MYSQL_BIN_LOG::open(const char *log_name, if (init_and_set_log_file_name(log_name, new_name, log_type_arg, io_cache_type_arg)) { - sql_print_error("MSYQL_BIN_LOG::open failed to generate new file name."); + sql_print_error("MYSQL_BIN_LOG::open failed to generate new file name."); DBUG_RETURN(1); } @@ -3086,7 +3086,7 @@ bool MYSQL_BIN_LOG::open(const char *log_name, } }); - sql_print_error("MSYQL_BIN_LOG::open failed to sync the index file."); + sql_print_error("MYSQL_BIN_LOG::open failed to sync the index file."); DBUG_RETURN(1); } DBUG_EXECUTE_IF("crash_create_non_critical_before_update_index", DBUG_SUICIDE();); @@ -3849,14 +3849,14 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log, if ((error= sync_purge_index_file())) { - sql_print_error("MSYQL_BIN_LOG::purge_logs failed to flush register file."); + sql_print_error("MYSQL_BIN_LOG::purge_logs failed to flush register file."); goto err; } /* We know how many files to delete. Update index file. */ if ((error=update_log_index(&log_info, need_update_threads))) { - sql_print_error("MSYQL_BIN_LOG::purge_logs failed to update the index file"); + sql_print_error("MYSQL_BIN_LOG::purge_logs failed to update the index file"); goto err; } @@ -3866,7 +3866,7 @@ err: /* Read each entry from purge_index_file and delete the file. */ if (is_inited_purge_index_file() && (error= purge_index_entry(thd, reclaimed_space, FALSE))) - sql_print_error("MSYQL_BIN_LOG::purge_logs failed to process registered files" + sql_print_error("MYSQL_BIN_LOG::purge_logs failed to process registered files" " that would be purged."); close_purge_index_file(); @@ -3983,7 +3983,7 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *reclaimed_space, if ((error=reinit_io_cache(&purge_index_file, READ_CACHE, 0, 0, 0))) { - sql_print_error("MSYQL_BIN_LOG::purge_index_entry failed to reinit register file " + sql_print_error("MYSQL_BIN_LOG::purge_index_entry failed to reinit register file " "for read"); goto err; } @@ -3998,7 +3998,7 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *reclaimed_space, if (purge_index_file.error) { error= purge_index_file.error; - sql_print_error("MSYQL_BIN_LOG::purge_index_entry error %d reading from " + sql_print_error("MYSQL_BIN_LOG::purge_index_entry error %d reading from " "register file.", error); goto err; } From 0a4b508173a0cd32f329df3514bf34c2f2001317 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 1 Dec 2016 20:04:36 +0100 Subject: [PATCH 10/21] MDEV-11242 MariaDB Server releases contains promotion of MariaDB Corporation --- scripts/mysql_install_db.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 5d53b252fd7..aefcc1a8384 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -512,10 +512,8 @@ then echo "The latest information about MariaDB is available at http://mariadb.org/." echo "You can find additional information about the MySQL part at:" echo "http://dev.mysql.com" - echo "Support MariaDB development by buying support/new features from MariaDB" - echo "Corporation Ab. You can contact us about this at sales@mariadb.com." - echo "Alternatively consider joining our community based development effort:" - echo "http://mariadb.com/kb/en/contributing-to-the-mariadb-project/" + echo "Consider joining MariaDB's strong and vibrant community:" + echo "https://mariadb.org/get-involved/" echo fi From 4a3acbcfd07291ecc141f37200eec79eb1713882 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 2 Dec 2016 00:19:49 +0100 Subject: [PATCH 11/21] MDEV-11241 Certain combining marks cause MariaDB to crash when doing Full-Text searches Don't assume that a word of n bytes can match a word of at most n * charset->mbmaxlen bytes, always go for the worst. --- mysql-test/r/fulltext_charsets.result | 7 +++++++ mysql-test/t/fulltext_charsets.test | 10 ++++++++++ storage/myisam/ft_boolean_search.c | 7 +------ 3 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 mysql-test/r/fulltext_charsets.result create mode 100644 mysql-test/t/fulltext_charsets.test diff --git a/mysql-test/r/fulltext_charsets.result b/mysql-test/r/fulltext_charsets.result new file mode 100644 index 00000000000..39ce02a3fce --- /dev/null +++ b/mysql-test/r/fulltext_charsets.result @@ -0,0 +1,7 @@ +set names utf8mb4; +create table t1 (a int, b text, fulltext (b)) charset=utf8mb4 collate=utf8mb4_unicode_ci; +insert t1 values (1000, 'C͓̙̯͔̩ͅͅi̩̘̜̲a̯̲̬̳̜̖̤o͕͓̜͓̺̖̗,̠̬͚ ̺T͇̲h͈̱e ̬̜D̖o̦̖͔̗͖̩̘c̣̼t̝͉̫̮̗o͉̫̭r̙͎̗.͓̪̥'); +select a from t1 where match(b) against ('ciao' in boolean mode); +a +1000 +drop table t1; diff --git a/mysql-test/t/fulltext_charsets.test b/mysql-test/t/fulltext_charsets.test new file mode 100644 index 00000000000..3ac9791bd1a --- /dev/null +++ b/mysql-test/t/fulltext_charsets.test @@ -0,0 +1,10 @@ +# +# MDEV-11241 Certain combining marks cause MariaDB to crash when doing Full-Text searches +# +set names utf8mb4; + +create table t1 (a int, b text, fulltext (b)) charset=utf8mb4 collate=utf8mb4_unicode_ci; +insert t1 values (1000, 'C͓̙̯͔̩ͅͅi̩̘̜̲a̯̲̬̳̜̖̤o͕͓̜͓̺̖̗,̠̬͚ ̺T͇̲h͈̱e ̬̜D̖o̦̖͔̗͖̩̘c̣̼t̝͉̫̮̗o͉̫̭r̙͎̗.͓̪̥'); +select a from t1 where match(b) against ('ciao' in boolean mode); +drop table t1; + diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c index b67f1ea6a25..16432d0161c 100644 --- a/storage/myisam/ft_boolean_search.c +++ b/storage/myisam/ft_boolean_search.c @@ -195,12 +195,7 @@ static int ftb_query_add_word(MYSQL_FTPARSER_PARAM *param, switch (info->type) { case FT_TOKEN_WORD: ftbw= (FTB_WORD *)alloc_root(&ftb_param->ftb->mem_root, - sizeof(FTB_WORD) + - (info->trunc ? HA_MAX_KEY_BUFF : - (word_len + 1) * - ftb_param->ftb->charset->mbmaxlen + - HA_FT_WLEN + - ftb_param->ftb->info->s->rec_reflength)); + sizeof(FTB_WORD) + HA_MAX_KEY_BUFF); ftbw->len= word_len + 1; ftbw->flags= 0; ftbw->off= 0; From 02d153c7b9739ce4c2445805aeaf4b185c6ac6f0 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 26 Jun 2016 13:37:27 +0200 Subject: [PATCH 12/21] str2decimal: don't return a negative zero --- mysql-test/r/type_decimal.result | 5 +++-- mysql-test/t/type_decimal.test | 5 +++++ storage/tokudb/mysql-test/tokudb/r/type_decimal.result | 2 -- strings/decimal.c | 2 ++ 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result index cde8816dee4..7ff74c8270a 100644 --- a/mysql-test/r/type_decimal.result +++ b/mysql-test/r/type_decimal.result @@ -221,7 +221,6 @@ drop table t1; create table t1 (a decimal(10,2) unsigned); insert into t1 values ("0.0"),("-0.0"),("+0.0"),("01.0"),("+01.0"),("-01.0"); Warnings: -Warning 1264 Out of range value for column 'a' at row 2 Warning 1264 Out of range value for column 'a' at row 6 insert into t1 values ("-.1"),("+.1"),(".1"); Warnings: @@ -280,7 +279,6 @@ drop table t1; create table t1 (a decimal(10,2) zerofill); insert into t1 values ("0.0"),("-0.0"),("+0.0"),("01.0"),("+01.0"),("-01.0"); Warnings: -Warning 1264 Out of range value for column 'a' at row 2 Warning 1264 Out of range value for column 'a' at row 6 insert into t1 values ("-.1"),("+.1"),(".1"); Warnings: @@ -1012,6 +1010,9 @@ SELECT COLUMN_NAME, DATA_TYPE, COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME DATA_TYPE COLUMN_TYPE a decimal decimal(10,2)/*old*/ DROP TABLE t1dec102; +select cast('-0.0' as decimal(5,1)) < 0; +cast('-0.0' as decimal(5,1)) < 0 +0 # # End of 5.5 tests # diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test index 659e75270ca..834fd0c5327 100644 --- a/mysql-test/t/type_decimal.test +++ b/mysql-test/t/type_decimal.test @@ -604,6 +604,11 @@ SHOW COLUMNS FROM t1dec102; SELECT COLUMN_NAME, DATA_TYPE, COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1dec102'; DROP TABLE t1dec102; +# +# MDEV-10552 equality operation on cast of the value "-0.0" to decimal not working +# +select cast('-0.0' as decimal(5,1)) < 0; + --echo # --echo # End of 5.5 tests --echo # diff --git a/storage/tokudb/mysql-test/tokudb/r/type_decimal.result b/storage/tokudb/mysql-test/tokudb/r/type_decimal.result index 5d271bc73fa..4540c24238b 100644 --- a/storage/tokudb/mysql-test/tokudb/r/type_decimal.result +++ b/storage/tokudb/mysql-test/tokudb/r/type_decimal.result @@ -222,7 +222,6 @@ drop table t1; create table t1 (a decimal(10,2) unsigned); insert into t1 values ("0.0"),("-0.0"),("+0.0"),("01.0"),("+01.0"),("-01.0"); Warnings: -Warning 1264 Out of range value for column 'a' at row 2 Warning 1264 Out of range value for column 'a' at row 6 insert into t1 values ("-.1"),("+.1"),(".1"); Warnings: @@ -281,7 +280,6 @@ drop table t1; create table t1 (a decimal(10,2) zerofill); insert into t1 values ("0.0"),("-0.0"),("+0.0"),("01.0"),("+01.0"),("-01.0"); Warnings: -Warning 1264 Out of range value for column 'a' at row 2 Warning 1264 Out of range value for column 'a' at row 6 insert into t1 values ("-.1"),("+.1"),(".1"); Warnings: diff --git a/strings/decimal.c b/strings/decimal.c index b0c57d3db0c..3d90a58ea8a 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -928,6 +928,8 @@ internal_str2dec(const char *from, decimal_t *to, char **end, my_bool fixed) error= decimal_shift(to, (int) exponent); } } + if (to->sign && decimal_is_zero(to)) + to->sign= 0; return error; fatal_error: From 18cdff6765b954431934f6e6d0b1e281c8f0e0b8 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 4 Dec 2016 12:37:01 +0100 Subject: [PATCH 13/21] MDEV-10293 'setupterm' was not declared in this scope Check for readline before checking for curses headers, because MYSQL_CHECK_READLINE fails when curses is not found, but CHECK_INCLUDE_FILES simply remembers the fact and continues. So if there's no curses, MYSQL_CHECK_READLINE will abort, the user will then installs curses and continue the build. Thus, CHECK_INCLUDE_HEADERS will remember that there is no curses, but other checks from MYSQL_CHECK_READLINE will remember that curses are there. It will result in inconsistent HAVE_xxx defines. --- cmake/readline.cmake | 1 + configure.cmake | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/readline.cmake b/cmake/readline.cmake index c72f8d0da5c..64e04ef8663 100644 --- a/cmake/readline.cmake +++ b/cmake/readline.cmake @@ -230,5 +230,6 @@ MACRO (MYSQL_CHECK_READLINE) SET(CMAKE_REQUIRED_LIBRARIES) SET(CMAKE_REQUIRED_INCLUDES) ENDIF(NOT WIN32) + CHECK_INCLUDE_FILES ("curses.h;term.h" HAVE_TERM_H) ENDMACRO() diff --git a/configure.cmake b/configure.cmake index f0517bfa41e..4051b553747 100644 --- a/configure.cmake +++ b/configure.cmake @@ -237,7 +237,6 @@ CHECK_INCLUDE_FILES (sys/socket.h HAVE_SYS_SOCKET_H) CHECK_INCLUDE_FILES (sys/stat.h HAVE_SYS_STAT_H) CHECK_INCLUDE_FILES (sys/stream.h HAVE_SYS_STREAM_H) CHECK_INCLUDE_FILES (sys/termcap.h HAVE_SYS_TERMCAP_H) -CHECK_INCLUDE_FILES ("curses.h;term.h" HAVE_TERM_H) CHECK_INCLUDE_FILES (asm/termbits.h HAVE_ASM_TERMBITS_H) CHECK_INCLUDE_FILES (termbits.h HAVE_TERMBITS_H) CHECK_INCLUDE_FILES (termios.h HAVE_TERMIOS_H) From 46dee0d1848e24e39fc236e78a438efa22356f8d Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 5 Dec 2016 16:50:12 +0400 Subject: [PATCH 14/21] MDEV-10717 Assertion `!null_value' failed in virtual bool Item::send(Protocol*, String*) The problem was that null_value was not set to "false" on a well-formed row. If an ill-formed row was followed by a well-forned row, null_value remained "true" in the call of Item::send() for the well-formed row. --- mysql-test/r/ctype_utf8.result | 26 ++++++++++++++++++++++++++ mysql-test/t/ctype_utf8.test | 14 ++++++++++++++ sql/item.cc | 1 + 3 files changed, 41 insertions(+) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 121168c2a2a..294c2cb2be1 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -5869,5 +5869,31 @@ SELECT length(data) AS len FROM (SELECT REPEAT('ä', 65537) AS data) AS sub; len 131074 # +# MDEV-10717 Assertion `!null_value' failed in virtual bool Item::send(Protocol*, String*) +# +CREATE TABLE t1 (i INT, KEY(i)); +INSERT INTO t1 VALUES (20081205),(20050327); +SELECT HEX(i), HEX(CHAR(i USING utf8)) FROM t1; +HEX(i) HEX(CHAR(i USING utf8)) +131F197 0131 +1326A35 01326A35 +Warnings: +Warning 1300 Invalid utf8 character string: 'F197' +SET sql_mode='STRICT_ALL_TABLES'; +SELECT HEX(i), HEX(CHAR(i USING utf8)) FROM t1; +HEX(i) HEX(CHAR(i USING utf8)) +131F197 NULL +1326A35 01326A35 +Warnings: +Warning 1300 Invalid utf8 character string: 'F197' +SELECT CHAR(i USING utf8) FROM t1; +CHAR(i USING utf8) +### +### +Warnings: +### 1300 Invalid utf8 character string: 'F197' +SET sql_mode=DEFAULT; +DROP TABLE t1; +# # End of 5.5 tests # diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index d6fdc6c6a2c..75581ede8fa 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1681,6 +1681,20 @@ 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; SELECT length(data) AS len FROM (SELECT REPEAT('ä', 65537) AS data) AS sub; +--echo # +--echo # MDEV-10717 Assertion `!null_value' failed in virtual bool Item::send(Protocol*, String*) +--echo # +CREATE TABLE t1 (i INT, KEY(i)); +INSERT INTO t1 VALUES (20081205),(20050327); +SELECT HEX(i), HEX(CHAR(i USING utf8)) FROM t1; +SET sql_mode='STRICT_ALL_TABLES'; +SELECT HEX(i), HEX(CHAR(i USING utf8)) FROM t1; +# Avoid garbage in the output +--replace_column 1 ### +SELECT CHAR(i USING utf8) FROM t1; +SET sql_mode=DEFAULT; +DROP TABLE t1; + --echo # --echo # End of 5.5 tests --echo # diff --git a/sql/item.cc b/sql/item.cc index 3448b236640..ede1df6aa9b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -5743,6 +5743,7 @@ String *Item::check_well_formed_result(String *str, bool send_error) uint wlen= cs->cset->well_formed_len(cs, str->ptr(), str->ptr() + str->length(), str->length(), &well_formed_error); + null_value= false; if (wlen < str->length()) { THD *thd= current_thd; From f988bcecfde819d3d3d2d7227789491fcc0ee430 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 21 Sep 2016 18:36:34 +0200 Subject: [PATCH 15/21] MDEV-10776: Server crash on query Exclude untouched in prepare phese subqueries from the select/unit tree because they became unreachable by execution. --- mysql-test/r/subselect.result | 11 +++++++++++ mysql-test/r/subselect_no_mat.result | 11 +++++++++++ mysql-test/r/subselect_no_opts.result | 11 +++++++++++ mysql-test/r/subselect_no_scache.result | 11 +++++++++++ mysql-test/r/subselect_no_semijoin.result | 11 +++++++++++ mysql-test/t/subselect.test | 14 ++++++++++++++ sql/item_subselect.cc | 22 +++++++++++++++++++--- sql/sql_lex.cc | 20 ++++++++++++++++++-- 8 files changed, 106 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 16ab4cf9d82..0a599a64f80 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -7094,3 +7094,14 @@ a 0 DROP TABLE t1; SET SESSION big_tables=0; +# +# MDEV-10776: Server crash on query +# +create table t1 (field1 int); +insert into t1 values (1); +select round((select 1 from t1 limit 1)) +from t1 +group by round((select 1 from t1 limit 1)); +round((select 1 from t1 limit 1)) +1 +drop table t1; diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result index aed4fb39a84..b819b1e4ef9 100644 --- a/mysql-test/r/subselect_no_mat.result +++ b/mysql-test/r/subselect_no_mat.result @@ -7091,6 +7091,17 @@ a 0 DROP TABLE t1; SET SESSION big_tables=0; +# +# MDEV-10776: Server crash on query +# +create table t1 (field1 int); +insert into t1 values (1); +select round((select 1 from t1 limit 1)) +from t1 +group by round((select 1 from t1 limit 1)); +round((select 1 from t1 limit 1)) +1 +drop table t1; set optimizer_switch=default; select @@optimizer_switch like '%materialization=on%'; @@optimizer_switch like '%materialization=on%' diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result index e1f08537788..e1001a51658 100644 --- a/mysql-test/r/subselect_no_opts.result +++ b/mysql-test/r/subselect_no_opts.result @@ -7089,4 +7089,15 @@ a 0 DROP TABLE t1; SET SESSION big_tables=0; +# +# MDEV-10776: Server crash on query +# +create table t1 (field1 int); +insert into t1 values (1); +select round((select 1 from t1 limit 1)) +from t1 +group by round((select 1 from t1 limit 1)); +round((select 1 from t1 limit 1)) +1 +drop table t1; set @optimizer_switch_for_subselect_test=null; diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result index b5fa7b1dd8f..e175e7e0072 100644 --- a/mysql-test/r/subselect_no_scache.result +++ b/mysql-test/r/subselect_no_scache.result @@ -7100,6 +7100,17 @@ a 0 DROP TABLE t1; SET SESSION big_tables=0; +# +# MDEV-10776: Server crash on query +# +create table t1 (field1 int); +insert into t1 values (1); +select round((select 1 from t1 limit 1)) +from t1 +group by round((select 1 from t1 limit 1)); +round((select 1 from t1 limit 1)) +1 +drop table t1; set optimizer_switch=default; select @@optimizer_switch like '%subquery_cache=on%'; @@optimizer_switch like '%subquery_cache=on%' diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result index b815559433c..a211d498762 100644 --- a/mysql-test/r/subselect_no_semijoin.result +++ b/mysql-test/r/subselect_no_semijoin.result @@ -7089,5 +7089,16 @@ a 0 DROP TABLE t1; SET SESSION big_tables=0; +# +# MDEV-10776: Server crash on query +# +create table t1 (field1 int); +insert into t1 values (1); +select round((select 1 from t1 limit 1)) +from t1 +group by round((select 1 from t1 limit 1)); +round((select 1 from t1 limit 1)) +1 +drop table t1; set @optimizer_switch_for_subselect_test=null; set @join_cache_level_for_subselect_test=NULL; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index b802761aff3..77b6c6c5582 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -5974,3 +5974,17 @@ INSERT INTO t1 VALUES(0),(0),(0); SELECT * FROM t1 WHERE a IN(SELECT MIN(a) FROM t1); DROP TABLE t1; SET SESSION big_tables=0; + + +--echo # +--echo # MDEV-10776: Server crash on query +--echo # +create table t1 (field1 int); + +insert into t1 values (1); + +select round((select 1 from t1 limit 1)) +from t1 +group by round((select 1 from t1 limit 1)); + +drop table t1; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 3727711a395..6427b0ecae4 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -209,6 +209,7 @@ bool Item_subselect::select_transformer(JOIN *join) { DBUG_ENTER("Item_subselect::select_transformer"); + DBUG_ASSERT(thd == join->thd); DBUG_RETURN(false); } @@ -579,7 +580,7 @@ bool Item_subselect::is_expensive() examined_rows+= cur_join->get_examined_rows(); } - + // here we are sure that subquery is optimized so thd is set return (examined_rows > thd->variables.expensive_subquery_limit); } @@ -643,6 +644,7 @@ bool Item_subselect::exec() subselect_engine *org_engine= engine; DBUG_ENTER("Item_subselect::exec"); + DBUG_ASSERT(fixed); /* Do not execute subselect in case of a fatal error @@ -688,6 +690,7 @@ int Item_in_subselect::optimize(double *out_rows, double *cost) { int res; DBUG_ENTER("Item_in_subselect::optimize"); + DBUG_ASSERT(fixed); SELECT_LEX *save_select= thd->lex->current_select; JOIN *join= unit->first_select()->join; @@ -802,6 +805,7 @@ bool Item_in_subselect::expr_cache_is_needed(THD *thd) bool Item_in_subselect::exec() { DBUG_ENTER("Item_in_subselect::exec"); + DBUG_ASSERT(fixed); /* Initialize the cache of the left predicate operand. This has to be done as late as now, because Cached_item directly contains a resolved field (not @@ -856,6 +860,7 @@ table_map Item_subselect::used_tables() const bool Item_subselect::const_item() const { + DBUG_ASSERT(thd); return (thd->lex->context_analysis_only ? FALSE : forced_const || const_item_cache); @@ -1049,10 +1054,11 @@ Item_singlerow_subselect::select_transformer(JOIN *join) DBUG_ENTER("Item_singlerow_subselect::select_transformer"); if (changed) DBUG_RETURN(false); + DBUG_ASSERT(join->thd == thd); SELECT_LEX *select_lex= join->select_lex; Query_arena *arena= thd->stmt_arena; - + if (!select_lex->master_unit()->is_union() && !select_lex->table_list.elements && select_lex->item_list.elements == 1 && @@ -1717,6 +1723,7 @@ Item_in_subselect::single_value_transformer(JOIN *join) { SELECT_LEX *select_lex= join->select_lex; DBUG_ENTER("Item_in_subselect::single_value_transformer"); + DBUG_ASSERT(thd == join->thd); /* Check that the right part of the subselect contains no more than one @@ -1829,9 +1836,9 @@ bool Item_allany_subselect::transform_into_max_min(JOIN *join) if (!test_strategy(SUBS_MAXMIN_INJECTED | SUBS_MAXMIN_ENGINE)) DBUG_RETURN(false); Item **place= optimizer->arguments() + 1; - THD *thd= join->thd; SELECT_LEX *select_lex= join->select_lex; Item *subs; + DBUG_ASSERT(thd == join->thd); /* */ @@ -1938,6 +1945,7 @@ bool Item_allany_subselect::transform_into_max_min(JOIN *join) bool Item_in_subselect::fix_having(Item *having, SELECT_LEX *select_lex) { bool fix_res= 0; + DBUG_ASSERT(thd); if (!having->fixed) { select_lex->having_fix_field= 1; @@ -2000,6 +2008,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, Item **having_item) { SELECT_LEX *select_lex= join->select_lex; + DBUG_ASSERT(thd == join->thd); /* The non-transformed HAVING clause of 'join' may be stored in two ways during JOIN::optimize: this->tmp_having= this->having; this->having= 0; @@ -2136,6 +2145,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) uint cols_num= left_expr->cols(); DBUG_ENTER("Item_in_subselect::row_value_transformer"); + DBUG_ASSERT(thd == join->thd); // psergey: duplicated_subselect_card_check if (select_lex->item_list.elements != cols_num) @@ -2248,6 +2258,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, !select_lex->table_list.elements); DBUG_ENTER("Item_in_subselect::create_row_in_to_exists_cond"); + DBUG_ASSERT(thd == join->thd); *where_item= NULL; *having_item= NULL; @@ -2473,6 +2484,7 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg) Item *having_item= join_arg->in_to_exists_having; DBUG_ENTER("Item_in_subselect::inject_in_to_exists_cond"); + DBUG_ASSERT(thd == join_arg->thd); if (where_item) { @@ -2561,6 +2573,7 @@ Item_in_subselect::select_in_like_transformer(JOIN *join) bool result; DBUG_ENTER("Item_in_subselect::select_in_like_transformer"); + DBUG_ASSERT(thd == join->thd); /* IN/SOME/ALL/ANY subqueries aren't support LIMIT clause. Without it @@ -2762,6 +2775,7 @@ bool Item_in_subselect::setup_mat_engine() subselect_single_select_engine *select_engine; DBUG_ENTER("Item_in_subselect::setup_mat_engine"); + DBUG_ASSERT(thd); /* The select_engine (that executes transformed IN=>EXISTS subselects) is @@ -2800,6 +2814,7 @@ bool Item_in_subselect::setup_mat_engine() bool Item_in_subselect::init_left_expr_cache() { JOIN *outer_join; + DBUG_ASSERT(thd); outer_join= unit->outer_select()->join; /* @@ -2826,6 +2841,7 @@ bool Item_in_subselect::init_left_expr_cache() bool Item_in_subselect::init_cond_guards() { + DBUG_ASSERT(thd); uint cols_num= left_expr->cols(); if (!abort_on_null && left_expr->maybe_null && !pushed_cond_guards) { diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 2462f0fea17..f2e7b4f7c3a 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3486,12 +3486,28 @@ bool st_select_lex::add_index_hint (THD *thd, char *str, uint length) bool st_select_lex::optimize_unflattened_subqueries(bool const_only) { - for (SELECT_LEX_UNIT *un= first_inner_unit(); un; un= un->next_unit()) + SELECT_LEX_UNIT *next_unit= NULL; + for (SELECT_LEX_UNIT *un= first_inner_unit(); + un; + un= next_unit ? next_unit : un->next_unit()) { Item_subselect *subquery_predicate= un->item; - + next_unit= NULL; + if (subquery_predicate) { + if (!subquery_predicate->fixed) + { + /* + This subquery was excluded as part of some expression so it is + invisible from all prepared expression. + */ + next_unit= un->next_unit(); + un->exclude_level(); + if (next_unit) + continue; + break; + } if (subquery_predicate->substype() == Item_subselect::IN_SUBS) { Item_in_subselect *in_subs= (Item_in_subselect*) subquery_predicate; From 035a5ac62a0215c2f6e3e363331e3e984d780138 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 26 Sep 2016 18:15:11 +0200 Subject: [PATCH 16/21] MDEV-10713: signal 11 error on multi-table update - crash in handler::increment_statistics or in make_select or assertion failure pfs_thread == ((PFS_thread*) pthread_getspecific((THR_PFS))) Move expression execution out of Item constructor. --- mysql-test/r/sp.result | 38 ++++++++++++++++++++++++++++++++ mysql-test/t/sp.test | 50 ++++++++++++++++++++++++++++++++++++++++++ sql/item_strfunc.cc | 14 +++++++++++- sql/item_strfunc.h | 28 ++++++++++------------- 4 files changed, 113 insertions(+), 17 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 6214fbcde35..d15031989bf 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -8016,4 +8016,42 @@ Warnings: Error 1329 No data - zero rows fetched, selected, or processed DROP PROCEDURE p1; DROP TABLE t1; +# +# MDEV-10713: signal 11 error on multi-table update - crash in +# handler::increment_statistics or in make_select or assertion +# failure pfs_thread == ((PFS_thread*) pthread_getspecific((THR_PFS))) +# +CREATE TABLE `t1` ( +`CLOSE_YN` varchar(10) COLLATE utf8_bin DEFAULT NULL +) DEFAULT CHARSET=utf8 COLLATE=utf8_bin ; +CREATE TABLE `t2` ( +`ap_close_to` varchar(8) COLLATE utf8_bin DEFAULT NULL +) DEFAULT CHARSET=utf8 COLLATE=utf8_bin ; +CREATE FUNCTION `f1`(`P_DC_CD` VARBINARY(50), `P_SYS_DATE` DATETIME) RETURNS datetime +DETERMINISTIC +SQL SECURITY INVOKER +BEGIN +DECLARE V_SYS_DATE DATETIME; +SELECT now() AS LOC_DATE INTO V_SYS_DATE ; +RETURN v_sys_date ; +END $$ +update t1 S +JOIN +( +SELECT CASE +WHEN DATE_FORMAT( f1('F01', NOW()) , '%Y%m%d') <= CLOSE_YMD +THEN '99991231' + ELSE '' END ACCOUNT_APPLY_YYYYMMDD +FROM ( +select case +when 'AP'='AP' + then ap_close_to +end AS CLOSE_YMD +from t2 +) A +) X +SET S.CLOSE_YN = '' +where 1=1; +drop function if exists f1; +drop table t1,t2; # End of 5.5 test diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index ecb12408654..b56ab6c3b11 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -9302,4 +9302,54 @@ CALL p1; DROP PROCEDURE p1; DROP TABLE t1; +--echo # +--echo # MDEV-10713: signal 11 error on multi-table update - crash in +--echo # handler::increment_statistics or in make_select or assertion +--echo # failure pfs_thread == ((PFS_thread*) pthread_getspecific((THR_PFS))) +--echo # + +CREATE TABLE `t1` ( + `CLOSE_YN` varchar(10) COLLATE utf8_bin DEFAULT NULL +) DEFAULT CHARSET=utf8 COLLATE=utf8_bin ; + + +CREATE TABLE `t2` ( + `ap_close_to` varchar(8) COLLATE utf8_bin DEFAULT NULL +) DEFAULT CHARSET=utf8 COLLATE=utf8_bin ; + + +--delimiter $$ + +CREATE FUNCTION `f1`(`P_DC_CD` VARBINARY(50), `P_SYS_DATE` DATETIME) RETURNS datetime + DETERMINISTIC + SQL SECURITY INVOKER +BEGIN + DECLARE V_SYS_DATE DATETIME; + SELECT now() AS LOC_DATE INTO V_SYS_DATE ; + RETURN v_sys_date ; +END $$ + +--delimiter ; + +update t1 S +JOIN +( + SELECT CASE + WHEN DATE_FORMAT( f1('F01', NOW()) , '%Y%m%d') <= CLOSE_YMD + THEN '99991231' + ELSE '' END ACCOUNT_APPLY_YYYYMMDD + FROM ( + select case + when 'AP'='AP' + then ap_close_to + end AS CLOSE_YMD + from t2 + ) A +) X +SET S.CLOSE_YN = '' +where 1=1; + +drop function if exists f1; +drop table t1,t2; + --echo # End of 5.5 test diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 94370d45cef..93e2edf9975 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2951,7 +2951,19 @@ String *Item_func_conv::val_str(String *str) String *Item_func_conv_charset::val_str(String *str) { DBUG_ASSERT(fixed == 1); - if (use_cached_value) + if (cached_value == CONST_WILL_BE_CACHED) + { + uint errors= 0; + String tmp, *str= args[0]->val_str(&tmp); + if (!str || str_value.copy(str->ptr(), str->length(), + str->charset(), conv_charset, &errors)) + null_value= 1; + cached_value= CACHED; + str_value.mark_as_const(); + safe= (errors == 0); + is_expensive_cache= 0; + } + if (cached_value == CACHED) return null_value ? 0 : &str_value; String *arg= args[0]->val_str(str); uint dummy_errors; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 7606c281548..459dc5af34e 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -817,31 +817,26 @@ public: class Item_func_conv_charset :public Item_str_func { - bool use_cached_value; String tmp_value; + enum state_of_cache { NOT_CONST, CONST_WILL_BE_CACHED, CACHED }; + enum state_of_cache cached_value; public: bool safe; CHARSET_INFO *conv_charset; // keep it public - Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a) - { conv_charset= cs; use_cached_value= 0; safe= 0; } - Item_func_conv_charset(Item *a, CHARSET_INFO *cs, bool cache_if_const) - :Item_str_func(a) + Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a), + cached_value(NOT_CONST), safe(0), conv_charset(cs) + {} + Item_func_conv_charset(Item *a, CHARSET_INFO *cs, bool cache_if_const) + :Item_str_func(a), conv_charset(cs) { - conv_charset= cs; - if (cache_if_const && args[0]->const_item() && !args[0]->is_expensive()) + if (cache_if_const && args[0]->const_item()) { - uint errors= 0; - String tmp, *str= args[0]->val_str(&tmp); - if (!str || str_value.copy(str->ptr(), str->length(), - str->charset(), conv_charset, &errors)) - null_value= 1; - use_cached_value= 1; - str_value.mark_as_const(); - safe= (errors == 0); + is_expensive_cache= MY_TEST(args[0]->is_expensive()); + cached_value= CONST_WILL_BE_CACHED; } else { - use_cached_value= 0; + cached_value= NOT_CONST; /* Conversion from and to "binary" is safe. Conversion to Unicode is safe. @@ -892,6 +887,7 @@ public: void fix_length_and_dec(); const char *func_name() const { return "convert"; } virtual void print(String *str, enum_query_type query_type); + virtual bool const_item() const { return cached_value != NOT_CONST; } }; class Item_func_set_collation :public Item_str_func From d67ef7a2fb3b52b3f61ce71dfe23cf4d610afc3c Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 5 Dec 2016 17:37:54 +0100 Subject: [PATCH 17/21] MDEV-10663: Use of Inline table columns in HAVING clause throws 1463 Error check for VIEW/DERIVED fields --- mysql-test/r/derived.result | 65 ++++++++++++++++++++++++++++++++ mysql-test/r/group_by.result | 14 +++++++ mysql-test/t/derived.test | 47 +++++++++++++++++++++++ mysql-test/t/group_by.test | 12 ++++++ sql/item.cc | 72 +++++++++++++++++++++--------------- 5 files changed, 181 insertions(+), 29 deletions(-) diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index 2c316a829a7..a4d474c9cdf 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -924,3 +924,68 @@ id select_type table type possible_keys key key_len ref rows Extra 3 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table 2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table DROP TABLES t1,t2; +# +# MDEV-10663: Use of Inline table columns in HAVING clause +# throws 1463 Error +# +set @save_sql_mode = @@sql_mode; +set sql_mode='ONLY_FULL_GROUP_BY,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'; +CREATE TABLE `example1463` ( +`Customer` varchar(255) NOT NULL, +`DeliveryStatus` varchar(255) NOT NULL, +`OrderSize` int(11) NOT NULL +); +INSERT INTO example1463 VALUES ('Charlie', 'Success', 100); +INSERT INTO example1463 VALUES ('David', 'Success', 110); +INSERT INTO example1463 VALUES ('Charlie', 'Failed', 200); +INSERT INTO example1463 VALUES ('David', 'Success', 100); +INSERT INTO example1463 VALUES ('David', 'Unknown', 100); +INSERT INTO example1463 VALUES ('Edward', 'Success', 150); +INSERT INTO example1463 VALUES ('Edward', 'Pending', 150); +SELECT Customer, Success, SUM(OrderSize) +FROM (SELECT Customer, +CASE WHEN DeliveryStatus='Success' THEN 'Yes' ELSE 'No' END AS Success, +OrderSize +FROM example1463) as subQ +GROUP BY Success, Customer +WITH ROLLUP; +Customer Success SUM(OrderSize) +Charlie No 200 +David No 100 +Edward No 150 +NULL No 450 +Charlie Yes 100 +David Yes 210 +Edward Yes 150 +NULL Yes 460 +NULL NULL 910 +SELECT Customer, Success, SUM(OrderSize) +FROM (SELECT Customer, +CASE WHEN DeliveryStatus='Success' THEN 'Yes' ELSE 'No' END AS Success, +OrderSize +FROM example1463) as subQ +GROUP BY Success, Customer; +Customer Success SUM(OrderSize) +Charlie No 200 +David No 100 +Edward No 150 +Charlie Yes 100 +David Yes 210 +Edward Yes 150 +SELECT Customer, Success, SUM(OrderSize) +FROM (SELECT Customer, +CASE WHEN DeliveryStatus='Success' THEN 'Yes' ELSE 'No' END AS Success, +OrderSize +FROM example1463) as subQ +GROUP BY Success, Customer +HAVING Success IS NOT NULL; +Customer Success SUM(OrderSize) +Charlie No 200 +David No 100 +Edward No 150 +Charlie Yes 100 +David Yes 210 +Edward Yes 150 +DROP TABLE example1463; +set sql_mode= @save_sql_mode; +# end of 5.5 diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 0b4973cc35b..262bb2ebd84 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -2517,3 +2517,17 @@ MAX(i) c 0 bar 7 foo drop table t1,t2; +# +# ONLY_FULL_GROUP_BY references +# +set @save_sql_mode = @@sql_mode; +set sql_mode='ONLY_FULL_GROUP_BY'; +create table t1 (a int, b int); +select a+b as x from t1 group by x having x > 1; +x +select a as x from t1 group by x having x > 1; +x +select a from t1 group by a having a > 1; +a +drop table t1; +set sql_mode= @save_sql_mode; diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index e10349b451c..e8a6ac34392 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -796,3 +796,50 @@ A.DIVISION=C1.DIVISION AND A.RECEIVABLE_GROUP=C1.RECEIVABLE_GROUP AND A.CREDIT_L ORDER BY TOTAL DESC; DROP TABLES t1,t2; + +--echo # +--echo # MDEV-10663: Use of Inline table columns in HAVING clause +--echo # throws 1463 Error +--echo # + +set @save_sql_mode = @@sql_mode; +set sql_mode='ONLY_FULL_GROUP_BY,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'; + +CREATE TABLE `example1463` ( + `Customer` varchar(255) NOT NULL, + `DeliveryStatus` varchar(255) NOT NULL, + `OrderSize` int(11) NOT NULL +); +INSERT INTO example1463 VALUES ('Charlie', 'Success', 100); +INSERT INTO example1463 VALUES ('David', 'Success', 110); +INSERT INTO example1463 VALUES ('Charlie', 'Failed', 200); +INSERT INTO example1463 VALUES ('David', 'Success', 100); +INSERT INTO example1463 VALUES ('David', 'Unknown', 100); +INSERT INTO example1463 VALUES ('Edward', 'Success', 150); +INSERT INTO example1463 VALUES ('Edward', 'Pending', 150); + +SELECT Customer, Success, SUM(OrderSize) + FROM (SELECT Customer, + CASE WHEN DeliveryStatus='Success' THEN 'Yes' ELSE 'No' END AS Success, + OrderSize + FROM example1463) as subQ + GROUP BY Success, Customer + WITH ROLLUP; +SELECT Customer, Success, SUM(OrderSize) + FROM (SELECT Customer, + CASE WHEN DeliveryStatus='Success' THEN 'Yes' ELSE 'No' END AS Success, + OrderSize + FROM example1463) as subQ + GROUP BY Success, Customer; +SELECT Customer, Success, SUM(OrderSize) + FROM (SELECT Customer, + CASE WHEN DeliveryStatus='Success' THEN 'Yes' ELSE 'No' END AS Success, + OrderSize + FROM example1463) as subQ + GROUP BY Success, Customer + HAVING Success IS NOT NULL; + +DROP TABLE example1463; +set sql_mode= @save_sql_mode; + +--echo # end of 5.5 diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index c94d27b1d16..4162e9c67a1 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -1691,6 +1691,18 @@ SELECT MAX(i), c FROM t1 WHERE c != 'qux' AND ( SELECT SUM(j) FROM t1, t2 ) IS NOT NULL GROUP BY c; drop table t1,t2; +--echo # +--echo # ONLY_FULL_GROUP_BY references +--echo # + +set @save_sql_mode = @@sql_mode; +set sql_mode='ONLY_FULL_GROUP_BY'; +create table t1 (a int, b int); +select a+b as x from t1 group by x having x > 1; +select a as x from t1 group by x having x > 1; +select a from t1 group by a having a > 1; +drop table t1; +set sql_mode= @save_sql_mode; # # End of MariaDB 5.5 tests # diff --git a/sql/item.cc b/sql/item.cc index ede1df6aa9b..53666aaf83d 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4556,8 +4556,6 @@ static Item** find_field_in_group_list(Item *find_item, ORDER *group_list) const char *field_name; ORDER *found_group= NULL; int found_match_degree= 0; - Item_ident *cur_field; - int cur_match_degree= 0; char name_buff[SAFE_NAME_LEN+1]; if (find_item->type() == Item::FIELD_ITEM || @@ -4582,54 +4580,70 @@ static Item** find_field_in_group_list(Item *find_item, ORDER *group_list) for (ORDER *cur_group= group_list ; cur_group ; cur_group= cur_group->next) { - if ((*(cur_group->item))->real_item()->type() == Item::FIELD_ITEM) + int cur_match_degree= 0; + + /* SELECT list element with explicit alias */ + if ((*(cur_group->item))->name && + !(*(cur_group->item))->is_autogenerated_name && + !my_strcasecmp(system_charset_info, + (*(cur_group->item))->name, field_name)) { - cur_field= (Item_ident*) *cur_group->item; - cur_match_degree= 0; - - DBUG_ASSERT(cur_field->field_name != 0); + ++cur_match_degree; + } + /* Reference on the field or view/derived field. */ + else if ((*(cur_group->item))->type() == Item::FIELD_ITEM || + (*(cur_group->item))->type() == Item::REF_ITEM ) + { + Item_ident *cur_field= (Item_ident*) *cur_group->item; + const char *l_db_name= cur_field->db_name; + const char *l_table_name= cur_field->table_name; + const char *l_field_name= cur_field->field_name; + + DBUG_ASSERT(l_field_name != 0); if (!my_strcasecmp(system_charset_info, - cur_field->field_name, field_name)) + l_field_name, field_name)) ++cur_match_degree; else continue; - if (cur_field->table_name && table_name) + if (l_table_name && table_name) { /* If field_name is qualified by a table name. */ - if (my_strcasecmp(table_alias_charset, cur_field->table_name, table_name)) + if (my_strcasecmp(table_alias_charset, l_table_name, table_name)) /* Same field names, different tables. */ return NULL; ++cur_match_degree; - if (cur_field->db_name && db_name) + if (l_db_name && db_name) { /* If field_name is also qualified by a database name. */ - if (strcmp(cur_field->db_name, db_name)) + if (strcmp(l_db_name, db_name)) /* Same field names, different databases. */ return NULL; ++cur_match_degree; } } + } + else + continue; - if (cur_match_degree > found_match_degree) - { - found_match_degree= cur_match_degree; - found_group= cur_group; - } - else if (found_group && (cur_match_degree == found_match_degree) && - ! (*(found_group->item))->eq(cur_field, 0)) - { - /* - If the current resolve candidate matches equally well as the current - best match, they must reference the same column, otherwise the field - is ambiguous. - */ - my_error(ER_NON_UNIQ_ERROR, MYF(0), - find_item->full_name(), current_thd->where); - return NULL; - } + if (cur_match_degree > found_match_degree) + { + found_match_degree= cur_match_degree; + found_group= cur_group; + } + else if (found_group && (cur_match_degree == found_match_degree) && + !(*(found_group->item))->eq((*(cur_group->item)), 0)) + { + /* + If the current resolve candidate matches equally well as the current + best match, they must reference the same column, otherwise the field + is ambiguous. + */ + my_error(ER_NON_UNIQ_ERROR, MYF(0), + find_item->full_name(), current_thd->where); + return NULL; } } From 1d702ff07c53770f45086c514f34bf6ec4e8b299 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Wed, 7 Dec 2016 14:42:08 +0400 Subject: [PATCH 18/21] MDEV-8329 MariaDB crashes when replicate_wild_ignore_table is set to NULL. Rpl_filter::parse_filter_rule() made NULL-safe. --- mysql-test/suite/sys_vars/r/replicate_do_db_basic.result | 4 ++++ mysql-test/suite/sys_vars/r/replicate_do_table_basic.result | 4 ++++ mysql-test/suite/sys_vars/r/replicate_ignore_db_basic.result | 4 ++++ .../suite/sys_vars/r/replicate_ignore_table_basic.result | 4 ++++ .../suite/sys_vars/r/replicate_wild_do_table_basic.result | 4 ++++ .../suite/sys_vars/r/replicate_wild_ignore_table_basic.result | 4 ++++ mysql-test/suite/sys_vars/t/replicate_do_db_basic.test | 3 +++ mysql-test/suite/sys_vars/t/replicate_do_table_basic.test | 3 +++ mysql-test/suite/sys_vars/t/replicate_ignore_db_basic.test | 3 +++ mysql-test/suite/sys_vars/t/replicate_ignore_table_basic.test | 3 +++ .../suite/sys_vars/t/replicate_wild_do_table_basic.test | 3 +++ .../suite/sys_vars/t/replicate_wild_ignore_table_basic.test | 3 +++ sql/rpl_filter.cc | 3 +++ 13 files changed, 45 insertions(+) diff --git a/mysql-test/suite/sys_vars/r/replicate_do_db_basic.result b/mysql-test/suite/sys_vars/r/replicate_do_db_basic.result index b964d3d14a1..a05b85a9bfd 100644 --- a/mysql-test/suite/sys_vars/r/replicate_do_db_basic.result +++ b/mysql-test/suite/sys_vars/r/replicate_do_db_basic.result @@ -33,5 +33,9 @@ SET @@GLOBAL.replicate_do_db=""; SELECT @@GLOBAL.replicate_do_db; @@GLOBAL.replicate_do_db +SET @@GLOBAL.replicate_do_db=null; +SELECT @@GLOBAL.replicate_do_db; +@@GLOBAL.replicate_do_db + # Cleanup. SET @@GLOBAL.replicate_do_db = @save_replicate_do_db; diff --git a/mysql-test/suite/sys_vars/r/replicate_do_table_basic.result b/mysql-test/suite/sys_vars/r/replicate_do_table_basic.result index fac237228ac..e67b1eeca01 100644 --- a/mysql-test/suite/sys_vars/r/replicate_do_table_basic.result +++ b/mysql-test/suite/sys_vars/r/replicate_do_table_basic.result @@ -40,5 +40,9 @@ SET @@GLOBAL.replicate_do_table=""; SELECT @@GLOBAL.replicate_do_table; @@GLOBAL.replicate_do_table +SET @@GLOBAL.replicate_do_table=null; +SELECT @@GLOBAL.replicate_do_table; +@@GLOBAL.replicate_do_table + # Cleanup. SET @@GLOBAL.replicate_do_table = @save_replicate_do_table; diff --git a/mysql-test/suite/sys_vars/r/replicate_ignore_db_basic.result b/mysql-test/suite/sys_vars/r/replicate_ignore_db_basic.result index c4d7a37321e..c7ff697b34f 100644 --- a/mysql-test/suite/sys_vars/r/replicate_ignore_db_basic.result +++ b/mysql-test/suite/sys_vars/r/replicate_ignore_db_basic.result @@ -33,5 +33,9 @@ SET @@GLOBAL.replicate_ignore_db=""; SELECT @@GLOBAL.replicate_ignore_db; @@GLOBAL.replicate_ignore_db +SET @@GLOBAL.replicate_ignore_db=null; +SELECT @@GLOBAL.replicate_ignore_db; +@@GLOBAL.replicate_ignore_db + # Cleanup. SET @@GLOBAL.replicate_ignore_db = @save_replicate_ignore_db; diff --git a/mysql-test/suite/sys_vars/r/replicate_ignore_table_basic.result b/mysql-test/suite/sys_vars/r/replicate_ignore_table_basic.result index bc463d07319..db97ce14c93 100644 --- a/mysql-test/suite/sys_vars/r/replicate_ignore_table_basic.result +++ b/mysql-test/suite/sys_vars/r/replicate_ignore_table_basic.result @@ -40,5 +40,9 @@ SET @@GLOBAL.replicate_ignore_table=""; SELECT @@GLOBAL.replicate_ignore_table; @@GLOBAL.replicate_ignore_table +SET @@GLOBAL.replicate_ignore_table=null; +SELECT @@GLOBAL.replicate_ignore_table; +@@GLOBAL.replicate_ignore_table + # Cleanup. SET @@GLOBAL.replicate_ignore_table = @save_replicate_ignore_table; diff --git a/mysql-test/suite/sys_vars/r/replicate_wild_do_table_basic.result b/mysql-test/suite/sys_vars/r/replicate_wild_do_table_basic.result index 5647cc964fb..8c55103080f 100644 --- a/mysql-test/suite/sys_vars/r/replicate_wild_do_table_basic.result +++ b/mysql-test/suite/sys_vars/r/replicate_wild_do_table_basic.result @@ -40,5 +40,9 @@ SET @@GLOBAL.replicate_wild_do_table=""; SELECT @@GLOBAL.replicate_wild_do_table; @@GLOBAL.replicate_wild_do_table +SET @@GLOBAL.replicate_wild_do_table=null; +SELECT @@GLOBAL.replicate_wild_do_table; +@@GLOBAL.replicate_wild_do_table + # Cleanup. SET @@GLOBAL.replicate_wild_do_table = @save_replicate_wild_do_table; diff --git a/mysql-test/suite/sys_vars/r/replicate_wild_ignore_table_basic.result b/mysql-test/suite/sys_vars/r/replicate_wild_ignore_table_basic.result index c6829b792a4..0f46ce38805 100644 --- a/mysql-test/suite/sys_vars/r/replicate_wild_ignore_table_basic.result +++ b/mysql-test/suite/sys_vars/r/replicate_wild_ignore_table_basic.result @@ -40,5 +40,9 @@ SET @@GLOBAL.replicate_wild_ignore_table=""; SELECT @@GLOBAL.replicate_wild_ignore_table; @@GLOBAL.replicate_wild_ignore_table +SET @@GLOBAL.replicate_wild_ignore_table=null; +SELECT @@GLOBAL.replicate_wild_ignore_table; +@@GLOBAL.replicate_wild_ignore_table + # Cleanup. SET @@GLOBAL.replicate_wild_ignore_table = @save_replicate_wild_ignore_table; diff --git a/mysql-test/suite/sys_vars/t/replicate_do_db_basic.test b/mysql-test/suite/sys_vars/t/replicate_do_db_basic.test index ccf50b1d6ab..59d0176add2 100644 --- a/mysql-test/suite/sys_vars/t/replicate_do_db_basic.test +++ b/mysql-test/suite/sys_vars/t/replicate_do_db_basic.test @@ -35,5 +35,8 @@ SELECT @@GLOBAL.replicate_do_db; SET @@GLOBAL.replicate_do_db=""; SELECT @@GLOBAL.replicate_do_db; +SET @@GLOBAL.replicate_do_db=null; +SELECT @@GLOBAL.replicate_do_db; + --echo # Cleanup. SET @@GLOBAL.replicate_do_db = @save_replicate_do_db; diff --git a/mysql-test/suite/sys_vars/t/replicate_do_table_basic.test b/mysql-test/suite/sys_vars/t/replicate_do_table_basic.test index f3b1585613e..346bdf3b038 100644 --- a/mysql-test/suite/sys_vars/t/replicate_do_table_basic.test +++ b/mysql-test/suite/sys_vars/t/replicate_do_table_basic.test @@ -44,5 +44,8 @@ SELECT @@GLOBAL.replicate_do_table; SET @@GLOBAL.replicate_do_table=""; SELECT @@GLOBAL.replicate_do_table; +SET @@GLOBAL.replicate_do_table=null; +SELECT @@GLOBAL.replicate_do_table; + --echo # Cleanup. SET @@GLOBAL.replicate_do_table = @save_replicate_do_table; diff --git a/mysql-test/suite/sys_vars/t/replicate_ignore_db_basic.test b/mysql-test/suite/sys_vars/t/replicate_ignore_db_basic.test index 3a0bc88109a..376397d1635 100644 --- a/mysql-test/suite/sys_vars/t/replicate_ignore_db_basic.test +++ b/mysql-test/suite/sys_vars/t/replicate_ignore_db_basic.test @@ -35,5 +35,8 @@ SELECT @@GLOBAL.replicate_ignore_db; SET @@GLOBAL.replicate_ignore_db=""; SELECT @@GLOBAL.replicate_ignore_db; +SET @@GLOBAL.replicate_ignore_db=null; +SELECT @@GLOBAL.replicate_ignore_db; + --echo # Cleanup. SET @@GLOBAL.replicate_ignore_db = @save_replicate_ignore_db; diff --git a/mysql-test/suite/sys_vars/t/replicate_ignore_table_basic.test b/mysql-test/suite/sys_vars/t/replicate_ignore_table_basic.test index aebe90732d2..56cf7f17c7f 100644 --- a/mysql-test/suite/sys_vars/t/replicate_ignore_table_basic.test +++ b/mysql-test/suite/sys_vars/t/replicate_ignore_table_basic.test @@ -44,5 +44,8 @@ SELECT @@GLOBAL.replicate_ignore_table; SET @@GLOBAL.replicate_ignore_table=""; SELECT @@GLOBAL.replicate_ignore_table; +SET @@GLOBAL.replicate_ignore_table=null; +SELECT @@GLOBAL.replicate_ignore_table; + --echo # Cleanup. SET @@GLOBAL.replicate_ignore_table = @save_replicate_ignore_table; diff --git a/mysql-test/suite/sys_vars/t/replicate_wild_do_table_basic.test b/mysql-test/suite/sys_vars/t/replicate_wild_do_table_basic.test index b96a62f8dd1..832d3397f89 100644 --- a/mysql-test/suite/sys_vars/t/replicate_wild_do_table_basic.test +++ b/mysql-test/suite/sys_vars/t/replicate_wild_do_table_basic.test @@ -44,5 +44,8 @@ SELECT @@GLOBAL.replicate_wild_do_table; SET @@GLOBAL.replicate_wild_do_table=""; SELECT @@GLOBAL.replicate_wild_do_table; +SET @@GLOBAL.replicate_wild_do_table=null; +SELECT @@GLOBAL.replicate_wild_do_table; + --echo # Cleanup. SET @@GLOBAL.replicate_wild_do_table = @save_replicate_wild_do_table; diff --git a/mysql-test/suite/sys_vars/t/replicate_wild_ignore_table_basic.test b/mysql-test/suite/sys_vars/t/replicate_wild_ignore_table_basic.test index 2900deab4d1..5cb1ff6c820 100644 --- a/mysql-test/suite/sys_vars/t/replicate_wild_ignore_table_basic.test +++ b/mysql-test/suite/sys_vars/t/replicate_wild_ignore_table_basic.test @@ -44,5 +44,8 @@ SELECT @@GLOBAL.replicate_wild_ignore_table; SET @@GLOBAL.replicate_wild_ignore_table=""; SELECT @@GLOBAL.replicate_wild_ignore_table; +SET @@GLOBAL.replicate_wild_ignore_table=null; +SELECT @@GLOBAL.replicate_wild_ignore_table; + --echo # Cleanup. SET @@GLOBAL.replicate_wild_ignore_table = @save_replicate_wild_ignore_table; diff --git a/sql/rpl_filter.cc b/sql/rpl_filter.cc index 9103cad337d..6205c253ffc 100644 --- a/sql/rpl_filter.cc +++ b/sql/rpl_filter.cc @@ -279,6 +279,9 @@ Rpl_filter::parse_filter_rule(const char* spec, Add_filter add) int status= 0; char *arg, *ptr, *pstr; + if (!spec) + return false; + if (! (ptr= my_strdup(spec, MYF(MY_WME)))) return true; From f5e0522d9261408aab8f7736ff9ab116b1e4358f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 7 Dec 2016 13:06:14 +0100 Subject: [PATCH 19/21] MDEV-10388 MariaDB 10.1.x keeps (deleted) ML* files in tmpdir after LOAD DATA completes truncate unused IO_CACHE backing store files in binlog_cache_data to release the disk space they were occupying --- sql/log.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sql/log.cc b/sql/log.cc index 077bbf5e711..dc87c39730c 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -263,6 +263,9 @@ public: { compute_statistics(); truncate(0); + if(cache_log.file != -1) + my_chsize(cache_log.file, 0, 0, MYF(MY_WME)); + changes_to_non_trans_temp_table_flag= FALSE; incident= FALSE; before_stmt_pos= MY_OFF_T_UNDEF; From ab65db6d3fc0c876130cefb45a63cdaad4018f8c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 8 Dec 2016 21:03:45 +0100 Subject: [PATCH 20/21] Revert "MDEV-10713: signal 11 error on multi-table update - crash in handler::increment_statistics or in make_select or assertion failure pfs_thread == ((PFS_thread*) pthread_getspecific((THR_PFS)))" This reverts commit 035a5ac62a0215c2f6e3e363331e3e984d780138. Two minor problems and one regression: 1. caching the value in str_result. Other Item methods may use it, destroying the cache. See, for example, Item::save_in_field, where str_result is moved to use a local buffer (this failed main.grant) 2. Item_func_conv_charset::safe is now set too late, it's initialized only in val_str() but checked before that, this failed many tests in optimized builds. to fix 1 - use tmp_result instead of str_result, to fix 2, use the else branch in the Item_func_conv_charset constructor to set safe purely from charset properties. But this introduces a regression, constant strings can no longer be converted, say, from utf8 to latin1 (because 'safe' will be false). This fails few tests too. There is no way to fix it without reverting the commit and converting constants, as before, in the constructor. --- sql/item_strfunc.cc | 14 +------------- sql/item_strfunc.h | 28 ++++++++++++++++------------ 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 93e2edf9975..94370d45cef 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2951,19 +2951,7 @@ String *Item_func_conv::val_str(String *str) String *Item_func_conv_charset::val_str(String *str) { DBUG_ASSERT(fixed == 1); - if (cached_value == CONST_WILL_BE_CACHED) - { - uint errors= 0; - String tmp, *str= args[0]->val_str(&tmp); - if (!str || str_value.copy(str->ptr(), str->length(), - str->charset(), conv_charset, &errors)) - null_value= 1; - cached_value= CACHED; - str_value.mark_as_const(); - safe= (errors == 0); - is_expensive_cache= 0; - } - if (cached_value == CACHED) + if (use_cached_value) return null_value ? 0 : &str_value; String *arg= args[0]->val_str(str); uint dummy_errors; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 459dc5af34e..7606c281548 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -817,26 +817,31 @@ public: class Item_func_conv_charset :public Item_str_func { + bool use_cached_value; String tmp_value; - enum state_of_cache { NOT_CONST, CONST_WILL_BE_CACHED, CACHED }; - enum state_of_cache cached_value; public: bool safe; CHARSET_INFO *conv_charset; // keep it public - Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a), - cached_value(NOT_CONST), safe(0), conv_charset(cs) - {} - Item_func_conv_charset(Item *a, CHARSET_INFO *cs, bool cache_if_const) - :Item_str_func(a), conv_charset(cs) + Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a) + { conv_charset= cs; use_cached_value= 0; safe= 0; } + Item_func_conv_charset(Item *a, CHARSET_INFO *cs, bool cache_if_const) + :Item_str_func(a) { - if (cache_if_const && args[0]->const_item()) + conv_charset= cs; + if (cache_if_const && args[0]->const_item() && !args[0]->is_expensive()) { - is_expensive_cache= MY_TEST(args[0]->is_expensive()); - cached_value= CONST_WILL_BE_CACHED; + uint errors= 0; + String tmp, *str= args[0]->val_str(&tmp); + if (!str || str_value.copy(str->ptr(), str->length(), + str->charset(), conv_charset, &errors)) + null_value= 1; + use_cached_value= 1; + str_value.mark_as_const(); + safe= (errors == 0); } else { - cached_value= NOT_CONST; + use_cached_value= 0; /* Conversion from and to "binary" is safe. Conversion to Unicode is safe. @@ -887,7 +892,6 @@ public: void fix_length_and_dec(); const char *func_name() const { return "convert"; } virtual void print(String *str, enum_query_type query_type); - virtual bool const_item() const { return cached_value != NOT_CONST; } }; class Item_func_set_collation :public Item_str_func From 03dabfa84d6bc9a8197c8d9fbe80f2a7f6a5b6ac Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 8 Dec 2016 22:54:58 +0100 Subject: [PATCH 21/21] MDEV-10713: signal 11 error on multi-table update - crash in handler::increment_statistics or in make_select or assertion failure pfs_thread == ((PFS_thread*) pthread_getspecific((THR_PFS))) Different fix. Don't allow Item_func_sp to be evaluated unless all tables are prelocked. Extend the test case to make sure Item_func_sp::val_str is called (the table must have at least one row for that). --- mysql-test/r/sp.result | 1 + mysql-test/t/sp.test | 1 + sql/item.h | 2 +- sql/item_func.cc | 3 ++- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index d15031989bf..823c6f78cee 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -8027,6 +8027,7 @@ CREATE TABLE `t1` ( CREATE TABLE `t2` ( `ap_close_to` varchar(8) COLLATE utf8_bin DEFAULT NULL ) DEFAULT CHARSET=utf8 COLLATE=utf8_bin ; +insert t1 values (1); CREATE FUNCTION `f1`(`P_DC_CD` VARBINARY(50), `P_SYS_DATE` DATETIME) RETURNS datetime DETERMINISTIC SQL SECURITY INVOKER diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index b56ab6c3b11..0e42bf3c831 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -9316,6 +9316,7 @@ CREATE TABLE `t1` ( CREATE TABLE `t2` ( `ap_close_to` varchar(8) COLLATE utf8_bin DEFAULT NULL ) DEFAULT CHARSET=utf8 COLLATE=utf8_bin ; +insert t1 values (1); --delimiter $$ diff --git a/sql/item.h b/sql/item.h index 41e6fe0e38e..89155ac00db 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3294,7 +3294,7 @@ public: if (result_type() == ROW_RESULT) orig_item->bring_value(); } - virtual bool is_expensive() { return orig_item->is_expensive(); } + bool is_expensive() { return orig_item->is_expensive(); } bool is_expensive_processor(uchar *arg) { return orig_item->is_expensive_processor(arg); } bool check_vcol_func_processor(uchar *arg) diff --git a/sql/item_func.cc b/sql/item_func.cc index 6c80c7d3d86..89d3cd9e32a 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -6778,7 +6778,8 @@ Item_func_sp::init_result_field(THD *thd) bool Item_func_sp::is_expensive() { - return !(m_sp->m_chistics->detistic); + return !m_sp->m_chistics->detistic || + current_thd->locked_tables_mode < LTM_LOCK_TABLES; }