From c06138e46d6ee789cc9cbdd0f8ed8c5f4cfbc4fb Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Mon, 11 Jan 2016 15:00:44 +0100 Subject: [PATCH 01/91] Raise version number after cloning 5.5.48 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 4bf30e8600e..ba54e70bc3e 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=48 +MYSQL_VERSION_PATCH=49 MYSQL_VERSION_EXTRA= From 79032a7ae1b4e000028a64ab0d2f216d4c23767b Mon Sep 17 00:00:00 2001 From: Shaohua Wang Date: Tue, 12 Jan 2016 15:08:09 +0800 Subject: [PATCH 02/91] BUG#22530768 Innodb freeze running REPLACE statements we can see from the hang stacktrace, srv_monitor_thread is blocked when getting log_sys::mutex, so that sync_arr_wake_threads_if_sema_free cannot get a change to break the mutex deadlock. The fix is simply removing any mutex wait in srv_monitor_thread. Patch is reviewed by Sunny over IM. --- storage/innobase/buf/buf0flu.c | 7 +++++-- storage/innobase/srv/srv0srv.c | 31 ++++++++++++++++--------------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c index 7abd014a364..d15f2e4601e 100644 --- a/storage/innobase/buf/buf0flu.c +++ b/storage/innobase/buf/buf0flu.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2016, 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 @@ -2103,7 +2103,10 @@ buf_flush_stat_update(void) ib_uint64_t lsn; ulint n_flushed; - lsn = log_get_lsn(); + if (!log_peek_lsn(&lsn)) { + return; + } + if (buf_flush_stat_cur.redo == 0) { /* First time around. Just update the current LSN and return. */ diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c index 573488bebca..f42a4a37c80 100644 --- a/storage/innobase/srv/srv0srv.c +++ b/storage/innobase/srv/srv0srv.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. @@ -2413,6 +2413,8 @@ exit_func: /*********************************************************************//** A thread which prints warnings about semaphore waits which have lasted too long. These can be used to track bugs which cause hangs. +Note: In order to make sync_arr_wake_threads_if_sema_free work as expected, +we should avoid waiting any mutexes in this function! @return a dummy parameter */ UNIV_INTERN os_thread_ret_t @@ -2450,23 +2452,22 @@ loop: /* Try to track a strange bug reported by Harald Fuchs and others, where the lsn seems to decrease at times */ + if (log_peek_lsn(&new_lsn)) { + if (new_lsn < old_lsn) { + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Error: old log sequence number %llu" + " was greater\n" + "InnoDB: than the new log sequence number %llu!\n" + "InnoDB: Please submit a bug report" + " to http://bugs.mysql.com\n", + old_lsn, new_lsn); + ut_ad(0); + } - new_lsn = log_get_lsn(); - - if (new_lsn < old_lsn) { - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: old log sequence number %llu" - " was greater\n" - "InnoDB: than the new log sequence number %llu!\n" - "InnoDB: Please submit a bug report" - " to http://bugs.mysql.com\n", - old_lsn, new_lsn); - ut_ad(0); + old_lsn = new_lsn; } - old_lsn = new_lsn; - if (difftime(time(NULL), srv_last_monitor_time) > 60) { /* We referesh InnoDB Monitor values so that averages are printed from at most 60 last seconds */ From 95825fa28a7e84a2f5dbdef5241078f7055c5b04 Mon Sep 17 00:00:00 2001 From: Knut Anders Hatlen Date: Thu, 7 Jan 2016 12:53:18 +0100 Subject: [PATCH 03/91] Bug#21682356: STOP INJECTING DATA ITEMS IN AN ERROR MESSAGE GENERATED BY THE EXP() FUNCTION When generating the error message for numeric overflow, pass a flag to Item::print() that prevents it from expanding constant expressions and parameters to the values they evaluate to. For consistency, also pass the flag to Item::print() when Item_func_spatial_collection::fix_length_and_dec() generates an error message. It doesn't make any difference at the moment, since constant expressions haven't been evaluated yet when this function is called. --- mysql-test/r/func_math.result | 4 ++-- sql/item.cc | 7 +++--- sql/item_func.h | 4 ++-- sql/item_geofunc.h | 4 ++-- sql/mysqld.h | 10 +++++++-- sql/sql_select.cc | 40 ++++++++++++++++++++++++++--------- 6 files changed, 48 insertions(+), 21 deletions(-) diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result index ec0ca748c49..8a505d8bb9d 100644 --- a/mysql-test/r/func_math.result +++ b/mysql-test/r/func_math.result @@ -632,9 +632,9 @@ ERROR 22003: BIGINT UNSIGNED value is out of range in '(18446744073709551615 DIV CREATE TABLE t1(a BIGINT, b BIGINT UNSIGNED); INSERT INTO t1 VALUES(-9223372036854775808, 9223372036854775809); SELECT -a FROM t1; -ERROR 22003: BIGINT value is out of range in '-('-9223372036854775808')' +ERROR 22003: BIGINT value is out of range in '-(`test`.`t1`.`a`)' SELECT -b FROM t1; -ERROR 22003: BIGINT value is out of range in '-('9223372036854775809')' +ERROR 22003: BIGINT value is out of range in '-(`test`.`t1`.`b`)' DROP TABLE t1; SET @a:=999999999999999999999999999999999999999999999999999999999999999999999999999999999; SELECT @a + @a; diff --git a/sql/item.cc b/sql/item.cc index beb68c5d321..5f02b96e59f 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2016, 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 @@ -3456,7 +3456,7 @@ Item_param::eq(const Item *arg, bool binary_cmp) const void Item_param::print(String *str, enum_query_type query_type) { - if (state == NO_VALUE) + if (state == NO_VALUE || query_type & QT_NO_DATA_EXPANSION) { str->append('?'); } @@ -6197,7 +6197,8 @@ Item *Item_field::update_value_transformer(uchar *select_arg) void Item_field::print(String *str, enum_query_type query_type) { - if (field && field->table->const_table) + if (field && field->table->const_table && + !(query_type & QT_NO_DATA_EXPANSION)) { char buff[MAX_FIELD_WIDTH]; String tmp(buff,sizeof(buff),str->charset()); diff --git a/sql/item_func.h b/sql/item_func.h index fc9fa4a65fb..6c83bc179f2 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1,7 +1,7 @@ #ifndef ITEM_FUNC_INCLUDED #define ITEM_FUNC_INCLUDED -/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, 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 @@ -217,7 +217,7 @@ public: char buf[256]; String str(buf, sizeof(buf), system_charset_info); str.length(0); - print(&str, QT_ORDINARY); + print(&str, QT_NO_DATA_EXPANSION); my_error(ER_DATA_OUT_OF_RANGE, MYF(0), type_name, str.c_ptr_safe()); } inline double raise_float_overflow() diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index 903257525f9..fe7ccf10fcc 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -1,7 +1,7 @@ #ifndef ITEM_GEOFUNC_INCLUDED #define ITEM_GEOFUNC_INCLUDED -/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, 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 @@ -187,7 +187,7 @@ public: if (args[i]->fixed && args[i]->field_type() != MYSQL_TYPE_GEOMETRY) { String str; - args[i]->print(&str, QT_ORDINARY); + args[i]->print(&str, QT_NO_DATA_EXPANSION); str.append('\0'); my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "non geometric", str.ptr()); diff --git a/sql/mysqld.h b/sql/mysqld.h index 0253c2a0b43..ee9f8c64840 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2016, 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 @@ -431,7 +431,13 @@ enum enum_query_type /// In utf8. QT_TO_SYSTEM_CHARSET= (1 << 0), /// Without character set introducers. - QT_WITHOUT_INTRODUCERS= (1 << 1) + QT_WITHOUT_INTRODUCERS= (1 << 1), + /** + If an expression is constant, print the expression, not the value + it evaluates to. Should be used for error messages, so that they + don't reveal values. + */ + QT_NO_DATA_EXPANSION= (1 << 9), }; /* query_id */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 96271f26b0f..b5ecebdadc8 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, 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 @@ -17427,26 +17427,46 @@ static void print_join(THD *thd, /* List is reversed => we should reverse it before using */ List_iterator_fast ti(*tables); TABLE_LIST **table; - uint non_const_tables= 0; + + /* + If the QT_NO_DATA_EXPANSION flag is specified, we print the + original table list, including constant tables that have been + optimized away, as the constant tables may be referenced in the + expression printed by Item_field::print() when this flag is given. + Otherwise, only non-const tables are printed. + + Example: + + Original SQL: + select * from (select 1) t + + Printed without QT_NO_DATA_EXPANSION: + select '1' AS `1` from dual + + Printed with QT_NO_DATA_EXPANSION: + select `t`.`1` from (select 1 AS `1`) `t` + */ + const bool print_const_tables= (query_type & QT_NO_DATA_EXPANSION); + size_t tables_to_print= 0; for (TABLE_LIST *t= ti++; t ; t= ti++) - if (!t->optimized_away) - non_const_tables++; - if (!non_const_tables) + if (print_const_tables || !t->optimized_away) + tables_to_print++; + if (tables_to_print == 0) { str->append(STRING_WITH_LEN("dual")); return; // all tables were optimized away } ti.rewind(); - if (!(table= (TABLE_LIST **)thd->alloc(sizeof(TABLE_LIST*) * - non_const_tables))) + if (!(table= static_cast(thd->alloc(sizeof(TABLE_LIST*) * + tables_to_print)))) return; // out of memory - TABLE_LIST *tmp, **t= table + (non_const_tables - 1); + TABLE_LIST *tmp, **t= table + (tables_to_print - 1); while ((tmp= ti++)) { - if (tmp->optimized_away) + if (tmp->optimized_away && !print_const_tables) continue; *t--= tmp; } @@ -17454,7 +17474,7 @@ static void print_join(THD *thd, DBUG_ASSERT(tables->elements >= 1); (*table)->print(thd, str, query_type); - TABLE_LIST **end= table + non_const_tables; + TABLE_LIST **end= table + tables_to_print; for (TABLE_LIST **tbl= table + 1; tbl < end; tbl++) { TABLE_LIST *curr= *tbl; From 7d19d4b2dd692deb38d230e64d3c4c3b64570ad6 Mon Sep 17 00:00:00 2001 From: Deepthi Eranti_Sreenivas Date: Wed, 20 Jan 2016 18:23:16 +0530 Subject: [PATCH 04/91] Bug#22086528 : TEST CODE DISABLED THOUGH THE HISTORIC REASONS - BUGS - ARE FIXED Problem: mysql-test/suite/rpl/t/rpl_killed_ddl.test This test contains code which was disabled because of certain bugs. BUG#44041 declared to be a duplicate of Bug#45516 which was fixed 2010 BUG#43353 fixed 2012 BUG#44171 fixed 2010 Fix: Enabled the test code related to the above mentioned bugs. --- mysql-test/suite/rpl/r/rpl_killed_ddl.result | 14 +++++++ mysql-test/suite/rpl/t/rpl_killed_ddl.test | 43 +++++++------------- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_killed_ddl.result b/mysql-test/suite/rpl/r/rpl_killed_ddl.result index a02c9b599bf..4d9f8b77735 100644 --- a/mysql-test/suite/rpl/r/rpl_killed_ddl.result +++ b/mysql-test/suite/rpl/r/rpl_killed_ddl.result @@ -56,6 +56,10 @@ CREATE VIEW v1 AS SELECT a FROM t1 WHERE a < 100; CREATE DATABASE d2; source include/kill_query.inc; include/rpl_diff.inc +ALTER DATABASE d1 +DEFAULT CHARACTER SET = 'utf8'; +source include/kill_query.inc; +include/rpl_diff.inc DROP DATABASE d1; source include/kill_query.inc; include/rpl_diff.inc @@ -67,6 +71,10 @@ ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY DO INSERT INTO test.t1 VALUES (2); source include/kill_query.inc; include/rpl_diff.inc +ALTER EVENT e1 +ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 2 DAY; +source include/kill_query.inc; +include/rpl_diff.inc DROP EVENT e1; source include/kill_query.inc; include/rpl_diff.inc @@ -83,6 +91,9 @@ include/rpl_diff.inc DROP FUNCTION f1; source include/kill_query.inc; include/rpl_diff.inc +DROP FUNCTION IF EXISTS f2; +source include/kill_query.inc; +include/rpl_diff.inc CREATE PROCEDURE p2 (OUT rows INT) BEGIN SELECT COUNT(*) INTO rows FROM t2; @@ -96,6 +107,9 @@ include/rpl_diff.inc DROP PROCEDURE p1; source include/kill_query.inc; include/rpl_diff.inc +DROP PROCEDURE IF EXISTS p2; +source include/kill_query.inc; +include/rpl_diff.inc CREATE TABLE t2 (b int); source include/kill_query.inc; include/rpl_diff.inc diff --git a/mysql-test/suite/rpl/t/rpl_killed_ddl.test b/mysql-test/suite/rpl/t/rpl_killed_ddl.test index a56a39a2784..76e9b3af091 100644 --- a/mysql-test/suite/rpl/t/rpl_killed_ddl.test +++ b/mysql-test/suite/rpl/t/rpl_killed_ddl.test @@ -26,10 +26,7 @@ # # There are some part of the test are temporarily disabled because of # the following bugs, please enable then once they get fixed: -# - BUG#44041 -# - BUG#43353 -# - BUG#25705 -# - BUG#44171 +# - BUG#22473427 source include/have_debug.inc; source include/master-slave.inc; @@ -145,11 +142,9 @@ let $rpl_diff_statement= SELECT schema_name FROM information_schema.schemata send CREATE DATABASE d2; source include/kill_query_and_diff_master_slave.inc; -# Temporarily disabled, see BUG#44041, the ALTER DATABASE can affect the -# collation of other database on slave -#send ALTER DATABASE d1 -# DEFAULT CHARACTER SET = 'utf8'; -#source include/kill_query_and_diff_master_slave.inc; +send ALTER DATABASE d1 + DEFAULT CHARACTER SET = 'utf8'; +source include/kill_query_and_diff_master_slave.inc; send DROP DATABASE d1; source include/kill_query_and_diff_master_slave.inc; @@ -168,11 +163,9 @@ send CREATE EVENT e2 DO INSERT INTO test.t1 VALUES (2); source include/kill_query_and_diff_master_slave.inc; -# Temporarily disabled because of BUG#44171, killing ALTER EVENT can -# crash the server -#send ALTER EVENT e1 -# ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 2 DAY; -#source include/kill_query_and_diff_master_slave.inc; +send ALTER EVENT e1 + ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 2 DAY; +source include/kill_query_and_diff_master_slave.inc; send DROP EVENT e1; source include/kill_query_and_diff_master_slave.inc; @@ -198,16 +191,8 @@ source include/kill_query_and_diff_master_slave.inc; # function f2 probably does not exist because the CREATE query was # killed -# -# Temporarily disabled. Because of BUG#43353, KILL the query may -# result in function not found, and for 5.1, DROP statements will be -# logged if the function is not found on master, so the following DROP -# FUNCTION statement may be interrupted and not drop the function on -# master, but still get logged and executed on slave and cause -# inconsistence. Also disable the following DROP PROCEDURE IF EXITS -# below. -#send DROP FUNCTION IF EXISTS f2; -#source include/kill_query_and_diff_master_slave.inc; +send DROP FUNCTION IF EXISTS f2; +source include/kill_query_and_diff_master_slave.inc; ######## PROCEDURE ######## @@ -228,9 +213,8 @@ source include/kill_query_and_diff_master_slave.inc; send DROP PROCEDURE p1; source include/kill_query_and_diff_master_slave.inc; -# Temporarily disabled because of bug#43353, see comment above for DROP FUNCTION IF EXISTS -#send DROP PROCEDURE IF EXISTS p2; -#source include/kill_query_and_diff_master_slave.inc; +send DROP PROCEDURE IF EXISTS p2; +source include/kill_query_and_diff_master_slave.inc; ######## TABLE ######## @@ -258,9 +242,10 @@ source include/kill_query_and_diff_master_slave.inc; ######## SERVER ######## -# Tempoarily disabled, see bug#25705 +# Temporarily disabled, see Bug #22473427 - DROP SERVER FAILS +# AFTER ALTER SERVER+KILL QUERY -# --let $rpl_diff_statement= SELECT * FROM mysql.server WHERE name like \'s%\' +# --let $rpl_diff_statement= SELECT * FROM mysql.servers WHERE Server_name like \'s%\' # send CREATE SERVER s2 # FOREIGN DATA WRAPPER mysql From 1624c26d429171c33ad33613e73bba23a5a3cbdd Mon Sep 17 00:00:00 2001 From: Deepthi Eranti_Sreenivas Date: Fri, 22 Jan 2016 16:51:21 +0530 Subject: [PATCH 05/91] Bug#22086528: TEST CODE DISABLED THOUGH THE HISTORIC REASONS - BUGS - ARE FIXED Post push fix for 5.5 and 5.6.Disabled the test code due to Bug#22587377 --- mysql-test/suite/rpl/r/rpl_killed_ddl.result | 4 ---- mysql-test/suite/rpl/t/rpl_killed_ddl.test | 9 ++++++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_killed_ddl.result b/mysql-test/suite/rpl/r/rpl_killed_ddl.result index 4d9f8b77735..ed8745ca2c1 100644 --- a/mysql-test/suite/rpl/r/rpl_killed_ddl.result +++ b/mysql-test/suite/rpl/r/rpl_killed_ddl.result @@ -71,10 +71,6 @@ ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY DO INSERT INTO test.t1 VALUES (2); source include/kill_query.inc; include/rpl_diff.inc -ALTER EVENT e1 -ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 2 DAY; -source include/kill_query.inc; -include/rpl_diff.inc DROP EVENT e1; source include/kill_query.inc; include/rpl_diff.inc diff --git a/mysql-test/suite/rpl/t/rpl_killed_ddl.test b/mysql-test/suite/rpl/t/rpl_killed_ddl.test index 76e9b3af091..e9f5a5c47c2 100644 --- a/mysql-test/suite/rpl/t/rpl_killed_ddl.test +++ b/mysql-test/suite/rpl/t/rpl_killed_ddl.test @@ -27,6 +27,7 @@ # There are some part of the test are temporarily disabled because of # the following bugs, please enable then once they get fixed: # - BUG#22473427 +# - Bug#22587377 source include/have_debug.inc; source include/master-slave.inc; @@ -163,9 +164,11 @@ send CREATE EVENT e2 DO INSERT INTO test.t1 VALUES (2); source include/kill_query_and_diff_master_slave.inc; -send ALTER EVENT e1 - ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 2 DAY; -source include/kill_query_and_diff_master_slave.inc; +# Temporarily disabled,see Bug#22587377-RPL.RPL_KILLED_DDL +# FAILS SPORADICALLY ON PB2 IN 5.5 AND 5.6 +#send ALTER EVENT e1 +# ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 2 DAY; +#source include/kill_query_and_diff_master_slave.inc; send DROP EVENT e1; source include/kill_query_and_diff_master_slave.inc; From a204ce5b3f42e6bdc95eac87acff58214bac415f Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Tue, 26 Jan 2016 09:18:10 +0100 Subject: [PATCH 06/91] Bug#21770366 backport bug#21657078 to 5.5 and 5.6 Post-push fix: The problem was that condition variable timeouts could in some cases (slow machines and/or short timeouts) be infinite. When the number of milliseconds to wait is computed, the end time is computed before the now() time. This can result in the now() time being later than the end time, leading to negative timeout. Which after conversion to unsigned becomes ~infinite. This patch fixes the problem by explicitly checking if we get negative timeout and then using 0 if this is the case. --- mysys/my_wincond.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mysys/my_wincond.c b/mysys/my_wincond.c index 567721baf27..cfb05272a6e 100644 --- a/mysys/my_wincond.c +++ b/mysys/my_wincond.c @@ -127,8 +127,12 @@ static DWORD get_milliseconds(const struct timespec *abstime) if (abstime == NULL) return INFINITE; - return (DWORD)(abstime->tv_sec * 1000 + abstime->tv_nsec / 1000000 - - my_getsystime() / 10000); + ulonglong future= abstime->tv_sec * 1000 + abstime->tv_nsec / 1000000; + ulonglong now= my_getsystime() / 10000; + /* Don't allow the timeout to be negative. */ + if (future < now) + return 0; + return (DWORD)(future - now); #endif } From 93e6f388860490a6066cc07253a6aab94029e502 Mon Sep 17 00:00:00 2001 From: Shaohua Wang Date: Wed, 27 Jan 2016 09:40:02 +0800 Subject: [PATCH 07/91] Followup:BUG#22530768 Innodb freeze running REPLACE statements Go back to __sync_* operations in TAS on x86. Patch is reviewed by Sunny over IM. --- storage/innobase/include/os0sync.h | 46 +++++++++++++++--------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h index 07628409192..ad661355783 100644 --- a/storage/innobase/include/os0sync.h +++ b/storage/innobase/include/os0sync.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -318,28 +318,7 @@ amount of increment. */ # define os_atomic_increment_ulint(ptr, amount) \ os_atomic_increment(ptr, amount) -# if defined(HAVE_IB_GCC_ATOMIC_TEST_AND_SET) - -/** Do an atomic test-and-set. -@param[in,out] ptr Memory location to set to non-zero -@return the previous value */ -static inline -lock_word_t -os_atomic_test_and_set(volatile lock_word_t* ptr) -{ - return(__atomic_test_and_set(ptr, __ATOMIC_ACQUIRE)); -} - -/** Do an atomic clear. -@param[in,out] ptr Memory location to set to zero */ -static inline -void -os_atomic_clear(volatile lock_word_t* ptr) -{ - __atomic_clear(ptr, __ATOMIC_RELEASE); -} - -# elif defined(IB_STRONG_MEMORY_MODEL) +# if defined(IB_STRONG_MEMORY_MODEL) /** Do an atomic test and set. @param[in,out] ptr Memory location to set to non-zero @@ -368,6 +347,27 @@ os_atomic_clear(volatile lock_word_t* ptr) return(__sync_lock_test_and_set(ptr, 0)); } +# elif defined(HAVE_IB_GCC_ATOMIC_TEST_AND_SET) + +/** Do an atomic test-and-set. +@param[in,out] ptr Memory location to set to non-zero +@return the previous value */ +static inline +lock_word_t +os_atomic_test_and_set(volatile lock_word_t* ptr) +{ + return(__atomic_test_and_set(ptr, __ATOMIC_ACQUIRE)); +} + +/** Do an atomic clear. +@param[in,out] ptr Memory location to set to zero */ +static inline +void +os_atomic_clear(volatile lock_word_t* ptr) +{ + __atomic_clear(ptr, __ATOMIC_RELEASE); +} + # else # error "Unsupported platform" From a4f2391d8dac3e1c65b269248e5b8a8045211897 Mon Sep 17 00:00:00 2001 From: Balasubramanian Kandasamy Date: Wed, 27 Jan 2016 18:42:52 +0530 Subject: [PATCH 08/91] BUG#22600974 - SYSV INITSCRIPT FOR RHEL DON'T ENABLE MYSQLD SERVICE BY DEFAULT Enable mysqld service by default in sysv initscrips --- packaging/rpm-oel/mysql.init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/rpm-oel/mysql.init b/packaging/rpm-oel/mysql.init index 79c8a8daa7d..262d0582f68 100644 --- a/packaging/rpm-oel/mysql.init +++ b/packaging/rpm-oel/mysql.init @@ -3,7 +3,7 @@ # mysqld This shell script takes care of starting and stopping # the MySQL subsystem (mysqld). # -# chkconfig: - 64 36 +# chkconfig: 345 64 36 # description: MySQL database server. # processname: mysqld # config: /etc/my.cnf From 01d41f68b7a6e6cc12565056661f1f28876beff5 Mon Sep 17 00:00:00 2001 From: Ajo Robert Date: Thu, 28 Jan 2016 17:40:17 +0530 Subject: [PATCH 09/91] Bug #16912362 LOAD DATA INFILE CLAIMS TO BE HOLDING 'SYSTEM LOCK' IN PROCESSLIST Analysis ========= Show processlist shows 'System Lock' in 'State' field while LOAD DATA INFILE is running. thd->proc_info update is missing in LOAD DATA INFILE path. Thus any request will get last unpdated status from lock_table() during open_table(). Fix: ======= Update state information from LOAD DATA INFILE path. --- sql/sql_load.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 5f72d3ce520..c084e5e3839 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2016, 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 @@ -253,6 +253,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, { DBUG_RETURN(TRUE); } + thd_proc_info(thd, "executing"); /* Let us emit an error if we are loading data to table which is used in subselect in SET clause like we do it for INSERT. From 718c787912e0d498c167e7436d840b2c837e90f9 Mon Sep 17 00:00:00 2001 From: Sreeharsha Ramanavarapu Date: Fri, 29 Jan 2016 08:29:06 +0530 Subject: [PATCH 10/91] Bug #18823979: PS: UCS2 + CASE WHEN THEN ELSE CRASH IN ITEM_PARAM::SAFE_CHARSET_CONVERTER ISSUE: ------ Charset conversion on a null parameter is not handled correctly. SOLUTION: --------- Item_param's charset converter does not handle the case where it might have to deal with a null value. This is fine for other charset converters since the value is not supplied to them at runtime. The fix is to check if the parameter is now set to null and return an Item_null object. Also, there is no need to initialize Item_param's cnvitem in the constructor to a string. This can be done in ITEM_PARAM::SAFE_CHARSET_CONVERTER itself. Members of Item_param, cnvbuf and cnvstr, have been removed and cnvitem has been made a local variable in ITEM_PARAM::SAFE_CHARSET_CONVERTER. --- sql/item.cc | 35 +++++++++++++++++++++++++---------- sql/item.h | 6 +----- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index 5f02b96e59f..c482f0e1a04 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -926,14 +926,31 @@ Item *Item_param::safe_charset_converter(CHARSET_INFO *tocs) { if (const_item()) { - uint cnv_errors; - String *ostr= val_str(&cnvstr); - cnvitem->str_value.copy(ostr->ptr(), ostr->length(), - ostr->charset(), tocs, &cnv_errors); - if (cnv_errors) - return NULL; - cnvitem->str_value.mark_as_const(); - cnvitem->max_length= cnvitem->str_value.numchars() * tocs->mbmaxlen; + Item *cnvitem; + String tmp, cstr, *ostr= val_str(&tmp); + + if (null_value) + { + cnvitem= new Item_null(); + if (cnvitem == NULL) + return NULL; + + cnvitem->collation.set(tocs); + } + else + { + uint conv_errors; + cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, + &conv_errors); + + if (conv_errors || !(cnvitem= new Item_string(cstr.ptr(), cstr.length(), + cstr.charset(), + collation.derivation))) + return NULL; + + cnvitem->str_value.copy(); + cnvitem->str_value.mark_as_const(); + } return cnvitem; } return Item::safe_charset_converter(tocs); @@ -2795,8 +2812,6 @@ Item_param::Item_param(uint pos_in_query_arg) : value is set. */ maybe_null= 1; - cnvitem= new Item_string("", 0, &my_charset_bin, DERIVATION_COERCIBLE); - cnvstr.set(cnvbuf, sizeof(cnvbuf), &my_charset_bin); } diff --git a/sql/item.h b/sql/item.h index 831343de7ad..8caa2bc5f9f 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1,7 +1,7 @@ #ifndef ITEM_INCLUDED #define ITEM_INCLUDED -/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, 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 @@ -1861,10 +1861,6 @@ public: class Item_param :public Item, private Settable_routine_parameter { - char cnvbuf[MAX_FIELD_WIDTH]; - String cnvstr; - Item *cnvitem; - public: enum enum_item_param_state { From 1fb6d4e6bf3dd79fffb034ca4b014930b0304e1f Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Mon, 8 Feb 2016 11:28:20 +0100 Subject: [PATCH 11/91] Bug#22680706: 5.5 DOES NOT BUILD WITH GCC5 Fix the following two build warnings so that 5.5 can be compiled with GCC5. storage/innobase/dict/dict0crea.c:1143:21: error: logical not is only applied to the left hand side of comparison [-Werror=logical-not-parentheses] ut_a(!node->index == (err != DB_SUCCESS)); ^ storage/innobase/log/log0recv.c:1770:20: error: logical not is only applied to the left hand side of comparison [-Werror=logical-not-parentheses] ut_ad(!allow_ibuf == mutex_own(&log_sys->mutex)); ^ --- storage/innobase/dict/dict0crea.c | 4 ++-- storage/innobase/log/log0recv.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.c index ac8a1eac03c..e568dfa16c7 100644 --- a/storage/innobase/dict/dict0crea.c +++ b/storage/innobase/dict/dict0crea.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2016, 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 @@ -1140,7 +1140,7 @@ dict_create_index_step( >= DICT_TF_FORMAT_ZIP); node->index = dict_index_get_if_in_cache_low(index_id); - ut_a(!node->index == (err != DB_SUCCESS)); + ut_a((node->index == NULL) == (err != DB_SUCCESS)); if (err != DB_SUCCESS) { diff --git a/storage/innobase/log/log0recv.c b/storage/innobase/log/log0recv.c index ae3912da552..846d430c294 100644 --- a/storage/innobase/log/log0recv.c +++ b/storage/innobase/log/log0recv.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1997, 2016, 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 @@ -1767,7 +1767,7 @@ loop: goto loop; } - ut_ad(!allow_ibuf == mutex_own(&log_sys->mutex)); + ut_ad((!allow_ibuf) == mutex_own(&log_sys->mutex)); if (!allow_ibuf) { recv_no_ibuf_operations = TRUE; From d9c541cb1be5b239787833d9d499067d44ea44d3 Mon Sep 17 00:00:00 2001 From: Nisha Gopalakrishnan Date: Wed, 10 Feb 2016 19:57:17 +0530 Subject: [PATCH 12/91] BUG#22037930: INSERT IGNORE FAILS TO IGNORE FOREIGN KEY CONSTRAINT. Analysis ======= INSERT and UPDATE operations using the IGNORE keyword which causes FOREIGN KEY constraint violations reports an error despite using the IGNORE keyword. Foreign key violation errors were not ignored and reported as errors instead of warnings even when IGNORE was set. Fix === Added code to ignore the foreign key violation errors and report them as warnings when the IGNORE keyword is used. --- mysql-test/r/insert.result | 38 +++++++++++++++++++++++++++++++++++ mysql-test/t/insert.test | 41 ++++++++++++++++++++++++++++++++++++++ sql/handler.cc | 27 ++++++++++++++++++++++++- sql/handler.h | 10 ++++++++-- sql/sql_insert.cc | 12 +++++++---- sql/sql_update.cc | 26 ++++++++++++++++++------ 6 files changed, 141 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result index 655303be7f4..1aa22349593 100644 --- a/mysql-test/r/insert.result +++ b/mysql-test/r/insert.result @@ -686,3 +686,41 @@ ERROR 42000: Column 'a' specified twice INSERT IGNORE t1 (a, a) SELECT 1,1 UNION SELECT 2,2; ERROR 42000: Column 'a' specified twice DROP TABLE t1; +# +# BUG#22037930: INSERT IGNORE FAILS TO IGNORE +# FOREIGN KEY CONSTRAINT +# Setup. +CREATE TABLE t1 (fld1 INT PRIMARY KEY) ENGINE=INNODB; +CREATE TABLE t2 (fld2 INT, FOREIGN KEY (fld2) REFERENCES t1 (fld1)) +ENGINE=INNODB; +INSERT INTO t1 VALUES(0); +INSERT INTO t2 VALUES(0); +# Without fix, an error is reported. +INSERT IGNORE INTO t2 VALUES(1); +Warnings: +Warning 1452 `test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`) +UPDATE IGNORE t2 SET fld2=20 WHERE fld2=0; +Warnings: +Warning 1452 `test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`) +UPDATE IGNORE t1 SET fld1=20 WHERE fld1=0; +Warnings: +Warning 1451 `test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`) +# Test for multi update. +UPDATE IGNORE t1, t2 SET t2.fld2= t2.fld2 + 3; +Warnings: +Warning 1452 `test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`) +UPDATE IGNORE t1, t2 SET t1.fld1= t1.fld1 + 3; +Warnings: +Warning 1451 `test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`) +# Reports an error since IGNORE is not used. +INSERT INTO t2 VALUES(1); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`)) +UPDATE t2 SET fld2=20 WHERE fld2=0; +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`)) +UPDATE t1 SET fld1=20 WHERE fld1=0; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`)) +UPDATE t1, t2 SET t2.fld2= t2.fld2 + 3; +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`)) +UPDATE t1, t2 SET t1.fld1= t1.fld1 + 3; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`)) +DROP TABLE t2, t1; diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test index 2bf543511ac..ea89872200c 100644 --- a/mysql-test/t/insert.test +++ b/mysql-test/t/insert.test @@ -550,3 +550,44 @@ INSERT IGNORE t1 (a, a) SELECT 1,1; INSERT IGNORE t1 (a, a) SELECT 1,1 UNION SELECT 2,2; DROP TABLE t1; + + +--echo # +--echo # BUG#22037930: INSERT IGNORE FAILS TO IGNORE +--echo # FOREIGN KEY CONSTRAINT + +--echo # Setup. +CREATE TABLE t1 (fld1 INT PRIMARY KEY) ENGINE=INNODB; +CREATE TABLE t2 (fld2 INT, FOREIGN KEY (fld2) REFERENCES t1 (fld1)) +ENGINE=INNODB; +INSERT INTO t1 VALUES(0); +INSERT INTO t2 VALUES(0); + +--echo # Without fix, an error is reported. +--enable_warnings +INSERT IGNORE INTO t2 VALUES(1); +UPDATE IGNORE t2 SET fld2=20 WHERE fld2=0; +UPDATE IGNORE t1 SET fld1=20 WHERE fld1=0; + +--echo # Test for multi update. +UPDATE IGNORE t1, t2 SET t2.fld2= t2.fld2 + 3; +UPDATE IGNORE t1, t2 SET t1.fld1= t1.fld1 + 3; +--disable_warnings + +--echo # Reports an error since IGNORE is not used. +--error ER_NO_REFERENCED_ROW_2 +INSERT INTO t2 VALUES(1); + +--error ER_NO_REFERENCED_ROW_2 +UPDATE t2 SET fld2=20 WHERE fld2=0; + +--error ER_ROW_IS_REFERENCED_2 +UPDATE t1 SET fld1=20 WHERE fld1=0; + +--error ER_NO_REFERENCED_ROW_2 +UPDATE t1, t2 SET t2.fld2= t2.fld2 + 3; + +--error ER_ROW_IS_REFERENCED_2 +UPDATE t1, t2 SET t1.fld1= t1.fld1 + 3; + +DROP TABLE t2, t1; diff --git a/sql/handler.cc b/sql/handler.cc index 6307e95a194..9d57cba73dc 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, 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 @@ -5452,3 +5452,28 @@ fl_create_iterator(enum handler_iterator_type type, } } #endif /*TRANS_LOG_MGM_EXAMPLE_CODE*/ + + +/** + Report a warning for FK constraint violation. + + @param thd Thread handle. + @param table table on which the operation is performed. + @param error handler error number. +*/ +void warn_fk_constraint_violation(THD *thd,TABLE *table, int error) +{ + String str; + switch(error) { + case HA_ERR_ROW_IS_REFERENCED: + table->file->get_error_message(error, &str); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_ROW_IS_REFERENCED_2, str.c_ptr_safe()); + break; + case HA_ERR_NO_REFERENCED_ROW: + table->file->get_error_message(error, &str); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_NO_REFERENCED_ROW_2, str.c_ptr_safe()); + break; + } +} diff --git a/sql/handler.h b/sql/handler.h index 17306fe7dd4..29b6a86c030 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -2,7 +2,7 @@ #define HANDLER_INCLUDED /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2016, 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 @@ -303,6 +303,7 @@ /* Flags for method is_fatal_error */ #define HA_CHECK_DUP_KEY 1 #define HA_CHECK_DUP_UNIQUE 2 +#define HA_CHECK_FK_ERROR 4 #define HA_CHECK_DUP (HA_CHECK_DUP_KEY + HA_CHECK_DUP_UNIQUE) enum legacy_db_type @@ -1485,7 +1486,10 @@ public: if (!error || ((flags & HA_CHECK_DUP_KEY) && (error == HA_ERR_FOUND_DUPP_KEY || - error == HA_ERR_FOUND_DUPP_UNIQUE))) + error == HA_ERR_FOUND_DUPP_UNIQUE)) || + ((flags & HA_CHECK_FK_ERROR) && + (error == HA_ERR_ROW_IS_REFERENCED || + error == HA_ERR_NO_REFERENCED_ROW))) return FALSE; return TRUE; } @@ -2362,4 +2366,6 @@ inline const char *table_case_name(HA_CREATE_INFO *info, const char *name) return ((lower_case_table_names == 2 && info->alias) ? info->alias : name); } +void warn_fk_constraint_violation(THD *thd, TABLE *table, int error); + #endif /* HANDLER_INCLUDED */ diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 7bfc7b083ac..a267108c847 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2016, 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 @@ -1522,7 +1522,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) else table->file->insert_id_for_cur_row= insert_id_for_cur_row; bool is_duplicate_key_error; - if (table->file->is_fatal_error(error, HA_CHECK_DUP)) + if (table->file->is_fatal_error(error, HA_CHECK_DUP | HA_CHECK_FK_ERROR)) goto err; is_duplicate_key_error= table->file->is_fatal_error(error, 0); if (!is_duplicate_key_error) @@ -1620,7 +1620,8 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) error != HA_ERR_RECORD_IS_THE_SAME) { if (info->ignore && - !table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) + !table->file->is_fatal_error(error, HA_CHECK_DUP_KEY | + HA_CHECK_FK_ERROR)) { goto ok_or_after_trg_err; } @@ -1733,7 +1734,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) { DEBUG_SYNC(thd, "write_row_noreplace"); if (!info->ignore || - table->file->is_fatal_error(error, HA_CHECK_DUP)) + table->file->is_fatal_error(error, HA_CHECK_DUP | HA_CHECK_FK_ERROR)) goto err; table->file->restore_auto_increment(prev_insert_id); goto ok_or_after_trg_err; @@ -1751,6 +1752,9 @@ ok_or_after_trg_err: my_safe_afree(key,table->s->max_unique_length,MAX_KEY_LENGTH); if (!table->file->has_transactions()) thd->transaction.stmt.modified_non_trans_table= TRUE; + if (info->ignore && + !table->file->is_fatal_error(error, HA_CHECK_FK_ERROR)) + warn_fk_constraint_violation(thd, table, error); DBUG_RETURN(trg_error); err: diff --git a/sql/sql_update.cc b/sql/sql_update.cc index a29d474fbfc..64d1b3e49dc 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, 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 @@ -735,7 +735,8 @@ int mysql_update(THD *thd, error= 0; } else if (!ignore || - table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) + table->file->is_fatal_error(error, HA_CHECK_DUP_KEY | + HA_CHECK_FK_ERROR)) { /* If (ignore && error is ignorable) we don't have to @@ -743,7 +744,8 @@ int mysql_update(THD *thd, */ myf flags= 0; - if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) + if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY | + HA_CHECK_FK_ERROR)) flags|= ME_FATALERROR; /* Other handler errors are fatal */ prepare_record_for_error_message(error, table); @@ -751,6 +753,9 @@ int mysql_update(THD *thd, error= 1; break; } + else if (ignore && !table->file->is_fatal_error(error, + HA_CHECK_FK_ERROR)) + warn_fk_constraint_violation(thd, table, error); } if (table->triggers && @@ -1883,7 +1888,8 @@ bool multi_update::send_data(List ¬_used_values) { updated--; if (!ignore || - table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) + table->file->is_fatal_error(error, HA_CHECK_DUP_KEY | + HA_CHECK_FK_ERROR)) { /* If (ignore && error == is ignorable) we don't have to @@ -1891,13 +1897,17 @@ bool multi_update::send_data(List ¬_used_values) */ myf flags= 0; - if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) + if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY | + HA_CHECK_FK_ERROR)) flags|= ME_FATALERROR; /* Other handler errors are fatal */ prepare_record_for_error_message(error, table); table->file->print_error(error,MYF(flags)); DBUG_RETURN(1); } + else if (ignore && !table->file->is_fatal_error(error, + HA_CHECK_FK_ERROR)) + warn_fk_constraint_violation(thd, table, error); } else { @@ -2138,8 +2148,12 @@ int multi_update::do_updates() local_error != HA_ERR_RECORD_IS_THE_SAME) { if (!ignore || - table->file->is_fatal_error(local_error, HA_CHECK_DUP_KEY)) + table->file->is_fatal_error(local_error, HA_CHECK_DUP_KEY | + HA_CHECK_FK_ERROR)) goto err; + else if (ignore && !table->file->is_fatal_error(local_error, + HA_CHECK_FK_ERROR)) + warn_fk_constraint_violation(thd, table, local_error); } if (local_error != HA_ERR_RECORD_IS_THE_SAME) updated++; From b3e9211e48a3fb586e88b0270a175d2348935424 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Fri, 19 Feb 2016 23:31:10 +0400 Subject: [PATCH 13/91] WL#9072: Backport WL#8785 to 5.5 --- client/client_priv.h | 36 ++++++++++++++++++- client/mysql.cc | 14 ++++---- client/mysql_upgrade.c | 7 +++- client/mysqladmin.cc | 7 ++-- client/mysqlcheck.c | 8 +++-- client/mysqldump.c | 9 ++--- client/mysqlimport.c | 8 ++--- client/mysqlshow.c | 10 +++--- client/mysqlslap.c | 8 ++--- client/mysqltest.cc | 12 ++++--- include/sslopt-case.h | 15 +++++++- include/sslopt-longopts.h | 5 ++- include/sslopt-vars.h | 12 +++++-- mysql-test/r/ssl_mode.result | 44 +++++++++++++++++++++++ mysql-test/r/ssl_mode_no_ssl.result | 22 ++++++++++++ mysql-test/t/ssl_mode.test | 47 +++++++++++++++++++++++++ mysql-test/t/ssl_mode_no_ssl-master.opt | 1 + mysql-test/t/ssl_mode_no_ssl.test | 41 +++++++++++++++++++++ 18 files changed, 265 insertions(+), 41 deletions(-) create mode 100644 mysql-test/r/ssl_mode.result create mode 100644 mysql-test/r/ssl_mode_no_ssl.result create mode 100644 mysql-test/t/ssl_mode.test create mode 100644 mysql-test/t/ssl_mode_no_ssl-master.opt create mode 100644 mysql-test/t/ssl_mode_no_ssl.test diff --git a/client/client_priv.h b/client/client_priv.h index 593c37b030a..e53ced7e790 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2001, 2016, 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 @@ -88,6 +88,7 @@ enum options_client OPT_DEFAULT_AUTH, OPT_DEFAULT_PLUGIN, OPT_ENABLE_CLEARTEXT_PLUGIN, + OPT_SSL_MODE, OPT_MAX_CLIENT_OPTION }; @@ -111,3 +112,36 @@ enum options_client */ #define PERFORMANCE_SCHEMA_DB_NAME "performance_schema" +/** + Wrapper for mysql_real_connect() that checks if SSL connection is establised. + + The function calls mysql_real_connect() first, then if given ssl_required==TRUE + argument (i.e. --ssl-mode=REQUIRED option used) checks current SSL chiper to + ensure that SSL is used for current connection. + Otherwise it returns NULL and sets errno to CR_SSL_CONNECTION_ERROR. + + All clients (except mysqlbinlog which disregards SSL options) use this function + instead of mysql_real_connect() to handle --ssl-mode=REQUIRED option. +*/ +MYSQL *mysql_connect_ssl_check(MYSQL *mysql_arg, const char *host, + const char *user, const char *passwd, + const char *db, uint port, + const char *unix_socket, ulong client_flag, + my_bool ssl_required __attribute__((unused))) +{ + MYSQL *mysql= mysql_real_connect(mysql_arg, host, user, passwd, db, port, + unix_socket, client_flag); +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) + if (mysql && /* connection established. */ + ssl_required && /* --ssl-mode=REQUIRED. */ + !mysql_get_ssl_cipher(mysql)) /* non-SSL connection. */ + { + NET *net= &mysql->net; + net->last_errno= CR_SSL_CONNECTION_ERROR; + strmov(net->last_error, "--ssl-mode=REQUIRED option forbids non SSL connections"); + strmov(net->sqlstate, "HY000"); + return NULL; + } +#endif + return mysql; +} diff --git a/client/mysql.cc b/client/mysql.cc index 84f5f097f06..cdc2ab0d6e0 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2016, 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 @@ -1316,8 +1316,9 @@ sig_handler handle_sigint(int sig) } kill_mysql= mysql_init(kill_mysql); - if (!mysql_real_connect(kill_mysql,current_host, current_user, opt_password, - "", opt_mysql_port, opt_mysql_unix_port,0)) + if (!mysql_connect_ssl_check(kill_mysql, current_host, current_user, opt_password, + "", opt_mysql_port, opt_mysql_unix_port, 0, + opt_ssl_required)) { tee_fprintf(stdout, "Ctrl-C -- sorry, cannot connect to server to kill query, giving up ...\n"); goto err; @@ -4457,9 +4458,10 @@ sql_real_connect(char *host,char *database,char *user,char *password, mysql_options(&mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN, (char*) &opt_enable_cleartext_plugin); - if (!mysql_real_connect(&mysql, host, user, password, - database, opt_mysql_port, opt_mysql_unix_port, - connect_flag | CLIENT_MULTI_STATEMENTS)) + if (!mysql_connect_ssl_check(&mysql, host, user, password, + database, opt_mysql_port, opt_mysql_unix_port, + connect_flag | CLIENT_MULTI_STATEMENTS, + opt_ssl_required)) { if (!silent || (mysql_errno(&mysql) != CR_CONN_HOST_ERROR && diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index fcbde2653e8..507df6f7843 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2006, 2016, 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 @@ -307,6 +307,7 @@ get_one_option(int optid, const struct my_option *opt, case OPT_DEFAULT_AUTH: /* --default-auth */ add_one_option(&conn_args, opt, argument); break; +#include } if (add_option) @@ -386,6 +387,10 @@ static int run_tool(char *tool_path, DYNAMIC_STRING *ds_res, ...) va_end(args); + /* If given --ssl-mode=REQUIRED propagate it to the tool. */ + if (opt_ssl_required) + dynstr_append(&ds_cmdline, "--ssl-mode=REQUIRED"); + #ifdef __WIN__ dynstr_append(&ds_cmdline, "\""); #endif diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index e8bb4a1a27c..f0ae2c12137 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2016, 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 @@ -518,8 +518,9 @@ static my_bool sql_connect(MYSQL *mysql, uint wait) for (;;) { - if (mysql_real_connect(mysql,host,user,opt_password,NullS,tcp_port, - unix_port, CLIENT_REMEMBER_OPTIONS)) + if (mysql_connect_ssl_check(mysql, host, user, opt_password, NullS, + tcp_port, unix_port, + CLIENT_REMEMBER_OPTIONS, opt_ssl_required)) { mysql->reconnect= 1; if (info) diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 0d5570434e4..a564e871281 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2001, 2016, 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 @@ -894,8 +894,10 @@ static int dbConnect(char *host, char *user, char *passwd) (char *) &opt_enable_cleartext_plugin); mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset); - if (!(sock = mysql_real_connect(&mysql_connection, host, user, passwd, - NULL, opt_mysql_port, opt_mysql_unix_port, 0))) + if (!(sock = mysql_connect_ssl_check(&mysql_connection, host, user, passwd, + NULL, opt_mysql_port, + opt_mysql_unix_port, 0, + opt_ssl_required))) { DBerror(&mysql_connection, "when trying to connect"); return 1; diff --git a/client/mysqldump.c b/client/mysqldump.c index 6bb249134e8..6c4fec313c5 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2016, 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 @@ -1498,9 +1498,10 @@ static int connect_to_db(char *host, char *user,char *passwd) mysql_options(&mysql_connection, MYSQL_ENABLE_CLEARTEXT_PLUGIN, (char *) &opt_enable_cleartext_plugin); - if (!(mysql= mysql_real_connect(&mysql_connection,host,user,passwd, - NULL,opt_mysql_port,opt_mysql_unix_port, - 0))) + if (!(mysql= mysql_connect_ssl_check(&mysql_connection, host, user, + passwd, NULL, opt_mysql_port, + opt_mysql_unix_port, 0, + opt_ssl_required))) { DB_error(&mysql_connection, "when trying to connect"); DBUG_RETURN(1); diff --git a/client/mysqlimport.c b/client/mysqlimport.c index f71111f7e9e..416159abd81 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2016, 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 @@ -449,9 +449,9 @@ static MYSQL *db_connect(char *host, char *database, (char*)&opt_enable_cleartext_plugin); mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset); - if (!(mysql_real_connect(mysql,host,user,passwd, - database,opt_mysql_port,opt_mysql_unix_port, - 0))) + if (!(mysql_connect_ssl_check(mysql, host, user, passwd, database, + opt_mysql_port, opt_mysql_unix_port, + 0, opt_ssl_required))) { ignore_errors=0; /* NO RETURN FROM db_error */ db_error(mysql); diff --git a/client/mysqlshow.c b/client/mysqlshow.c index 6cbbc5e2463..4d1df00c8fd 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2016, 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 @@ -139,10 +139,10 @@ int main(int argc, char **argv) mysql_options(&mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN, (char*)&opt_enable_cleartext_plugin); - if (!(mysql_real_connect(&mysql,host,user,opt_password, - (first_argument_uses_wildcards) ? "" : - argv[0],opt_mysql_port,opt_mysql_unix_port, - 0))) + if (!(mysql_connect_ssl_check(&mysql, host, user, opt_password, + (first_argument_uses_wildcards) ? "" : + argv[0], opt_mysql_port, opt_mysql_unix_port, + 0, opt_ssl_required))) { fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql)); exit(1); diff --git a/client/mysqlslap.c b/client/mysqlslap.c index 8c50898fb01..eb2b577948c 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2005, 2016, 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 @@ -355,9 +355,9 @@ int main(int argc, char **argv) (char*) &opt_enable_cleartext_plugin); if (!opt_only_print) { - if (!(mysql_real_connect(&mysql, host, user, opt_password, - NULL, opt_mysql_port, - opt_mysql_unix_port, connect_flags))) + if (!(mysql_connect_ssl_check(&mysql, host, user, opt_password, + NULL, opt_mysql_port, opt_mysql_unix_port, + connect_flags, opt_ssl_required))) { fprintf(stderr,"%s: Error when connecting to server: %s\n", my_progname,mysql_error(&mysql)); diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 78dcdd77659..79d448cf811 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, 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 @@ -5281,8 +5281,9 @@ void safe_connect(MYSQL* mysql, const char *name, const char *host, verbose_msg("Connecting to server %s:%d (socket %s) as '%s'" ", connection '%s', attempt %d ...", host, port, sock, user, name, failed_attempts); - while(!mysql_real_connect(mysql, host,user, pass, db, port, sock, - CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS)) + while(!mysql_connect_ssl_check(mysql, host,user, pass, db, port, sock, + CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS, + opt_ssl_required)) { /* Connect failed @@ -5382,8 +5383,9 @@ int connect_n_handle_errors(struct st_command *command, dynstr_append_mem(ds, ";\n", 2); } - while (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0, - CLIENT_MULTI_STATEMENTS)) + while (!mysql_connect_ssl_check(con, host, user, pass, db, port, + sock ? sock: 0, CLIENT_MULTI_STATEMENTS, + opt_ssl_required)) { /* If we have used up all our connections check whether this diff --git a/include/sslopt-case.h b/include/sslopt-case.h index 2da5ff317e1..57702b3b352 100644 --- a/include/sslopt-case.h +++ b/include/sslopt-case.h @@ -1,7 +1,7 @@ #ifndef SSLOPT_CASE_INCLUDED #define SSLOPT_CASE_INCLUDED -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, 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 @@ -28,5 +28,18 @@ */ opt_use_ssl= 1; break; +#ifdef MYSQL_CLIENT + case OPT_SSL_MODE: + if (my_strcasecmp(&my_charset_latin1, argument, "required")) + { + fprintf(stderr, + "Unknown value to --ssl-mode: '%s'. Use --ssl-mode=REQUIRED\n", + argument); + exit(1); + } + else + opt_ssl_required= 1; + break; +#endif /* MYSQL_CLIENT */ #endif #endif /* SSLOPT_CASE_INCLUDED */ diff --git a/include/sslopt-longopts.h b/include/sslopt-longopts.h index db99d1dfa26..fd42e83eb04 100644 --- a/include/sslopt-longopts.h +++ b/include/sslopt-longopts.h @@ -1,7 +1,7 @@ #ifndef SSLOPT_LONGOPTS_INCLUDED #define SSLOPT_LONGOPTS_INCLUDED -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, 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 @@ -44,6 +44,9 @@ "when connecting. This option is disabled by default.", &opt_ssl_verify_server_cert, &opt_ssl_verify_server_cert, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"ssl-mode", OPT_SSL_MODE, + "SSL connection mode.", + 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif #endif /* HAVE_OPENSSL */ #endif /* SSLOPT_LONGOPTS_INCLUDED */ diff --git a/include/sslopt-vars.h b/include/sslopt-vars.h index 01093feceaf..6c9bd4296ef 100644 --- a/include/sslopt-vars.h +++ b/include/sslopt-vars.h @@ -1,7 +1,7 @@ #ifndef SSLOPT_VARS_INCLUDED #define SSLOPT_VARS_INCLUDED -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, 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 @@ -28,8 +28,14 @@ SSL_STATIC char *opt_ssl_capath = 0; SSL_STATIC char *opt_ssl_cert = 0; SSL_STATIC char *opt_ssl_cipher = 0; SSL_STATIC char *opt_ssl_key = 0; + #ifdef MYSQL_CLIENT SSL_STATIC my_bool opt_ssl_verify_server_cert= 0; -#endif -#endif +SSL_STATIC my_bool opt_ssl_required= 0; +#endif /* MYSQL_CLIENT */ + +#else /* HAVE_OPENSSL */ +#define opt_ssl_required 0 +#endif /* HAVE_OPENSSL */ + #endif /* SSLOPT_VARS_INCLUDED */ diff --git a/mysql-test/r/ssl_mode.result b/mysql-test/r/ssl_mode.result new file mode 100644 index 00000000000..38fc4e1dca2 --- /dev/null +++ b/mysql-test/r/ssl_mode.result @@ -0,0 +1,44 @@ +# positive client tests +# mysql +Variable_name Value +Ssl_cipher DHE-RSA-AES256-SHA +Variable_name Value +Ssl_cipher DHE-RSA-AES256-SHA +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(0); +# mysqldump +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; +INSERT INTO `t1` VALUES (0); +# mysqladmin +mysqld is alive +# mysqlcheck +test.t1 OK +# mysqlimport +CREATE TABLE words(a VARCHAR(255)); +test.words: Records: 70 Deleted: 0 Skipped: 0 Warnings: 0 +DROP TABLE words; +# mysqlshow +Database: test ++--------+ +| Tables | ++--------+ +| t1 | ++--------+ +# mysqlslap +# mysqltest +Output from mysqltest-x.inc +DROP TABLE t1; +# negative client tests +# mysql +Unknown value to --ssl-mode: ''. Use --ssl-mode=REQUIRED +Unknown value to --ssl-mode: 'DERIUQER'. Use --ssl-mode=REQUIRED +ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections +ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections +ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections + +End of tests diff --git a/mysql-test/r/ssl_mode_no_ssl.result b/mysql-test/r/ssl_mode_no_ssl.result new file mode 100644 index 00000000000..409b7a0fa1b --- /dev/null +++ b/mysql-test/r/ssl_mode_no_ssl.result @@ -0,0 +1,22 @@ +# negative client tests +# mysql +ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections +ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections +ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections +ERROR 2026 (HY000): --ssl-mode=REQUIRED option forbids non SSL connections +# mysqldump +mysqldump: Got error: 2026: --ssl-mode=REQUIRED option forbids non SSL connections when trying to connect +# mysqladmin +mysqladmin: error: '--ssl-mode=REQUIRED option forbids non SSL connections' +# mysqlcheck +mysqlcheck: Got error: 2026: --ssl-mode=REQUIRED option forbids non SSL connections when trying to connect +# mysqlimport +mysqlimport: Error: 2026 --ssl-mode=REQUIRED option forbids non SSL connections +# mysqlshow +mysqlshow: --ssl-mode=REQUIRED option forbids non SSL connections +# mysqlslap +mysqlslap: Error when connecting to server: --ssl-mode=REQUIRED option forbids non SSL connections +# mysqltest +mysqltest: Could not open connection 'default': 2026 --ssl-mode=REQUIRED option forbids non SSL connections + +End of tests diff --git a/mysql-test/t/ssl_mode.test b/mysql-test/t/ssl_mode.test new file mode 100644 index 00000000000..ce1f2aa5e0a --- /dev/null +++ b/mysql-test/t/ssl_mode.test @@ -0,0 +1,47 @@ +-- source include/not_embedded.inc +-- source include/have_ssl_communication.inc + +--echo # positive client tests +--echo # mysql +--exec $MYSQL test --ssl-mode=ReQuIrEd --ssl-cipher=DHE-RSA-AES256-SHA -e "SHOW STATUS LIKE 'Ssl_cipher'" 2>&1 +--exec $MYSQL test --ssl-mode=REQUIRED --ssl --ssl-cipher=DHE-RSA-AES256-SHA -e "SHOW STATUS LIKE 'Ssl_cipher'" 2>&1 + +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(0); + +--echo # mysqldump +--exec $MYSQL_DUMP --ssl-mode=REQUIRED --ssl-cipher=DHE-RSA-AES256-SHA --compact --skip-comments test 2>&1 +--echo # mysqladmin +--exec $MYSQLADMIN --ssl-mode=REQUIRED --ssl-cipher=DHE-RSA-AES256-SHA -S $MASTER_MYSOCK -P $MASTER_MYPORT -u root --password= ping 2>&1 +--echo # mysqlcheck +--exec $MYSQL_CHECK --ssl-mode=REQUIRED --ssl-cipher=DHE-RSA-AES256-SHA test 2>&1 +--echo # mysqlimport +CREATE TABLE words(a VARCHAR(255)); +--exec $MYSQL_IMPORT --ssl-mode=REQUIRED --ssl-cipher=DHE-RSA-AES256-SHA test $MYSQLTEST_VARDIR/std_data/words.dat 2>&1 +DROP TABLE words; +--echo # mysqlshow +--exec $MYSQL_SHOW --ssl-mode=REQUIRED --ssl-cipher=DHE-RSA-AES256-SHA test 2>&1 +--echo # mysqlslap +--exec $MYSQL_SLAP --ssl-mode=REQUIRED --ssl-cipher=DHE-RSA-AES256-SHA --create-schema=test --query="select * from t1" --silent 2>&1 +--echo # mysqltest +--exec $MYSQL_TEST --ssl-mode=REQUIRED --ssl-cipher=DHE-RSA-AES256-SHA -x $MYSQL_TEST_DIR/include/mysqltest-x.inc 2>&1 + +DROP TABLE t1; + +--echo # negative client tests +--echo # mysql +--error 5 +--exec $MYSQL test --ssl-mode +--error 1 +--exec $MYSQL test --ssl-mode= 2>&1 +--error 1 +--exec $MYSQL test --ssl-mode=DERIUQER 2>&1 +--error 1 +--exec $MYSQL test --ssl-mode=REQUIRED 2>&1 +--error 1 +--exec $MYSQL test --ssl-mode=REQUIRED --ssl 2>&1 +--error 1 +--exec $MYSQL test --ssl-mode=REQUIRED --ssl-cipher=DHE-RSA-AES256-SHA --skip-ssl 2>&1 + +--echo +--echo End of tests diff --git a/mysql-test/t/ssl_mode_no_ssl-master.opt b/mysql-test/t/ssl_mode_no_ssl-master.opt new file mode 100644 index 00000000000..0ca403efdfb --- /dev/null +++ b/mysql-test/t/ssl_mode_no_ssl-master.opt @@ -0,0 +1 @@ +--skip-ssl diff --git a/mysql-test/t/ssl_mode_no_ssl.test b/mysql-test/t/ssl_mode_no_ssl.test new file mode 100644 index 00000000000..65f7d1cd46b --- /dev/null +++ b/mysql-test/t/ssl_mode_no_ssl.test @@ -0,0 +1,41 @@ +-- source include/not_embedded.inc + +--echo # negative client tests +--echo # mysql +--error 1 +--exec $MYSQL test --ssl-mode=REQUIRED 2>&1 +--error 1 +--exec $MYSQL test --ssl-mode=REQUIRED --ssl 2>&1 +--error 1 +--exec $MYSQL test --ssl-mode=REQUIRED --ssl-cipher=DHE-RSA-AES256-SHA 2>&1 +--error 1 +--exec $MYSQL test --ssl-mode=REQUIRED --ssl --ssl-cipher=DHE-RSA-AES256-SHA 2>&1 +--echo # mysqldump +--error 2 +--exec $MYSQL_DUMP --ssl-mode=REQUIRED test 2>&1 +--echo # mysqladmin +--replace_regex /.*mysqladmin.*/mysqladmin: / +--error 1 +--exec $MYSQLADMIN --ssl-mode=REQUIRED -S $MASTER_MYSOCK -P $MASTER_MYPORT -u root --password= ping 2>&1 +--echo # mysqlcheck +--replace_regex /.*mysqlcheck(\.exe)*/mysqlcheck/ +--error 2 +--exec $MYSQL_CHECK --ssl-mode=REQUIRED test 2>&1 +--echo # mysqlimport +--replace_regex /.*mysqlimport(\.exe)*/mysqlimport/ +--error 1 +--exec $MYSQL_IMPORT --ssl-mode=REQUIRED test $MYSQLTEST_VARDIR/tmp/t1.txt 2>&1 +--echo # mysqlshow +--replace_regex /.*mysqlshow(\.exe)*/mysqlshow/ +--error 1 +--exec $MYSQL_SHOW --ssl-mode=REQUIRED test 2>&1 +--echo # mysqlslap +--replace_regex /.*mysqlslap(\.exe)*/mysqlslap/ +--error 1 +--exec $MYSQL_SLAP --ssl-mode=REQUIRED 2>&1 +--echo # mysqltest +--error 1 +--exec $MYSQL_TEST --ssl-mode=REQUIRED -x $MYSQL_TEST_DIR/include/mysqltest-x.inc 2>&1 + +--echo +--echo End of tests From 02fa3b8eea24ae3366d2f0bd69db487ccf33c715 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 20 Feb 2016 01:02:48 +0100 Subject: [PATCH 14/91] - Fix to MDEV-9579 be testing for void result. modified: storage/connect/tabodbc.cpp --- storage/connect/tabodbc.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp index fd9a049a05a..b8961789ccd 100644 --- a/storage/connect/tabodbc.cpp +++ b/storage/connect/tabodbc.cpp @@ -5,7 +5,7 @@ /* */ /* COPYRIGHT: */ /* ---------- */ -/* (C) Copyright to the author Olivier BERTRAND 2000-2015 */ +/* (C) Copyright to the author Olivier BERTRAND 2000-2016 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -912,19 +912,21 @@ bool TDBODBC::OpenDB(PGLOBAL g) if ((n = Ocp->GetResultSize(Query->GetStr(), Cnp)) < 0) { strcpy(g->Message, "Cannot get result size"); return true; - } // endif n + } else if (n) { + Ocp->m_Rows = n; - Ocp->m_Rows = n; + if ((Qrp = Ocp->AllocateResult(g))) + Memory = 2; // Must be filled + else { + strcpy(g->Message, "Result set memory allocation failed"); + return true; + } // endif n - if ((Qrp = Ocp->AllocateResult(g))) - Memory = 2; // Must be filled - else { - strcpy(g->Message, "Result set memory allocation failed"); - return true; - } // endif n + } else // Void result + Memory = 0; - Ocp->m_Rows = 0; - } else + Ocp->m_Rows = 0; + } else return true; } // endif Memory From 83d20ca3fbab4ffa160fd3554e9e36a868fb2ab1 Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Tue, 23 Feb 2016 11:41:03 +0530 Subject: [PATCH 15/91] --- storage/myisam/ft_boolean_search.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c index a9ce4436025..fc8713f0d32 100644 --- a/storage/myisam/ft_boolean_search.c +++ b/storage/myisam/ft_boolean_search.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2001, 2016, 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 @@ -199,7 +199,8 @@ static int ftb_query_add_word(MYSQL_FTPARSER_PARAM *param, ftbw= (FTB_WORD *)alloc_root(&ftb_param->ftb->mem_root, sizeof(FTB_WORD) + (info->trunc ? MI_MAX_KEY_BUFF : - word_len * ftb_param->ftb->charset->mbmaxlen + + (word_len + 1) * + ftb_param->ftb->charset->mbmaxlen + HA_FT_WLEN + ftb_param->ftb->info->s->rec_reflength)); ftbw->len= word_len + 1; @@ -362,6 +363,8 @@ static int _ft2_search_no_lock(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) MI_INFO *info=ftb->info; uint UNINIT_VAR(off), extra= HA_FT_WLEN + info->s->rec_reflength; uchar *lastkey_buf=ftbw->word+ftbw->off; + uint max_word_length= (ftbw->flags & FTB_FLAG_TRUNC) ? MI_MAX_KEY_BUFF : + ((ftbw->len) * ftb->charset->mbmaxlen) + extra; if (ftbw->flags & FTB_FLAG_TRUNC) lastkey_buf+=ftbw->len; @@ -421,7 +424,7 @@ static int _ft2_search_no_lock(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) (my_bool) (ftbw->flags & FTB_FLAG_TRUNC),0); } - if (r) /* not found */ + if (r || info->lastkey_length > max_word_length) /* not found */ { if (!ftbw->off || !(ftbw->flags & FTB_FLAG_TRUNC)) { From 447eaa5bc04761555f066d911397e41187d43af5 Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Tue, 23 Feb 2016 11:54:59 +0530 Subject: [PATCH 16/91] --- sql/sql_acl.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index a939ae72ecb..5ff6f38d18d 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, 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 @@ -717,7 +717,6 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) init_read_record(&read_record_info,thd,table= tables[0].table,NULL,1,0, FALSE); table->use_all_columns(); - (void) my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST),20,50); while (!(read_record_info.read_record(&read_record_info))) { ACL_HOST host; @@ -766,7 +765,6 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) init_read_record(&read_record_info,thd,table=tables[1].table,NULL,1,0,FALSE); table->use_all_columns(); - (void) my_init_dynamic_array(&acl_users,sizeof(ACL_USER),50,100); password_length= table->field[2]->field_length / table->field[2]->charset()->mbmaxlen; if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH_323) @@ -981,7 +979,6 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) init_read_record(&read_record_info,thd,table=tables[2].table,NULL,1,0,FALSE); table->use_all_columns(); - (void) my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB),50,100); while (!(read_record_info.read_record(&read_record_info))) { ACL_DB db; @@ -1038,8 +1035,6 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) end_read_record(&read_record_info); freeze_size(&acl_dbs); - (void) my_init_dynamic_array(&acl_proxy_users, sizeof(ACL_PROXY_USER), - 50, 100); if (tables[3].table) { init_read_record(&read_record_info, thd, table= tables[3].table, NULL, 1, @@ -1075,6 +1070,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) return_val= FALSE; end: + end_read_record(&read_record_info); thd->variables.sql_mode= old_sql_mode; DBUG_RETURN(return_val); } @@ -1089,12 +1085,12 @@ void acl_free(bool end) delete_dynamic(&acl_wild_hosts); delete_dynamic(&acl_proxy_users); my_hash_free(&acl_check_hosts); - plugin_unlock(0, native_password_plugin); - plugin_unlock(0, old_password_plugin); if (!end) acl_cache->clear(1); /* purecov: inspected */ else { + plugin_unlock(0, native_password_plugin); + plugin_unlock(0, old_password_plugin); delete acl_cache; acl_cache=0; } @@ -1168,6 +1164,10 @@ my_bool acl_reload(THD *thd) old_acl_users= acl_users; old_acl_proxy_users= acl_proxy_users; old_acl_dbs= acl_dbs; + my_init_dynamic_array(&acl_hosts, sizeof(ACL_HOST), 20, 50); + my_init_dynamic_array(&acl_users, sizeof(ACL_USER), 50, 100); + my_init_dynamic_array(&acl_dbs, sizeof(ACL_DB), 50, 100); + my_init_dynamic_array(&acl_proxy_users, sizeof(ACL_PROXY_USER), 50, 100); old_mem= mem; delete_dynamic(&acl_wild_hosts); my_hash_free(&acl_check_hosts); From 4ed09d54f53771383b943ee6610dae5faa068cff Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Tue, 23 Feb 2016 12:10:41 +0530 Subject: [PATCH 17/91] --- storage/federated/ha_federated.cc | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index 8209b5a2fcf..b47c4565743 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2004, 2016, 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 @@ -1675,6 +1675,7 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked) int ha_federated::close(void) { + THD *thd= current_thd; DBUG_ENTER("ha_federated::close"); free_result(); @@ -1686,7 +1687,7 @@ int ha_federated::close(void) FLUSH TABLES will quit the connection and if connection is broken, it will reconnect again and quit silently. */ - if (mysql && !vio_is_connected(mysql->net.vio)) + if (mysql && (!mysql->net.vio || !vio_is_connected(mysql->net.vio))) mysql->net.error= 2; /* Disconnect from mysql */ @@ -1700,9 +1701,16 @@ int ha_federated::close(void) if the original query was not issued against the FEDERATED table. So, don't propagate errors from mysql_close(). */ - if (table->in_use) + if (table->in_use && thd != table->in_use) table->in_use->clear_error(); + /* + Errors from mysql_close() are silently ignored for flush tables. + Close the connection silently. + */ + if (thd && thd->lex->sql_command == SQLCOM_FLUSH) + thd->clear_error(); + DBUG_RETURN(free_share(share)); } From 29cc2c28832ae4733804ac6b29d650238ee0559c Mon Sep 17 00:00:00 2001 From: Venkatesh Duggirala Date: Fri, 26 Feb 2016 09:01:49 +0530 Subject: [PATCH 18/91] BUG#20574550 MAIN.MERGE TEST CASE FAILS IF BINLOG_FORMAT=ROW The main.merge test case was failing when tested using row based binlog format. While analyzing the issue it was found the following issues: a) The server is calling binlog related code even when a statement will not be binlogged; b) The child table list was not present into table structure by the time to generate the create table statement; c) The tables in the child table list will not be opened yet when generating table create info using row based replication; d) CREATE TABLE LIKE TEMP_TABLE does not preserve original table storage engine when using row based replication; This patch addressed all above issues. @ sql/sql_class.h Added a function to determine if the binary log is disabled to the current session. This is related with issue (a) above. @ sql/sql_table.cc Added code to skip binary logging related code if the statement will not be binlogged. This is related with issue (a) above. Added code to add the children to the query list of the table that will have its CREATE TABLE generated. This is related with issue (b) above. Added code to force the storage engine to be generated into the CREATE TABLE. This is related with issue (d) above. @ storage/myisammrg/ha_myisammrg.cc Added a test to skip a table getting info about a child table if the child table is not opened. This is related to issue (c) above. --- .../suite/binlog/r/binlog_row_binlog.result | 4 +- .../suite/rpl/r/rpl_row_merge_engine.result | 5 +- .../suite/rpl/r/rpl_tmp_table_and_DDL.result | 10 ++++ .../suite/rpl/t/rpl_row_merge_engine.test | 6 ++- .../suite/rpl/t/rpl_tmp_table_and_DDL.test | 51 +++++++++++++++++++ sql/sql_class.h | 14 ++++- sql/sql_table.cc | 20 +++++++- storage/myisammrg/ha_myisammrg.cc | 4 +- 8 files changed, 104 insertions(+), 10 deletions(-) diff --git a/mysql-test/suite/binlog/r/binlog_row_binlog.result b/mysql-test/suite/binlog/r/binlog_row_binlog.result index 75105689246..1fcc915fa1f 100644 --- a/mysql-test/suite/binlog/r/binlog_row_binlog.result +++ b/mysql-test/suite/binlog/r/binlog_row_binlog.result @@ -1203,7 +1203,7 @@ master-bin.000001 # Query # # use `test`; CREATE TABLE IF NOT EXISTS `t2` ( master-bin.000001 # Query # # COMMIT master-bin.000001 # Query # # use `test`; CREATE TABLE IF NOT EXISTS `t3` ( `a` int(11) DEFAULT NULL -) +) ENGINE=MyISAM master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (mysql.user) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F @@ -1238,7 +1238,7 @@ master-bin.000001 # Query # # use `test`; CREATE TABLE IF NOT EXISTS `t2` ( master-bin.000001 # Query # # COMMIT master-bin.000001 # Query # # use `test`; CREATE TABLE IF NOT EXISTS `t3` ( `a` int(11) DEFAULT NULL -) +) ENGINE=MyISAM master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (mysql.user) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F diff --git a/mysql-test/suite/rpl/r/rpl_row_merge_engine.result b/mysql-test/suite/rpl/r/rpl_row_merge_engine.result index c61167e84e0..3b2e02bf97c 100644 --- a/mysql-test/suite/rpl/r/rpl_row_merge_engine.result +++ b/mysql-test/suite/rpl/r/rpl_row_merge_engine.result @@ -4,8 +4,9 @@ CREATE TABLE t1 (a int) ENGINE=MyISAM; CREATE TABLE t2 (a int) ENGINE=MyISAM; INSERT INTO t1 VALUES (1), (2), (3); INSERT INTO t2 VALUES (4), (5), (6); -CREATE TABLE IF NOT EXISTS t1_merge LIKE t1; -ALTER TABLE t1_merge ENGINE=MERGE UNION (t2, t1); +CREATE TEMPORARY TABLE IF NOT EXISTS tt1_merge LIKE t1; +ALTER TABLE tt1_merge ENGINE=MERGE UNION (t2, t1); +CREATE TABLE t1_merge LIKE tt1_merge; include/diff_tables.inc [master:test.t1, slave:test.t1] include/diff_tables.inc [master:test.t2, slave:test.t2] UPDATE t1_merge SET a=10 WHERE a=1; diff --git a/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result b/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result index 0264c9421fc..fb4e8f8ab8a 100644 --- a/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result +++ b/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result @@ -192,4 +192,14 @@ DROP FUNCTION f2; DROP PROCEDURE p2; DROP EVENT e2; DROP TABLE t1, t2; +CREATE TEMPORARY TABLE temp_t1 (c1 INT) ENGINE=InnoDB; +CREATE TEMPORARY TABLE temp_t2 (c1 INT) ENGINE=MyISAM; +CREATE TABLE t1 LIKE temp_t1; +CREATE TABLE t2 LIKE temp_t2; +include/assert.inc ["t1 on master and temp_t1 have the same storage engine"] +include/assert.inc ["t2 on master and temp_t2 have the same storage engine"] +include/assert.inc ["t1 on slave and temp_t1 have the same storage engine"] +include/assert.inc ["t2 on slave and temp_t2 have the same storage engine"] +DROP TEMPORARY TABLE temp_t1, temp_t2; +DROP TABLE t1, t2; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_merge_engine.test b/mysql-test/suite/rpl/t/rpl_row_merge_engine.test index 5add8dc1cda..dcbb8b891d8 100644 --- a/mysql-test/suite/rpl/t/rpl_row_merge_engine.test +++ b/mysql-test/suite/rpl/t/rpl_row_merge_engine.test @@ -20,8 +20,10 @@ CREATE TABLE t1 (a int) ENGINE=MyISAM; CREATE TABLE t2 (a int) ENGINE=MyISAM; INSERT INTO t1 VALUES (1), (2), (3); INSERT INTO t2 VALUES (4), (5), (6); -CREATE TABLE IF NOT EXISTS t1_merge LIKE t1; -ALTER TABLE t1_merge ENGINE=MERGE UNION (t2, t1); +# Changed a little to check also an issue reported on BUG#20574550 +CREATE TEMPORARY TABLE IF NOT EXISTS tt1_merge LIKE t1; +ALTER TABLE tt1_merge ENGINE=MERGE UNION (t2, t1); +CREATE TABLE t1_merge LIKE tt1_merge; --sync_slave_with_master diff --git a/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test b/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test index d722a15f255..decbdcc1f99 100644 --- a/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test +++ b/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test @@ -166,4 +166,55 @@ DROP PROCEDURE p2; DROP EVENT e2; DROP TABLE t1, t2; +--sync_slave_with_master +# +# BUG#20574550 +# CREATE TABLE LIKE does not preserve original table storage +# engine when using row based replication +# +--connection master + +# Define temp_t1 and temp_t2 storage engines +--let $engine_temp_t1= InnoDB +--let $engine_temp_t2= MyISAM + +# Create the two temporary tables +--eval CREATE TEMPORARY TABLE temp_t1 (c1 INT) ENGINE=$engine_temp_t1 +--eval CREATE TEMPORARY TABLE temp_t2 (c1 INT) ENGINE=$engine_temp_t2 + +# Create t1 and t2 based on temporary tables +CREATE TABLE t1 LIKE temp_t1; +CREATE TABLE t2 LIKE temp_t2; +--sync_slave_with_master + +# On master +--connection master +# Assert that t1 and t2 have the same storage engines as temp_t1 and temp_t2 +--let $engine_t1= query_get_value(SHOW TABLE STATUS WHERE Name='t1', Engine, 1) +--let $assert_cond= "$engine_t1" = "$engine_temp_t1" +--let $assert_text= "t1 on master and temp_t1 have the same storage engine" +--source include/assert.inc + +--let $engine_t2= query_get_value(SHOW TABLE STATUS WHERE Name='t2', Engine, 1) +--let $assert_cond= "$engine_t2" = "$engine_temp_t2" +--let $assert_text= "t2 on master and temp_t2 have the same storage engine" +--source include/assert.inc + +# On slave +--connection slave +# Assert that t1 and t2 have the same storage engines as temp_t1 and temp_t2 +--let $engine_t1= query_get_value(SHOW TABLE STATUS WHERE Name='t1', Engine, 1) +--let $assert_cond= "$engine_t1" = "$engine_temp_t1" +--let $assert_text= "t1 on slave and temp_t1 have the same storage engine" +--source include/assert.inc + +--let $engine_t2= query_get_value(SHOW TABLE STATUS WHERE Name='t2', Engine, 1) +--let $assert_cond= "$engine_t2" = "$engine_temp_t2" +--let $assert_text= "t2 on slave and temp_t2 have the same storage engine" +--source include/assert.inc + +# Cleanup +--connection master +DROP TEMPORARY TABLE temp_t1, temp_t2; +DROP TABLE t1, t2; --source include/rpl_end.inc diff --git a/sql/sql_class.h b/sql/sql_class.h index c9900231615..0df8c70e184 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, 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 @@ -1662,6 +1662,18 @@ public: current_stmt_binlog_format == BINLOG_FORMAT_ROW); return current_stmt_binlog_format == BINLOG_FORMAT_ROW; } + /** + Determine if binlogging is disabled for this session + @retval 0 if the current statement binlogging is disabled + (could be because of binlog closed/binlog option + is set to false). + @retval 1 if the current statement will be binlogged + */ + inline bool is_current_stmt_binlog_disabled() const + { + return (!(variables.option_bits & OPTION_BIN_LOG) || + !mysql_bin_log.is_open()); + } private: /** diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 7b4d08613cf..49f05c6116e 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2016, 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 @@ -4709,7 +4709,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, /* We have to write the query before we unlock the tables. */ - if (thd->is_current_stmt_binlog_format_row()) + if (!thd->is_current_stmt_binlog_disabled() && + thd->is_current_stmt_binlog_format_row()) { /* Since temporary tables are not replicated under row-based @@ -4751,6 +4752,21 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, if (open_table(thd, table, thd->mem_root, &ot_ctx)) goto err; + /* + After opening a MERGE table add the children to the query list of + tables, so that children tables info can be used on "CREATE TABLE" + statement generation by the binary log. + Note that placeholders don't have the handler open. + */ + if (table->table->file->extra(HA_EXTRA_ADD_CHILDREN_LIST)) + goto err; + + /* + As the reference table is temporary and may not exist on slave, we must + force the ENGINE to be present into CREATE TABLE. + */ + create_info->used_fields|= HA_CREATE_USED_ENGINE; + int result __attribute__((unused))= store_create_info(thd, table, &query, create_info, TRUE /* show_database */); diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index b7e043c99f1..1ffdd83358d 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, 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 @@ -1481,6 +1481,8 @@ void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info) open_table != file->end_table ; open_table++) { + if (!open_table->table) + continue; TABLE_LIST *ptr; LEX_STRING db, name; LINT_INIT(db.str); From e7061f7e5a96c66cb2e0bf46bec7f6ff35801a69 Mon Sep 17 00:00:00 2001 From: Yashwant Sahu Date: Fri, 26 Feb 2016 11:53:56 +0530 Subject: [PATCH 19/91] Bug #22738607: YASSL FUNCTION X509_NAME_GET_INDEX_BY_NID IS NOT WORKING AS EXPECTED. --- extra/yassl/README | 6 ++++++ extra/yassl/include/openssl/ssl.h | 2 +- extra/yassl/include/yassl_int.hpp | 8 +++++-- extra/yassl/src/cert_wrapper.cpp | 9 ++++++-- extra/yassl/src/ssl.cpp | 10 ++++----- extra/yassl/src/yassl_int.cpp | 31 ++++++++++++++++------------ extra/yassl/taocrypt/include/asn.hpp | 8 +++++++ extra/yassl/taocrypt/src/asn.cpp | 12 +++++++++-- extra/yassl/testsuite/test.hpp | 22 ++++++++++++++++++-- 9 files changed, 80 insertions(+), 28 deletions(-) diff --git a/extra/yassl/README b/extra/yassl/README index 81d573d0b20..b5eb88824fb 100644 --- a/extra/yassl/README +++ b/extra/yassl/README @@ -12,6 +12,12 @@ before calling SSL_new(); *** end Note *** +yaSSL Release notes, version 2.3.9b (2/03/2016) + This release of yaSSL fixes the OpenSSL compatibility function + X509_NAME_get_index_by_NID() to use the actual index of the common name + instead of searching on the format prefix. Thanks for the report from + yashwant.sahu@oracle.com . Anyone using this function should update. + yaSSL Release notes, version 2.3.9 (12/01/2015) This release of yaSSL fixes two client side Diffie-Hellman problems. yaSSL was only handling the cases of zero or one leading zeros for the key diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h index 095b3c6aa80..83daf3cc81f 100644 --- a/extra/yassl/include/openssl/ssl.h +++ b/extra/yassl/include/openssl/ssl.h @@ -35,7 +35,7 @@ #include "rsa.h" -#define YASSL_VERSION "2.3.9" +#define YASSL_VERSION "2.3.9b" #if defined(__cplusplus) diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp index 573f4f2264f..642afb25368 100644 --- a/extra/yassl/include/yassl_int.hpp +++ b/extra/yassl/include/yassl_int.hpp @@ -191,14 +191,18 @@ private: class X509_NAME { char* name_; size_t sz_; + int cnPosition_; // start of common name, -1 is none + int cnLen_; // length of above ASN1_STRING entry_; public: - X509_NAME(const char*, size_t sz); + X509_NAME(const char*, size_t sz, int pos, int len); ~X509_NAME(); const char* GetName() const; ASN1_STRING* GetEntry(int i); size_t GetLength() const; + int GetCnPosition() const { return cnPosition_; } + int GetCnLength() const { return cnLen_; } private: X509_NAME(const X509_NAME&); // hide copy X509_NAME& operator=(const X509_NAME&); // and assign @@ -226,7 +230,7 @@ class X509 { StringHolder afterDate_; // not valid after public: X509(const char* i, size_t, const char* s, size_t, - const char* b, int, const char* a, int); + const char* b, int, const char* a, int, int, int, int, int); ~X509() {} X509_NAME* GetIssuer(); diff --git a/extra/yassl/src/cert_wrapper.cpp b/extra/yassl/src/cert_wrapper.cpp index ff359c6ad71..f620f5efce0 100644 --- a/extra/yassl/src/cert_wrapper.cpp +++ b/extra/yassl/src/cert_wrapper.cpp @@ -293,7 +293,10 @@ int CertManager::Validate() int aSz = (int)strlen(cert.GetAfterDate()) + 1; peerX509_ = NEW_YS X509(cert.GetIssuer(), iSz, cert.GetCommonName(), sSz, cert.GetBeforeDate(), bSz, - cert.GetAfterDate(), aSz); + cert.GetAfterDate(), aSz, + cert.GetIssuerCnStart(), cert.GetIssuerCnLength(), + cert.GetSubjectCnStart(), cert.GetSubjectCnLength() + ); if (err == TaoCrypt::SIG_OTHER_E && verifyCallback_) { X509_STORE_CTX store; @@ -345,7 +348,9 @@ void CertManager::setPeerX509(X509* x) peerX509_ = NEW_YS X509(issuer->GetName(), issuer->GetLength(), subject->GetName(), subject->GetLength(), (const char*) before->data, - before->length, (const char*) after->data, after->length); + before->length, (const char*) after->data, after->length, + issuer->GetCnPosition(), issuer->GetCnLength(), + subject->GetCnPosition(), subject->GetCnLength()); } diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp index 845b35bac8b..cde32df4f43 100644 --- a/extra/yassl/src/ssl.cpp +++ b/extra/yassl/src/ssl.cpp @@ -1351,15 +1351,13 @@ int ASN1_STRING_type(ASN1_STRING *x) int X509_NAME_get_index_by_NID(X509_NAME* name,int nid, int lastpos) { int idx = -1; // not found - const char* start = &name->GetName()[lastpos + 1]; + int cnPos = -1; switch (nid) { case NID_commonName: - const char* found = strstr(start, "/CN="); - if (found) { - found += 4; // advance to str - idx = found - start + lastpos + 1; - } + cnPos = name->GetCnPosition(); + if (lastpos < cnPos) + idx = cnPos; break; } diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp index 19ba6386efd..f041850f85f 100644 --- a/extra/yassl/src/yassl_int.cpp +++ b/extra/yassl/src/yassl_int.cpp @@ -1555,7 +1555,9 @@ void SSL_SESSION::CopyX509(X509* x) peerX509_ = NEW_YS X509(issuer->GetName(), issuer->GetLength(), subject->GetName(), subject->GetLength(), (const char*) before->data, - before->length, (const char*) after->data, after->length); + before->length, (const char*) after->data, after->length, + issuer->GetCnPosition(), issuer->GetCnLength(), + subject->GetCnPosition(), subject->GetCnLength()); } @@ -2472,8 +2474,8 @@ void Security::set_resuming(bool b) } -X509_NAME::X509_NAME(const char* n, size_t sz) - : name_(0), sz_(sz) +X509_NAME::X509_NAME(const char* n, size_t sz, int pos, int len) + : name_(0), sz_(sz), cnPosition_(pos), cnLen_(len) { if (sz) { name_ = NEW_YS char[sz]; @@ -2503,8 +2505,9 @@ size_t X509_NAME::GetLength() const X509::X509(const char* i, size_t iSz, const char* s, size_t sSz, - const char* b, int bSz, const char* a, int aSz) - : issuer_(i, iSz), subject_(s, sSz), + const char* b, int bSz, const char* a, int aSz, int issPos, + int issLen, int subPos, int subLen) + : issuer_(i, iSz, issPos, issLen), subject_(s, sSz, subPos, subLen), beforeDate_(b, bSz), afterDate_(a, aSz) {} @@ -2538,17 +2541,19 @@ ASN1_STRING* X509_NAME::GetEntry(int i) if (i < 0 || i >= int(sz_)) return 0; + if (i != cnPosition_ || cnLen_ <= 0) // only entry currently supported + return 0; + + if (cnLen_ > int(sz_-i)) // make sure there's room in read buffer + return 0; + if (entry_.data) ysArrayDelete(entry_.data); - entry_.data = NEW_YS byte[sz_]; // max size; + entry_.data = NEW_YS byte[cnLen_+1]; // max size; - memcpy(entry_.data, &name_[i], sz_ - i); - if (entry_.data[sz_ -i - 1]) { - entry_.data[sz_ - i] = 0; - entry_.length = int(sz_) - i; - } - else - entry_.length = int(sz_) - i - 1; + memcpy(entry_.data, &name_[i], cnLen_); + entry_.data[cnLen_] = 0; + entry_.length = cnLen_; entry_.type = 0; return &entry_; diff --git a/extra/yassl/taocrypt/include/asn.hpp b/extra/yassl/taocrypt/include/asn.hpp index c7d01d00323..9a10064ce02 100644 --- a/extra/yassl/taocrypt/include/asn.hpp +++ b/extra/yassl/taocrypt/include/asn.hpp @@ -283,6 +283,10 @@ public: const byte* GetHash() const { return subjectHash_; } const char* GetBeforeDate() const { return beforeDate_; } const char* GetAfterDate() const { return afterDate_; } + int GetSubjectCnStart() const { return subCnPos_; } + int GetIssuerCnStart() const { return issCnPos_; } + int GetSubjectCnLength() const { return subCnLen_; } + int GetIssuerCnLength() const { return issCnLen_; } void DecodeToKey(); private: @@ -292,6 +296,10 @@ private: word32 sigLength_; // length of signature word32 signatureOID_; // sum of algorithm object id word32 keyOID_; // sum of key algo object id + int subCnPos_; // subject common name start, -1 is none + int subCnLen_; // length of above + int issCnPos_; // issuer common name start, -1 is none + int issCnLen_; // length of above byte subjectHash_[SHA_SIZE]; // hash of all Names byte issuerHash_[SHA_SIZE]; // hash of all Names byte* signature_; diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp index c419ec0a992..a210d805452 100644 --- a/extra/yassl/taocrypt/src/asn.cpp +++ b/extra/yassl/taocrypt/src/asn.cpp @@ -474,8 +474,9 @@ void DH_Decoder::Decode(DH& key) CertDecoder::CertDecoder(Source& s, bool decode, SignerList* signers, bool noVerify, CertType ct) - : BER_Decoder(s), certBegin_(0), sigIndex_(0), sigLength_(0), - signature_(0), verify_(!noVerify) + : BER_Decoder(s), certBegin_(0), sigIndex_(0), sigLength_(0), subCnPos_(-1), + subCnLen_(0), issCnPos_(-1), issCnLen_(0), signature_(0), + verify_(!noVerify) { issuer_[0] = 0; subject_[0] = 0; @@ -796,6 +797,13 @@ void CertDecoder::GetName(NameType nt) case COMMON_NAME: if (!(ptr = AddTag(ptr, buf_end, "/CN=", 4, strLen))) return; + if (nt == ISSUER) { + issCnPos_ = (int)(ptr - strLen - issuer_); + issCnLen_ = (int)strLen; + } else { + subCnPos_ = (int)(ptr - strLen - subject_); + subCnLen_ = (int)strLen; + } break; case SUR_NAME: if (!(ptr = AddTag(ptr, buf_end, "/SN=", 4, strLen))) diff --git a/extra/yassl/testsuite/test.hpp b/extra/yassl/testsuite/test.hpp index 3e15ce81489..5c9dc7ce117 100644 --- a/extra/yassl/testsuite/test.hpp +++ b/extra/yassl/testsuite/test.hpp @@ -470,10 +470,28 @@ inline void showPeer(SSL* ssl) char* issuer = X509_NAME_oneline(X509_get_issuer_name(peer), 0, 0); char* subject = X509_NAME_oneline(X509_get_subject_name(peer), 0, 0); - printf("peer's cert info:\n issuer : %s\n subject: %s\n", issuer, - subject); + X509_NAME_ENTRY* se = NULL; + ASN1_STRING* sd = NULL; + char* subCN = NULL; + + X509_NAME* sub = X509_get_subject_name(peer); + int lastpos = -1; + if (sub) + lastpos = X509_NAME_get_index_by_NID(sub, NID_commonName, lastpos); + if (lastpos >= 0) { + se = X509_NAME_get_entry(sub, lastpos); + if (se) + sd = X509_NAME_ENTRY_get_data(se); + if (sd) + subCN = (char*)ASN1_STRING_data(sd); + } + + printf("peer's cert info:\n issuer : %s\n subject: %s\n" + " subject cn: %s\n", issuer, subject, subCN); + free(subject); free(issuer); + } else printf("peer has no cert!\n"); From fb9e2fa33f531aaa0a853f0db1150a86ca3512e0 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Wed, 16 Mar 2016 19:17:55 +0100 Subject: [PATCH 20/91] - Fix MDEV-9603 compiler error. modified: storage/connect/tabmysql.cpp - Test invalid CSV separator when creating the table (MDEV-9714) modified: storage/connect/ha_connect.cc - Stop using SQLDescribeParam anymore modified: storage/connect/odbconn.cpp - Fix MDEV-9723 Regression due to calling Cardinality instead of GetMaxSize in info. modified: storage/connect/tabtbl.h modified: storage/connect/mysql-test/connect/r/tbl.result modified: storage/connect/mysql-test/connect/t/tbl.test - Typo modified: storage/connect/tabodbc.cpp --- storage/connect/ha_connect.cc | 29 ++++++++---- .../connect/mysql-test/connect/r/tbl.result | 45 +++++++++++++------ storage/connect/mysql-test/connect/t/tbl.test | 43 ++++++++++++------ storage/connect/odbconn.cpp | 9 ++-- storage/connect/tabmysql.cpp | 2 +- storage/connect/tabtbl.h | 3 +- 6 files changed, 92 insertions(+), 39 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 81e373a62d2..d82c6a278d8 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -169,9 +169,9 @@ #define JSONMAX 10 // JSON Default max grp size extern "C" { - char version[]= "Version 1.04.0005 January 24, 2016"; + char version[]= "Version 1.04.0006 March 12, 2016"; #if defined(__WIN__) - char compver[]= "Version 1.04.0005 " __DATE__ " " __TIME__; + char compver[]= "Version 1.04.0006 " __DATE__ " " __TIME__; char slash= '\\'; #else // !__WIN__ char slash= '/'; @@ -5160,7 +5160,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, fncn= topt->catfunc; fnc= GetFuncID(fncn); sep= topt->separator; - spc= (!sep) ? ',' : (!strcmp(sep, "\\t")) ? '\t' : *sep; + spc= (!sep) ? ',' : *sep; qch= topt->qchar ? *topt->qchar : (signed)topt->quoted >= 0 ? '"' : 0; hdr= (int)topt->header; tbl= topt->tablist; @@ -5227,7 +5227,6 @@ static int connect_assisted_discovery(handlerton *, THD* thd, goto err; } // endif rc - if (!tab) { if (ttp == TAB_TBL) { // Make tab the first table of the list @@ -5296,8 +5295,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd, case TAB_CSV: if (!fn && fnc != FNC_NO) sprintf(g->Message, "Missing %s file name", topt->type); - else - ok= true; + else if (sep && strlen(sep) > 1) + sprintf(g->Message, "Invalid separator %s", sep); + else + ok= true; break; case TAB_MYSQL: @@ -5978,7 +5979,19 @@ int ha_connect::create(const char *name, TABLE *table_arg, DBUG_RETURN(rc); } // endif lrecl - } // endif type + } // endif type JSON + + if (type == TAB_CSV) { + const char *sep = options->separator; + + if (sep && strlen(sep) > 1) { + sprintf(g->Message, "Invalid separator %s", sep); + my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); + rc= HA_ERR_INTERNAL_ERROR; + DBUG_RETURN(rc); + } // endif sep + + } // endif type CSV // Check column types for (field= table_arg->field; *field; field++) { @@ -6766,7 +6779,7 @@ maria_declare_plugin(connect) 0x0104, /* version number (1.04) */ NULL, /* status variables */ connect_system_variables, /* system variables */ - "1.04.0005", /* string version */ + "1.04.0006", /* string version */ MariaDB_PLUGIN_MATURITY_BETA /* maturity */ } maria_declare_plugin_end; diff --git a/storage/connect/mysql-test/connect/r/tbl.result b/storage/connect/mysql-test/connect/r/tbl.result index bc77516c22d..c584a9dd61f 100644 --- a/storage/connect/mysql-test/connect/r/tbl.result +++ b/storage/connect/mysql-test/connect/r/tbl.result @@ -44,8 +44,8 @@ ta message 1 Testing 2 myisam table 3 t4 -CREATE TABLE total (tabname CHAR(8) NOT NULL SPECIAL='TABID', ta TINYINT NOT NULL FLAG=1, message CHAR(20)) engine=CONNECT table_type=TBL table_list='t1,t2,t3,t4' option_list='port=PORT'; -select * from total; +CREATE TABLE total (tabname CHAR(8) NOT NULL SPECIAL='TABID', ta TINYINT NOT NULL FLAG=1, message CHAR(20)) ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t1,t2,t3,t4' OPTION_LIST='port=PORT'; +SELECT * FROM total; tabname ta message t1 1 Testing t1 2 dos table @@ -59,15 +59,15 @@ t3 3 t3 t4 1 Testing t4 2 myisam table t4 3 t4 -select * from total where tabname = 't2'; +SELECT * FROM total WHERE tabname = 't2'; tabname ta message t2 1 Testing t2 2 NULL t2 3 t2 -select * from total where tabname = 't2' and ta = 3; +SELECT * FROM total WHERE tabname = 't2' AND ta = 3; tabname ta message t2 3 t2 -select * from total where tabname in ('t1','t4'); +SELECT * FROM total WHERE tabname IN ('t1','t4'); tabname ta message t1 1 Testing t1 2 dos table @@ -75,11 +75,11 @@ t1 3 t1 t4 1 Testing t4 2 myisam table t4 3 t4 -select * from total where ta = 3 and tabname in ('t1','t2'); +SELECT * FROM total WHERE ta = 3 AND tabname IN ('t1','t2'); tabname ta message t1 3 t1 t2 3 t2 -select * from total where tabname <> 't2'; +SELECT * FROM total WHERE tabname <> 't2'; tabname ta message t1 1 Testing t1 2 dos table @@ -90,12 +90,12 @@ t3 3 t3 t4 1 Testing t4 2 myisam table t4 3 t4 -select * from total where tabname != 't2' and ta = 3; +SELECT * FROM total WHERE tabname != 't2' AND ta = 3; tabname ta message t1 3 t1 t3 3 t3 t4 3 t4 -select * from total where tabname not in ('t2','t3'); +SELECT * FROM total WHERE tabname NOT IN ('t2','t3'); tabname ta message t1 1 Testing t1 2 dos table @@ -103,11 +103,11 @@ t1 3 t1 t4 1 Testing t4 2 myisam table t4 3 t4 -select * from total where ta = 3 and tabname in ('t2','t3'); +SELECT * FROM total WHERE ta = 3 AND tabname IN ('t2','t3'); tabname ta message t2 3 t2 t3 3 t3 -select * from total where ta = 3 or tabname in ('t2','t4'); +SELECT * FROM total WHERE ta = 3 OR tabname IN ('t2','t4'); tabname ta message t1 3 t1 t2 1 Testing @@ -117,7 +117,7 @@ t3 3 t3 t4 1 Testing t4 2 myisam table t4 3 t4 -select * from total where not tabname = 't2'; +SELECT * FROM total WHERE NOT tabname = 't2'; tabname ta message t1 1 Testing t1 2 dos table @@ -128,7 +128,7 @@ t3 3 t3 t4 1 Testing t4 2 myisam table t4 3 t4 -select * from total where tabname = 't2' or tabname = 't1'; +SELECT * FROM total WHERE tabname = 't2' OR tabname = 't1'; tabname ta message t1 1 Testing t1 2 dos table @@ -141,3 +141,22 @@ DROP TABLE t1; DROP TABLE t2; DROP TABLE t3; DROP TABLE t4; +# +# Checking thread TBL tables +# +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL SRCDEF='select 11 as v'; +SELECT * FROM t1; +v +11 +CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL SRCDEF='select 22 as v'; +SELECT * FROM t2; +v +22 +CREATE TABLE total (v BIGINT(20) UNSIGNED NOT NULL) ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t1,t2' OPTION_LIST='thread=yes,port=PORT';; +SELECT * FROM total; +v +22 +11 +DROP TABLE total; +DROP TABLE t1; +DROP TABLE t2; diff --git a/storage/connect/mysql-test/connect/t/tbl.test b/storage/connect/mysql-test/connect/t/tbl.test index 43c506c9403..8478679d22c 100644 --- a/storage/connect/mysql-test/connect/t/tbl.test +++ b/storage/connect/mysql-test/connect/t/tbl.test @@ -31,23 +31,40 @@ INSERT INTO t4 (message) VALUES ('Testing'),('myisam table'),('t4'); SELECT * FROM t4; --replace_result $PORT PORT ---eval CREATE TABLE total (tabname CHAR(8) NOT NULL SPECIAL='TABID', ta TINYINT NOT NULL FLAG=1, message CHAR(20)) engine=CONNECT table_type=TBL table_list='t1,t2,t3,t4' option_list='port=$PORT' +--eval CREATE TABLE total (tabname CHAR(8) NOT NULL SPECIAL='TABID', ta TINYINT NOT NULL FLAG=1, message CHAR(20)) ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t1,t2,t3,t4' OPTION_LIST='port=$PORT' -select * from total; -select * from total where tabname = 't2'; -select * from total where tabname = 't2' and ta = 3; -select * from total where tabname in ('t1','t4'); -select * from total where ta = 3 and tabname in ('t1','t2'); -select * from total where tabname <> 't2'; -select * from total where tabname != 't2' and ta = 3; -select * from total where tabname not in ('t2','t3'); -select * from total where ta = 3 and tabname in ('t2','t3'); -select * from total where ta = 3 or tabname in ('t2','t4'); -select * from total where not tabname = 't2'; -select * from total where tabname = 't2' or tabname = 't1'; +SELECT * FROM total; +SELECT * FROM total WHERE tabname = 't2'; +SELECT * FROM total WHERE tabname = 't2' AND ta = 3; +SELECT * FROM total WHERE tabname IN ('t1','t4'); +SELECT * FROM total WHERE ta = 3 AND tabname IN ('t1','t2'); +SELECT * FROM total WHERE tabname <> 't2'; +SELECT * FROM total WHERE tabname != 't2' AND ta = 3; +SELECT * FROM total WHERE tabname NOT IN ('t2','t3'); +SELECT * FROM total WHERE ta = 3 AND tabname IN ('t2','t3'); +SELECT * FROM total WHERE ta = 3 OR tabname IN ('t2','t4'); +SELECT * FROM total WHERE NOT tabname = 't2'; +SELECT * FROM total WHERE tabname = 't2' OR tabname = 't1'; DROP TABLE total; DROP TABLE t1; DROP TABLE t2; DROP TABLE t3; DROP TABLE t4; + +--echo # +--echo # Checking thread TBL tables +--echo # +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL SRCDEF='select 11 as v'; +SELECT * FROM t1; + +CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL SRCDEF='select 22 as v'; +SELECT * FROM t2; + +--replace_result $PORT PORT +--eval CREATE TABLE total (v BIGINT(20) UNSIGNED NOT NULL) ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t1,t2' OPTION_LIST='thread=yes,port=$PORT'; +SELECT * FROM total; + +DROP TABLE total; +DROP TABLE t1; +DROP TABLE t2; diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp index cb21a8bda15..55ccbdbada1 100644 --- a/storage/connect/odbconn.cpp +++ b/storage/connect/odbconn.cpp @@ -1758,7 +1758,9 @@ bool ODBConn::BindParam(ODBCCOL *colp) SQLLEN *strlen = colp->GetStrLen(); SQLRETURN rc; +#if 0 try { + // This function is often not or badly implemented by data sources rc = SQLDescribeParam(m_hstmt, n, &sqlt, &colsize, &dec, &nul); if (!Check(rc)) @@ -1766,11 +1768,12 @@ bool ODBConn::BindParam(ODBCCOL *colp) } catch(DBX *x) { sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0)); +#endif // 0 colsize = colp->GetPrecision(); sqlt = GetSQLType(buftype); - dec = IsTypeChar(buftype) ? 0 : colp->GetScale(); - nul = SQL_NULLABLE_UNKNOWN; - } // end try/catch + dec = IsTypeNum(buftype) ? colp->GetScale() : 0; + nul = colp->IsNullable() ? SQL_NULLABLE : SQL_NO_NULLS; +//} // end try/catch buf = colp->GetBuffer(0); len = IsTypeChar(buftype) ? colp->GetBuflen() : 0; diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index b9cede52a21..77be29ac12d 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -334,7 +334,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int) Delayed = !!GetIntCatInfo("Delayed", 0); } else { // MYSQL access from a PROXY table - Database = GetStringCatInfo(g, "Database", Schema ? Schema : "*"); + Database = GetStringCatInfo(g, "Database", Schema ? Schema : (PSZ)"*"); Isview = GetBoolCatInfo("View", false); // We must get other connection parms from the calling table diff --git a/storage/connect/tabtbl.h b/storage/connect/tabtbl.h index 9d3f297f9e7..3a5ec45d025 100644 --- a/storage/connect/tabtbl.h +++ b/storage/connect/tabtbl.h @@ -138,7 +138,8 @@ class DllExport TDBTBM : public TDBTBL { virtual void ResetDB(void); // Database routines - virtual int GetMaxSize(PGLOBAL g) {return 10;} // Temporary + virtual int Cardinality(PGLOBAL g) { return 10; } + virtual int GetMaxSize(PGLOBAL g) { return 10; } // Temporary virtual int RowNumber(PGLOBAL g, bool b = FALSE); virtual bool OpenDB(PGLOBAL g); virtual int ReadDB(PGLOBAL g); From 66890975ebf6a7d7ab9f19ba25543223b78c8c82 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Wed, 16 Mar 2016 23:56:43 +0100 Subject: [PATCH 21/91] - Fix crash when sorting a TBL table with thread=yes. This was because Tablist can be NULL when no lacal tables are in the list. modified: storage/connect/tabtbl.cpp modified: storage/connect/mysql-test/connect/r/tbl.result modified: storage/connect/mysql-test/connect/t/tbl.test --- storage/connect/mysql-test/connect/r/tbl.result | 2 +- storage/connect/mysql-test/connect/t/tbl.test | 2 +- storage/connect/tabtbl.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/storage/connect/mysql-test/connect/r/tbl.result b/storage/connect/mysql-test/connect/r/tbl.result index c584a9dd61f..f51b4dfa57f 100644 --- a/storage/connect/mysql-test/connect/r/tbl.result +++ b/storage/connect/mysql-test/connect/r/tbl.result @@ -153,7 +153,7 @@ SELECT * FROM t2; v 22 CREATE TABLE total (v BIGINT(20) UNSIGNED NOT NULL) ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t1,t2' OPTION_LIST='thread=yes,port=PORT';; -SELECT * FROM total; +SELECT * FROM total order by v desc; v 22 11 diff --git a/storage/connect/mysql-test/connect/t/tbl.test b/storage/connect/mysql-test/connect/t/tbl.test index 8478679d22c..3dc4b2e64b0 100644 --- a/storage/connect/mysql-test/connect/t/tbl.test +++ b/storage/connect/mysql-test/connect/t/tbl.test @@ -63,7 +63,7 @@ SELECT * FROM t2; --replace_result $PORT PORT --eval CREATE TABLE total (v BIGINT(20) UNSIGNED NOT NULL) ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t1,t2' OPTION_LIST='thread=yes,port=$PORT'; -SELECT * FROM total; +SELECT * FROM total order by v desc; DROP TABLE total; DROP TABLE t1; diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp index 6b72c715517..36849146746 100644 --- a/storage/connect/tabtbl.cpp +++ b/storage/connect/tabtbl.cpp @@ -607,7 +607,7 @@ void TDBTBM::ResetDB(void) for (PTABLE tabp = Tablist; tabp; tabp = tabp->GetNext()) ((PTDBASE)tabp->GetTo_Tdb())->ResetDB(); - Tdbp = (PTDBASE)Tablist->GetTo_Tdb(); + Tdbp = (Tablist) ? (PTDBASE)Tablist->GetTo_Tdb() : NULL; Crp = 0; } // end of ResetDB @@ -679,7 +679,7 @@ bool TDBTBM::OpenDB(PGLOBAL g) /* Table already open, replace it at its beginning. */ /*******************************************************************/ ResetDB(); - return Tdbp->OpenDB(g); // Re-open fist table + return (Tdbp) ? Tdbp->OpenDB(g) : false; // Re-open fist table } // endif use #if 0 From c1efc4a4ddbc2ab8c409b19e57aa4e54336b38c9 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 19 Mar 2016 12:13:36 +0100 Subject: [PATCH 22/91] - Fix compile error when copying a string on itself. modified: storage/connect/value.cpp - Fix compile error of MDEV-9603 modified: storage/connect/tabmysql.cpp --- storage/connect/tabmysql.cpp | 2 +- storage/connect/value.cpp | 29 ++++++++++++++--------------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index 77be29ac12d..ed474de036a 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -334,7 +334,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int) Delayed = !!GetIntCatInfo("Delayed", 0); } else { // MYSQL access from a PROXY table - Database = GetStringCatInfo(g, "Database", Schema ? Schema : (PSZ)"*"); + Database = GetStringCatInfo(g, "Database", Schema ? Schema : PlugDup(g, "*")); Isview = GetBoolCatInfo("View", false); // We must get other connection parms from the calling table diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index 60471c9b0d8..74ab9806e5c 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -1344,10 +1344,13 @@ bool TYPVAL::SetValue_pval(PVAL valp, bool chktype) /***********************************************************************/ bool TYPVAL::SetValue_char(char *p, int n) { - bool rc; + bool rc = false; - if (p && n > 0) { - rc = n > Len; + if (!p || n == 0) { + Reset(); + Null = Nullable; + } else if (p != Strp) { + rc = n > Len; if ((n = MY_MIN(n, Len))) { strncpy(Strp, p, n); @@ -1366,10 +1369,6 @@ bool TYPVAL::SetValue_char(char *p, int n) Reset(); Null = false; - } else { - rc = false; - Reset(); - Null = Nullable; } // endif p return rc; @@ -1380,12 +1379,12 @@ bool TYPVAL::SetValue_char(char *p, int n) /***********************************************************************/ void TYPVAL::SetValue_psz(PSZ s) { - if (s) { - strncpy(Strp, s, Len); + if (!s) { + Reset(); + Null = Nullable; + } else if (s != Strp) { + strncpy(Strp, s, Len); Null = false; - } else { - Reset(); - Null = Nullable; } // endif s } // end of SetValue_psz @@ -1643,7 +1642,7 @@ bool TYPVAL::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op) assert(np == 1 || np == 2); if (np == 2) - strncpy(Strp, p[0], Len); + SetValue_psz(p[0]); if ((i = Len - (signed)strlen(Strp)) > 0) strncat(Strp, p[np - 1], i); @@ -1651,11 +1650,11 @@ bool TYPVAL::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op) break; case OP_MIN: assert(np == 2); - strcpy(Strp, (strcmp(p[0], p[1]) < 0) ? p[0] : p[1]); + SetValue_psz((strcmp(p[0], p[1]) < 0) ? p[0] : p[1]); break; case OP_MAX: assert(np == 2); - strcpy(Strp, (strcmp(p[0], p[1]) > 0) ? p[0] : p[1]); + SetValue_psz((strcmp(p[0], p[1]) > 0) ? p[0] : p[1]); break; default: // sprintf(g->Message, MSG(BAD_EXP_OPER), op); From e80c4b3186c0ceda522874400a196fd144dede91 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Thu, 24 Mar 2016 23:36:39 +0100 Subject: [PATCH 23/91] - Fix MDEV-9779. Connection was not recognized in the option list. This was a regression bug. modified: storage/connect/ha_connect.cc modified: storage/connect/mysql-test/connect/r/part_table.result modified: storage/connect/mysql-test/connect/t/part_table.test --- storage/connect/ha_connect.cc | 6 +++-- .../mysql-test/connect/r/part_table.result | 25 +++++++++++++++++++ .../mysql-test/connect/t/part_table.test | 15 +++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index d82c6a278d8..a7840122147 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -1150,7 +1150,7 @@ char *ha_connect::GetRealString(const char *s) { char *sv; - if (IsPartitioned() && s) { + if (IsPartitioned() && s && partname && *partname) { sv= (char*)PlugSubAlloc(xp->g, NULL, 0); sprintf(sv, s, partname); PlugSubAlloc(xp->g, NULL, strlen(sv) + 1); @@ -1173,7 +1173,9 @@ char *ha_connect::GetStringOption(char *opname, char *sdef) : table->s->connect_string; if (cnc.length) - opval= GetRealString(strz(xp->g, cnc)); + opval= strz(xp->g, cnc); + else + opval= GetListOption(xp->g, opname, options->oplist); } else if (!stricmp(opname, "Query_String")) opval= thd_query_string(table->in_use)->str; diff --git a/storage/connect/mysql-test/connect/r/part_table.result b/storage/connect/mysql-test/connect/r/part_table.result index 122c328fa59..f3a556ae784 100644 --- a/storage/connect/mysql-test/connect/r/part_table.result +++ b/storage/connect/mysql-test/connect/r/part_table.result @@ -191,6 +191,31 @@ id msg 35 thirty five 81 big DROP TABLE t1; +CREATE TABLE t1 ( +id INT KEY NOT NULL, +msg VARCHAR(32)) +ENGINE=CONNECT TABLE_TYPE=MYSQL +OPTION_LIST='connect=mysql://root@localhost/test/xt%s' +PARTITION BY RANGE COLUMNS(id) ( +PARTITION `1` VALUES LESS THAN(10), +PARTITION `2` VALUES LESS THAN(50), +PARTITION `3` VALUES LESS THAN(MAXVALUE)); +Warnings: +Warning 1105 Data repartition in 1 is unchecked +Warning 1105 Data repartition in 2 is unchecked +Warning 1105 Data repartition in 3 is unchecked +SELECT * FROM t1; +id msg +4 four +7 sept +1 one +8 eight +40 forty +10 ten +11 eleven +35 thirty five +81 big +DROP TABLE t1; DROP TABLE xt1; DROP TABLE xt2; DROP TABLE xt3; diff --git a/storage/connect/mysql-test/connect/t/part_table.test b/storage/connect/mysql-test/connect/t/part_table.test index d839337ba6f..5edd5766bd6 100644 --- a/storage/connect/mysql-test/connect/t/part_table.test +++ b/storage/connect/mysql-test/connect/t/part_table.test @@ -82,6 +82,21 @@ SELECT * FROM t1; DELETE FROM t1 WHERE id in (60,72); SELECT * FROM t1; DROP TABLE t1; + +# +# Using a connection string +# +CREATE TABLE t1 ( +id INT KEY NOT NULL, +msg VARCHAR(32)) +ENGINE=CONNECT TABLE_TYPE=MYSQL +OPTION_LIST='connect=mysql://root@localhost/test/xt%s' +PARTITION BY RANGE COLUMNS(id) ( +PARTITION `1` VALUES LESS THAN(10), +PARTITION `2` VALUES LESS THAN(50), +PARTITION `3` VALUES LESS THAN(MAXVALUE)); +SELECT * FROM t1; +DROP TABLE t1; DROP TABLE xt1; DROP TABLE xt2; DROP TABLE xt3; From 2c4715b3e2414f653f8d940c30c51ba3e1fe65cc Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Fri, 25 Mar 2016 11:11:25 +0100 Subject: [PATCH 24/91] Bigger partname to avoid MDEV-9779 --- storage/connect/ha_connect.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h index 05cc872fa2a..629e4a01183 100644 --- a/storage/connect/ha_connect.h +++ b/storage/connect/ha_connect.h @@ -554,7 +554,7 @@ protected: PVAL sdvalin4; // Used to convert date values PVAL sdvalout; // Used to convert date values bool istable; // True for table handler - char partname[64]; // The partition name + char partname[128]; // The partition name MODE xmod; // Table mode XINFO xinfo; // The table info structure bool valid_info; // True if xinfo is valid From 8c9fd074d2269ccb0a1b18b9463e847a52b27fce Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Fri, 25 Mar 2016 12:46:42 +0100 Subject: [PATCH 25/91] - Fix MDEV-9779. Avoid buffer overflow when setting partname. modified: storage/connect/ha_connect.cc modified: storage/connect/ha_connect.h --- storage/connect/ha_connect.cc | 22 ++++++++++++---------- storage/connect/ha_connect.h | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index a7840122147..67cfb29254f 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -757,7 +757,7 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg) sdvalout= NULL; xmod= MODE_ANY; istable= false; - *partname= 0; + memset(partname, 0, sizeof(partname)); bzero((char*) &xinfo, sizeof(XINFO)); valid_info= false; valid_query_id= 0; @@ -3123,13 +3123,14 @@ int ha_connect::open(const char *name, int mode, uint test_if_locked) #if defined(WITH_PARTITION_STORAGE_ENGINE) if (table->part_info) { if (GetStringOption("Filename") || GetStringOption("Tabname") - || GetStringOption("Connect")) { - strcpy(partname, decode(g, strrchr(name, '#') + 1)); + || GetStringOption("Connect")) { + strncpy(partname, decode(g, strrchr(name, '#') + 1), sizeof(partname) - 1); // strcpy(partname, table->part_info->curr_part_elem->partition_name); - part_id= &table->part_info->full_part_field_set; +// part_id= &table->part_info->full_part_field_set; } else // Inward table - strcpy(partname, strrchr(name, slash) + 1); - part_id= &table->part_info->full_part_field_set; // Temporary + strncpy(partname, strrchr(name, slash) + 1, sizeof(partname) - 1); + + part_id= &table->part_info->full_part_field_set; // Temporary } // endif part_info #endif // WITH_PARTITION_STORAGE_ENGINE } else @@ -6144,7 +6145,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, strcpy(dbpath, name); p= strrchr(dbpath, slash); - strcpy(partname, ++p); + strncpy(partname, ++p, sizeof(partname) - 1); strcat(strcat(strcpy(buf, p), "."), lwt); *p= 0; } else { @@ -6195,7 +6196,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, #if defined(WITH_PARTITION_STORAGE_ENGINE) if (part_info && !inward) - strcpy(partname, decode(g, strrchr(name, '#') + 1)); + strncpy(partname, decode(g, strrchr(name, '#') + 1), sizeof(partname) - 1); // strcpy(partname, part_info->curr_part_elem->partition_name); #endif // WITH_PARTITION_STORAGE_ENGINE @@ -6236,8 +6237,9 @@ int ha_connect::create(const char *name, TABLE *table_arg, #if defined(WITH_PARTITION_STORAGE_ENGINE) if (part_info) - strcpy(partname, - decode(g, strrchr(name, (inward ? slash : '#')) + 1)); + strncpy(partname, + decode(g, strrchr(name, (inward ? slash : '#')) + 1), + sizeof(partname) - 1); #endif // WITH_PARTITION_STORAGE_ENGINE if ((rc= optimize(table->in_use, NULL))) { diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h index 629e4a01183..669d45db25a 100644 --- a/storage/connect/ha_connect.h +++ b/storage/connect/ha_connect.h @@ -554,7 +554,7 @@ protected: PVAL sdvalin4; // Used to convert date values PVAL sdvalout; // Used to convert date values bool istable; // True for table handler - char partname[128]; // The partition name + char partname[65]; // The partition name MODE xmod; // Table mode XINFO xinfo; // The table info structure bool valid_info; // True if xinfo is valid From 777c2131dd7aeaf25adbbbbb0c213950e852f22b Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Sat, 2 Apr 2016 00:04:47 +0400 Subject: [PATCH 26/91] MDEV-9862 Illegal mix of collation, when comparing column with CASE expression --- mysql-test/r/ctype_cp850.result | 14 ++++++++++++++ mysql-test/t/ctype_cp850.test | 16 ++++++++++++++++ sql/item.h | 2 +- 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 mysql-test/r/ctype_cp850.result create mode 100644 mysql-test/t/ctype_cp850.test diff --git a/mysql-test/r/ctype_cp850.result b/mysql-test/r/ctype_cp850.result new file mode 100644 index 00000000000..c028f72b58a --- /dev/null +++ b/mysql-test/r/ctype_cp850.result @@ -0,0 +1,14 @@ +# +# Start of 5.5 tests +# +# +# MDEV-9862 Illegal mix of collation, when comparing column with CASE expression +# +SET NAMES cp850; +CREATE TABLE t1 (a CHAR(1) CHARACTER SET latin1); +SELECT a FROM t1 WHERE CASE a WHEN 'aaaa' THEN 'Y' WHEN 'aaaa' THEN 'Y' ELSE NULL END <> a; +a +DROP TABLE t1; +# +# End of 5.5 tests +# diff --git a/mysql-test/t/ctype_cp850.test b/mysql-test/t/ctype_cp850.test new file mode 100644 index 00000000000..358829eb351 --- /dev/null +++ b/mysql-test/t/ctype_cp850.test @@ -0,0 +1,16 @@ +--echo # +--echo # Start of 5.5 tests +--echo # + +--echo # +--echo # MDEV-9862 Illegal mix of collation, when comparing column with CASE expression +--echo # +SET NAMES cp850; +CREATE TABLE t1 (a CHAR(1) CHARACTER SET latin1); +SELECT a FROM t1 WHERE CASE a WHEN 'aaaa' THEN 'Y' WHEN 'aaaa' THEN 'Y' ELSE NULL END <> a; +DROP TABLE t1; + + +--echo # +--echo # End of 5.5 tests +--echo # diff --git a/sql/item.h b/sql/item.h index d09f6572487..41e6fe0e38e 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2175,7 +2175,7 @@ public: max_length= 0; name= name_par ? name_par : (char*) "NULL"; fixed= 1; - collation.set(&my_charset_bin, DERIVATION_IGNORABLE); + collation.set(&my_charset_bin, DERIVATION_IGNORABLE, MY_REPERTOIRE_ASCII); } enum Type type() const { return NULL_ITEM; } bool eq(const Item *item, bool binary_cmp) const; From f8adeccd78bff80725a95b73447e34a5f4528179 Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Mon, 4 Apr 2016 17:04:14 +0300 Subject: [PATCH 27/91] MDEV-9713 Sporadic test failure: sys_vars.innodb_buffer_pool_load_now_basic Previous fix using wait condition did not work because of MDEV-9867, so we have to use conditional sleep instead. Sleep will only happen if the test is executed after another one which also ran buffer pool dump without server restart between two tests --- .../t/innodb_buffer_pool_load_now_basic.test | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_now_basic.test b/mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_now_basic.test index 160b3ba52cc..a0409901865 100644 --- a/mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_now_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_now_basic.test @@ -13,11 +13,19 @@ let $old_status= `SELECT variable_value FROM information_schema.global_status # A previous test could have run buffer pool dump already; # in this case we want to make sure that the current time is different -# from the timestamp in the status variable +# from the timestamp in the status variable. +# We should have had a smart wait condition here, like the commented one below, +# but we can't because of MDEV-9867, so there will be just sleep instead. +# And it might be not enough to sleep one second, so we'll have to sleep two. +# let $wait_condition = +# SELECT TRIM(SUBSTR('$old_status', -8)) != DATE_FORMAT(CURTIME(), '%k:%i:%s'); +# -- source include/wait_condition.inc -let $wait_condition = - SELECT TRIM(SUBSTR('$old_status', -8)) != DATE_FORMAT(CURTIME(), '%k:%i:%s'); --- source include/wait_condition.inc +if (`SELECT variable_value LIKE '%dump completed at%' FROM information_schema.global_status + WHERE LOWER(variable_name) = 'innodb_buffer_pool_dump_status'`) +{ + -- sleep 2 +} # Do the dump SET GLOBAL innodb_buffer_pool_dump_now = ON; From c9e56d5ca9ebd0737ed543a7e1b3c990a8ab94fa Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 18 Apr 2016 17:38:05 +0200 Subject: [PATCH 28/91] 5.5.48-37.8 --- storage/xtradb/buf/buf0flu.c | 7 ++++-- storage/xtradb/handler/ha_innodb.cc | 2 +- storage/xtradb/handler/ha_innodb.h | 23 ++++++++++++++++++ storage/xtradb/handler/handler0alter.cc | 16 +++++++++++++ storage/xtradb/include/univ.i | 2 +- storage/xtradb/srv/srv0srv.c | 31 +++++++++++++------------ 6 files changed, 62 insertions(+), 19 deletions(-) diff --git a/storage/xtradb/buf/buf0flu.c b/storage/xtradb/buf/buf0flu.c index 0afdeb3fd02..88c4d29648b 100644 --- a/storage/xtradb/buf/buf0flu.c +++ b/storage/xtradb/buf/buf0flu.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2016, 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 @@ -2217,7 +2217,10 @@ buf_flush_stat_update(void) ib_uint64_t lsn; ulint n_flushed; - lsn = log_get_lsn(); + if (!log_peek_lsn(&lsn)) { + return; + } + if (buf_flush_stat_cur.redo == 0) { /* First time around. Just update the current LSN and return. */ diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index d9df6e6cc27..effff7cf0c4 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -4498,7 +4498,7 @@ building based on the assumption that there is no concurrent index creation/drop and DMLs that requires index lookup. All table handle will be closed before the index creation/drop. @return TRUE if index translation table built successfully */ -static +UNIV_INTERN ibool innobase_build_index_translation( /*=============================*/ diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h index 2324793767e..4f21dcff7e8 100644 --- a/storage/xtradb/handler/ha_innodb.h +++ b/storage/xtradb/handler/ha_innodb.h @@ -347,3 +347,26 @@ innobase_index_name_is_reserved( ulint num_of_keys); /*!< in: Number of indexes to be created. */ +/*******************************************************************//** +This function builds a translation table in INNOBASE_SHARE +structure for fast index location with mysql array number from its +table->key_info structure. This also provides the necessary translation +between the key order in mysql key_info and Innodb ib_table->indexes if +they are not fully matched with each other. +Note we do not have any mutex protecting the translation table +building based on the assumption that there is no concurrent +index creation/drop and DMLs that requires index lookup. All table +handle will be closed before the index creation/drop. +@return TRUE if index translation table built successfully */ +UNIV_INTERN +ibool +innobase_build_index_translation( +/*=============================*/ + const TABLE* table, /*!< in: table in MySQL data + dictionary */ + dict_table_t* ib_table, /*!< in: table in Innodb data + dictionary */ + INNOBASE_SHARE* share); /*!< in/out: share structure + where index translation table + will be constructed in. */ + diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index b4d63fc23b7..1c3c72e6245 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -1082,6 +1082,22 @@ ha_innobase::final_add_index( trx_free_for_mysql(trx); + /* Rebuild index translation table now for temporary tables if we are + restoring secondary keys, as ha_innobase::open will not be called for + the next access. */ + if (add->indexed_table == prebuilt->table + && dict_table_is_temporary(prebuilt->table)) + { + if (!innobase_build_index_translation(add_arg->table, + prebuilt->table, share)) + { + /* We don't know whether index translation build failed + because of DD mismatch or OOM, return non-specific + error code. */ + err = -1; + } + } + /* There might be work for utility threads.*/ srv_active_wake_master_thread(); diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index 46c1bd1b23c..4814a07d3a4 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 37.7 +#define PERCONA_INNODB_VERSION 37.8 #endif #define INNODB_VERSION_STR MYSQL_SERVER_VERSION diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c index a830f22ba7d..26ad32cb1d1 100644 --- a/storage/xtradb/srv/srv0srv.c +++ b/storage/xtradb/srv/srv0srv.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. @@ -2880,6 +2880,8 @@ exit_func: /*********************************************************************//** A thread which prints warnings about semaphore waits which have lasted too long. These can be used to track bugs which cause hangs. +Note: In order to make sync_arr_wake_threads_if_sema_free work as expected, +we should avoid waiting any mutexes in this function! @return a dummy parameter */ UNIV_INTERN os_thread_ret_t @@ -2917,23 +2919,22 @@ loop: /* Try to track a strange bug reported by Harald Fuchs and others, where the lsn seems to decrease at times */ + if (log_peek_lsn(&new_lsn)) { + if (new_lsn < old_lsn) { + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Error: old log sequence number %llu" + " was greater\n" + "InnoDB: than the new log sequence number %llu!\n" + "InnoDB: Please submit a bug report" + " to http://bugs.mysql.com\n", + old_lsn, new_lsn); + ut_ad(0); + } - new_lsn = log_get_lsn(); - - if (new_lsn < old_lsn) { - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: old log sequence number %llu" - " was greater\n" - "InnoDB: than the new log sequence number %llu!\n" - "InnoDB: Please submit a bug report" - " to http://bugs.mysql.com\n", - old_lsn, new_lsn); - ut_ad(0); + old_lsn = new_lsn; } - old_lsn = new_lsn; - if (difftime(time(NULL), srv_last_monitor_time) > 60) { /* We referesh InnoDB Monitor values so that averages are printed from at most 60 last seconds */ From 6fd54c01bb5bc480497b143d63181837148ff47f Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 18 Apr 2016 23:15:15 +0400 Subject: [PATCH 29/91] MDEV-9521 Least function returns 0000-00-00 for null date columns instead of null Item_func_ifnull::date_op() and Item_func_coalesce::date_op() could erroneously return 0000-00-00 instead of NULL when get_date() was called with the TIME_FUZZY_DATES flag, e.g. from LEAST(). --- mysql-test/r/type_date.result | 35 +++++++++++++++++++++++++++++++++++ mysql-test/t/type_date.test | 29 +++++++++++++++++++++++++++++ sql/item_cmpfunc.cc | 14 ++++---------- 3 files changed, 68 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result index 4e299ecf0b1..7678f038862 100644 --- a/mysql-test/r/type_date.result +++ b/mysql-test/r/type_date.result @@ -440,3 +440,38 @@ id select_type table type possible_keys key key_len ref rows Extra select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1; 1 drop table t1; +# +# MDEV-9521 Least function returns 0000-00-00 for null date columns instead of null +# +CREATE TABLE t1 ( +id BIGINT NOT NULL, +date_debut DATE NOT NULL, +date_fin DATE DEFAULT NULL); +CREATE TABLE t2( +id BIGINT NOT NULL, +date_debut DATE NOT NULL, +date_fin DATE DEFAULT NULL); +INSERT INTO t1 VALUES (1,'2016-01-01','2016-01-31'); +INSERT INTO t1 VALUES (2,'2016-02-01',null); +INSERT INTO t1 VALUES (3,'2016-03-01','2016-03-31'); +INSERT INTO t1 VALUES (4,'2016-04-01',null); +INSERT INTO t2 VALUES (1,'2016-01-01','2016-01-31'); +INSERT INTO t2 VALUES (2,'2016-02-01','2016-01-28'); +INSERT INTO t2 VALUES (3,'2016-03-01',null); +INSERT INTO t2 VALUES (4,'2016-04-01',null); +SELECT t1.id, +GREATEST(t2.date_debut, t1.date_debut) AS date_debut, +LEAST(IFNULL(t2.date_fin, IFNULL(t1.date_fin, NULL)), +IFNULL(t1.date_fin, IFNULL(t2.date_fin, NULL))) AS date_fin +FROM t1 LEFT JOIN t2 ON (t1.id=t2.id); +id date_debut date_fin +1 2016-01-01 2016-01-31 00:00:00 +2 2016-02-01 2016-01-28 00:00:00 +3 2016-03-01 2016-03-31 00:00:00 +4 2016-04-01 NULL +DROP TABLE t1,t2; +SELECT +LEAST(COALESCE(DATE(NULL), DATE(NULL)), COALESCE(DATE(NULL), DATE(NULL))) AS d0, +LEAST(IFNULL(DATE(NULL), DATE(NULL)), IFNULL(DATE(NULL), DATE(NULL))) AS d1; +d0 d1 +NULL NULL diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test index 0b2ce16b7cc..4b058171ad2 100644 --- a/mysql-test/t/type_date.test +++ b/mysql-test/t/type_date.test @@ -386,3 +386,32 @@ select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1; select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1; drop table t1; +--echo # +--echo # MDEV-9521 Least function returns 0000-00-00 for null date columns instead of null +--echo # +CREATE TABLE t1 ( + id BIGINT NOT NULL, + date_debut DATE NOT NULL, + date_fin DATE DEFAULT NULL); +CREATE TABLE t2( + id BIGINT NOT NULL, + date_debut DATE NOT NULL, + date_fin DATE DEFAULT NULL); +INSERT INTO t1 VALUES (1,'2016-01-01','2016-01-31'); +INSERT INTO t1 VALUES (2,'2016-02-01',null); +INSERT INTO t1 VALUES (3,'2016-03-01','2016-03-31'); +INSERT INTO t1 VALUES (4,'2016-04-01',null); + +INSERT INTO t2 VALUES (1,'2016-01-01','2016-01-31'); +INSERT INTO t2 VALUES (2,'2016-02-01','2016-01-28'); +INSERT INTO t2 VALUES (3,'2016-03-01',null); +INSERT INTO t2 VALUES (4,'2016-04-01',null); +SELECT t1.id, + GREATEST(t2.date_debut, t1.date_debut) AS date_debut, + LEAST(IFNULL(t2.date_fin, IFNULL(t1.date_fin, NULL)), + IFNULL(t1.date_fin, IFNULL(t2.date_fin, NULL))) AS date_fin +FROM t1 LEFT JOIN t2 ON (t1.id=t2.id); +DROP TABLE t1,t2; +SELECT + LEAST(COALESCE(DATE(NULL), DATE(NULL)), COALESCE(DATE(NULL), DATE(NULL))) AS d0, + LEAST(IFNULL(DATE(NULL), DATE(NULL)), IFNULL(DATE(NULL), DATE(NULL))) AS d1; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 81688f3321c..9287b74a867 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2558,10 +2558,7 @@ bool Item_func_ifnull::date_op(MYSQL_TIME *ltime, uint fuzzydate) DBUG_ASSERT(fixed == 1); if (!args[0]->get_date(ltime, fuzzydate & ~TIME_FUZZY_DATES)) return (null_value= false); - if (!args[1]->get_date(ltime, fuzzydate & ~TIME_FUZZY_DATES)) - return (null_value= false); - bzero((char*) ltime,sizeof(*ltime)); - return null_value= !(fuzzydate & TIME_FUZZY_DATES); + return (null_value= args[1]->get_date(ltime, fuzzydate & ~TIME_FUZZY_DATES)); } @@ -3311,15 +3308,12 @@ double Item_func_coalesce::real_op() bool Item_func_coalesce::date_op(MYSQL_TIME *ltime,uint fuzzydate) { DBUG_ASSERT(fixed == 1); - null_value= 0; for (uint i= 0; i < arg_count; i++) { - bool res= args[i]->get_date(ltime, fuzzydate & ~TIME_FUZZY_DATES); - if (!args[i]->null_value) - return res; + if (!args[i]->get_date(ltime, fuzzydate & ~TIME_FUZZY_DATES)) + return (null_value= false); } - bzero((char*) ltime,sizeof(*ltime)); - return null_value|= !(fuzzydate & TIME_FUZZY_DATES); + return (null_value= true); } From 18ff6f654b1ca595fc5c0eebddbc1d0c5ee0d09e Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Tue, 19 Apr 2016 12:38:00 +0400 Subject: [PATCH 30/91] MDEV-9944 - main.events_2 fails sporadically Fixed wait condition in test case to actually wait for get_lock() completion (not for lock acquisition as it was before). This removes sporadic extra row in subsequent processlist queries. --- mysql-test/t/events_2.test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/t/events_2.test b/mysql-test/t/events_2.test index 48949d5630b..5443f76d1a1 100644 --- a/mysql-test/t/events_2.test +++ b/mysql-test/t/events_2.test @@ -67,10 +67,10 @@ select /*2*/ user, host, db, command, state, info select release_lock("test_lock2"); drop event закачка; -# Wait for release_lock("test_lock2") to complete, +# Wait for get_lock("test_lock2") to complete, # to avoid polluting the next test information_schema.processlist let $wait_condition= select count(*) = 0 from information_schema.processlist - where (state like 'User lock%' AND info like 'select get_lock%'); + where info='select get_lock("test_lock2", 20)'; --source include/wait_condition.inc From 9c64735986042432a207d9183b61c6d675beaf71 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 29 Mar 2016 12:50:56 +0200 Subject: [PATCH 31/91] MDEV-9748 Include Twin (mysys_err.h is included twice in mysys/my_copy.c) --- mysys/my_copy.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mysys/my_copy.c b/mysys/my_copy.c index 21de1e953a2..82cb2cc2f5f 100644 --- a/mysys/my_copy.c +++ b/mysys/my_copy.c @@ -18,7 +18,6 @@ #include "mysys_err.h" #include /* for stat */ #include -#include "mysys_err.h" #if defined(HAVE_UTIME_H) #include #elif defined(HAVE_SYS_UTIME_H) From edf71fd1d7b2d93c7f550d7b2cfecaf6b048fcec Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 16 Apr 2016 10:28:03 +0200 Subject: [PATCH 32/91] MDEV-9928 LC_TIME_NAMES=de_AT; unusual name for february s/Feber/Februar/ --- mysql-test/r/locale.result | 11 +++++++++++ mysql-test/t/locale.test | 9 +++++++++ sql/sql_locale.cc | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/locale.result b/mysql-test/r/locale.result index aa61d8cd86f..195468c4c12 100644 --- a/mysql-test/r/locale.result +++ b/mysql-test/r/locale.result @@ -90,3 +90,14 @@ SELECT DATE_FORMAT('2001-01-07', '%w %a %W'); DATE_FORMAT('2001-01-07', '%w %a %W') 0 Du Duminică End of 5.4 tests +SET NAMES utf8; +SET lc_time_names=de_AT; +SELECT monthname('2001-01-01'); +monthname('2001-01-01') +Jänner +SELECT monthname('2001-02-01'); +monthname('2001-02-01') +Februar +SELECT monthname('2001-03-01'); +monthname('2001-03-01') +März diff --git a/mysql-test/t/locale.test b/mysql-test/t/locale.test index 04ac95cea06..899d293545d 100644 --- a/mysql-test/t/locale.test +++ b/mysql-test/t/locale.test @@ -54,3 +54,12 @@ SELECT DATE_FORMAT('2001-01-05', '%w %a %W'); SELECT DATE_FORMAT('2001-01-06', '%w %a %W'); SELECT DATE_FORMAT('2001-01-07', '%w %a %W'); --echo End of 5.4 tests + +# +# MDEV-9928 LC_TIME_NAMES=de_AT; unusual name for february +# +SET NAMES utf8; +SET lc_time_names=de_AT; +SELECT monthname('2001-01-01'); +SELECT monthname('2001-02-01'); +SELECT monthname('2001-03-01'); diff --git a/sql/sql_locale.cc b/sql/sql_locale.cc index 13e00c99f19..3123474a59b 100644 --- a/sql/sql_locale.cc +++ b/sql/sql_locale.cc @@ -426,7 +426,7 @@ MY_LOCALE my_locale_da_DK /***** LOCALE BEGIN de_AT: German - Austria *****/ static const char *my_locale_month_names_de_AT[13] = - {"Jänner","Feber","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember", NullS }; + {"Jänner","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember", NullS }; static const char *my_locale_ab_month_names_de_AT[13] = {"Jän","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez", NullS }; static const char *my_locale_day_names_de_AT[8] = From 4f133fbf7951d0f48860cdefe79416f930615dab Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 16 Apr 2016 12:39:20 +0200 Subject: [PATCH 33/91] MDEV-9493 --tc-heuristic-recover option values off by one fix typelib to match defines: #define TC_HEURISTIC_RECOVER_COMMIT 1 #define TC_HEURISTIC_RECOVER_ROLLBACK 2 --- mysql-test/r/mysqld--help.result | 2 +- sql/mysqld.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 8bcad2a3cf5..ef68c064dd4 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -1091,7 +1091,7 @@ sysdate-is-now FALSE table-cache 400 table-definition-cache 400 table-open-cache 400 -tc-heuristic-recover COMMIT +tc-heuristic-recover OFF thread-cache-size 0 thread-stack 294912 time-format %H:%i:%s diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 45fb49f9cd9..fb52041fbc2 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -279,7 +279,7 @@ const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"}; static const char *tc_heuristic_recover_names[]= { - "COMMIT", "ROLLBACK", NullS + "OFF", "COMMIT", "ROLLBACK", NullS }; static TYPELIB tc_heuristic_recover_typelib= { From 3294cd11f852357b638cac74ba32578ffb456fc7 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 16 Apr 2016 17:36:47 +0200 Subject: [PATCH 34/91] MDEV-9929 MariaDB segfaults on command "mysqld --version" with ignore-db-dir option on /etc/my.cnf don't put command-line arguments into opt_ignore_db_dirs - it is supposed to contain a malloc()'ed accumulated list of all ignored dirs --- sql/mysqld.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index fb52041fbc2..3450447ceb9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7800,6 +7800,7 @@ mysqld_get_one_option(int optid, case OPT_IGNORE_DB_DIRECTORY: + opt_ignore_db_dirs= NULL; // will be set in ignore_db_dirs_process_additions if (*argument == 0) ignore_db_dirs_reset(); else From 95fe71afa6f1243af63429c5295b8b4bd74d6459 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 17 Apr 2016 18:51:54 +0200 Subject: [PATCH 35/91] MDEV-9707 MAX(timestamp(6) column) in correlated sub-query returns non-existent row data in original table special treatment for temporal values in create_tmp_field_from_item(). old code only did it when result_type() was STRING_RESULT, but Item_cache_temporal::result_type() is INT_RESULT --- mysql-test/r/cache_temporal_4265.result | 13 +++++++++++++ mysql-test/t/cache_temporal_4265.test | 11 +++++++++++ sql/sql_select.cc | 17 +++++++++-------- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/cache_temporal_4265.result b/mysql-test/r/cache_temporal_4265.result index 1b4b3c2c4aa..7f215de43fb 100644 --- a/mysql-test/r/cache_temporal_4265.result +++ b/mysql-test/r/cache_temporal_4265.result @@ -7,4 +7,17 @@ a 2002-03-04 Warnings: Note 1003 2000-01-01 +set debug_dbug=''; +drop table t1; +create table t1 (id int not null, ut timestamp(6) not null); +insert into t1 values(1, '2001-01-01 00:00:00.2'); +insert into t1 values(1, '2001-01-01 00:00:00.1'); +select * from t1; +id ut +1 2001-01-01 00:00:00.200000 +1 2001-01-01 00:00:00.100000 +select (select max(m2.ut) from t1 m2 where m1.id <> 0) from t1 m1; +(select max(m2.ut) from t1 m2 where m1.id <> 0) +2001-01-01 00:00:00.200000 +2001-01-01 00:00:00.200000 drop table t1; diff --git a/mysql-test/t/cache_temporal_4265.test b/mysql-test/t/cache_temporal_4265.test index 6135438f023..c62f3c3c506 100644 --- a/mysql-test/t/cache_temporal_4265.test +++ b/mysql-test/t/cache_temporal_4265.test @@ -7,5 +7,16 @@ create table t1 (a date); insert t1 values ('2000-01-02'), ('2001-02-03'), ('2002-03-04'); set debug_dbug='d,str_to_datetime_warn'; select * from t1 where a > date_add('2000-01-01', interval 5 day); +set debug_dbug=''; +drop table t1; + +# +# MDEV-9707 MAX(timestamp(6) column) in correlated sub-query returns non-existent row data in original table +# +create table t1 (id int not null, ut timestamp(6) not null); +insert into t1 values(1, '2001-01-01 00:00:00.2'); +insert into t1 values(1, '2001-01-01 00:00:00.1'); +select * from t1; +select (select max(m2.ut) from t1 m2 where m1.id <> 0) from t1 m1; drop table t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b1e22537b37..828dab7ef99 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -14544,6 +14544,14 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, Field *new_field; LINT_INIT(new_field); + /* + To preserve type or DATE/TIME and GEOMETRY fields, + they need to be handled separately. + */ + if (item->cmp_type() == TIME_RESULT || + item->field_type() == MYSQL_TYPE_GEOMETRY) + new_field= item->tmp_table_field_from_field_type(table, 1); + else switch (item->result_type()) { case REAL_RESULT: new_field= new Field_double(item->max_length, maybe_null, @@ -14566,18 +14574,11 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, case STRING_RESULT: DBUG_ASSERT(item->collation.collation); - /* - DATE/TIME and GEOMETRY fields have STRING_RESULT result type. - To preserve type they needed to be handled separately. - */ - if (item->cmp_type() == TIME_RESULT || - item->field_type() == MYSQL_TYPE_GEOMETRY) - new_field= item->tmp_table_field_from_field_type(table, 1); /* Make sure that the blob fits into a Field_varstring which has 2-byte lenght. */ - else if (item->max_length/item->collation.collation->mbmaxlen > 255 && + if (item->max_length/item->collation.collation->mbmaxlen > 255 && convert_blob_length <= Field_varstring::MAX_SIZE && convert_blob_length) new_field= new Field_varstring(convert_blob_length, maybe_null, From ce355304e6ecd47c4e65d437267842acb8aae6b7 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 17 Apr 2016 19:52:15 +0200 Subject: [PATCH 36/91] MDEV-9885 Client doesn't start if 'TERM' unknown 1. don't exit if setupterm() failed 2. don't use vidattr() if setupterm() failed --- client/mysql.cc | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index d33f8b186a0..65af4b8ddb8 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -95,9 +95,16 @@ extern "C" { #endif } -#if !defined(HAVE_VIDATTR) -#undef vidattr -#define vidattr(A) {} // Can't get this to work +#ifdef HAVE_VIDATTR +static int have_curses= 0; +static void my_vidattr(chtype attrs) +{ + if (have_curses) + vidattr(attrs); +} +#else +#undef HAVE_SETUPTERM +#define my_vidattr(A) {} // Can't get this to work #endif #ifdef FN_NO_CASE_SENSE @@ -4726,9 +4733,9 @@ com_status(String *buffer __attribute__((unused)), if (skip_updates) { - vidattr(A_BOLD); + my_vidattr(A_BOLD); tee_fprintf(stdout, "\nAll updates ignored to this database\n"); - vidattr(A_NORMAL); + my_vidattr(A_NORMAL); } #ifdef USE_POPEN tee_fprintf(stdout, "Current pager:\t\t%s\n", pager); @@ -4796,9 +4803,9 @@ com_status(String *buffer __attribute__((unused)), } if (safe_updates) { - vidattr(A_BOLD); + my_vidattr(A_BOLD); tee_fprintf(stdout, "\nNote that you are running in safe_update_mode:\n"); - vidattr(A_NORMAL); + my_vidattr(A_NORMAL); tee_fprintf(stdout, "\ UPDATEs and DELETEs that don't use a key in the WHERE clause are not allowed.\n\ (One can force an UPDATE/DELETE by adding LIMIT # at the end of the command.)\n\ @@ -4891,9 +4898,10 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate) { if (!inited) { + int errret; inited=1; #ifdef HAVE_SETUPTERM - (void) setupterm((char *)0, 1, (int *) 0); + have_curses= setupterm((char *)0, 1, &errret) != ERR; #endif } if (info_type == INFO_ERROR) @@ -4906,7 +4914,7 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate) putchar('\a'); /* This should make a bell */ #endif } - vidattr(A_STANDOUT); + my_vidattr(A_STANDOUT); if (error) { if (sqlstate) @@ -4925,9 +4933,9 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate) tee_fputs(": ", file); } else - vidattr(A_BOLD); + my_vidattr(A_BOLD); (void) tee_puts(str, file); - vidattr(A_NORMAL); + my_vidattr(A_NORMAL); } if (unbuffered) fflush(file); From 608c0e1c22ea6e2348bbb64d92d8c62d9c3410e8 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 18 Apr 2016 11:57:34 +0200 Subject: [PATCH 37/91] MDEV-5982 `make` fail @ ".../libmysql_versions.ld:155:9: invalid use of VERSION in input file" add a workaround for gold --- libmysql/CMakeLists.txt | 46 +++++++++++++++++++++++++++++--- libmysql/libmysql_versions.ld.in | 16 ++--------- 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt index e611efae65a..76156302c12 100644 --- a/libmysql/CMakeLists.txt +++ b/libmysql/CMakeLists.txt @@ -251,6 +251,25 @@ SET(CLIENT_API_FUNCTIONS ) IF(CMAKE_SYSTEM_NAME MATCHES "Linux") + IF (NOT DISABLE_LIBMYSQLCLIENT_SYMBOL_VERSIONING) + + INCLUDE (CheckCSourceCompiles) + FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.ld" + "VERSION {\nlibmysqlclient_18 {\nglobal: *;\n};\n}\n") + SET(CMAKE_REQUIRED_LIBRARIES "-Wl,src.ld") + CHECK_C_SOURCE_COMPILES("int main() { return 0; }" + SUPPORTS_VERSION_IN_LINK_SCRIPT) + SET(CMAKE_REQUIRED_LIBRARIES) + + IF (NOT SUPPORTS_VERSION_IN_LINK_SCRIPT) + # https://sourceware.org/bugzilla/show_bug.cgi?id=16895 + MESSAGE(SEND_ERROR "Your current linker does not support VERSION " + "command in linker scripts like a GNU ld or any compatible linker " + "should. Perhaps you're using gold? Either switch to GNU ld compatible " + "linker or run cmake with -DDISABLE_LIBMYSQLCLIENT_SYMBOL_VERSIONING=TRUE " + "to be able to complete the build") + ENDIF (NOT SUPPORTS_VERSION_IN_LINK_SCRIPT) + # When building RPM, or DEB package on Debian, use ELF symbol versioning # for compatibility with distribution packages, so client shared library can # painlessly replace the one supplied by the distribution. @@ -335,14 +354,26 @@ IF(CMAKE_SYSTEM_NAME MATCHES "Linux") make_scrambled_password_323 ) - # Linker script to version symbols in Fedora- and Debian- compatible way, MDEV-5529 - SET(VERSION_SCRIPT_TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/libmysql_versions.ld.in) - # Generate version script. # Create semicolon separated lists of functions to export from # Since RPM packages use separate versioning for 5.1 API # and 5.5 API (libmysqlclient_16 vs libmysqlclient_18), # we need 2 lists. + SET (VERSION_HEADER +"VERSION { + libmysqlclient_18 { + global:") + SET (VERSION_FOOTER +" local: + *; + }; + + libmysqlclient_16 { + /* empty here. aliases are added above */ + }; +} +") + SET (CLIENT_API_5_1_LIST) SET (CLIENT_API_5_1_ALIASES) FOREACH (f ${CLIENT_API_FUNCTIONS_5_1} ${CLIENT_API_5_1_EXTRA}) @@ -355,6 +386,13 @@ IF(CMAKE_SYSTEM_NAME MATCHES "Linux") SET(CLIENT_API_5_5_LIST "${CLIENT_API_5_5_LIST}\t${f};\n") ENDFOREACH() + ELSE (NOT DISABLE_LIBMYSQLCLIENT_SYMBOL_VERSIONING) + SET (CLIENT_API_5_1_ALIASES "/* Versioning disabled per user request. MDEV-5982 */") + ENDIF (NOT DISABLE_LIBMYSQLCLIENT_SYMBOL_VERSIONING) + + # Linker script to version symbols in Fedora- and Debian- compatible way, MDEV-5529 + SET(VERSION_SCRIPT_TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/libmysql_versions.ld.in) + CONFIGURE_FILE( ${VERSION_SCRIPT_TEMPLATE} ${CMAKE_CURRENT_BINARY_DIR}/libmysql_versions.ld @@ -363,7 +401,7 @@ IF(CMAKE_SYSTEM_NAME MATCHES "Linux") SET(VERSION_SCRIPT_LINK_FLAGS "-Wl,${CMAKE_CURRENT_BINARY_DIR}/libmysql_versions.ld") -ENDIF() +ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux") SET(CLIENT_SOURCES diff --git a/libmysql/libmysql_versions.ld.in b/libmysql/libmysql_versions.ld.in index 8d97da5b2eb..0cf5b45cc18 100644 --- a/libmysql/libmysql_versions.ld.in +++ b/libmysql/libmysql_versions.ld.in @@ -27,19 +27,7 @@ mysql_get_charset_by_csname = get_charset_by_csname; mysql_net_realloc = net_realloc; mysql_client_errors = client_errors; -VERSION { - -libmysqlclient_18 { - global: +@VERSION_HEADER@ @CLIENT_API_5_1_LIST@ @CLIENT_API_5_5_LIST@ - - local: - *; -}; - -libmysqlclient_16 { - /* empty here. aliases are added above */ -}; - -} +@VERSION_FOOTER@ From cc04a9fc0f60610d900f27ef60f8916a4ce1bb4c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 18 Apr 2016 18:30:42 +0200 Subject: [PATCH 38/91] MDEV-9835 Valid password is not working after server restart On SET PASSWORD if the plugin is mysql_native_password or mysql_old_password, do reset plugin and auth_str fields. --- mysql-test/r/set_password_plugin-9835.result | 158 +++++++++++++++++++ mysql-test/t/set_password_plugin-9835.test | 128 +++++++++++++++ sql/sql_acl.cc | 17 +- 3 files changed, 298 insertions(+), 5 deletions(-) create mode 100644 mysql-test/r/set_password_plugin-9835.result create mode 100644 mysql-test/t/set_password_plugin-9835.test diff --git a/mysql-test/r/set_password_plugin-9835.result b/mysql-test/r/set_password_plugin-9835.result new file mode 100644 index 00000000000..e9ee09fe952 --- /dev/null +++ b/mysql-test/r/set_password_plugin-9835.result @@ -0,0 +1,158 @@ +create user natauth@localhost identified via 'mysql_native_password' using '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29'; +create user newpass@localhost identified by password '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29'; +create user newpassnat@localhost identified via 'mysql_native_password'; +set password for newpassnat@localhost = '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29'; +create user oldauth@localhost identified with 'mysql_old_password' using '378b243e220ca493'; +create user oldpass@localhost identified by password '378b243e220ca493'; +create user oldpassold@localhost identified with 'mysql_old_password'; +set password for oldpassold@localhost = '378b243e220ca493'; +select user, host, password, plugin, authentication_string from mysql.user where user != 'root'; +user host password plugin authentication_string +natauth localhost mysql_native_password *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29 +newpass localhost *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29 +newpassnat localhost *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29 +oldauth localhost mysql_old_password 378b243e220ca493 +oldpass localhost 378b243e220ca493 +oldpassold localhost 378b243e220ca493 +connect con,localhost,natauth,test,; +select current_user(); +current_user() +natauth@localhost +disconnect con; +connect con,localhost,newpass,test,; +select current_user(); +current_user() +newpass@localhost +disconnect con; +connect con,localhost,newpassnat,test,; +select current_user(); +current_user() +newpassnat@localhost +disconnect con; +connect con,localhost,oldauth,test,; +select current_user(); +current_user() +oldauth@localhost +disconnect con; +connect con,localhost,oldpass,test,; +select current_user(); +current_user() +oldpass@localhost +disconnect con; +connect con,localhost,oldpassold,test,; +select current_user(); +current_user() +oldpassold@localhost +disconnect con; +connection default; +flush privileges; +connect con,localhost,natauth,test,; +select current_user(); +current_user() +natauth@localhost +disconnect con; +connect con,localhost,newpass,test,; +select current_user(); +current_user() +newpass@localhost +disconnect con; +connect con,localhost,newpassnat,test,; +select current_user(); +current_user() +newpassnat@localhost +disconnect con; +connect con,localhost,oldauth,test,; +select current_user(); +current_user() +oldauth@localhost +disconnect con; +connect con,localhost,oldpass,test,; +select current_user(); +current_user() +oldpass@localhost +disconnect con; +connect con,localhost,oldpassold,test,; +select current_user(); +current_user() +oldpassold@localhost +disconnect con; +connection default; +set password for natauth@localhost = PASSWORD('test2'); +set password for newpass@localhost = PASSWORD('test2'); +set password for newpassnat@localhost = PASSWORD('test2'); +set password for oldauth@localhost = PASSWORD('test2'); +set password for oldpass@localhost = PASSWORD('test2'); +set password for oldpassold@localhost = PASSWORD('test2'); +select user, host, password, plugin, authentication_string from mysql.user where user != 'root'; +user host password plugin authentication_string +natauth localhost *7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E +newpass localhost *7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E +newpassnat localhost *7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E +oldauth localhost *7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E +oldpass localhost *7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E +oldpassold localhost *7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E +connect con,localhost,natauth,test2,; +select current_user(); +current_user() +natauth@localhost +disconnect con; +connect con,localhost,newpass,test2,; +select current_user(); +current_user() +newpass@localhost +disconnect con; +connect con,localhost,newpassnat,test2,; +select current_user(); +current_user() +newpassnat@localhost +disconnect con; +connect con,localhost,oldauth,test2,; +select current_user(); +current_user() +oldauth@localhost +disconnect con; +connect con,localhost,oldpass,test2,; +select current_user(); +current_user() +oldpass@localhost +disconnect con; +connect con,localhost,oldpassold,test2,; +select current_user(); +current_user() +oldpassold@localhost +disconnect con; +connection default; +flush privileges; +connect con,localhost,natauth,test2,; +select current_user(); +current_user() +natauth@localhost +disconnect con; +connect con,localhost,newpass,test2,; +select current_user(); +current_user() +newpass@localhost +disconnect con; +connect con,localhost,newpassnat,test2,; +select current_user(); +current_user() +newpassnat@localhost +disconnect con; +connect con,localhost,oldauth,test2,; +select current_user(); +current_user() +oldauth@localhost +disconnect con; +connect con,localhost,oldpass,test2,; +select current_user(); +current_user() +oldpass@localhost +disconnect con; +connect con,localhost,oldpassold,test2,; +select current_user(); +current_user() +oldpassold@localhost +disconnect con; +connection default; +drop user natauth@localhost, newpass@localhost, newpassnat@localhost; +drop user oldauth@localhost, oldpass@localhost, oldpassold@localhost; diff --git a/mysql-test/t/set_password_plugin-9835.test b/mysql-test/t/set_password_plugin-9835.test new file mode 100644 index 00000000000..a10a339540f --- /dev/null +++ b/mysql-test/t/set_password_plugin-9835.test @@ -0,0 +1,128 @@ +# +# MDEV-9835 Valid password is not working after server restart. +# +# Various combinations of SET PASSWORD and not-empty mysql.user.plugin field +# +--source include/not_embedded.inc + +--enable_connect_log + +# The hash (old and new) is for 'test' +create user natauth@localhost identified via 'mysql_native_password' using '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29'; + +create user newpass@localhost identified by password '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29'; + +create user newpassnat@localhost identified via 'mysql_native_password'; +set password for newpassnat@localhost = '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29'; + +create user oldauth@localhost identified with 'mysql_old_password' using '378b243e220ca493'; + +create user oldpass@localhost identified by password '378b243e220ca493'; + +create user oldpassold@localhost identified with 'mysql_old_password'; +set password for oldpassold@localhost = '378b243e220ca493'; + +--sorted_result +select user, host, password, plugin, authentication_string from mysql.user where user != 'root'; + +--connect(con,localhost,natauth,test,) +select current_user(); +--disconnect con +--connect(con,localhost,newpass,test,) +select current_user(); +--disconnect con +--connect(con,localhost,newpassnat,test,) +select current_user(); +--disconnect con +--connect(con,localhost,oldauth,test,) +select current_user(); +--disconnect con +--connect(con,localhost,oldpass,test,) +select current_user(); +--disconnect con +--connect(con,localhost,oldpassold,test,) +select current_user(); +--disconnect con + +--connection default + +flush privileges; + +--connect(con,localhost,natauth,test,) +select current_user(); +--disconnect con +--connect(con,localhost,newpass,test,) +select current_user(); +--disconnect con +--connect(con,localhost,newpassnat,test,) +select current_user(); +--disconnect con +--connect(con,localhost,oldauth,test,) +select current_user(); +--disconnect con +--connect(con,localhost,oldpass,test,) +select current_user(); +--disconnect con +--connect(con,localhost,oldpassold,test,) +select current_user(); +--disconnect con + +--connection default + +# changing to the NEW password hash +set password for natauth@localhost = PASSWORD('test2'); +set password for newpass@localhost = PASSWORD('test2'); +set password for newpassnat@localhost = PASSWORD('test2'); +set password for oldauth@localhost = PASSWORD('test2'); +set password for oldpass@localhost = PASSWORD('test2'); +set password for oldpassold@localhost = PASSWORD('test2'); + +--sorted_result +select user, host, password, plugin, authentication_string from mysql.user where user != 'root'; + +--connect(con,localhost,natauth,test2,) +select current_user(); +--disconnect con +--connect(con,localhost,newpass,test2,) +select current_user(); +--disconnect con +--connect(con,localhost,newpassnat,test2,) +select current_user(); +--disconnect con +--connect(con,localhost,oldauth,test2,) +select current_user(); +--disconnect con +--connect(con,localhost,oldpass,test2,) +select current_user(); +--disconnect con +--connect(con,localhost,oldpassold,test2,) +select current_user(); +--disconnect con + +--connection default + +flush privileges; + +--connect(con,localhost,natauth,test2,) +select current_user(); +--disconnect con +--connect(con,localhost,newpass,test2,) +select current_user(); +--disconnect con +--connect(con,localhost,newpassnat,test2,) +select current_user(); +--disconnect con +--connect(con,localhost,oldauth,test2,) +select current_user(); +--disconnect con +--connect(con,localhost,oldpass,test2,) +select current_user(); +--disconnect con +--connect(con,localhost,oldpassold,test2,) +select current_user(); +--disconnect con + +--connection default +drop user natauth@localhost, newpass@localhost, newpassnat@localhost; +drop user oldauth@localhost, oldpass@localhost, oldpassold@localhost; + diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index da7c3f17c63..de76f27dee6 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -557,9 +557,8 @@ static void init_check_host(void); static void rebuild_check_host(void); static ACL_USER *find_acl_user(const char *host, const char *user, my_bool exact); -static bool update_user_table(THD *thd, TABLE *table, const char *host, - const char *user, const char *new_password, - uint new_password_len); +static bool update_user_table(THD *, TABLE *, const char *, const char *, const + char *, uint, bool); static my_bool acl_load(THD *thd, TABLE_LIST *tables); static my_bool grant_load(THD *thd, TABLE_LIST *tables); static inline void get_grantor(THD *thd, char* grantor); @@ -1912,6 +1911,7 @@ bool change_password(THD *thd, const char *host, const char *user, bool save_binlog_row_based; uint new_password_len= (uint) strlen(new_password); bool result= 1; + bool use_salt= 0; DBUG_ENTER("change_password"); DBUG_PRINT("enter",("host: '%s' user: '%s' new_password: '%s'", host,user,new_password)); @@ -1967,6 +1967,7 @@ bool change_password(THD *thd, const char *host, const char *user, acl_user->auth_string.length= new_password_len; set_user_salt(acl_user, new_password, new_password_len); set_user_plugin(acl_user, new_password_len); + use_salt= 1; } else push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, @@ -1975,7 +1976,7 @@ bool change_password(THD *thd, const char *host, const char *user, if (update_user_table(thd, table, acl_user->host.hostname ? acl_user->host.hostname : "", acl_user->user ? acl_user->user : "", - new_password, new_password_len)) + new_password, new_password_len, use_salt)) { mysql_mutex_unlock(&acl_cache->lock); /* purecov: deadcode */ goto end; @@ -2223,7 +2224,8 @@ bool hostname_requires_resolving(const char *hostname) static bool update_user_table(THD *thd, TABLE *table, const char *host, const char *user, - const char *new_password, uint new_password_len) + const char *new_password, uint new_password_len, + bool reset_plugin) { char user_key[MAX_KEY_LENGTH]; int error; @@ -2246,6 +2248,11 @@ static bool update_user_table(THD *thd, TABLE *table, } store_record(table,record[1]); table->field[2]->store(new_password, new_password_len, system_charset_info); + if (reset_plugin && table->s->fields >= 41) + { + table->field[40]->reset(); + table->field[41]->reset(); + } if ((error=table->file->ha_update_row(table->record[1],table->record[0])) && error != HA_ERR_RECORD_IS_THE_SAME) { From 1bc0b0b5245977172e2c3a3c64a42a2c4e762e06 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 19 Apr 2016 11:08:16 +0200 Subject: [PATCH 39/91] fix a couple of dbug tests not to write to /tmp --- mysql-test/r/mdev6830.result | 3 +-- mysql-test/r/select_debug.result | 2 +- mysql-test/t/mdev6830-master.opt | 1 - mysql-test/t/mdev6830.test | 10 +++++----- mysql-test/t/select_debug.test | 2 +- 5 files changed, 8 insertions(+), 10 deletions(-) delete mode 100644 mysql-test/t/mdev6830-master.opt diff --git a/mysql-test/r/mdev6830.result b/mysql-test/r/mdev6830.result index 0570659e860..d1cf8c98ac1 100644 --- a/mysql-test/r/mdev6830.result +++ b/mysql-test/r/mdev6830.result @@ -1,5 +1,4 @@ -drop table if exists t1,t2,t3; -drop view if exists v2,v3; +set @@debug_dbug= 'd,opt'; CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=MyISAM; CREATE TABLE t2 ( f1 DATE, diff --git a/mysql-test/r/select_debug.result b/mysql-test/r/select_debug.result index a056affc2cd..55882ad337a 100644 --- a/mysql-test/r/select_debug.result +++ b/mysql-test/r/select_debug.result @@ -6,7 +6,7 @@ insert into t1 values (2,2), (1,1); create table t2 (a int); insert into t2 values (2), (3); set session join_cache_level=3; -set @@debug_dbug= 'd:t:O,/tmp/trace.out'; +set @@debug_dbug= 'd,opt'; explain select t1.b from t1,t2 where t1.b=t2.a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where diff --git a/mysql-test/t/mdev6830-master.opt b/mysql-test/t/mdev6830-master.opt deleted file mode 100644 index 2a8c27d4731..00000000000 --- a/mysql-test/t/mdev6830-master.opt +++ /dev/null @@ -1 +0,0 @@ ---debug diff --git a/mysql-test/t/mdev6830.test b/mysql-test/t/mdev6830.test index 24565d04fed..3898d5bbef6 100644 --- a/mysql-test/t/mdev6830.test +++ b/mysql-test/t/mdev6830.test @@ -1,10 +1,10 @@ - +# +# MDEV-6830 Server crashes in best_access_path after a sequence of SELECTs invollving a temptable view +# --source include/have_debug.inc ---disable_warnings -drop table if exists t1,t2,t3; -drop view if exists v2,v3; ---enable_warnings +set @@debug_dbug= 'd,opt'; + CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=MyISAM; CREATE TABLE t2 ( diff --git a/mysql-test/t/select_debug.test b/mysql-test/t/select_debug.test index 4b77f9fd047..49415400db3 100644 --- a/mysql-test/t/select_debug.test +++ b/mysql-test/t/select_debug.test @@ -10,7 +10,7 @@ create table t2 (a int); insert into t2 values (2), (3); set session join_cache_level=3; -set @@debug_dbug= 'd:t:O,/tmp/trace.out'; +set @@debug_dbug= 'd,opt'; explain select t1.b from t1,t2 where t1.b=t2.a; select t1.b from t1,t2 where t1.b=t2.a; From 6c0e231c0282b43d6a46a4983f5971e960d3b8ca Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Tue, 19 Apr 2016 14:05:52 +0400 Subject: [PATCH 40/91] MDEV-9945 - main.kill_processlist-6619 fails sporadically SHOW PROCESSLIST output can be affected by not completed concurrent queries. Removed this affected SHOW PROCESSLIST since it doesn't seem to affect original problem. --- mysql-test/r/kill_processlist-6619.result | 4 ---- mysql-test/t/kill_processlist-6619.test | 2 -- 2 files changed, 6 deletions(-) diff --git a/mysql-test/r/kill_processlist-6619.result b/mysql-test/r/kill_processlist-6619.result index 588c8e6d139..a3d971e2115 100644 --- a/mysql-test/r/kill_processlist-6619.result +++ b/mysql-test/r/kill_processlist-6619.result @@ -1,8 +1,4 @@ connect con1,localhost,root,,; -SHOW PROCESSLIST; -Id User Host db Command Time State Info Progress -# root # test Sleep # # NULL 0.000 -# root # test Query # # SHOW PROCESSLIST 0.000 connection default; KILL QUERY con_id; connection con1; diff --git a/mysql-test/t/kill_processlist-6619.test b/mysql-test/t/kill_processlist-6619.test index 2333f02eac6..d73859ce8cd 100644 --- a/mysql-test/t/kill_processlist-6619.test +++ b/mysql-test/t/kill_processlist-6619.test @@ -5,8 +5,6 @@ --enable_connect_log --connect (con1,localhost,root,,) --let $con_id = `SELECT CONNECTION_ID()` ---replace_column 1 # 3 # 6 # 7 # -SHOW PROCESSLIST; --connection default --replace_result $con_id con_id eval KILL QUERY $con_id; From 9a987142f93756b37b2ff02d513034cc4079c978 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 20 Apr 2016 08:53:30 +0400 Subject: [PATCH 41/91] MDEV-9745 Crash with CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 4 END This is a backport of the patch for MDEV-9653 (fixed earlier in 10.1.13). The code in Item_func_case::fix_length_and_dec() did not calculate max_length and decimals properly. In case of any numeric result (DECIMAL, REAL, INT) a generic method Item_func_case::agg_num_lengths() was called, which could erroneously result into a DECIMAL item with max_length==0 and decimals==0, so the constructor of Field_new_decimals tried to create a field of DECIMAL(0,0) type, which caused a crash. Unlike Item_func_case, the code responsible for merging attributes in Item_func_coalesce::fix_length_and_dec() works fine: it has specific execution branches for all distinct numeric types and correctly creates a DECIMAL(1,0) column instead of DECIMAL(0,0) for the same set of arguments. The fix does the following: - Moves the attribute merging code from Item_func_coalesce::fix_length_and_dec() to a new method Item_func_hybrid_result_type::fix_attributes() - Removes the wrong code from Item_func_case::fix_length_and_dec() and reuses fix_attributes() in both Item_func_coalesce::fix_length_and_dec() and Item_func_case::fix_length_and_dec() - Fixes count_real_length() and count_decimal_length() to get an array of Items as an argument, instead of using Item::args directly. This is needed for Item_func_case::fix_length_and_dec(). - Moves methods Item_func::count_xxx_length() from "public" to "protected". - Removes Item_func_case::agg_num_length(), as it's not used any more. - Additionally removes Item_func_case::agg_str_length(), as it also was not used (dead code). --- mysql-test/r/case.result | 13 ++++++++++ mysql-test/t/case.test | 9 +++++++ sql/item_cmpfunc.cc | 51 ++++++++++++++-------------------------- sql/item_cmpfunc.h | 2 -- sql/item_func.cc | 22 ++++++++--------- sql/item_func.h | 15 ++++++------ 6 files changed, 59 insertions(+), 53 deletions(-) diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result index 3852da5d4b0..274d5da7d1c 100644 --- a/mysql-test/r/case.result +++ b/mysql-test/r/case.result @@ -231,3 +231,16 @@ case t1.f1 when '00:00:00' then 1 end 1 NULL drop table t1; +# +# MDEV-9745 Crash with CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 4 END +# +CREATE TABLE t1 SELECT CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 4 END AS a; +DESCRIBE t1; +Field Type Null Key Default Extra +a decimal(1,0) YES NULL +DROP TABLE t1; +CREATE TABLE t1 SELECT CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 40 END AS a; +DESCRIBE t1; +Field Type Null Key Default Extra +a decimal(2,0) YES NULL +DROP TABLE t1; diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test index f536f556780..c127836d352 100644 --- a/mysql-test/t/case.test +++ b/mysql-test/t/case.test @@ -193,3 +193,12 @@ insert t1 values ('00:00:00'),('00:01:00'); select case t1.f1 when '00:00:00' then 1 end from t1; drop table t1; +--echo # +--echo # MDEV-9745 Crash with CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 4 END +--echo # +CREATE TABLE t1 SELECT CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 4 END AS a; +DESCRIBE t1; +DROP TABLE t1; +CREATE TABLE t1 SELECT CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 40 END AS a; +DESCRIBE t1; +DROP TABLE t1; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 9287b74a867..fb75c9af794 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -3015,24 +3015,6 @@ bool Item_func_case::fix_fields(THD *thd, Item **ref) } -void Item_func_case::agg_str_lengths(Item* arg) -{ - fix_char_length(max(max_char_length(), arg->max_char_length())); - set_if_bigger(decimals, arg->decimals); - unsigned_flag= unsigned_flag && arg->unsigned_flag; -} - - -void Item_func_case::agg_num_lengths(Item *arg) -{ - uint len= my_decimal_length_to_precision(arg->max_length, arg->decimals, - arg->unsigned_flag) - arg->decimals; - set_if_bigger(max_length, len); - set_if_bigger(decimals, arg->decimals); - unsigned_flag= unsigned_flag && arg->unsigned_flag; -} - - /** Check if (*place) and new_value points to different Items and call THD::change_item_tree() if needed. @@ -3098,17 +3080,7 @@ void Item_func_case::fix_length_and_dec() } else { - collation.set_numeric(); - max_length=0; - decimals=0; - unsigned_flag= TRUE; - for (uint i= 0; i < ncases; i+= 2) - agg_num_lengths(args[i + 1]); - if (else_expr_num != -1) - agg_num_lengths(args[else_expr_num]); - max_length= my_decimal_precision_to_length_no_truncation(max_length + - decimals, decimals, - unsigned_flag); + fix_attributes(agg, nagg); } /* @@ -3336,19 +3308,32 @@ void Item_func_coalesce::fix_length_and_dec() { cached_field_type= agg_field_type(args, arg_count); agg_result_type(&cached_result_type, args, arg_count); + fix_attributes(args, arg_count); +} + + +#if MYSQL_VERSION_ID > 100100 +#error Rename this to Item_hybrid_func::fix_attributes() when mering to 10.1 +#endif +void Item_func_hybrid_result_type::fix_attributes(Item **items, uint nitems) +{ switch (cached_result_type) { case STRING_RESULT: - if (count_string_result_length(cached_field_type, args, arg_count)) + if (count_string_result_length(field_type(), + items, nitems)) return; break; case DECIMAL_RESULT: - count_decimal_length(); + collation.set_numeric(); + count_decimal_length(items, nitems); break; case REAL_RESULT: - count_real_length(); + collation.set_numeric(); + count_real_length(items, nitems); break; case INT_RESULT: - count_only_length(args, arg_count); + collation.set_numeric(); + count_only_length(items, nitems); decimals= 0; break; case ROW_RESULT: diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 0faba016ba8..0194f9cd0e0 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1255,8 +1255,6 @@ public: Item *find_item(String *str); CHARSET_INFO *compare_collation() { return cmp_collation.collation; } void cleanup(); - void agg_str_lengths(Item *arg); - void agg_num_lengths(Item *arg); }; /* diff --git a/sql/item_func.cc b/sql/item_func.cc index 252ca9e504b..bd6553d45d4 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -641,16 +641,16 @@ void Item_func::count_datetime_length(Item **item, uint nitems) result length/precision depends on argument ones. */ -void Item_func::count_decimal_length() +void Item_func::count_decimal_length(Item **item, uint nitems) { int max_int_part= 0; decimals= 0; unsigned_flag= 1; - for (uint i=0 ; i < arg_count ; i++) + for (uint i=0 ; i < nitems ; i++) { - set_if_bigger(decimals, args[i]->decimals); - set_if_bigger(max_int_part, args[i]->decimal_int_part()); - set_if_smaller(unsigned_flag, args[i]->unsigned_flag); + set_if_bigger(decimals, item[i]->decimals); + set_if_bigger(max_int_part, item[i]->decimal_int_part()); + set_if_smaller(unsigned_flag, item[i]->unsigned_flag); } int precision= min(max_int_part + decimals, DECIMAL_MAX_PRECISION); fix_char_length(my_decimal_precision_to_length_no_truncation(precision, @@ -681,19 +681,19 @@ void Item_func::count_only_length(Item **item, uint nitems) result length/precision depends on argument ones. */ -void Item_func::count_real_length() +void Item_func::count_real_length(Item **item, uint nitems) { uint32 length= 0; decimals= 0; max_length= 0; - for (uint i=0 ; i < arg_count ; i++) + for (uint i=0 ; i < nitems ; i++) { if (decimals != NOT_FIXED_DEC) { - set_if_bigger(decimals, args[i]->decimals); - set_if_bigger(length, (args[i]->max_length - args[i]->decimals)); + set_if_bigger(decimals, item[i]->decimals); + set_if_bigger(length, (item[i]->max_length - item[i]->decimals)); } - set_if_bigger(max_length, args[i]->max_length); + set_if_bigger(max_length, item[i]->max_length); } if (decimals != NOT_FIXED_DEC) { @@ -811,7 +811,7 @@ void Item_num_op::fix_length_and_dec(void) if (r0 == REAL_RESULT || r1 == REAL_RESULT || r0 == STRING_RESULT || r1 ==STRING_RESULT) { - count_real_length(); + count_real_length(args, arg_count); max_length= float_length(decimals); cached_result_type= REAL_RESULT; } diff --git a/sql/item_func.h b/sql/item_func.h index 33fa49f9168..9776ec0a5b7 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -39,6 +39,13 @@ protected: 0 means get this number from first argument */ uint allowed_arg_cols; + + void count_only_length(Item **item, uint nitems); + void count_real_length(Item **item, uint nitems); + void count_decimal_length(Item **item, uint nitems); + void count_datetime_length(Item **item, uint nitems); + bool count_string_result_length(enum_field_types field_type, + Item **item, uint nitems); public: uint arg_count; table_map used_tables_cache, not_null_tables_cache; @@ -146,16 +153,10 @@ public: virtual void print(String *str, enum_query_type query_type); void print_op(String *str, enum_query_type query_type); void print_args(String *str, uint from, enum_query_type query_type); - void count_only_length(Item **item, uint nitems); - void count_real_length(); - void count_decimal_length(); inline bool get_arg0_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) { return (null_value=args[0]->get_date(ltime, fuzzy_date)); } - void count_datetime_length(Item **item, uint nitems); - bool count_string_result_length(enum_field_types field_type, - Item **item, uint nitems); inline bool get_arg0_time(MYSQL_TIME *ltime) { null_value= args[0]->get_time(ltime); @@ -436,7 +437,7 @@ class Item_func_hybrid_result_type: public Item_func } protected: Item_result cached_result_type; - + void fix_attributes(Item **item, uint nitems); public: Item_func_hybrid_result_type() :Item_func(), cached_result_type(REAL_RESULT) { collation.set_numeric(); } From 2564650fb91faec3e409d6ffe369c82252042710 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 20 Apr 2016 11:02:34 +0400 Subject: [PATCH 42/91] MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool) The patch for MDEV-9745 earlier fixed the problem reported in MDEV-9662 as well. Only adding tests. --- mysql-test/include/ctype_numconv.inc | 6 ++++++ mysql-test/r/ctype_binary.result | 9 +++++++++ mysql-test/r/ctype_cp1251.result | 9 +++++++++ mysql-test/r/ctype_latin1.result | 9 +++++++++ mysql-test/r/ctype_ucs.result | 9 +++++++++ mysql-test/r/ctype_utf8.result | 9 +++++++++ 6 files changed, 51 insertions(+) diff --git a/mysql-test/include/ctype_numconv.inc b/mysql-test/include/ctype_numconv.inc index 25314d53fba..9b21e7f38c1 100644 --- a/mysql-test/include/ctype_numconv.inc +++ b/mysql-test/include/ctype_numconv.inc @@ -1794,6 +1794,12 @@ SELECT f1() FROM t1 LEFT JOIN (SELECT 1 AS a FROM t1 LIMIT 0) AS d ON 1 GROUP BY DROP FUNCTION f1; DROP TABLE t1; +--echo # +--echo # MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool) +--echo # +SELECT @@collation_connection; +SELECT CASE 1 WHEN 2 THEN ( - '3' ) END; + --echo # --echo # MDEV-5702 Incorrect results are returned with NULLIF() --echo # diff --git a/mysql-test/r/ctype_binary.result b/mysql-test/r/ctype_binary.result index 73c81c4eb06..e7bf1238210 100644 --- a/mysql-test/r/ctype_binary.result +++ b/mysql-test/r/ctype_binary.result @@ -2849,6 +2849,15 @@ f1() DROP FUNCTION f1; DROP TABLE t1; # +# MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool) +# +SELECT @@collation_connection; +@@collation_connection +binary +SELECT CASE 1 WHEN 2 THEN ( - '3' ) END; +CASE 1 WHEN 2 THEN ( - '3' ) END +NULL +# # MDEV-5702 Incorrect results are returned with NULLIF() # CREATE TABLE t1 (d DATE); diff --git a/mysql-test/r/ctype_cp1251.result b/mysql-test/r/ctype_cp1251.result index 313f60ef276..2a7d4ed1fb4 100644 --- a/mysql-test/r/ctype_cp1251.result +++ b/mysql-test/r/ctype_cp1251.result @@ -3241,6 +3241,15 @@ f1() DROP FUNCTION f1; DROP TABLE t1; # +# MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool) +# +SELECT @@collation_connection; +@@collation_connection +cp1251_general_ci +SELECT CASE 1 WHEN 2 THEN ( - '3' ) END; +CASE 1 WHEN 2 THEN ( - '3' ) END +NULL +# # MDEV-5702 Incorrect results are returned with NULLIF() # CREATE TABLE t1 (d DATE); diff --git a/mysql-test/r/ctype_latin1.result b/mysql-test/r/ctype_latin1.result index 11a9479afa3..dc96495b1ac 100644 --- a/mysql-test/r/ctype_latin1.result +++ b/mysql-test/r/ctype_latin1.result @@ -3423,6 +3423,15 @@ f1() DROP FUNCTION f1; DROP TABLE t1; # +# MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool) +# +SELECT @@collation_connection; +@@collation_connection +latin1_swedish_ci +SELECT CASE 1 WHEN 2 THEN ( - '3' ) END; +CASE 1 WHEN 2 THEN ( - '3' ) END +NULL +# # MDEV-5702 Incorrect results are returned with NULLIF() # CREATE TABLE t1 (d DATE); diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index f9e9a69de42..96e0970e4a6 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -4239,6 +4239,15 @@ f1() DROP FUNCTION f1; DROP TABLE t1; # +# MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool) +# +SELECT @@collation_connection; +@@collation_connection +ucs2_general_ci +SELECT CASE 1 WHEN 2 THEN ( - '3' ) END; +CASE 1 WHEN 2 THEN ( - '3' ) END +NULL +# # MDEV-5702 Incorrect results are returned with NULLIF() # CREATE TABLE t1 (d DATE); diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 09bb5195b74..217d3ca26d8 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -5060,6 +5060,15 @@ f1() DROP FUNCTION f1; DROP TABLE t1; # +# MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool) +# +SELECT @@collation_connection; +@@collation_connection +utf8_general_ci +SELECT CASE 1 WHEN 2 THEN ( - '3' ) END; +CASE 1 WHEN 2 THEN ( - '3' ) END +NULL +# # MDEV-5702 Incorrect results are returned with NULLIF() # CREATE TABLE t1 (d DATE); From e90f8b7a683a47b47417d847b69c52e2138e2259 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 20 Apr 2016 11:11:13 +0400 Subject: [PATCH 43/91] MDEV-9413 "datetime >= coalesce(c1(NULL))" doesn't return expected NULL The patch for MDEV-9521 earlier fixed the problem reported in MDEV-9413. Only adding tests. --- mysql-test/r/type_timestamp.result | 9 +++++++++ mysql-test/t/type_timestamp.test | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result index 52c7f05839e..1f17247b02a 100644 --- a/mysql-test/r/type_timestamp.result +++ b/mysql-test/r/type_timestamp.result @@ -644,4 +644,13 @@ SELECT MAX(dt) = '2011-01-06 12:34:30' FROM t1; MAX(dt) = '2011-01-06 12:34:30' 1 DROP TABLE t1; +# +# MDEV-9413 "datetime >= coalesce(c1(NULL))" doesn't return expected NULL +# +CREATE TABLE t1(c1 TIMESTAMP(6) NULL DEFAULT NULL); +INSERT INTO t1 VALUES(NULL); +SELECT c1, '2016-06-13 20:00:00.000003' >= COALESCE( c1 ) FROM t1; +c1 '2016-06-13 20:00:00.000003' >= COALESCE( c1 ) +NULL NULL +DROP TABLE t1; End of 5.5 tests diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test index 575c30431b6..0cc9c37fee9 100644 --- a/mysql-test/t/type_timestamp.test +++ b/mysql-test/t/type_timestamp.test @@ -446,4 +446,12 @@ SELECT MAX(ts) = '2011-01-06 12:34:30' FROM t1; SELECT MAX(dt) = '2011-01-06 12:34:30' FROM t1; DROP TABLE t1; +--echo # +--echo # MDEV-9413 "datetime >= coalesce(c1(NULL))" doesn't return expected NULL +--echo # +CREATE TABLE t1(c1 TIMESTAMP(6) NULL DEFAULT NULL); +INSERT INTO t1 VALUES(NULL); +SELECT c1, '2016-06-13 20:00:00.000003' >= COALESCE( c1 ) FROM t1; +DROP TABLE t1; + --echo End of 5.5 tests From 62122ba5d5f02a731742af233a858da3ff4ad426 Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Wed, 20 Apr 2016 00:36:58 +0300 Subject: [PATCH 44/91] MDEV-9953 Debian packages install broken 'maria' test suite which cannot be run Debian packages create empty maria/t and maria/r directories, and MTR cannot run maria.* tests --- debian/mariadb-test-5.5.dirs | 2 -- 1 file changed, 2 deletions(-) diff --git a/debian/mariadb-test-5.5.dirs b/debian/mariadb-test-5.5.dirs index f45bf43f7e9..65dbbc81c2a 100644 --- a/debian/mariadb-test-5.5.dirs +++ b/debian/mariadb-test-5.5.dirs @@ -50,8 +50,6 @@ usr/share/mysql/mysql-test/suite/ndb usr/share/mysql/mysql-test/suite/ndb/t usr/share/mysql/mysql-test/suite/ndb/r usr/share/mysql/mysql-test/suite/maria -usr/share/mysql/mysql-test/suite/maria/t -usr/share/mysql/mysql-test/suite/maria/r usr/share/mysql/mysql-test/suite/funcs_2 usr/share/mysql/mysql-test/suite/funcs_2/lib usr/share/mysql/mysql-test/suite/funcs_2/t From 0c0a865fad6c59b141892bfcb5be2dc2c11ae1a7 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Tue, 19 Apr 2016 16:16:13 +0400 Subject: [PATCH 45/91] MDEV-9943 - TokuDB fails to compile with gcc 5.2.1 For some reason check_cxx_compiler_flag() passes result variable name down to compiler: https://github.com/Kitware/CMake/blob/master/Modules/CheckCXXSourceCompiles.cmake#L57 But compiler doesn't permit dashes in macro name, like in -DHAVE_CXX_-fimplicit-templates. Workarounded by renaming HAVE_CXX_-fimplicit-templates to HAVE_CXX_IMPLICIT_TEMPLAES. --- .../cmake_modules/TokuSetupCompiler.cmake | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/storage/tokudb/ft-index/cmake_modules/TokuSetupCompiler.cmake b/storage/tokudb/ft-index/cmake_modules/TokuSetupCompiler.cmake index 99629e40bdb..fe99c9167d3 100644 --- a/storage/tokudb/ft-index/cmake_modules/TokuSetupCompiler.cmake +++ b/storage/tokudb/ft-index/cmake_modules/TokuSetupCompiler.cmake @@ -61,12 +61,13 @@ endmacro(set_cflags_if_supported_named) ## adds a compiler flag if the compiler supports it macro(set_cflags_if_supported) foreach(flag ${ARGN}) - check_c_compiler_flag(${flag} HAVE_C_${flag}) - if (HAVE_C_${flag}) + STRING(REGEX REPLACE "[-,= ]" "_" res ${flag}) + check_c_compiler_flag(${flag} HAVE_C_${res}) + if (HAVE_C_${res}) set(CMAKE_C_FLAGS "${flag} ${CMAKE_C_FLAGS}") endif () - check_cxx_compiler_flag(${flag} HAVE_CXX_${flag}) - if (HAVE_CXX_${flag}) + check_cxx_compiler_flag(${flag} HAVE_CXX_${res}) + if (HAVE_CXX_${res}) set(CMAKE_CXX_FLAGS "${flag} ${CMAKE_CXX_FLAGS}") endif () endforeach(flag) @@ -75,8 +76,9 @@ endmacro(set_cflags_if_supported) ## adds a linker flag if the compiler supports it macro(set_ldflags_if_supported) foreach(flag ${ARGN}) - check_cxx_compiler_flag(${flag} HAVE_${flag}) - if (HAVE_${flag}) + STRING(REGEX REPLACE "[-,= ]" "_" res ${flag}) + check_cxx_compiler_flag(${flag} HAVE_${res}) + if (HAVE_${res}) set(CMAKE_EXE_LINKER_FLAGS "${flag} ${CMAKE_EXE_LINKER_FLAGS}") set(CMAKE_SHARED_LINKER_FLAGS "${flag} ${CMAKE_SHARED_LINKER_FLAGS}") endif () @@ -103,8 +105,8 @@ set_cflags_if_supported( if (CMAKE_CXX_FLAGS MATCHES -fno-implicit-templates) # must append this because mysql sets -fno-implicit-templates and we need to override it - check_cxx_compiler_flag(-fimplicit-templates HAVE_CXX_-fimplicit-templates) - if (HAVE_CXX_-fimplicit-templates) + check_cxx_compiler_flag(-fimplicit-templates HAVE_CXX_IMPLICIT_TEMPLATES) + if (HAVE_CXX_IMPLICIT_TEMPLATES) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fimplicit-templates") endif () endif() From 8f1f869f68581238b7718169fd50e9d7b6c7f0a3 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 20 Apr 2016 15:26:37 +0200 Subject: [PATCH 46/91] another test case for ER_DATA_OUT_OF_RANGE on insert tests it with a non-const table too --- mysql-test/r/func_math.result | 5 +++++ mysql-test/t/func_math.test | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result index 3f8ab6c78d9..d122d435ac7 100644 --- a/mysql-test/r/func_math.result +++ b/mysql-test/r/func_math.result @@ -663,6 +663,11 @@ SELECT -a FROM t1; ERROR 22003: BIGINT value is out of range in '-(`test`.`t1`.`a`)' SELECT -b FROM t1; ERROR 22003: BIGINT value is out of range in '-(`test`.`t1`.`b`)' +INSERT INTO t1 VALUES(0,0); +SELECT -a FROM t1; +ERROR 22003: BIGINT value is out of range in '-(`test`.`t1`.`a`)' +SELECT -b FROM t1; +ERROR 22003: BIGINT value is out of range in '-(`test`.`t1`.`b`)' DROP TABLE t1; SET @a:=999999999999999999999999999999999999999999999999999999999999999999999999999999999; SELECT @a + @a; diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test index b843cf8c364..cd90184ebf5 100644 --- a/mysql-test/t/func_math.test +++ b/mysql-test/t/func_math.test @@ -484,6 +484,14 @@ SELECT -a FROM t1; --error ER_DATA_OUT_OF_RANGE SELECT -b FROM t1; +# try with two rows now +INSERT INTO t1 VALUES(0,0); + +--error ER_DATA_OUT_OF_RANGE +SELECT -a FROM t1; +--error ER_DATA_OUT_OF_RANGE +SELECT -b FROM t1; + DROP TABLE t1; # Decimal overflows From 9e826bfa36a57f10540ca6ea649cb450add48cf4 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 20 Apr 2016 15:28:44 +0200 Subject: [PATCH 47/91] trivial optimization don't call write_bin_log() when binlog is known to be disable --- sql/sql_table.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 9d161ebc0de..024ca9b58e1 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4880,8 +4880,10 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, /* We have to write the query before we unlock the tables. */ - if (!thd->is_current_stmt_binlog_disabled() && - thd->is_current_stmt_binlog_format_row()) + if (thd->is_current_stmt_binlog_disabled()) + goto err; + + if (thd->is_current_stmt_binlog_format_row()) { /* Since temporary tables are not replicated under row-based From 072ca71d26487817d025ee97955e6360c3c5c086 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Wed, 20 Apr 2016 18:20:31 +0400 Subject: [PATCH 48/91] MDEV-9281 - Debian: the Lintian complains about "shlib-calls-exit" in handlersocket.so MDEV-9278 - Debian: the Lintian complains about "shlib-calls-exit" in ha_spider.so Handlersocket handles errors in a way that it aborts program execution. In most cases it is done via abort(). One exception was host/service resolution failure, which was aborted with exit(). As a workaround replaced this exit() with abort() for symmetry with other error handling. --- plugin/handler_socket/client/hslongrun.cpp | 6 +++--- plugin/handler_socket/libhsclient/fatal.cpp | 8 -------- plugin/handler_socket/libhsclient/fatal.hpp | 1 - plugin/handler_socket/libhsclient/socket.cpp | 2 +- storage/spider/hs_client/fatal.cpp | 20 -------------------- storage/spider/hs_client/fatal.hpp | 2 -- storage/spider/hs_client/socket.cpp | 2 +- 7 files changed, 5 insertions(+), 36 deletions(-) diff --git a/plugin/handler_socket/client/hslongrun.cpp b/plugin/handler_socket/client/hslongrun.cpp index e82c12b166b..b7c02951340 100644 --- a/plugin/handler_socket/client/hslongrun.cpp +++ b/plugin/handler_socket/client/hslongrun.cpp @@ -39,7 +39,7 @@ struct auto_mysql : private noncopyable { mysql_close(db); } if ((db = mysql_init(0)) == 0) { - fatal_exit("failed to initialize mysql client"); + fatal_abort("failed to initialize mysql client"); } } operator MYSQL *() const { return db; } @@ -870,7 +870,7 @@ mysql_do(MYSQL *db, const char *query) { if (mysql_real_query(db, query, strlen(query)) != 0) { fprintf(stderr, "mysql: e=[%s] q=[%s]\n", mysql_error(db), query); - fatal_exit("mysql_do"); + fatal_abort("mysql_do"); } } @@ -886,7 +886,7 @@ hs_longrun_init_table(const config& conf, int num_prepare, if (!mysql_real_connect(db, mysql_host.c_str(), mysql_user.c_str(), mysql_passwd.c_str(), mysql_dbname.c_str(), mysql_port, 0, 0)) { fprintf(stderr, "mysql: error=[%s]\n", mysql_error(db)); - fatal_exit("hs_longrun_init_table"); + fatal_abort("hs_longrun_init_table"); } mysql_do(db, "drop database if exists hstestdb"); mysql_do(db, "create database hstestdb"); diff --git a/plugin/handler_socket/libhsclient/fatal.cpp b/plugin/handler_socket/libhsclient/fatal.cpp index 5cdd8879ab1..8e109cf13ba 100644 --- a/plugin/handler_socket/libhsclient/fatal.cpp +++ b/plugin/handler_socket/libhsclient/fatal.cpp @@ -17,14 +17,6 @@ namespace dena { const int opt_syslog = LOG_ERR | LOG_PID | LOG_CONS; -void -fatal_exit(const std::string& message) -{ - fprintf(stderr, "FATAL_EXIT: %s\n", message.c_str()); - syslog(opt_syslog, "FATAL_EXIT: %s", message.c_str()); - _exit(1); -} - void fatal_abort(const std::string& message) { diff --git a/plugin/handler_socket/libhsclient/fatal.hpp b/plugin/handler_socket/libhsclient/fatal.hpp index 8a630fab1cb..5eaa3db8687 100644 --- a/plugin/handler_socket/libhsclient/fatal.hpp +++ b/plugin/handler_socket/libhsclient/fatal.hpp @@ -13,7 +13,6 @@ namespace dena { -void fatal_exit(const std::string& message); void fatal_abort(const std::string& message); }; diff --git a/plugin/handler_socket/libhsclient/socket.cpp b/plugin/handler_socket/libhsclient/socket.cpp index cf19d4bbe14..2c93a3b4846 100644 --- a/plugin/handler_socket/libhsclient/socket.cpp +++ b/plugin/handler_socket/libhsclient/socket.cpp @@ -43,7 +43,7 @@ socket_args::set(const config& conf) } else { const char *nd = node.empty() ? 0 : node.c_str(); if (resolve(nd, port.c_str()) != 0) { - fatal_exit("getaddrinfo failed: " + node + ":" + port); + fatal_abort("getaddrinfo failed: " + node + ":" + port); } } } diff --git a/storage/spider/hs_client/fatal.cpp b/storage/spider/hs_client/fatal.cpp index bec031153e4..260a2e75372 100644 --- a/storage/spider/hs_client/fatal.cpp +++ b/storage/spider/hs_client/fatal.cpp @@ -25,26 +25,6 @@ namespace dena { const int opt_syslog = LOG_ERR | LOG_PID | LOG_CONS; */ -void -fatal_exit(const String& message) -{ - fprintf(stderr, "FATAL_EXIT: %s\n", message.ptr()); -/* - syslog(opt_syslog, "FATAL_EXIT: %s", message.ptr()); -*/ - _exit(1); -} - -void -fatal_exit(const char *message) -{ - fprintf(stderr, "FATAL_EXIT: %s\n", message); -/* - syslog(opt_syslog, "FATAL_EXIT: %s", message); -*/ - _exit(1); -} - void fatal_abort(const String& message) { diff --git a/storage/spider/hs_client/fatal.hpp b/storage/spider/hs_client/fatal.hpp index a75c56bddad..e1190ae49c1 100644 --- a/storage/spider/hs_client/fatal.hpp +++ b/storage/spider/hs_client/fatal.hpp @@ -22,8 +22,6 @@ namespace dena { -void fatal_exit(const String& message); -void fatal_exit(const char *message); void fatal_abort(const String& message); void fatal_abort(const char *message); diff --git a/storage/spider/hs_client/socket.cpp b/storage/spider/hs_client/socket.cpp index 2082d1f024e..c61b39d140f 100644 --- a/storage/spider/hs_client/socket.cpp +++ b/storage/spider/hs_client/socket.cpp @@ -67,7 +67,7 @@ socket_args::set(const config& conf) message.append(node); message.q_append(":", sizeof(":") - 1); message.append(port); - fatal_exit(message); + fatal_abort(message); } } } From 24ac546d0f16d5f56b11c068e4f187a9c4c56bd0 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 20 Apr 2016 18:27:23 +0200 Subject: [PATCH 49/91] use consistent error messaging for IGNORE 1. the same message text for INSERT and INSERT IGNORE 2. no new warnings in UPDATE IGNORE yet (big change for 5.5) and replace a commonly used expression with a named constant --- mysql-test/r/insert_innodb.result | 9 --------- sql/handler.cc | 25 ------------------------- sql/handler.h | 3 +-- sql/sql_insert.cc | 13 +++++-------- sql/sql_update.cc | 24 +++++------------------- 5 files changed, 11 insertions(+), 63 deletions(-) diff --git a/mysql-test/r/insert_innodb.result b/mysql-test/r/insert_innodb.result index e7a133a8945..ffba9388ec4 100644 --- a/mysql-test/r/insert_innodb.result +++ b/mysql-test/r/insert_innodb.result @@ -11,20 +11,11 @@ INSERT INTO t2 VALUES(0); INSERT IGNORE INTO t2 VALUES(1); Warnings: Warning 1452 Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`)) -Warning 1452 `test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`) UPDATE IGNORE t2 SET fld2=20 WHERE fld2=0; -Warnings: -Warning 1452 `test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`) UPDATE IGNORE t1 SET fld1=20 WHERE fld1=0; -Warnings: -Warning 1451 `test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`) # Test for multi update. UPDATE IGNORE t1, t2 SET t2.fld2= t2.fld2 + 3; -Warnings: -Warning 1452 `test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`) UPDATE IGNORE t1, t2 SET t1.fld1= t1.fld1 + 3; -Warnings: -Warning 1451 `test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`) # Reports an error since IGNORE is not used. INSERT INTO t2 VALUES(1); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`)) diff --git a/sql/handler.cc b/sql/handler.cc index 1a318334ef3..d528c0aea7a 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -5463,28 +5463,3 @@ fl_create_iterator(enum handler_iterator_type type, } } #endif /*TRANS_LOG_MGM_EXAMPLE_CODE*/ - - -/** - Report a warning for FK constraint violation. - - @param thd Thread handle. - @param table table on which the operation is performed. - @param error handler error number. -*/ -void warn_fk_constraint_violation(THD *thd,TABLE *table, int error) -{ - String str; - switch(error) { - case HA_ERR_ROW_IS_REFERENCED: - table->file->get_error_message(error, &str); - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_ROW_IS_REFERENCED_2, str.c_ptr_safe()); - break; - case HA_ERR_NO_REFERENCED_ROW: - table->file->get_error_message(error, &str); - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_NO_REFERENCED_ROW_2, str.c_ptr_safe()); - break; - } -} diff --git a/sql/handler.h b/sql/handler.h index 11718ba775c..3d6c8dea2bf 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -335,6 +335,7 @@ #define HA_CHECK_DUP_UNIQUE 2 #define HA_CHECK_FK_ERROR 4 #define HA_CHECK_DUP (HA_CHECK_DUP_KEY + HA_CHECK_DUP_UNIQUE) +#define HA_CHECK_ALL (~0U) enum legacy_db_type { @@ -3110,6 +3111,4 @@ inline const char *table_case_name(HA_CREATE_INFO *info, const char *name) return ((lower_case_table_names == 2 && info->alias) ? info->alias : name); } -void warn_fk_constraint_violation(THD *thd, TABLE *table, int error); - #endif /* HANDLER_INCLUDED */ diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 7e3a898b3da..c60ef6fcc6e 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1609,9 +1609,10 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) else table->file->insert_id_for_cur_row= insert_id_for_cur_row; bool is_duplicate_key_error; - if (table->file->is_fatal_error(error, HA_CHECK_DUP | HA_CHECK_FK_ERROR)) + if (table->file->is_fatal_error(error, HA_CHECK_ALL)) goto err; - is_duplicate_key_error= table->file->is_fatal_error(error, 0); + is_duplicate_key_error= + table->file->is_fatal_error(error, HA_CHECK_ALL & ~HA_CHECK_DUP); if (!is_duplicate_key_error) { /* @@ -1712,8 +1713,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) error != HA_ERR_RECORD_IS_THE_SAME) { if (info->ignore && - !table->file->is_fatal_error(error, HA_CHECK_DUP_KEY | - HA_CHECK_FK_ERROR)) + !table->file->is_fatal_error(error, HA_CHECK_ALL)) { if (!(thd->variables.old_behavior & OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE)) @@ -1845,7 +1845,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) { DEBUG_SYNC(thd, "write_row_noreplace"); if (!info->ignore || - table->file->is_fatal_error(error, HA_CHECK_DUP | HA_CHECK_FK_ERROR)) + table->file->is_fatal_error(error, HA_CHECK_ALL)) goto err; if (!(thd->variables.old_behavior & OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE)) @@ -1866,9 +1866,6 @@ ok_or_after_trg_err: my_safe_afree(key,table->s->max_unique_length,MAX_KEY_LENGTH); if (!table->file->has_transactions()) thd->transaction.stmt.modified_non_trans_table= TRUE; - if (info->ignore && - !table->file->is_fatal_error(error, HA_CHECK_FK_ERROR)) - warn_fk_constraint_violation(thd, table, error); DBUG_RETURN(trg_error); err: diff --git a/sql/sql_update.cc b/sql/sql_update.cc index d1b6e945b23..f134e0ba266 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -774,8 +774,7 @@ int mysql_update(THD *thd, error= 0; } else if (!ignore || - table->file->is_fatal_error(error, HA_CHECK_DUP_KEY | - HA_CHECK_FK_ERROR)) + table->file->is_fatal_error(error, HA_CHECK_ALL)) { /* If (ignore && error is ignorable) we don't have to @@ -783,8 +782,7 @@ int mysql_update(THD *thd, */ myf flags= 0; - if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY | - HA_CHECK_FK_ERROR)) + if (table->file->is_fatal_error(error, HA_CHECK_ALL)) flags|= ME_FATALERROR; /* Other handler errors are fatal */ prepare_record_for_error_message(error, table); @@ -792,9 +790,6 @@ int mysql_update(THD *thd, error= 1; break; } - else if (ignore && !table->file->is_fatal_error(error, - HA_CHECK_FK_ERROR)) - warn_fk_constraint_violation(thd, table, error); } if (table->triggers && @@ -1974,8 +1969,7 @@ int multi_update::send_data(List ¬_used_values) { updated--; if (!ignore || - table->file->is_fatal_error(error, HA_CHECK_DUP_KEY | - HA_CHECK_FK_ERROR)) + table->file->is_fatal_error(error, HA_CHECK_ALL)) { /* If (ignore && error == is ignorable) we don't have to @@ -1983,17 +1977,13 @@ int multi_update::send_data(List ¬_used_values) */ myf flags= 0; - if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY | - HA_CHECK_FK_ERROR)) + if (table->file->is_fatal_error(error, HA_CHECK_ALL)) flags|= ME_FATALERROR; /* Other handler errors are fatal */ prepare_record_for_error_message(error, table); table->file->print_error(error,MYF(flags)); DBUG_RETURN(1); } - else if (ignore && !table->file->is_fatal_error(error, - HA_CHECK_FK_ERROR)) - warn_fk_constraint_violation(thd, table, error); } else { @@ -2266,15 +2256,11 @@ int multi_update::do_updates() local_error != HA_ERR_RECORD_IS_THE_SAME) { if (!ignore || - table->file->is_fatal_error(local_error, HA_CHECK_DUP_KEY | - HA_CHECK_FK_ERROR)) + table->file->is_fatal_error(local_error, HA_CHECK_ALL)) { err_table= table; goto err; } - else if (ignore && !table->file->is_fatal_error(local_error, - HA_CHECK_FK_ERROR)) - warn_fk_constraint_violation(thd, table, local_error); } if (local_error != HA_ERR_RECORD_IS_THE_SAME) updated++; From 2a45fa900b5916e9b789b1a4052ffd7c724f4166 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 20 Apr 2016 19:03:59 +0200 Subject: [PATCH 50/91] MDEV-9836 Connection lost when using SSL Don't read from socket in yassl in SSL_pending(). Just return size of the buffered processed data. This is what OpenSSL is documented to do too: SSL_pending() returns the number of bytes which have been processed, buffered and are available inside ssl for immediate read. --- extra/yassl/src/ssl.cpp | 4 ---- mysql-test/r/ssl_timeout-9836.result | 7 +++++++ mysql-test/t/ssl_timeout-9836.opt | 1 + mysql-test/t/ssl_timeout-9836.test | 11 +++++++++++ 4 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 mysql-test/r/ssl_timeout-9836.result create mode 100644 mysql-test/t/ssl_timeout-9836.opt create mode 100644 mysql-test/t/ssl_timeout-9836.test diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp index 9516e8b985e..23465335922 100644 --- a/extra/yassl/src/ssl.cpp +++ b/extra/yassl/src/ssl.cpp @@ -1471,10 +1471,6 @@ int SSL_peek(SSL* ssl, void* buffer, int sz) int SSL_pending(SSL* ssl) { - // Just in case there's pending data that hasn't been processed yet... - char c; - SSL_peek(ssl, &c, 1); - return ssl->bufferedData(); } diff --git a/mysql-test/r/ssl_timeout-9836.result b/mysql-test/r/ssl_timeout-9836.result new file mode 100644 index 00000000000..bc2e19e1475 --- /dev/null +++ b/mysql-test/r/ssl_timeout-9836.result @@ -0,0 +1,7 @@ +SET @@net_read_timeout=1; +SELECT 1; +1 +1 +SELECT 1; +1 +1 diff --git a/mysql-test/t/ssl_timeout-9836.opt b/mysql-test/t/ssl_timeout-9836.opt new file mode 100644 index 00000000000..7a2696875b8 --- /dev/null +++ b/mysql-test/t/ssl_timeout-9836.opt @@ -0,0 +1 @@ +--loose-thread-handling=pool-of-threads diff --git a/mysql-test/t/ssl_timeout-9836.test b/mysql-test/t/ssl_timeout-9836.test new file mode 100644 index 00000000000..5b57917f3b8 --- /dev/null +++ b/mysql-test/t/ssl_timeout-9836.test @@ -0,0 +1,11 @@ +# +# MDEV-9836 Connection lost when using SSL +# +-- source include/have_ssl_communication.inc +connect(con1,localhost,root,,,,,SSL); +SET @@net_read_timeout=1; +SELECT 1; +# MDEV-9836 - YASSL bug - SSL connection lost if it has been idle, for longer than net_read_timeout +-- sleep 2 +SELECT 1; +disconnect con1; From e5410da190d3e37af997f5b9bb1de2acb818f6f5 Mon Sep 17 00:00:00 2001 From: Igor Pashev Date: Thu, 21 Apr 2016 08:18:54 -0700 Subject: [PATCH 51/91] SEGFAULT in get_column_grant() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to a typo, the wrong grant_table was used when fetching privileges for roles. Signed-off-by: VicenÈ›iu Ciorbaru --- sql/sql_acl.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index a70afe4fca9..bbd1dd86880 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -7453,7 +7453,8 @@ ulong get_column_grant(THD *thd, GRANT_INFO *grant, if (!grant_column) priv|= (grant->privilege | grant_table_role->privs); else - priv|= (grant->privilege | grant_table->privs | grant_column->rights); + priv|= (grant->privilege | grant_table_role->privs | + grant_column->rights); } } mysql_rwlock_unlock(&LOCK_grant); From 628bc576b328f85ed2674c49c1d2ab5dd3a63d2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 21 Apr 2016 10:52:52 +0300 Subject: [PATCH 52/91] MDEV-9918: [ERROR] mysqld got signal 11 during ALTER TABLE `name` COLUMN ADD Problem was that in-place online alter table was used on a table that had mismatch between MySQL frm file and InnoDB data dictionary. Fixed so that traditional "Copy" method is used if the MySQL frm and InnoDB data dictionary is not consistent. --- .../innodb/r/innodb-corrupted-table.result | 49 ++++++ .../innodb/t/innodb-corrupted-table.test | 46 ++++++ storage/innobase/handler/ha_innodb.cc | 145 +++++++++++++----- storage/innobase/handler/ha_innodb.h | 14 ++ storage/innobase/handler/handler0alter.cc | 14 ++ storage/innobase/include/dict0mem.h | 17 ++ storage/xtradb/handler/ha_innodb.cc | 145 +++++++++++++----- storage/xtradb/handler/ha_innodb.h | 14 ++ storage/xtradb/handler/handler0alter.cc | 14 ++ storage/xtradb/include/dict0mem.h | 17 ++ 10 files changed, 393 insertions(+), 82 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb-corrupted-table.result create mode 100644 mysql-test/suite/innodb/t/innodb-corrupted-table.test diff --git a/mysql-test/suite/innodb/r/innodb-corrupted-table.result b/mysql-test/suite/innodb/r/innodb-corrupted-table.result new file mode 100644 index 00000000000..61d10fbb949 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-corrupted-table.result @@ -0,0 +1,49 @@ +call mtr.add_suppression("Table .* has a primary key in InnoDB data dictionary, but not in MySQL.*"); +call mtr.add_suppression("InnoDB: Table .* contains .* indexes inside InnoDB, which is different from the number of indexes .* defined in the MySQL.*"); +create table t1 (pk int, i int, key(i)) engine=InnoDB; +insert into t1 values (1,1),(2,2); +flush tables; +# Save the .frm file without the PK +alter table t1 add primary key (pk); +# Stop the server, replace the frm with the old one and restart the server +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `pk` int(11) DEFAULT NULL, + `i` int(11) DEFAULT NULL, + KEY `i` (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +Warnings: +Warning 1082 InnoDB: Table test/t1 has a primary key in InnoDB data dictionary, but not in MySQL! +Warning 1082 InnoDB: Table test/t1 contains 2 indexes inside InnoDB, which is different from the number of indexes 1 defined in the MySQL +select * from t1; +pk i +1 1 +2 2 +alter table t1 add j int; +Warnings: +Warning 1082 InnoDB: Table test/t1 contains 2 indexes inside InnoDB, which is different from the number of indexes 1 defined in the MySQL +show warnings; +Level Code Message +Warning 1082 InnoDB: Table test/t1 contains 2 indexes inside InnoDB, which is different from the number of indexes 1 defined in the MySQL +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `pk` int(11) DEFAULT NULL, + `i` int(11) DEFAULT NULL, + `j` int(11) DEFAULT NULL, + KEY `i` (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +alter table t1 add primary key (pk); +show warnings; +Level Code Message +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `pk` int(11) NOT NULL DEFAULT '0', + `i` int(11) DEFAULT NULL, + `j` int(11) DEFAULT NULL, + PRIMARY KEY (`pk`), + KEY `i` (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +drop table t1; diff --git a/mysql-test/suite/innodb/t/innodb-corrupted-table.test b/mysql-test/suite/innodb/t/innodb-corrupted-table.test new file mode 100644 index 00000000000..94c5454429f --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-corrupted-table.test @@ -0,0 +1,46 @@ +--source include/have_innodb.inc +--source include/not_embedded.inc + +# +# MDEV-9918: [ERROR] mysqld got signal 11 during ALTER TABLE `name` COLUMN ADD +# + +call mtr.add_suppression("Table .* has a primary key in InnoDB data dictionary, but not in MySQL.*"); +call mtr.add_suppression("InnoDB: Table .* contains .* indexes inside InnoDB, which is different from the number of indexes .* defined in the MySQL.*"); + +create table t1 (pk int, i int, key(i)) engine=InnoDB; +insert into t1 values (1,1),(2,2); + +--let $datadir= `select @@datadir` + +flush tables; + +--echo # Save the .frm file without the PK + +--copy_file $datadir/test/t1.frm $MYSQLTEST_VARDIR/tmp/t1.frm + +alter table t1 add primary key (pk); + +--echo # Stop the server, replace the frm with the old one and restart the server + +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server 10 +--source include/wait_until_disconnected.inc + +--remove_file $datadir/test/t1.frm +--copy_file $MYSQLTEST_VARDIR/tmp/t1.frm $datadir/test/t1.frm + +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--enable_reconnect +--source include/wait_until_connected_again.inc + +show create table t1; +select * from t1; +alter table t1 add j int; +show warnings; +show create table t1; +alter table t1 add primary key (pk); +show warnings; +show create table t1; +# Cleanup +drop table t1; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index bcd8a8890f8..42cbc1d7076 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4,7 +4,7 @@ Copyright (c) 2000, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2014 SkySQL Ab. All Rights Reserved. +Copyright (c) 2013, 2016, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -5513,20 +5513,14 @@ table_opened: prebuilt->clust_index_was_generated = FALSE; if (UNIV_UNLIKELY(primary_key >= MAX_KEY)) { - sql_print_error("Table %s has a primary key in " - "InnoDB data dictionary, but not " - "in MySQL!", name); + ib_table->dict_frm_mismatch = DICT_FRM_NO_PK; /* This mismatch could cause further problems if not attended, bring this to the user's attention by printing a warning in addition to log a message in the errorlog */ - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_NO_SUCH_INDEX, - "InnoDB: Table %s has a " - "primary key in InnoDB data " - "dictionary, but not in " - "MySQL!", name); + + ib_push_frm_error(thd, ib_table, table, 0, true); /* If primary_key >= MAX_KEY, its (primary_key) value could be out of bound if continue to index @@ -5573,27 +5567,14 @@ table_opened: } } else { if (primary_key != MAX_KEY) { - sql_print_error( - "Table %s has no primary key in InnoDB data " - "dictionary, but has one in MySQL! If you " - "created the table with a MySQL version < " - "3.23.54 and did not define a primary key, " - "but defined a unique key with all non-NULL " - "columns, then MySQL internally treats that " - "key as the primary key. You can fix this " - "error by dump + DROP + CREATE + reimport " - "of the table.", name); + + ib_table->dict_frm_mismatch = DICT_NO_PK_FRM_HAS; /* This mismatch could cause further problems if not attended, bring this to the user attention by printing a warning in addition to log a message in the errorlog */ - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_NO_SUCH_INDEX, - "InnoDB: Table %s has no " - "primary key in InnoDB data " - "dictionary, but has one in " - "MySQL!", name); + ib_push_frm_error(thd, ib_table, table, 0, true); } prebuilt->clust_index_was_generated = TRUE; @@ -11669,12 +11650,8 @@ ha_innobase::info_low( } if (table->s->keys != num_innodb_index) { - sql_print_error("InnoDB: Table %s contains %lu " - "indexes inside InnoDB, which " - "is different from the number of " - "indexes %u defined in the MySQL ", - ib_table->name, num_innodb_index, - table->s->keys); + ib_table->dict_frm_mismatch = DICT_FRM_INCONSISTENT_KEYS; + ib_push_frm_error(user_thd, ib_table, table, num_innodb_index, true); } if (!(flag & HA_STATUS_NO_LOCK)) { @@ -11694,15 +11671,8 @@ ha_innobase::info_low( dict_index_t* index = innobase_get_index(i); if (index == NULL) { - sql_print_error("Table %s contains fewer " - "indexes inside InnoDB than " - "are defined in the MySQL " - ".frm file. Have you mixed up " - ".frm files from different " - "installations? See " - REFMAN - "innodb-troubleshooting.html\n", - ib_table->name); + ib_table->dict_frm_mismatch = DICT_FRM_INCONSISTENT_KEYS; + ib_push_frm_error(user_thd, ib_table, table, num_innodb_index, true); break; } @@ -17874,3 +17844,96 @@ ib_push_warning( my_free(buf); va_end(args); } + +/********************************************************************//** +Helper function to push frm mismatch error to error log and +if needed to sql-layer. */ +UNIV_INTERN +void +ib_push_frm_error( +/*==============*/ + THD* thd, /*!< in: MySQL thd */ + dict_table_t* ib_table, /*!< in: InnoDB table */ + TABLE* table, /*!< in: MySQL table */ + ulint n_keys, /*!< in: InnoDB #keys */ + bool push_warning) /*!< in: print warning ? */ +{ + switch (ib_table->dict_frm_mismatch) { + case DICT_FRM_NO_PK: + sql_print_error("Table %s has a primary key in " + "InnoDB data dictionary, but not " + "in MySQL!" + " Have you mixed up " + ".frm files from different " + "installations? See " + REFMAN + "innodb-troubleshooting.html\n", + ib_table->name); + + if (push_warning) { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_NO_SUCH_INDEX, + "InnoDB: Table %s has a " + "primary key in InnoDB data " + "dictionary, but not in " + "MySQL!", ib_table->name); + } + break; + case DICT_NO_PK_FRM_HAS: + sql_print_error( + "Table %s has no primary key in InnoDB data " + "dictionary, but has one in MySQL! If you " + "created the table with a MySQL version < " + "3.23.54 and did not define a primary key, " + "but defined a unique key with all non-NULL " + "columns, then MySQL internally treats that " + "key as the primary key. You can fix this " + "error by dump + DROP + CREATE + reimport " + "of the table.", ib_table->name); + + if (push_warning) { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_NO_SUCH_INDEX, + "InnoDB: Table %s has no " + "primary key in InnoDB data " + "dictionary, but has one in " + "MySQL!", + ib_table->name); + } + break; + + case DICT_FRM_INCONSISTENT_KEYS: + sql_print_error("InnoDB: Table %s contains %lu " + "indexes inside InnoDB, which " + "is different from the number of " + "indexes %u defined in the MySQL " + " Have you mixed up " + ".frm files from different " + "installations? See " + REFMAN + "innodb-troubleshooting.html\n", + ib_table->name, n_keys, + table->s->keys); + + if (push_warning) { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_NO_SUCH_INDEX, + "InnoDB: Table %s contains %lu " + "indexes inside InnoDB, which " + "is different from the number of " + "indexes %u defined in the MySQL ", + ib_table->name, n_keys, + table->s->keys); + } + break; + + case DICT_FRM_CONSISTENT: + default: + sql_print_error("InnoDB: Table %s is consistent " + "on InnoDB data dictionary and MySQL " + " FRM file.", + ib_table->name); + ut_error; + break; + } +} diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 5cebc425769..54ef548406f 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2000, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2013, 2016, 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 @@ -640,3 +641,16 @@ innobase_copy_frm_flags_from_table_share( /*=====================================*/ dict_table_t* innodb_table, /*!< in/out: InnoDB table */ const TABLE_SHARE* table_share); /*!< in: table share */ + +/********************************************************************//** +Helper function to push frm mismatch error to error log and +if needed to sql-layer. */ +UNIV_INTERN +void +ib_push_frm_error( +/*==============*/ + THD* thd, /*!< in: MySQL thd */ + dict_table_t* ib_table, /*!< in: InnoDB table */ + TABLE* table, /*!< in: MySQL table */ + ulint n_keys, /*!< in: InnoDB #keys */ + bool push_warning); /*!< in: print warning ? */ diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 476e841b892..1848ac6db4f 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -435,6 +435,20 @@ ha_innobase::check_if_supported_inplace_alter( } } + ulint n_indexes = UT_LIST_GET_LEN((prebuilt->table)->indexes); + + /* If InnoDB dictionary and MySQL frm file are not consistent + use "Copy" method. */ + if (prebuilt->table->dict_frm_mismatch) { + + ha_alter_info->unsupported_reason = innobase_get_err_msg( + ER_NO_SUCH_INDEX); + ib_push_frm_error(user_thd, prebuilt->table, altered_table, + n_indexes, true); + + DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); + } + /* We should be able to do the operation in-place. See if we can do it online (LOCK=NONE). */ bool online = true; diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 5f6811f0719..7a84e4e991d 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -2,6 +2,7 @@ Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2015, 2016, 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 @@ -903,6 +904,18 @@ if table->memcached_sync_count == DICT_TABLE_IN_DDL means there's DDL running on the table, DML from memcached will be blocked. */ #define DICT_TABLE_IN_DDL -1 +/** These are used when MySQL FRM and InnoDB data dictionary are +in inconsistent state. */ +typedef enum { + DICT_FRM_CONSISTENT = 0, /*!< Consistent state */ + DICT_FRM_NO_PK = 1, /*!< MySQL has no primary key + but InnoDB dictionary has + non-generated one. */ + DICT_NO_PK_FRM_HAS = 2, /*!< MySQL has primary key but + InnoDB dictionary has not. */ + DICT_FRM_INCONSISTENT_KEYS = 3 /*!< Key count mismatch */ +} dict_frm_t; + /** Data structure for a database table. Most fields will be initialized to 0, NULL or FALSE in dict_mem_table_create(). */ struct dict_table_t{ @@ -961,6 +974,10 @@ struct dict_table_t{ /*!< True if the table belongs to a system database (mysql, information_schema or performance_schema) */ + dict_frm_t dict_frm_mismatch; + /*!< !DICT_FRM_CONSISTENT==0 if data + dictionary information and + MySQL FRM information mismatch. */ #ifndef UNIV_HOTBACKUP hash_node_t name_hash; /*!< hash chain node */ hash_node_t id_hash; /*!< hash chain node */ diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index a3e9166c15e..4dd764cac2c 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -4,7 +4,7 @@ Copyright (c) 2000, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2014 SkySQL Ab. All Rights Reserved. +Copyright (c) 2013, 2016, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -5950,20 +5950,14 @@ table_opened: prebuilt->clust_index_was_generated = FALSE; if (UNIV_UNLIKELY(primary_key >= MAX_KEY)) { - sql_print_error("Table %s has a primary key in " - "InnoDB data dictionary, but not " - "in MySQL!", name); + ib_table->dict_frm_mismatch = DICT_FRM_NO_PK; /* This mismatch could cause further problems if not attended, bring this to the user's attention by printing a warning in addition to log a message in the errorlog */ - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_NO_SUCH_INDEX, - "InnoDB: Table %s has a " - "primary key in InnoDB data " - "dictionary, but not in " - "MySQL!", name); + + ib_push_frm_error(thd, ib_table, table, 0, true); /* If primary_key >= MAX_KEY, its (primary_key) value could be out of bound if continue to index @@ -6010,27 +6004,14 @@ table_opened: } } else { if (primary_key != MAX_KEY) { - sql_print_error( - "Table %s has no primary key in InnoDB data " - "dictionary, but has one in MySQL! If you " - "created the table with a MySQL version < " - "3.23.54 and did not define a primary key, " - "but defined a unique key with all non-NULL " - "columns, then MySQL internally treats that " - "key as the primary key. You can fix this " - "error by dump + DROP + CREATE + reimport " - "of the table.", name); + + ib_table->dict_frm_mismatch = DICT_NO_PK_FRM_HAS; /* This mismatch could cause further problems if not attended, bring this to the user attention by printing a warning in addition to log a message in the errorlog */ - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_NO_SUCH_INDEX, - "InnoDB: Table %s has no " - "primary key in InnoDB data " - "dictionary, but has one in " - "MySQL!", name); + ib_push_frm_error(thd, ib_table, table, 0, true); } prebuilt->clust_index_was_generated = TRUE; @@ -12244,12 +12225,8 @@ ha_innobase::info_low( } if (table->s->keys != num_innodb_index) { - sql_print_error("InnoDB: Table %s contains %lu " - "indexes inside InnoDB, which " - "is different from the number of " - "indexes %u defined in the MySQL ", - ib_table->name, num_innodb_index, - table->s->keys); + ib_table->dict_frm_mismatch = DICT_FRM_INCONSISTENT_KEYS; + ib_push_frm_error(user_thd, ib_table, table, num_innodb_index, true); } if (!(flag & HA_STATUS_NO_LOCK)) { @@ -12269,15 +12246,8 @@ ha_innobase::info_low( dict_index_t* index = innobase_get_index(i); if (index == NULL) { - sql_print_error("Table %s contains fewer " - "indexes inside InnoDB than " - "are defined in the MySQL " - ".frm file. Have you mixed up " - ".frm files from different " - "installations? See " - REFMAN - "innodb-troubleshooting.html\n", - ib_table->name); + ib_table->dict_frm_mismatch = DICT_FRM_INCONSISTENT_KEYS; + ib_push_frm_error(user_thd, ib_table, table, num_innodb_index, true); break; } @@ -19182,3 +19152,96 @@ ib_push_warning( my_free(buf); va_end(args); } + +/********************************************************************//** +Helper function to push frm mismatch error to error log and +if needed to sql-layer. */ +UNIV_INTERN +void +ib_push_frm_error( +/*==============*/ + THD* thd, /*!< in: MySQL thd */ + dict_table_t* ib_table, /*!< in: InnoDB table */ + TABLE* table, /*!< in: MySQL table */ + ulint n_keys, /*!< in: InnoDB #keys */ + bool push_warning) /*!< in: print warning ? */ +{ + switch (ib_table->dict_frm_mismatch) { + case DICT_FRM_NO_PK: + sql_print_error("Table %s has a primary key in " + "InnoDB data dictionary, but not " + "in MySQL!" + " Have you mixed up " + ".frm files from different " + "installations? See " + REFMAN + "innodb-troubleshooting.html\n", + ib_table->name); + + if (push_warning) { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_NO_SUCH_INDEX, + "InnoDB: Table %s has a " + "primary key in InnoDB data " + "dictionary, but not in " + "MySQL!", ib_table->name); + } + break; + case DICT_NO_PK_FRM_HAS: + sql_print_error( + "Table %s has no primary key in InnoDB data " + "dictionary, but has one in MySQL! If you " + "created the table with a MySQL version < " + "3.23.54 and did not define a primary key, " + "but defined a unique key with all non-NULL " + "columns, then MySQL internally treats that " + "key as the primary key. You can fix this " + "error by dump + DROP + CREATE + reimport " + "of the table.", ib_table->name); + + if (push_warning) { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_NO_SUCH_INDEX, + "InnoDB: Table %s has no " + "primary key in InnoDB data " + "dictionary, but has one in " + "MySQL!", + ib_table->name); + } + break; + + case DICT_FRM_INCONSISTENT_KEYS: + sql_print_error("InnoDB: Table %s contains %lu " + "indexes inside InnoDB, which " + "is different from the number of " + "indexes %u defined in the MySQL " + " Have you mixed up " + ".frm files from different " + "installations? See " + REFMAN + "innodb-troubleshooting.html\n", + ib_table->name, n_keys, + table->s->keys); + + if (push_warning) { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_NO_SUCH_INDEX, + "InnoDB: Table %s contains %lu " + "indexes inside InnoDB, which " + "is different from the number of " + "indexes %u defined in the MySQL ", + ib_table->name, n_keys, + table->s->keys); + } + break; + + case DICT_FRM_CONSISTENT: + default: + sql_print_error("InnoDB: Table %s is consistent " + "on InnoDB data dictionary and MySQL " + " FRM file.", + ib_table->name); + ut_error; + break; + } +} diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h index 823d136d54b..093c9ce82c0 100644 --- a/storage/xtradb/handler/ha_innodb.h +++ b/storage/xtradb/handler/ha_innodb.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2000, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2013, 2016, 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 @@ -645,3 +646,16 @@ innobase_copy_frm_flags_from_table_share( /*=====================================*/ dict_table_t* innodb_table, /*!< in/out: InnoDB table */ const TABLE_SHARE* table_share); /*!< in: table share */ + +/********************************************************************//** +Helper function to push frm mismatch error to error log and +if needed to sql-layer. */ +UNIV_INTERN +void +ib_push_frm_error( +/*==============*/ + THD* thd, /*!< in: MySQL thd */ + dict_table_t* ib_table, /*!< in: InnoDB table */ + TABLE* table, /*!< in: MySQL table */ + ulint n_keys, /*!< in: InnoDB #keys */ + bool push_warning); /*!< in: print warning ? */ diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index 4f1e37926e5..fc5a4257b59 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -435,6 +435,20 @@ ha_innobase::check_if_supported_inplace_alter( } } + ulint n_indexes = UT_LIST_GET_LEN((prebuilt->table)->indexes); + + /* If InnoDB dictionary and MySQL frm file are not consistent + use "Copy" method. */ + if (prebuilt->table->dict_frm_mismatch) { + + ha_alter_info->unsupported_reason = innobase_get_err_msg( + ER_NO_SUCH_INDEX); + ib_push_frm_error(user_thd, prebuilt->table, altered_table, + n_indexes, true); + + DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); + } + /* We should be able to do the operation in-place. See if we can do it online (LOCK=NONE). */ bool online = true; diff --git a/storage/xtradb/include/dict0mem.h b/storage/xtradb/include/dict0mem.h index b8df96acc30..e9234b8c14d 100644 --- a/storage/xtradb/include/dict0mem.h +++ b/storage/xtradb/include/dict0mem.h @@ -2,6 +2,7 @@ Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2015, 2016, 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 @@ -914,6 +915,18 @@ if table->memcached_sync_count == DICT_TABLE_IN_DDL means there's DDL running on the table, DML from memcached will be blocked. */ #define DICT_TABLE_IN_DDL -1 +/** These are used when MySQL FRM and InnoDB data dictionary are +in inconsistent state. */ +typedef enum { + DICT_FRM_CONSISTENT = 0, /*!< Consistent state */ + DICT_FRM_NO_PK = 1, /*!< MySQL has no primary key + but InnoDB dictionary has + non-generated one. */ + DICT_NO_PK_FRM_HAS = 2, /*!< MySQL has primary key but + InnoDB dictionary has not. */ + DICT_FRM_INCONSISTENT_KEYS = 3 /*!< Key count mismatch */ +} dict_frm_t; + /** Data structure for a database table. Most fields will be initialized to 0, NULL or FALSE in dict_mem_table_create(). */ struct dict_table_t{ @@ -972,6 +985,10 @@ struct dict_table_t{ /*!< True if the table belongs to a system database (mysql, information_schema or performance_schema) */ + dict_frm_t dict_frm_mismatch; + /*!< !DICT_FRM_CONSISTENT==0 if data + dictionary information and + MySQL FRM information mismatch. */ #ifndef UNIV_HOTBACKUP hash_node_t name_hash; /*!< hash chain node */ hash_node_t id_hash; /*!< hash chain node */ From 298e1d3f71cce89c83645ea9cc1eade4bdaf4917 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 22 Apr 2016 11:36:10 +0300 Subject: [PATCH 53/91] Improve error diagnostics on I/O errors. If node->name is NULL try to use space->name instead. --- storage/innobase/fil/fil0fil.cc | 13 +++++++++---- storage/xtradb/fil/fil0fil.cc | 13 +++++++++---- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 4b64d7285a2..38ccf46cd52 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -5034,12 +5034,15 @@ retry: os_offset_t offset = ((os_offset_t) (start_page_no - file_start_page_no)) * page_size; + + const char* name = node->name == NULL ? space->name : node->name; + #ifdef UNIV_HOTBACKUP - success = os_file_write(node->name, node->handle, buf, + success = os_file_write(name, node->handle, buf, offset, page_size * n_pages); #else success = os_aio(OS_FILE_WRITE, OS_AIO_SYNC, - node->name, node->handle, buf, + name, node->handle, buf, offset, page_size * n_pages, NULL, NULL); #endif /* UNIV_HOTBACKUP */ @@ -5610,18 +5613,20 @@ fil_io( ut_a(byte_offset % OS_FILE_LOG_BLOCK_SIZE == 0); ut_a((len % OS_FILE_LOG_BLOCK_SIZE) == 0); + const char* name = node->name == NULL ? space->name : node->name; + #ifdef UNIV_HOTBACKUP /* In mysqlbackup do normal i/o, not aio */ if (type == OS_FILE_READ) { ret = os_file_read(node->handle, buf, offset, len); } else { ut_ad(!srv_read_only_mode); - ret = os_file_write(node->name, node->handle, buf, + ret = os_file_write(name, node->handle, buf, offset, len); } #else /* Queue the aio request */ - ret = os_aio(type, mode | wake_later, node->name, node->handle, buf, + ret = os_aio(type, mode | wake_later, name, node->handle, buf, offset, len, node, message); #endif /* UNIV_HOTBACKUP */ diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc index bbef1afcda6..99a44ffa639 100644 --- a/storage/xtradb/fil/fil0fil.cc +++ b/storage/xtradb/fil/fil0fil.cc @@ -5060,12 +5060,15 @@ retry: os_offset_t offset = ((os_offset_t) (start_page_no - file_start_page_no)) * page_size; + + const char* name = node->name == NULL ? space->name : node->name; + #ifdef UNIV_HOTBACKUP - success = os_file_write(node->name, node->handle, buf, + success = os_file_write(name, node->handle, buf, offset, page_size * n_pages); #else success = os_aio(OS_FILE_WRITE, OS_AIO_SYNC, - node->name, node->handle, buf, + name, node->handle, buf, offset, page_size * n_pages, NULL, NULL, space_id, NULL); #endif /* UNIV_HOTBACKUP */ @@ -5664,7 +5667,9 @@ _fil_io( } /* Queue the aio request */ - ret = os_aio(type, mode | wake_later, node->name, node->handle, buf, + const char* name = node->name == NULL ? space->name : node->name; + + ret = os_aio(type, mode | wake_later, name, node->handle, buf, offset, len, node, message, space_id, trx); #else @@ -5673,7 +5678,7 @@ _fil_io( ret = os_file_read(node->handle, buf, offset, len); } else { ut_ad(!srv_read_only_mode); - ret = os_file_write(node->name, node->handle, buf, + ret = os_file_write(name, node->handle, buf, offset, len); } #endif /* !UNIV_HOTBACKUP */ From 994030c0e25c26c51602fde14d316552edf0a922 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Thu, 21 Apr 2016 16:51:00 +0400 Subject: [PATCH 54/91] MDEV-8889 - Assertion `next_insert_id == 0' failed in handler::ha_external_lock There was a race condition between delayed insert thread and connection thread actually performing INSERT/REPLACE DELAYED. It was triggered by concurrent INSERT/REPLACE DELAYED and statements that flush the same table either explicitely or implicitely (like FLUSH TABLE, ALTER TABLE, ...). This race condition was caused by a gap in delayed thread shutdown logic, which allowed concurrent connection running INSERT/REPLACE DELAYED to change essential data consequently leaving table in semi-consistent state. Specifically query thread could decrease "tables_in_use" reference counter in this gap, causing delayed insert thread to shutdown without releasing auto increment and table lock. Fixed by extending condition so that delayed insert thread won't shutdown until there're locked tables. Also removed volatile qualifier from tables_in_use and stacked_inserts since they're supposed to be protected by mutexes. --- sql/sql_insert.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 42d88395060..b0151182a88 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1978,7 +1978,7 @@ public: TABLE *table; mysql_mutex_t mutex; mysql_cond_t cond, cond_client; - volatile uint tables_in_use,stacked_inserts; + uint tables_in_use, stacked_inserts; volatile bool status; /** When the handler thread starts, it clones a metadata lock ticket @@ -2863,7 +2863,8 @@ pthread_handler_t handle_delayed_insert(void *arg) lock_count=di->lock_count(); mysql_mutex_unlock(&LOCK_delayed_insert); mysql_mutex_lock(&di->mutex); - if (!lock_count && !di->tables_in_use && !di->stacked_inserts) + if (!lock_count && !di->tables_in_use && !di->stacked_inserts && + !thd->lock) break; // Time to die } From 250a89cfecd0c7902be584b5ed2ca753ee835774 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 22 Apr 2016 15:30:10 +0400 Subject: [PATCH 55/91] MDEV-9283 - Debian: the Lintian complains about "shlib-calls-exit" in ha_oqgraph.so exit() was called by Judy error handler. This patch overrides Judy error handler so that it calls abort() instead of exit(). --- storage/oqgraph/oqgraph_judy.cc | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/storage/oqgraph/oqgraph_judy.cc b/storage/oqgraph/oqgraph_judy.cc index 020cab57ed2..44c7e28e268 100644 --- a/storage/oqgraph/oqgraph_judy.cc +++ b/storage/oqgraph/oqgraph_judy.cc @@ -23,6 +23,28 @@ */ #include "oqgraph_judy.h" + +/* + Currently the only active code that can return error is: + judy_bitset::reset()/J1U() + judy_bitset::setbit()/J1S() + + In most cases errors are either about wrong parameters passed to Judy + functions or internal structures corruption. These definitely deserve + abnormal process termination instead of exit() as it is done by original + JUDYERROR. + + TODO: there's one exception that should be handled properly though: OOM. +*/ +#include +#define JUDYERROR(CallerFile, CallerLine, JudyFunc, JudyErrno, JudyErrID) \ + { \ + (void) fprintf(stderr, "File '%s', line %d: %s(), " \ + "JU_ERRNO_* == %d, ID == %d\n", \ + CallerFile, CallerLine, \ + JudyFunc, JudyErrno, JudyErrID); \ + abort(); \ + } #include void open_query::judy_bitset::clear() From 3f0d07e55b0a2ab8c7bdc1209d55ec2f66542830 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 22 Apr 2016 16:04:20 +0400 Subject: [PATCH 56/91] MDEV-9372 select 100 between 1 and 9223372036854775808 returns false Integer comparison of INT expressions with different signess in BETWEEN is not safe. Switching to DECIMAL comparison in case if INT arguments have different signess. --- mysql-test/r/bigint.result | 6 ++++++ mysql-test/t/bigint.test | 5 +++++ sql/item_cmpfunc.cc | 11 +++++++++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result index 505d655b6bb..b06ec5805a0 100644 --- a/mysql-test/r/bigint.result +++ b/mysql-test/r/bigint.result @@ -502,3 +502,9 @@ a SELECT * FROM t1 WHERE a IN (0.8,0.9); a DROP TABLE t1; +# +# MDEV-9372 select 100 between 1 and 9223372036854775808 returns false +# +SELECT 100 BETWEEN 1 AND 9223372036854775808; +100 BETWEEN 1 AND 9223372036854775808 +1 diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test index 41f33b8a7f2..fb18d60edd9 100644 --- a/mysql-test/t/bigint.test +++ b/mysql-test/t/bigint.test @@ -409,3 +409,8 @@ SELECT * FROM t1 WHERE a=0.9; SELECT * FROM t1 WHERE a IN (0.8,0.9); DROP TABLE t1; + +--echo # +--echo # MDEV-9372 select 100 between 1 and 9223372036854775808 returns false +--echo # +SELECT 100 BETWEEN 1 AND 9223372036854775808; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index fb75c9af794..3bd0b5b3fa2 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -160,10 +160,11 @@ static int cmp_row_type(Item* item1, Item* item2) static int agg_cmp_type(Item_result *type, Item **items, uint nitems) { - uint i; + uint unsigned_count= items[0]->unsigned_flag; type[0]= items[0]->cmp_type(); - for (i= 1 ; i < nitems ; i++) + for (uint i= 1 ; i < nitems ; i++) { + unsigned_count+= items[i]->unsigned_flag; type[0]= item_cmp_type(type[0], items[i]->cmp_type()); /* When aggregating types of two row expressions we have to check @@ -175,6 +176,12 @@ static int agg_cmp_type(Item_result *type, Item **items, uint nitems) if (type[0] == ROW_RESULT && cmp_row_type(items[0], items[i])) return 1; // error found: invalid usage of rows } + /** + If all arguments are of INT type but have different unsigned_flag values, + switch to DECIMAL_RESULT. + */ + if (type[0] == INT_RESULT && unsigned_count != nitems && unsigned_count != 0) + type[0]= DECIMAL_RESULT; return 0; } From bd75ee748ba9c2f7a06481668ff064cb5217d265 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Fri, 22 Apr 2016 09:10:00 -0400 Subject: [PATCH 57/91] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index ba54e70bc3e..58a6b369de9 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=49 +MYSQL_VERSION_PATCH=50 MYSQL_VERSION_EXTRA= From 618e300bce133cd4b4379b9f456d65144ae4c62b Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 22 Apr 2016 12:57:39 +0400 Subject: [PATCH 58/91] MDEV-9970 - main.sp-threads fails sporadically Added proper waiting for thread to enter required state. Also reduced amount of information dumped from processlist. --- mysql-test/r/sp-threads.result | 9 +++------ mysql-test/t/sp-threads.test | 9 ++++++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/sp-threads.result b/mysql-test/r/sp-threads.result index 4dc4d81224b..ddf709d462b 100644 --- a/mysql-test/r/sp-threads.result +++ b/mysql-test/r/sp-threads.result @@ -32,12 +32,9 @@ update t1, t2 set val= 1 where id1=id2; call bug9486(); lock tables t2 write; call bug9486(); -show processlist; -Id User Host db Command Time State Info Progress -# root localhost test Sleep # NULL 0.000 -# root localhost test Query # Waiting for table metadata lock update t1, t2 set val= 1 where id1=id2 0.000 -# root localhost test Query # NULL show processlist 0.000 -# root localhost test Sleep # NULL 0.000 +SELECT state,info FROM information_schema.processlist WHERE id=con1root_id; +state info +Waiting for table metadata lock update t1, t2 set val= 1 where id1=id2 unlock tables; drop procedure bug9486; drop table t1, t2; diff --git a/mysql-test/t/sp-threads.test b/mysql-test/t/sp-threads.test index e1012e2b72d..7a6d1258331 100644 --- a/mysql-test/t/sp-threads.test +++ b/mysql-test/t/sp-threads.test @@ -77,12 +77,15 @@ call bug9486(); connection con2root; lock tables t2 write; connection con1root; +let $con1root_id=`SELECT CONNECTION_ID()`; send call bug9486(); connection con2root; ---sleep 2 # There should be call statement in locked state. ---replace_column 1 # 3 localhost 6 # -show processlist; +let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist WHERE + id=$con1root_id AND state='Waiting for table metadata lock'; +--source include/wait_condition.inc +--replace_result $con1root_id con1root_id +eval SELECT state,info FROM information_schema.processlist WHERE id=$con1root_id; unlock tables; connection con1root; reap; From 0ea4c73dae689fb80e2c1c1cc347a917534edfae Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Sat, 23 Apr 2016 12:15:18 +0400 Subject: [PATCH 59/91] Fixed compilation failure due to unused var. --- client/mysql.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 43c09cafe9e..9d255b55430 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -4898,11 +4898,11 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate) { if (!inited) { - int errret; - inited=1; #ifdef HAVE_SETUPTERM + int errret; have_curses= setupterm((char *)0, 1, &errret) != ERR; #endif + inited=1; } if (info_type == INFO_ERROR) { From 19e3597e0c718a4cfdfe8789c7b4b11a4e0ba0c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 7 Apr 2016 10:47:46 +0300 Subject: [PATCH 60/91] MDEV-9142 :Adding Constraint with no database reference results in ERROR 1046 (3D000) at line 13: No database selected. Use database from create table to foreign key database if nothing else is given. --- mysql-test/suite/innodb/r/innodb-fk.result | 44 ++++++++++++++++++++++ mysql-test/suite/innodb/t/innodb-fk.test | 41 ++++++++++++++++++++ sql/sql_parse.cc | 30 ++++++++++++--- sql/sql_parse.h | 3 +- sql/sql_table.cc | 2 +- 5 files changed, 113 insertions(+), 7 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-fk.result b/mysql-test/suite/innodb/r/innodb-fk.result index 6c3306f5c15..7ba300b245e 100644 --- a/mysql-test/suite/innodb/r/innodb-fk.result +++ b/mysql-test/suite/innodb/r/innodb-fk.result @@ -68,3 +68,47 @@ Warning 150 Alter table `test`.`t2` with foreign key constraint failed. Referen Error 1005 Can't create table '#sql-temporary' (errno: 150) drop table t2; drop table t1; +CREATE DATABASE kg_test1; +CREATE DATABASE kg_test2; +CREATE TABLE `kg_test1`.`group` ( +Id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `kg_test1`.`person` ( +`Id` INT(11) NOT NULL AUTO_INCREMENT, +`Name` VARCHAR(50) NOT NULL, +PRIMARY KEY (`Id`), +CONSTRAINT `fk_person_group` FOREIGN KEY (`Id`) REFERENCES `group` (`Id`) +) ENGINE=INNODB DEFAULT CHARSET=utf8; +show create table `kg_test1`.`person`; +Table Create Table +person CREATE TABLE `person` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Name` varchar(50) NOT NULL, + PRIMARY KEY (`Id`), + CONSTRAINT `fk_person_group` FOREIGN KEY (`Id`) REFERENCES `group` (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 +CREATE TABLE `kg_test2`.`person2` ( +`Id` INT(11) NOT NULL AUTO_INCREMENT, +`Name` VARCHAR(50) NOT NULL, +PRIMARY KEY (`Id`), +CONSTRAINT `fk_person_group` FOREIGN KEY (`Id`) REFERENCES `group` (`Id`) +) ENGINE=INNODB DEFAULT CHARSET=utf8; +ERROR HY000: Can't create table 'kg_test2.person2' (errno: 150) +CREATE TABLE `kg_test2`.`person2` ( +`Id` INT(11) NOT NULL AUTO_INCREMENT, +`Name` VARCHAR(50) NOT NULL, +PRIMARY KEY (`Id`), +CONSTRAINT `fk_person_group` FOREIGN KEY (`Id`) REFERENCES `kg_test1`.`group` (`Id`) +) ENGINE=INNODB DEFAULT CHARSET=utf8; +show create table `kg_test2`.`person2`; +Table Create Table +person2 CREATE TABLE `person2` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Name` varchar(50) NOT NULL, + PRIMARY KEY (`Id`), + CONSTRAINT `fk_person_group` FOREIGN KEY (`Id`) REFERENCES `kg_test1`.`group` (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 +SHOW WARNINGS; +Level Code Message +DROP DATABASE kg_test2; +DROP DATABASE kg_test1; diff --git a/mysql-test/suite/innodb/t/innodb-fk.test b/mysql-test/suite/innodb/t/innodb-fk.test index 9bfd16b88e9..fd8dce7594c 100644 --- a/mysql-test/suite/innodb/t/innodb-fk.test +++ b/mysql-test/suite/innodb/t/innodb-fk.test @@ -124,3 +124,44 @@ show warnings; drop table t2; drop table t1; + +# +# MDEV-9142 :Adding Constraint with no database reference +# results in ERROR 1046 (3D000) at line 13: No database selected +# +CREATE DATABASE kg_test1; +CREATE DATABASE kg_test2; + +CREATE TABLE `kg_test1`.`group` ( + Id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `kg_test1`.`person` ( +`Id` INT(11) NOT NULL AUTO_INCREMENT, +`Name` VARCHAR(50) NOT NULL, +PRIMARY KEY (`Id`), +CONSTRAINT `fk_person_group` FOREIGN KEY (`Id`) REFERENCES `group` (`Id`) +) ENGINE=INNODB DEFAULT CHARSET=utf8; + +show create table `kg_test1`.`person`; + +--error 1005 +CREATE TABLE `kg_test2`.`person2` ( +`Id` INT(11) NOT NULL AUTO_INCREMENT, +`Name` VARCHAR(50) NOT NULL, +PRIMARY KEY (`Id`), +CONSTRAINT `fk_person_group` FOREIGN KEY (`Id`) REFERENCES `group` (`Id`) +) ENGINE=INNODB DEFAULT CHARSET=utf8; + +CREATE TABLE `kg_test2`.`person2` ( +`Id` INT(11) NOT NULL AUTO_INCREMENT, +`Name` VARCHAR(50) NOT NULL, +PRIMARY KEY (`Id`), +CONSTRAINT `fk_person_group` FOREIGN KEY (`Id`) REFERENCES `kg_test1`.`group` (`Id`) +) ENGINE=INNODB DEFAULT CHARSET=utf8; + +show create table `kg_test2`.`person2`; + +SHOW WARNINGS; +DROP DATABASE kg_test2; +DROP DATABASE kg_test1; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a52d55b47e9..a3114aba7d3 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5395,6 +5395,7 @@ bool check_global_access(THD *thd, ulong want_access, bool no_errors) temporary table flag) @param alter_info [in] Initial list of columns and indexes for the table to be created + @param create_db [in] Database of the created table @retval false ok. @@ -5403,7 +5404,8 @@ bool check_global_access(THD *thd, ulong want_access, bool no_errors) */ bool check_fk_parent_table_access(THD *thd, HA_CREATE_INFO *create_info, - Alter_info *alter_info) + Alter_info *alter_info, + const char* create_db) { Key *key; List_iterator key_iterator(alter_info->key_list); @@ -5443,10 +5445,28 @@ bool check_fk_parent_table_access(THD *thd, return true; } } - else if (thd->lex->copy_db_to(&db_name.str, &db_name.length)) - return true; else - is_qualified_table_name= false; + { + if (!thd->db) + { + db_name.str= (char *) thd->memdup(create_db, strlen(create_db)+1); + db_name.length= strlen(create_db); + is_qualified_table_name= true; + + if(create_db && check_db_name(&db_name)) + { + my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str); + return true; + } + } + else + { + if (thd->lex->copy_db_to(&db_name.str, &db_name.length)) + return true; + else + is_qualified_table_name= false; + } + } // if lower_case_table_names is set then convert tablename to lower case. if (lower_case_table_names) @@ -7462,7 +7482,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, goto err; } - if (check_fk_parent_table_access(thd, &lex->create_info, &lex->alter_info)) + if (check_fk_parent_table_access(thd, &lex->create_info, &lex->alter_info, create_table->db)) goto err; error= FALSE; diff --git a/sql/sql_parse.h b/sql/sql_parse.h index 60d5925c573..4c3070d197d 100644 --- a/sql/sql_parse.h +++ b/sql/sql_parse.h @@ -47,7 +47,8 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *create_table); bool check_fk_parent_table_access(THD *thd, HA_CREATE_INFO *create_info, - Alter_info *alter_info); + Alter_info *alter_info, + const char* create_db); bool parse_sql(THD *thd, Parser_state *parser_state, diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 024ca9b58e1..2cd36ceb4de 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6305,7 +6305,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, till this point for the alter operation. */ if ((alter_info->flags & ALTER_FOREIGN_KEY) && - check_fk_parent_table_access(thd, create_info, alter_info)) + check_fk_parent_table_access(thd, create_info, alter_info, new_db)) goto err; /* From 011497bd6035d0eceb6488b62319a86831418fae Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 21 Apr 2016 10:04:26 +0200 Subject: [PATCH 61/91] MDEV-9869 INSTALL SONAME 'ha_connect' make storage engine RPMs require the exact server version RPM: "MariaDB = %{version}-%{release}", other plugins require simply "MariaDB", as before. --- cmake/plugin.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmake/plugin.cmake b/cmake/plugin.cmake index 0a80bbc1434..e1d2af2add6 100644 --- a/cmake/plugin.cmake +++ b/cmake/plugin.cmake @@ -194,8 +194,11 @@ MACRO(MYSQL_ADD_PLUGIN) # Install dynamic library IF(ARG_COMPONENT) IF(CPACK_COMPONENTS_ALL AND NOT CPACK_COMPONENTS_ALL MATCHES ${ARG_COMPONENT}) + IF (ARG_STORAGE_ENGINE) + SET(ver " = %{version}-%{release}") + ENDIF() SET(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} ${ARG_COMPONENT} PARENT_SCOPE) - SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_REQUIRES "MariaDB" PARENT_SCOPE) + SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_REQUIRES "MariaDB${ver}" PARENT_SCOPE) IF (NOT ARG_CONFIG) SET(ARG_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/${target}.cnf") From 6651005e623e3a12ca0af6a645483a165941f8fe Mon Sep 17 00:00:00 2001 From: Andrew McDonnell Date: Fri, 22 Jan 2016 21:13:33 +1030 Subject: [PATCH 62/91] Fix for MDEV-8206, as per Jira comments of 2015-11-16 and 2015-11-30 --- storage/oqgraph/ha_oqgraph.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/storage/oqgraph/ha_oqgraph.cc b/storage/oqgraph/ha_oqgraph.cc index f5412c3b83a..ec12cebe53a 100644 --- a/storage/oqgraph/ha_oqgraph.cc +++ b/storage/oqgraph/ha_oqgraph.cc @@ -1103,6 +1103,10 @@ int ha_oqgraph::info(uint flag) int ha_oqgraph::extra(enum ha_extra_function operation) { + if (graph->get_thd() != current_thd) { + DBUG_PRINT( "oq-debug", ("rnd_pos g->table->in_use: 0x%lx <-- current_thd 0x%lx", (long) graph->get_thd(), (long) current_thd)); + graph->set_thd(current_thd); + } return edges->file->extra(operation); } From 23b1b69b101f8f22319a8e661ebe8b4587c435d4 Mon Sep 17 00:00:00 2001 From: Andrew McDonnell Date: Sat, 9 Apr 2016 22:39:22 +0930 Subject: [PATCH 63/91] Comment from https://github.com/MariaDB/server/pull/153 --- storage/oqgraph/ha_oqgraph.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/oqgraph/ha_oqgraph.cc b/storage/oqgraph/ha_oqgraph.cc index ec12cebe53a..f7add0d4204 100644 --- a/storage/oqgraph/ha_oqgraph.cc +++ b/storage/oqgraph/ha_oqgraph.cc @@ -1103,7 +1103,7 @@ int ha_oqgraph::info(uint flag) int ha_oqgraph::extra(enum ha_extra_function operation) { - if (graph->get_thd() != current_thd) { + if (graph->get_thd() != ha_thd()) { DBUG_PRINT( "oq-debug", ("rnd_pos g->table->in_use: 0x%lx <-- current_thd 0x%lx", (long) graph->get_thd(), (long) current_thd)); graph->set_thd(current_thd); } From d821dd106ad5086299e3e469f02dfd32eddf04ae Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 21 Apr 2016 14:51:37 +0200 Subject: [PATCH 64/91] MDEV-9580 SHOW GRANTS FOR fails use get_current_user() to distinguish user name without a hostname and a role name. move privilege checks inside mysql_show_grants() to remove duplicate get_current_user() calls --- mysql-test/r/grant5.result | 16 ++++++++++++++++ mysql-test/t/grant5.test | 18 ++++++++++++++++++ sql/sql_acl.cc | 26 +++++++++++++------------- sql/sql_parse.cc | 13 +------------ 4 files changed, 48 insertions(+), 25 deletions(-) diff --git a/mysql-test/r/grant5.result b/mysql-test/r/grant5.result index 2df394c0432..d7f3b6812bb 100644 --- a/mysql-test/r/grant5.result +++ b/mysql-test/r/grant5.result @@ -1,2 +1,18 @@ SHOW GRANTS FOR root@invalid_host; ERROR 42000: There is no such grant defined for user 'root' on host 'invalid_host' +create user test; +create user foo; +create role foo; +grant foo to test; +set role foo; +show grants for test; +Grants for test@% +GRANT foo TO 'test'@'%' +GRANT USAGE ON *.* TO 'test'@'%' +show grants for foo; +Grants for foo +GRANT USAGE ON *.* TO 'foo' +show grants for foo@'%'; +ERROR 42000: Access denied for user 'test'@'%' to database 'mysql' +drop user test, foo; +drop role foo; diff --git a/mysql-test/t/grant5.test b/mysql-test/t/grant5.test index db953d97fb3..14f2fd65020 100644 --- a/mysql-test/t/grant5.test +++ b/mysql-test/t/grant5.test @@ -5,3 +5,21 @@ # --error ER_NONEXISTING_GRANT SHOW GRANTS FOR root@invalid_host; + +# +# MDEV-9580 SHOW GRANTS FOR fails +# +create user test; +create user foo; +create role foo; +grant foo to test; +--connect (conn_1, localhost, test,,) +set role foo; +show grants for test; # user +show grants for foo; # role +--error ER_DBACCESS_DENIED_ERROR +show grants for foo@'%'; # user +--connection default +drop user test, foo; +drop role foo; + diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index bbd1dd86880..502e9ff83f2 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -7559,9 +7559,6 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user) DBUG_RETURN(TRUE); } - mysql_rwlock_rdlock(&LOCK_grant); - mysql_mutex_lock(&acl_cache->lock); - if (lex_user->user.str == current_user.str) { username= thd->security_ctx->priv_user; @@ -7579,23 +7576,28 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user) } else { - lex_user= get_current_user(thd, lex_user, false); + Security_context *sctx= thd->security_ctx; + bool do_check_access; + + lex_user= get_current_user(thd, lex_user); if (!lex_user) - { - mysql_mutex_unlock(&acl_cache->lock); - mysql_rwlock_unlock(&LOCK_grant); DBUG_RETURN(TRUE); - } if (lex_user->is_role()) { rolename= lex_user->user.str; + do_check_access= strcmp(rolename, sctx->priv_role); } else { username= lex_user->user.str; hostname= lex_user->host.str; + do_check_access= strcmp(username, sctx->priv_user) || + strcmp(hostname, sctx->priv_host); } + + if (do_check_access && check_access(thd, SELECT_ACL, "mysql", 0, 0, 1, 0)) + DBUG_RETURN(TRUE); } DBUG_ASSERT(rolename || username); @@ -7610,12 +7612,10 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user) field_list.push_back(field); if (protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) - { - mysql_mutex_unlock(&acl_cache->lock); - mysql_rwlock_unlock(&LOCK_grant); - DBUG_RETURN(TRUE); - } + + mysql_rwlock_rdlock(&LOCK_grant); + mysql_mutex_lock(&acl_cache->lock); if (username) { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d2fed787ba9..b91455888b8 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4374,21 +4374,10 @@ end_with_restore_list: case SQLCOM_SHOW_GRANTS: { LEX_USER *grant_user= lex->grant_user; - Security_context *sctx= thd->security_ctx; if (!grant_user) goto error; - if (grant_user->user.str && !strcmp(sctx->priv_user, grant_user->user.str) && - grant_user->host.str && !strcmp(sctx->priv_host, grant_user->host.str)) - grant_user->user= current_user; - - if (grant_user->user.str == current_user.str || - grant_user->user.str == current_role.str || - grant_user->user.str == current_user_and_current_role.str || - !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 0)) - { - res = mysql_show_grants(thd, grant_user); - } + res = mysql_show_grants(thd, grant_user); break; } #endif From 97728e107a5262266a2f6ed61bae9639a1717831 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 22 Apr 2016 08:16:06 +0200 Subject: [PATCH 65/91] comment clarify Alter_inplace_info::ALTER_PARTITIONED --- sql/handler.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sql/handler.h b/sql/handler.h index 8dc05a1d9df..6ec9769036c 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1822,7 +1822,10 @@ public: // Virtual columns changed static const HA_ALTER_FLAGS ALTER_COLUMN_VCOL = 1L << 30; - // ALTER TABLE for a partitioned table + /** + ALTER TABLE for a partitioned table. The engine needs to commit + online alter of all partitions atomically (using group_commit_ctx) + */ static const HA_ALTER_FLAGS ALTER_PARTITIONED = 1L << 31; /** From b233b15ccda8d8a1633e82113e5731cefce5eb84 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 22 Apr 2016 08:25:36 +0200 Subject: [PATCH 66/91] MDEV-9868 Altering a partitioned table comment does a full copy let handler::check_if_supported_inplace_alter() (that detects frm-only changes) to work for partitioned tables too. --- mysql-test/r/alter_table_online.result | 4 +++- mysql-test/t/alter_table_online.test | 11 ++++++++--- sql/handler.cc | 1 + 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/alter_table_online.result b/mysql-test/r/alter_table_online.result index db7319cadf1..7254fbec413 100644 --- a/mysql-test/r/alter_table_online.result +++ b/mysql-test/r/alter_table_online.result @@ -1,4 +1,3 @@ -drop table if exists t1,t2,t3; create table t1 (a int not null primary key, b int, c varchar(80), e enum('a','b')); insert into t1 (a) values (1),(2),(3); alter online table t1 modify b int default 5; @@ -62,3 +61,6 @@ create table t3 (a int not null primary key, b int, c varchar(80)) engine=merge alter online table t3 union=(t1,t2); ERROR 0A000: LOCK=NONE/SHARED is not supported for this operation. Try LOCK=EXCLUSIVE. drop table t1,t2,t3; +create table t1 (i int) partition by hash(i) partitions 2; +alter online table t1 comment 'test'; +drop table t1; diff --git a/mysql-test/t/alter_table_online.test b/mysql-test/t/alter_table_online.test index a160abc8fe2..9ff2f766803 100644 --- a/mysql-test/t/alter_table_online.test +++ b/mysql-test/t/alter_table_online.test @@ -3,9 +3,7 @@ # --source include/have_innodb.inc ---disable_warnings -drop table if exists t1,t2,t3; ---enable_warnings +--source include/have_partition.inc # # Test of things that can be done online # @@ -101,3 +99,10 @@ create table t3 (a int not null primary key, b int, c varchar(80)) engine=merge --error ER_ALTER_OPERATION_NOT_SUPPORTED alter online table t3 union=(t1,t2); drop table t1,t2,t3; + +# +# MDEV-9868 Altering a partitioned table comment does a full copy +# +create table t1 (i int) partition by hash(i) partitions 2; +alter online table t1 comment 'test'; +drop table t1; diff --git a/sql/handler.cc b/sql/handler.cc index 9b217c60100..61d2b37c90f 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -4209,6 +4209,7 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table, Alter_inplace_info::ALTER_COLUMN_DEFAULT | Alter_inplace_info::ALTER_COLUMN_OPTION | Alter_inplace_info::CHANGE_CREATE_OPTION | + Alter_inplace_info::ALTER_PARTITIONED | Alter_inplace_info::ALTER_RENAME; /* Is there at least one operation that requires copy algorithm? */ From 78989b67d1b41259a7ce646ca93485d604ba215b Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 22 Apr 2016 08:46:38 +0200 Subject: [PATCH 67/91] MDEV-9168 altering a column comment does a full copy add a test case --- mysql-test/r/alter_table_online.result | 9 +++++++++ mysql-test/t/alter_table_online.test | 15 +++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/mysql-test/r/alter_table_online.result b/mysql-test/r/alter_table_online.result index 7254fbec413..f416c53f42c 100644 --- a/mysql-test/r/alter_table_online.result +++ b/mysql-test/r/alter_table_online.result @@ -64,3 +64,12 @@ drop table t1,t2,t3; create table t1 (i int) partition by hash(i) partitions 2; alter online table t1 comment 'test'; drop table t1; +create table t1 (a int); +alter online table t1 modify a int comment 'test'; +drop table t1; +create table t1 (a int) engine=innodb; +alter online table t1 modify a int comment 'test'; +drop table t1; +create table t1 (a int) partition by hash(a) partitions 2; +alter online table t1 modify a int comment 'test'; +drop table t1; diff --git a/mysql-test/t/alter_table_online.test b/mysql-test/t/alter_table_online.test index 9ff2f766803..d9c2a2c4d4f 100644 --- a/mysql-test/t/alter_table_online.test +++ b/mysql-test/t/alter_table_online.test @@ -106,3 +106,18 @@ drop table t1,t2,t3; create table t1 (i int) partition by hash(i) partitions 2; alter online table t1 comment 'test'; drop table t1; + +# +# MDEV-9168 altering a column comment does a full copy +# +create table t1 (a int); +alter online table t1 modify a int comment 'test'; +drop table t1; + +create table t1 (a int) engine=innodb; +alter online table t1 modify a int comment 'test'; +drop table t1; + +create table t1 (a int) partition by hash(a) partitions 2; +alter online table t1 modify a int comment 'test'; +drop table t1; From 906f97d3108df8370489f1f5a2531d8a43d8ce1a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 22 Apr 2016 13:10:14 +0200 Subject: [PATCH 68/91] MDEV-8481 mysql-test - main.func_crypt fails if FIPS=1 disable the test when crypt(3) doesn't work --- mysql-test/include/have_crypt.inc | 9 +++++---- mysql-test/r/have_crypt.require | 2 -- 2 files changed, 5 insertions(+), 6 deletions(-) delete mode 100644 mysql-test/r/have_crypt.require diff --git a/mysql-test/include/have_crypt.inc b/mysql-test/include/have_crypt.inc index cbf0a7ac876..422f8922edc 100644 --- a/mysql-test/include/have_crypt.inc +++ b/mysql-test/include/have_crypt.inc @@ -1,4 +1,5 @@ --- require r/have_crypt.require -disable_query_log; -show variables like 'have_crypt'; -enable_query_log; +# encrypt('a') is NULL if crypt(3) is not available +# encrypt('a') is "*0" in fips mode +if (`select length(encrypt('a')) > 3 IS NOT TRUE`) { + skip No crypt(3); +} diff --git a/mysql-test/r/have_crypt.require b/mysql-test/r/have_crypt.require deleted file mode 100644 index 739fbb738f0..00000000000 --- a/mysql-test/r/have_crypt.require +++ /dev/null @@ -1,2 +0,0 @@ -Variable_name Value -have_crypt YES From 797cadce47ecacd9dff2ee4829786e0be3009748 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 22 Apr 2016 13:13:48 +0200 Subject: [PATCH 69/91] MDEV-8482 mysql-test - main.func_encrypt fails if FIPS=1 * check for openssl errors in DES_ENCRYPT/DES_DECRYPT * disable the test when DES doesn't work * also disable main.func_des_encrypt --- mysql-test/include/have_des.inc | 6 ++++++ mysql-test/t/func_des_encrypt.test | 2 +- mysql-test/t/func_encrypt.test | 2 +- sql/item_strfunc.cc | 10 ++++++---- 4 files changed, 14 insertions(+), 6 deletions(-) create mode 100644 mysql-test/include/have_des.inc diff --git a/mysql-test/include/have_des.inc b/mysql-test/include/have_des.inc new file mode 100644 index 00000000000..5abdaf6e2aa --- /dev/null +++ b/mysql-test/include/have_des.inc @@ -0,0 +1,6 @@ +# in the FIPS mode, OpenSSL disables DES and other weak algorithms +source include/have_ssl_crypto_functs.inc; + +if (`select des_encrypt("a", "b") IS NULL`) { + skip DES is disabled (fips mode?); +} diff --git a/mysql-test/t/func_des_encrypt.test b/mysql-test/t/func_des_encrypt.test index e121aedab06..c9661b81cc0 100644 --- a/mysql-test/t/func_des_encrypt.test +++ b/mysql-test/t/func_des_encrypt.test @@ -1,4 +1,4 @@ --- source include/have_ssl_crypto_functs.inc +-- source include/have_des.inc # This test can't be in func_encrypt.test, because it requires # --des-key-file to not be set. diff --git a/mysql-test/t/func_encrypt.test b/mysql-test/t/func_encrypt.test index 18fb072966b..e24cb80f995 100644 --- a/mysql-test/t/func_encrypt.test +++ b/mysql-test/t/func_encrypt.test @@ -1,4 +1,4 @@ --- source include/have_ssl_crypto_functs.inc +-- source include/have_des.inc --disable_warnings drop table if exists t1; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 3b8bc1580bb..4ea3075e69c 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -828,9 +828,10 @@ String *Item_func_des_encrypt::val_str(String *str) /* We make good 24-byte (168 bit) key from given plaintext key with MD5 */ bzero((char*) &ivec,sizeof(ivec)); - EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL, + if (!EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL, (uchar*) keystr->ptr(), (int) keystr->length(), - 1, (uchar*) &keyblock,ivec); + 1, (uchar*) &keyblock,ivec)) + goto error; DES_set_key_unchecked(&keyblock.key1,&keyschedule.ks1); DES_set_key_unchecked(&keyblock.key2,&keyschedule.ks2); DES_set_key_unchecked(&keyblock.key3,&keyschedule.ks3); @@ -921,9 +922,10 @@ String *Item_func_des_decrypt::val_str(String *str) goto error; bzero((char*) &ivec,sizeof(ivec)); - EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL, + if (!EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL, (uchar*) keystr->ptr(),(int) keystr->length(), - 1,(uchar*) &keyblock,ivec); + 1,(uchar*) &keyblock,ivec)) + goto error; // Here we set all 64-bit keys (56 effective) one by one DES_set_key_unchecked(&keyblock.key1,&keyschedule.ks1); DES_set_key_unchecked(&keyblock.key2,&keyschedule.ks2); From 0ee919b86e214a79541f1e9a16b63ae8784b4790 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 22 Apr 2016 13:15:04 +0200 Subject: [PATCH 70/91] MDEV-8480 mysql-test - main.func_encrypt_ucs2 fails if FIPS=1 disable the test when DES doesn't work --- mysql-test/t/func_encrypt_ucs2.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/func_encrypt_ucs2.test b/mysql-test/t/func_encrypt_ucs2.test index 8b4cd44d354..1242c3b9e6a 100644 --- a/mysql-test/t/func_encrypt_ucs2.test +++ b/mysql-test/t/func_encrypt_ucs2.test @@ -1,4 +1,4 @@ --- source include/have_ssl_crypto_functs.inc +-- source include/have_des.inc -- source include/have_ucs2.inc --echo # From 7b58fd5ef0c1ecdc7c6d6d3347110620e67313c2 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 23 Apr 2016 18:49:19 +0200 Subject: [PATCH 71/91] tests -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci This fixes: MDEV-7693 MariaDB - mysql-test - SUITE:funcs_1 - funcs_1.is_tables_mysql is failing on TABLE_COLLATION /DATABASE_COLLATION MDEV-8487 mysql-test - main.information_schema 'xtradb' fails MDEV-8486 mysql-test - main.bootstrap fails --- mysql-test/mysql-test-run.pl | 2 +- mysql-test/r/mysqld--help.result | 2 -- mysql-test/t/bootstrap.test | 2 +- mysql-test/t/mysqld--help.test | 1 + scripts/mysql_system_tables.sql | 2 +- tests/mysql_client_test.c | 14 +++++++------- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index e90e464d118..81001174172 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -3638,7 +3638,7 @@ sub mysql_install_db { # Create mtr database mtr_tofile($bootstrap_sql_file, - "CREATE DATABASE mtr;\n"); + "CREATE DATABASE mtr CHARSET=latin1;\n"); # Add help tables and data for warning detection and supression mtr_tofile($bootstrap_sql_file, diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 65045416a5b..e5a5f61cf83 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -1079,10 +1079,8 @@ binlog-stmt-cache-size 32768 bulk-insert-buffer-size 8388608 character-set-client-handshake TRUE character-set-filesystem binary -character-set-server latin1 character-sets-dir MYSQL_CHARSETSDIR/ chroot (No default value) -collation-server latin1_swedish_ci completion-type NO_CHAIN concurrent-insert AUTO console FALSE diff --git a/mysql-test/t/bootstrap.test b/mysql-test/t/bootstrap.test index 97376eb7412..e2d21c0d990 100644 --- a/mysql-test/t/bootstrap.test +++ b/mysql-test/t/bootstrap.test @@ -79,7 +79,7 @@ EOF # --write_file $MYSQLTEST_VARDIR/tmp/bootstrap_plugins.sql use test; -create table t1(a int) engine=example; +create table t1(a int) engine=example charset=latin1; EOF --exec $MYSQLD_BOOTSTRAP_CMD --plugin-dir=$PLUGIN_DIR < $MYSQLTEST_VARDIR/tmp/bootstrap_plugins.sql >> $MYSQLTEST_VARDIR/tmp/bootstrap.log 2>&1 --remove_file $MYSQLTEST_VARDIR/tmp/bootstrap_plugins.sql diff --git a/mysql-test/t/mysqld--help.test b/mysql-test/t/mysqld--help.test index fabc2e21f18..cee9337ccc3 100644 --- a/mysql-test/t/mysqld--help.test +++ b/mysql-test/t/mysqld--help.test @@ -22,6 +22,7 @@ perl; log-slow-queries pid-file slow-query-log-file log-basename datadir slave-load-tmpdir tmpdir socket thread-pool-size large-files-support lower-case-file-system system-time-zone + collation-server character-set-server version.*/; # Plugins which may or may not be there: diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql index 14b59bb3411..ab4ea6dfe41 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mysql_system_tables.sql @@ -229,7 +229,7 @@ SET @cmd= "CREATE TABLE IF NOT EXISTS gtid_slave_pos ( sub_id BIGINT UNSIGNED NOT NULL, server_id INT UNSIGNED NOT NULL, seq_no BIGINT UNSIGNED NOT NULL, - PRIMARY KEY (domain_id, sub_id)) + PRIMARY KEY (domain_id, sub_id)) CHARSET=latin1 COMMENT='Replication slave GTID position'"; SET @str=CONCAT(@cmd, ' ENGINE=', @innodb_or_myisam); PREPARE stmt FROM @str; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 473084e1b57..fcc89482f4e 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -2261,7 +2261,7 @@ static void test_ps_query_cache() return; } - rc= mysql_query(mysql, "SET SQL_MODE=''"); + rc= mysql_set_character_set(mysql, "utf8"); myquery(rc); /* prepare the table */ @@ -2306,7 +2306,7 @@ static void test_ps_query_cache() mysql_close(lmysql); DIE_UNLESS(0); } - rc= mysql_query(lmysql, "SET SQL_MODE=''"); + rc= mysql_set_character_set(lmysql, "utf8"); myquery(rc); if (!opt_silent) @@ -16647,7 +16647,7 @@ static void test_bug30472() /* Switch client character set. */ - DIE_IF(mysql_set_character_set(&con, "utf8")); + DIE_IF(mysql_set_character_set(&con, "latin2")); /* Retrieve character set information. */ @@ -16663,10 +16663,10 @@ static void test_bug30472() 2) new character set is different from the original one. */ - DIE_UNLESS(strcmp(character_set_name_2, "utf8") == 0); - DIE_UNLESS(strcmp(character_set_client_2, "utf8") == 0); - DIE_UNLESS(strcmp(character_set_results_2, "utf8") == 0); - DIE_UNLESS(strcmp(collation_connnection_2, "utf8_general_ci") == 0); + DIE_UNLESS(strcmp(character_set_name_2, "latin2") == 0); + DIE_UNLESS(strcmp(character_set_client_2, "latin2") == 0); + DIE_UNLESS(strcmp(character_set_results_2, "latin2") == 0); + DIE_UNLESS(strcmp(collation_connnection_2, "latin2_general_ci") == 0); DIE_UNLESS(strcmp(character_set_name_1, character_set_name_2) != 0); DIE_UNLESS(strcmp(character_set_client_1, character_set_client_2) != 0); From ce38adddfa91949b30956abd0e4cab201effcdef Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 24 Apr 2016 11:18:59 +0200 Subject: [PATCH 72/91] MDEV-9617 solaris sparc build fails on 10.0 Spider: SunPro only supports array declarations with constant size. Spider already has a workaround for that, inside #ifdef _MSC_VER. Enable this code also for __SUNPRO_CC Connect: Don't use anonymous union. Cast for mmap. Don't pass gcc-ish -W... options to SunPro --- storage/connect/CMakeLists.txt | 2 ++ storage/connect/maputil.cpp | 4 ++-- storage/connect/xindex.cpp | 26 ++++++++++++------------ storage/connect/xindex.h | 4 ++-- storage/spider/spd_conn.cc | 34 ++++++++++++++++---------------- storage/spider/spd_db_conn.cc | 4 ++-- storage/spider/spd_ping_table.cc | 4 ++-- storage/spider/spd_table.cc | 16 +++++++-------- storage/spider/spd_trx.cc | 12 +++++------ 9 files changed, 54 insertions(+), 52 deletions(-) diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index 7ff2ca7753c..0702e44bcf2 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -45,6 +45,7 @@ add_definitions( -DHUGE_SUPPORT -DZIP_SUPPORT -DPIVOT_SUPPORT ) # OS specific C flags, definitions and source files. # IF(UNIX) + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") # Bar: -Wfatal-errors removed (does not present in gcc on solaris10) if(WITH_WARNINGS) add_definitions(-Wall -Wextra -Wmissing-declarations) @@ -71,6 +72,7 @@ IF(UNIX) #message(STATUS "CONNECT: GCC: Some warnings disabled") endif(WITH_WARNINGS) + endif() add_definitions( -DUNIX -DLINUX -DUBUNTU ) diff --git a/storage/connect/maputil.cpp b/storage/connect/maputil.cpp index c4e016f1511..87263b3adf6 100644 --- a/storage/connect/maputil.cpp +++ b/storage/connect/maputil.cpp @@ -190,8 +190,8 @@ bool CloseMemMap(void *memory, size_t dwSize) { if (memory) { // All this must be redesigned - int rc = msync(memory, dwSize, MS_SYNC); - return (munmap(memory, dwSize) < 0) ? true : false; + int rc = msync((char*)memory, dwSize, MS_SYNC); + return (munmap((char*)memory, dwSize) < 0) ? true : false; } else return false; diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp index a2d75cec8ab..69aa7e2c20e 100755 --- a/storage/connect/xindex.cpp +++ b/storage/connect/xindex.cpp @@ -1279,7 +1279,7 @@ bool XINDEX::MapInit(PGLOBAL g) IOFF *noff = (IOFF*)mbase; // Position the memory base at the offset of this index - mbase += noff[id].Low; + mbase += noff[id].v.Low; } // endif id // Now start the mapping process. @@ -2347,10 +2347,10 @@ bool XFILE::Open(PGLOBAL g, char *filename, int id, MODE mode) return true; } // endif - NewOff.Low = (int)ftell(Xfile); + NewOff.v.Low = (int)ftell(Xfile); if (trace) - htrc("XFILE Open: NewOff.Low=%d\n", NewOff.Low); + htrc("XFILE Open: NewOff.v.Low=%d\n", NewOff.v.Low); } else if (mode == MODE_WRITE) { if (id >= 0) { @@ -2358,10 +2358,10 @@ bool XFILE::Open(PGLOBAL g, char *filename, int id, MODE mode) memset(noff, 0, sizeof(noff)); Write(g, noff, sizeof(IOFF), MAX_INDX, rc); fseek(Xfile, 0, SEEK_END); - NewOff.Low = (int)ftell(Xfile); + NewOff.v.Low = (int)ftell(Xfile); if (trace) - htrc("XFILE Open: NewOff.Low=%d\n", NewOff.Low); + htrc("XFILE Open: NewOff.v.Low=%d\n", NewOff.v.Low); } // endif id @@ -2373,10 +2373,10 @@ bool XFILE::Open(PGLOBAL g, char *filename, int id, MODE mode) } // endif MAX_INDX if (trace) - htrc("XFILE Open: noff[%d].Low=%d\n", id, noff[id].Low); + htrc("XFILE Open: noff[%d].v.Low=%d\n", id, noff[id].v.Low); // Position the cursor at the offset of this index - if (fseek(Xfile, noff[id].Low, SEEK_SET)) { + if (fseek(Xfile, noff[id].v.Low, SEEK_SET)) { sprintf(g->Message, MSG(FUNC_ERRNO), errno, "Xseek"); return true; } // endif @@ -2566,14 +2566,14 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode) return true; } // endif - NewOff.Low = (int)rc; - NewOff.High = (int)high; + NewOff.v.Low = (int)rc; + NewOff.v.High = (int)high; } else if (mode == MODE_WRITE) { if (id >= 0) { // New not sep index file. Write the header. memset(noff, 0, sizeof(noff)); rc = WriteFile(Hfile, noff, sizeof(noff), &drc, NULL); - NewOff.Low = (int)drc; + NewOff.v.Low = (int)drc; } // endif id } else if (mode == MODE_READ && id >= 0) { @@ -2586,8 +2586,8 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode) } // endif rc // Position the cursor at the offset of this index - rc = SetFilePointer(Hfile, noff[id].Low, - (PLONG)&noff[id].High, FILE_BEGIN); + rc = SetFilePointer(Hfile, noff[id].v.Low, + (PLONG)&noff[id].v.High, FILE_BEGIN); if (rc == INVALID_SET_FILE_POINTER) { sprintf(g->Message, MSG(FUNC_ERRNO), GetLastError(), "SetFilePointer"); @@ -2649,7 +2649,7 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode) if (id >= 0) { // New not sep index file. Write the header. memset(noff, 0, sizeof(noff)); - NewOff.Low = write(Hfile, &noff, sizeof(noff)); + NewOff.v.Low = write(Hfile, &noff, sizeof(noff)); } // endif id if (trace) diff --git a/storage/connect/xindex.h b/storage/connect/xindex.h index 51b678992ea..ef2e934e5ee 100644 --- a/storage/connect/xindex.h +++ b/storage/connect/xindex.h @@ -66,9 +66,9 @@ typedef struct index_def : public BLOCK { typedef struct index_off { union { #if defined(WORDS_BIGENDIAN) - struct {int High; int Low;}; + struct {int High; int Low;} v; #else // !WORDS_BIGENDIAN - struct {int Low; int High;}; + struct {int Low; int High;} v; #endif //!WORDS_BIGENDIAN longlong Val; // File position }; // end of union diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc index c5c47064403..2f7fdb62ad4 100644 --- a/storage/spider/spd_conn.cc +++ b/storage/spider/spd_conn.cc @@ -2706,7 +2706,7 @@ void *spider_bg_sts_action( SPIDER_TRX *trx; int error_num = 0, roop_count; ha_spider spider; -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) int *need_mons; SPIDER_CONN **conns; uint *conn_link_idx; @@ -2733,7 +2733,7 @@ void *spider_bg_sts_action( my_thread_init(); DBUG_ENTER("spider_bg_sts_action"); /* init start */ -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) if (!(need_mons = (int *) spider_bulk_malloc(spider_current_trx, 21, MYF(MY_WME), @@ -2777,7 +2777,7 @@ void *spider_bg_sts_action( share->bg_sts_init = FALSE; pthread_mutex_unlock(&share->sts_mutex); my_thread_end(); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_free(NULL, need_mons, MYF(MY_WME)); #endif DBUG_RETURN(NULL); @@ -2801,7 +2801,7 @@ void *spider_bg_sts_action( my_pthread_setspecific_ptr(THR_THD, NULL); #endif my_thread_end(); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_free(NULL, need_mons, MYF(MY_WME)); #endif DBUG_RETURN(NULL); @@ -2866,7 +2866,7 @@ void *spider_bg_sts_action( my_pthread_setspecific_ptr(THR_THD, NULL); #endif my_thread_end(); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_free(NULL, need_mons, MYF(MY_WME)); #endif DBUG_RETURN(NULL); @@ -2897,7 +2897,7 @@ void *spider_bg_sts_action( my_pthread_setspecific_ptr(THR_THD, NULL); #endif my_thread_end(); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_free(NULL, need_mons, MYF(MY_WME)); #endif DBUG_RETURN(NULL); @@ -3088,7 +3088,7 @@ void *spider_bg_crd_action( int error_num = 0, roop_count; ha_spider spider; TABLE table; -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) int *need_mons; SPIDER_CONN **conns; uint *conn_link_idx; @@ -3115,7 +3115,7 @@ void *spider_bg_crd_action( my_thread_init(); DBUG_ENTER("spider_bg_crd_action"); /* init start */ -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) if (!(need_mons = (int *) spider_bulk_malloc(spider_current_trx, 22, MYF(MY_WME), @@ -3159,7 +3159,7 @@ void *spider_bg_crd_action( share->bg_crd_init = FALSE; pthread_mutex_unlock(&share->crd_mutex); my_thread_end(); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_free(NULL, need_mons, MYF(MY_WME)); #endif DBUG_RETURN(NULL); @@ -3183,7 +3183,7 @@ void *spider_bg_crd_action( my_pthread_setspecific_ptr(THR_THD, NULL); #endif my_thread_end(); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_free(NULL, need_mons, MYF(MY_WME)); #endif DBUG_RETURN(NULL); @@ -3252,7 +3252,7 @@ void *spider_bg_crd_action( my_pthread_setspecific_ptr(THR_THD, NULL); #endif my_thread_end(); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_free(NULL, need_mons, MYF(MY_WME)); #endif DBUG_RETURN(NULL); @@ -3283,7 +3283,7 @@ void *spider_bg_crd_action( my_pthread_setspecific_ptr(THR_THD, NULL); #endif my_thread_end(); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_free(NULL, need_mons, MYF(MY_WME)); #endif DBUG_RETURN(NULL); @@ -3417,7 +3417,7 @@ int spider_create_mon_threads( { char link_idx_str[SPIDER_SQL_INT_LEN]; int link_idx_str_length; -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_string conv_name_str(share->table_name_length + SPIDER_SQL_INT_LEN + 1); conv_name_str.set_charset(system_charset_info); @@ -3748,7 +3748,7 @@ int spider_conn_first_link_idx( int roop_count, active_links = 0; longlong balance_total = 0, balance_val; double rand_val; -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) int *link_idxs, link_idx; long *balances; #else @@ -3756,7 +3756,7 @@ int spider_conn_first_link_idx( long balances[link_count]; #endif DBUG_ENTER("spider_conn_first_link_idx"); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) if (!(link_idxs = (int *) spider_bulk_malloc(spider_current_trx, 24, MYF(MY_WME), &link_idxs, sizeof(int) * link_count, @@ -3782,7 +3782,7 @@ int spider_conn_first_link_idx( if (active_links == 0) { DBUG_PRINT("info",("spider all links are failed")); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_free(spider_current_trx, link_idxs, MYF(MY_WME)); #endif DBUG_RETURN(-1); @@ -3811,7 +3811,7 @@ int spider_conn_first_link_idx( } DBUG_PRINT("info",("spider first link_idx=%d", link_idxs[roop_count])); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) link_idx = link_idxs[roop_count]; spider_free(spider_current_trx, link_idxs, MYF(MY_WME)); DBUG_RETURN(link_idx); diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index 9f46e55ca09..c29172a474a 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -9294,7 +9294,7 @@ int spider_db_udf_ping_table( { int init_sql_alloc_size = spider_param_init_sql_alloc_size(trx->thd, share->init_sql_alloc_size); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_string sql_str(init_sql_alloc_size); sql_str.set_charset(system_charset_info); spider_string where_str(init_sql_alloc_size); @@ -9517,7 +9517,7 @@ int spider_db_udf_ping_table_mon_next( SPIDER_SHARE *share = table_mon->share; int init_sql_alloc_size = spider_param_init_sql_alloc_size(thd, share->init_sql_alloc_size); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_string sql_str(init_sql_alloc_size); sql_str.set_charset(thd->variables.character_set_client); #else diff --git a/storage/spider/spd_ping_table.cc b/storage/spider/spd_ping_table.cc index 41c5c240dd3..f59f7760359 100644 --- a/storage/spider/spd_ping_table.cc +++ b/storage/spider/spd_ping_table.cc @@ -241,7 +241,7 @@ void spider_release_ping_table_mon_list( DBUG_PRINT("info", ("spider link_idx=%d", link_idx)); link_idx_str_length = my_sprintf(link_idx_str, (link_idx_str, "%010d", link_idx)); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_string conv_name_str(conv_name_length + link_idx_str_length + 1); conv_name_str.set_charset(system_charset_info); #else @@ -1362,7 +1362,7 @@ int spider_ping_table_mon_from_table( link_idx_str_length = my_sprintf(link_idx_str, (link_idx_str, "%010d", link_idx)); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_string conv_name_str(conv_name_length + link_idx_str_length + 1); conv_name_str.set_charset(system_charset_info); *((char *)(conv_name_str.ptr() + conv_name_length + link_idx_str_length)) = diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index 07572fa7973..ead335c07ea 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -3703,7 +3703,7 @@ int spider_create_conn_keys( #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) char *tmp_hs_r_name, *tmp_hs_w_name; #endif -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) uint *conn_keys_lengths; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) uint *hs_r_conn_keys_lengths; @@ -3717,7 +3717,7 @@ int spider_create_conn_keys( #endif #endif DBUG_ENTER("spider_create_conn_keys"); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) if (!(conn_keys_lengths = (uint *) spider_bulk_alloc_mem(spider_current_trx, 44, __func__, __FILE__, __LINE__, MYF(MY_WME), @@ -3806,7 +3806,7 @@ int spider_create_conn_keys( #endif NullS)) ) { -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_free(spider_current_trx, conn_keys_lengths, MYF(MY_WME)); #endif DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -3823,7 +3823,7 @@ int spider_create_conn_keys( sizeof(uint) * share->all_link_count); #endif -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_free(spider_current_trx, conn_keys_lengths, MYF(MY_WME)); #endif @@ -4676,7 +4676,7 @@ SPIDER_SHARE *spider_get_share( share->link_count, SPIDER_LINK_STATUS_OK); if (search_link_idx == -1) { -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) char *db, *table_name; if (!(db = (char *) spider_bulk_malloc(spider_current_trx, 48, MYF(MY_WME), @@ -4702,7 +4702,7 @@ SPIDER_SHARE *spider_get_share( table_name[table_share->table_name.length] = '\0'; my_printf_error(ER_SPIDER_ALL_LINKS_FAILED_NUM, ER_SPIDER_ALL_LINKS_FAILED_STR, MYF(0), db, table_name); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_free(spider->trx, db, MYF(MY_WME)); #endif *error_num = ER_SPIDER_ALL_LINKS_FAILED_NUM; @@ -5100,7 +5100,7 @@ SPIDER_SHARE *spider_get_share( share->link_count, SPIDER_LINK_STATUS_OK); if (search_link_idx == -1) { -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) char *db, *table_name; if (!(db = (char *) spider_bulk_malloc(spider_current_trx, 50, MYF(MY_WME), @@ -5123,7 +5123,7 @@ SPIDER_SHARE *spider_get_share( table_name[table_share->table_name.length] = '\0'; my_printf_error(ER_SPIDER_ALL_LINKS_FAILED_NUM, ER_SPIDER_ALL_LINKS_FAILED_STR, MYF(0), db, table_name); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_free(spider->trx, db, MYF(MY_WME)); #endif *error_num = ER_SPIDER_ALL_LINKS_FAILED_NUM; diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc index d7127fa0084..18b6fd5ec89 100644 --- a/storage/spider/spd_trx.cc +++ b/storage/spider/spd_trx.cc @@ -3710,7 +3710,7 @@ int spider_check_trx_and_get_conn( { TABLE *table = spider->get_table(); TABLE_SHARE *table_share = table->s; -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) char *db, *table_name; if (!(db = (char *) spider_bulk_malloc(spider_current_trx, 57, MYF(MY_WME), @@ -3732,7 +3732,7 @@ int spider_check_trx_and_get_conn( table_name[table_share->table_name.length] = '\0'; my_printf_error(ER_SPIDER_ALL_LINKS_FAILED_NUM, ER_SPIDER_ALL_LINKS_FAILED_STR, MYF(0), db, table_name); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_free(trx, db, MYF(MY_WME)); #endif DBUG_RETURN(ER_SPIDER_ALL_LINKS_FAILED_NUM); @@ -3869,7 +3869,7 @@ int spider_check_trx_and_get_conn( { TABLE *table = spider->get_table(); TABLE_SHARE *table_share = table->s; -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) char *db, *table_name; if (!(db = (char *) spider_bulk_malloc(spider_current_trx, 57, MYF(MY_WME), @@ -3891,7 +3891,7 @@ int spider_check_trx_and_get_conn( table_name[table_share->table_name.length] = '\0'; my_printf_error(ER_SPIDER_LINK_MON_JUST_NG_NUM, ER_SPIDER_LINK_MON_JUST_NG_STR, MYF(0), db, table_name); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_free(trx, db, MYF(MY_WME)); #endif DBUG_RETURN(ER_SPIDER_LINK_MON_JUST_NG_NUM); @@ -4015,7 +4015,7 @@ int spider_check_trx_and_get_conn( { TABLE *table = spider->get_table(); TABLE_SHARE *table_share = table->s; -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) char *db, *table_name; if (!(db = (char *) spider_bulk_malloc(spider_current_trx, 57, MYF(MY_WME), @@ -4037,7 +4037,7 @@ int spider_check_trx_and_get_conn( table_name[table_share->table_name.length] = '\0'; my_printf_error(ER_SPIDER_LINK_MON_JUST_NG_NUM, ER_SPIDER_LINK_MON_JUST_NG_STR, MYF(0), db, table_name); -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SUNPRO_CC) spider_free(trx, db, MYF(MY_WME)); #endif DBUG_RETURN(ER_SPIDER_LINK_MON_JUST_NG_NUM); From 2b7573ecdda4e542fc65e5d0992f5c05474975c0 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Sun, 24 Apr 2016 13:36:51 +0400 Subject: [PATCH 73/91] MDEV-9975 - main.partition_innodb_plugin fails sporadically Fixed wait condition to wait for InnoDB to actually acquire row locks instead of waiting for thread to enter "Searching rows for update" state (which happens earlier). Also use default wait timeout, 2 seconds can be too few for threads to enter appropriate state. --- mysql-test/t/partition_innodb_plugin.test | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/mysql-test/t/partition_innodb_plugin.test b/mysql-test/t/partition_innodb_plugin.test index 4693288a4dd..a951945a87c 100644 --- a/mysql-test/t/partition_innodb_plugin.test +++ b/mysql-test/t/partition_innodb_plugin.test @@ -124,12 +124,8 @@ SEND; UPDATE `t``\""e` SET a = 12 WHERE a = 0; --echo # default connection connection default; -let $wait_timeout= 2; -let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST -WHERE ID = $id_1 AND STATE = 'Searching rows for update'; +let $wait_condition= SELECT COUNT(*)=2 FROM INFORMATION_SCHEMA.INNODB_LOCKS; --source include/wait_condition.inc -#--echo # tested wait condition $wait_condition_reps times -# INNODB_LOCKS only exists in innodb_plugin --sorted_result SELECT lock_table, COUNT(*) FROM INFORMATION_SCHEMA.INNODB_LOCKS GROUP BY lock_table; From 26adbb2dd50db0d62e6f7f5d12bdab0cd3a0bf31 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Mon, 25 Apr 2016 00:13:06 +0200 Subject: [PATCH 74/91] - Fix an error causing MYSQL table to fail saying "no result set" when joining a table to a MYSQL indexed table. modified: storage/connect/myconn.cpp modified: storage/connect/myconn.h modified: storage/connect/tabmysql.cpp - Add more tests to the mysql_index.test file modified: storage/connect/mysql-test/connect/r/mysql_index.result modified: storage/connect/mysql-test/connect/t/mysql_index.test - Fix and error causing remote indexing to fail when for not unique index. Was experienced with MYSQL, ODBC and JDBC tables. modified: storage/connect/connect.cc - Fix MDEV-9966 (zero lines returned) modified: storage/connect/ha_connect.cc modified: storage/federatedx/ha_federatedx.cc --- storage/connect/connect.cc | 2 +- storage/connect/ha_connect.cc | 2 +- storage/connect/myconn.cpp | 11 +- storage/connect/myconn.h | 2 +- .../mysql-test/connect/r/mysql_index.result | 321 ++++++++++++++++++ .../mysql-test/connect/t/mysql_index.test | 67 ++++ storage/connect/tabmysql.cpp | 6 +- storage/federatedx/ha_federatedx.cc | 26 +- 8 files changed, 412 insertions(+), 25 deletions(-) diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc index 56a0fc4fd4f..460d47bcf62 100644 --- a/storage/connect/connect.cc +++ b/storage/connect/connect.cc @@ -752,7 +752,7 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op, return RC_FX; } else if (x == 2) { // Remote index - if (ptdb->ReadKey(g, op, kr)) + if (op != OP_SAME && ptdb->ReadKey(g, op, kr)) return RC_FX; goto rnd; diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 67cfb29254f..2055b93927f 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -2288,7 +2288,7 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q, op= OP_EQ; break; case HA_READ_AFTER_KEY: - op= (stlen >= len) ? (!i ? OP_GT : OP_LE) : OP_GE; + op= (stlen >= len || i > 0) ? (i > 0 ? OP_LE : OP_GT) : OP_GE; break; case HA_READ_KEY_OR_NEXT: op= OP_GE; diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp index ada0109a820..e9bd64cf8e6 100644 --- a/storage/connect/myconn.cpp +++ b/storage/connect/myconn.cpp @@ -959,11 +959,16 @@ void MYSQLC::FreeResult(void) /***********************************************************************/ /* Place the cursor at the beginning of the result set. */ /***********************************************************************/ -void MYSQLC::Rewind(void) +int MYSQLC::Rewind(PGLOBAL g, PSZ sql) { - if (m_Res) - DataSeek(0); + int rc = RC_OK; + if (m_Res) + DataSeek(0); + else if (sql) + rc = ExecSQL(g, sql); + + return rc; } // end of Rewind /***********************************************************************/ diff --git a/storage/connect/myconn.h b/storage/connect/myconn.h index fa34edd804c..79f095f5c93 100644 --- a/storage/connect/myconn.h +++ b/storage/connect/myconn.h @@ -80,7 +80,7 @@ class DllItem MYSQLC { int Fetch(PGLOBAL g, int pos); char *GetCharField(int i); int GetFieldLength(int i); - void Rewind(void); + int Rewind(PGLOBAL g, PSZ sql); void FreeResult(void); void Close(void); diff --git a/storage/connect/mysql-test/connect/r/mysql_index.result b/storage/connect/mysql-test/connect/r/mysql_index.result index 4ebf10802ae..dd1864529ca 100644 --- a/storage/connect/mysql-test/connect/r/mysql_index.result +++ b/storage/connect/mysql-test/connect/r/mysql_index.result @@ -112,3 +112,324 @@ id msg 6 Six DROP TABLE t2; DROP TABLE t1; +# +# Make local FIX table with indices matricule and nom/prenom +# +CREATE TABLE t1 +( +matricule INT(4) KEY NOT NULL field_format='Z', +nom VARCHAR(16) NOT NULL, +prenom VARCHAR(20) NOT NULL, +sexe SMALLINT(1) NOT NULL COMMENT 'sexe 1:M 2:F', +aanais INT(4) NOT NULL, +mmnais INT(2) NOT NULL, +ddentree DATE NOT NULL date_format='YYYYMM', +ddnom DATE NOT NULL date_format='YYYYMM', +brut INT(5) NOT NULL, +net DOUBLE(8,2) NOT NULL, +service INT(2) NOT NULL, +sitmat CHAR(1) NOT NULL, +formation CHAR(5) NOT NULL, +INDEX NP(nom,prenom) +) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='emp.txt' ENDING=2; +# +# Make MYSQL table with same indices +# +CREATE TABLE t2 +( +matricule INT(4) KEY NOT NULL, +nom VARCHAR(16) NOT NULL, +prenom VARCHAR(20) NOT NULL, +sexe SMALLINT(1) NOT NULL, +aanais INT(4) NOT NULL, +mmnais INT(2) NOT NULL, +ddentree DATE NOT NULL date_format='YYYYMM', +ddnom DATE NOT NULL date_format='YYYYMM', +brut INT(5) NOT NULL, +net DOUBLE(8,2) NOT NULL, +service INT(2) NOT NULL, +sitmat CHAR(1) NOT NULL, +formation CHAR(5) NOT NULL, +INDEX NP(nom,prenom) +) ENGINE=CONNECT TABLE_TYPE=MYSQL CONNECTIOn='mysql://root@localhost/test/t1'; +SELECT * FROM t2 limit 10; +matricule nom prenom sexe aanais mmnais ddentree ddnom brut net service sitmat formation +5745 ESCOURCHE BENEDICTE 2 1935 7 1962-12-01 1994-05-01 18345 14275.50 0 M TECHN +9692 VICENTE LAURENCE 2 1941 8 1967-10-01 1989-01-01 16212 13032.80 0 M ANGL +9146 NICOLAS ROGER 1 1941 6 1964-07-01 1995-02-01 34173 25098.65 0 M SANS +2985 TESSEREAU MARIE HELENE 2 1941 9 1967-01-01 1990-01-01 19323 14933.78 0 V SANS +3368 MOGADOR ALAIN 1 1941 1 1961-09-01 1993-11-01 43303 31420.55 0 C SANS +7394 CHAUSSEE ERIC DENIS 1 1944 9 1965-11-01 1983-12-01 32002 23583.86 0 M ANGL +4655 MAILLOT GEORGES 1 1945 5 1970-09-01 1986-12-01 24700 18541.64 0 C ANGL +2825 CAMILLE NADINE 2 1956 9 1994-01-01 1993-01-01 19494 15050.45 0 M SANS +1460 BRUYERES JEAN MARC 1 1958 8 1984-08-01 1988-05-01 20902 15980.07 0 M SANS +4974 LONES GERARD 1 1959 10 1979-01-01 1994-12-01 16081 12916.70 0 M SANS +SELECT matricule, nom, prenom FROM t2 WHERE nom IN ('FOCH','MOGADOR'); +matricule nom prenom +1977 FOCH BERNADETTE +5707 FOCH DENIS +2552 FOCH FRANCK +2634 FOCH JOCELYNE +5765 FOCH ROBERT +4080 FOCH SERGE +3368 MOGADOR ALAIN +SELECT matricule, nom, prenom FROM t2 WHERE nom = 'FOCH' OR nom = 'MOGADOR'; +matricule nom prenom +1977 FOCH BERNADETTE +5707 FOCH DENIS +2552 FOCH FRANCK +2634 FOCH JOCELYNE +5765 FOCH ROBERT +4080 FOCH SERGE +3368 MOGADOR ALAIN +SELECT matricule, nom, prenom FROM t2 WHERE nom < 'ADDAX'; +matricule nom prenom +4552 ABBADIE MONIQUE +307 ABBAYE ANNICK +6627 ABBAYE GERALD +7961 ABBE KATIA +1340 ABBE MICHELE +9270 ABBE SOPHIE +2945 ABBEVILLE PASCAL +8596 ABEBERRY PATRICK +6399 ABEILLES RENE +8673 ABEL JEAN PIERRE +6124 ABELIAS DELIA +6314 ABERDEN EVELYNE +895 ABORD CHANTAL +2728 ABOUT CATHERINE MARIE +398 ABREUVOIR JEAN LUC +1122 ACACIAS SERGE +1644 ACARDIE BEATE +115 ACHILLE JACQUES +4038 ADAM JANICK +3395 ADAM JEAN CLAUDE +SELECT matricule, nom, prenom FROM t2 WHERE nom <= 'ABEL'; +matricule nom prenom +4552 ABBADIE MONIQUE +307 ABBAYE ANNICK +6627 ABBAYE GERALD +7961 ABBE KATIA +1340 ABBE MICHELE +9270 ABBE SOPHIE +2945 ABBEVILLE PASCAL +8596 ABEBERRY PATRICK +6399 ABEILLES RENE +8673 ABEL JEAN PIERRE +SELECT matricule, nom, prenom FROM t2 WHERE nom > 'YVON'; +matricule nom prenom +9742 YZENGREMER MICHEL +8738 ZILINA JEAN LOUIS +5357 ZOLA BERNARD +5441 ZOLA BRIGITTE +1325 ZOLA CHRISTINE +4859 ZORI CATHERINE +4102 ZOUAVES ALAIN +SELECT matricule, nom, prenom FROM t2 WHERE nom >= 'YVON'; +matricule nom prenom +5389 YVON CAROLE +9742 YZENGREMER MICHEL +8738 ZILINA JEAN LOUIS +5357 ZOLA BERNARD +5441 ZOLA BRIGITTE +1325 ZOLA CHRISTINE +4859 ZORI CATHERINE +4102 ZOUAVES ALAIN +SELECT matricule, nom, prenom FROM t2 WHERE nom <= 'ABEL' OR nom > 'YVON'; +matricule nom prenom +4552 ABBADIE MONIQUE +307 ABBAYE ANNICK +6627 ABBAYE GERALD +7961 ABBE KATIA +1340 ABBE MICHELE +9270 ABBE SOPHIE +2945 ABBEVILLE PASCAL +8596 ABEBERRY PATRICK +6399 ABEILLES RENE +8673 ABEL JEAN PIERRE +9742 YZENGREMER MICHEL +8738 ZILINA JEAN LOUIS +5357 ZOLA BERNARD +5441 ZOLA BRIGITTE +1325 ZOLA CHRISTINE +4859 ZORI CATHERINE +4102 ZOUAVES ALAIN +SELECT matricule, nom, prenom FROM t2 WHERE nom > 'HELEN' AND nom < 'HEROS'; +matricule nom prenom +9096 HELENA PHILIPPE +3309 HELENE ISABELLE +8365 HELIOTROPES LISE +4666 HELLEN PIERRE +5781 HELSINKI DANIELLE +7626 HENIN PHILIPPE +4254 HENIN SERGE +2673 HENNER LILIANE +9716 HENRI JACQUES +2085 HEOL GUY PAUL +2579 HERANDIERE PIERRE +7093 HERAULTS DANIEL +4050 HERBILLON FRANCOIS +9231 HERBILLON MADELEINE +1291 HERMITAGE XAVIER +6185 HERMITTE FRANCOIS +403 HERMITTE PHILIPPE +9749 HEROLD ISABELLE +SELECT matricule, nom, prenom FROM t2 WHERE nom BETWEEN 'HELEN' AND 'HEROS'; +matricule nom prenom +6199 HELEN MARTIAL +9096 HELENA PHILIPPE +3309 HELENE ISABELLE +8365 HELIOTROPES LISE +4666 HELLEN PIERRE +5781 HELSINKI DANIELLE +7626 HENIN PHILIPPE +4254 HENIN SERGE +2673 HENNER LILIANE +9716 HENRI JACQUES +2085 HEOL GUY PAUL +2579 HERANDIERE PIERRE +7093 HERAULTS DANIEL +4050 HERBILLON FRANCOIS +9231 HERBILLON MADELEINE +1291 HERMITAGE XAVIER +6185 HERMITTE FRANCOIS +403 HERMITTE PHILIPPE +9749 HEROLD ISABELLE +8445 HEROS SYLVIE +SELECT matricule, nom, prenom FROM t2 WHERE nom BETWEEN 'HELEN' AND 'HEROS' AND prenom = 'PHILIPPE'; +matricule nom prenom +9096 HELENA PHILIPPE +7626 HENIN PHILIPPE +403 HERMITTE PHILIPPE +SELECT matricule, nom, prenom FROM t2 ORDER BY nom LIMIT 10; +matricule nom prenom +4552 ABBADIE MONIQUE +6627 ABBAYE GERALD +307 ABBAYE ANNICK +7961 ABBE KATIA +1340 ABBE MICHELE +9270 ABBE SOPHIE +2945 ABBEVILLE PASCAL +8596 ABEBERRY PATRICK +6399 ABEILLES RENE +8673 ABEL JEAN PIERRE +SELECT a.nom, a.prenom, b.nom FROM t1 a STRAIGHT_JOIN t2 b ON a.prenom = b.prenom WHERE a.nom = 'FOCH' AND a.nom != b.nom; +nom prenom nom +FOCH SERGE ACACIAS +FOCH ROBERT AGRIANT +FOCH JOCELYNE ALEXIS +FOCH DENIS AMBOISE +FOCH SERGE ANDALUCIA +FOCH ROBERT ANNECY +FOCH SERGE ARCACHON +FOCH JOCELYNE AUGUSTE +FOCH JOCELYNE BASSE +FOCH SERGE BEACH +FOCH FRANCK BEARN +FOCH SERGE BELLES +FOCH DENIS BERARD +FOCH DENIS BERIN +FOCH BERNADETTE BERTIN +FOCH DENIS BILLEHOU +FOCH DENIS BOILEAU +FOCH BERNADETTE BOISSY +FOCH ROBERT BONVIN +FOCH SERGE BOUTON +FOCH SERGE BREUIL +FOCH SERGE CARREFOUR +FOCH JOCELYNE CARRERE +FOCH JOCELYNE CHAPELLE +FOCH SERGE CHATEAU +FOCH ROBERT CHENIER +FOCH SERGE COLLETTE +FOCH DENIS CONNE +FOCH SERGE COOLE +FOCH DENIS COULOUBRIER +FOCH DENIS COUTURIER +FOCH ROBERT CURAT +FOCH ROBERT DAUDET +FOCH SERGE ECLUSE +FOCH SERGE EGUILLON +FOCH DENIS EPINETTES +FOCH DENIS FIGOURNAS +FOCH JOCELYNE FLEMING +FOCH JOCELYNE GAMBADES +FOCH ROBERT GIOTERAIE +FOCH SERGE GOAS +FOCH ROBERT GRAFFIANE +FOCH SERGE GREFFIER +FOCH ROBERT GUILLOTIERE +FOCH SERGE HENIN +FOCH BERNADETTE HUNTZIGER +FOCH FRANCK ILLIERS +FOCH DENIS ISTANBUL +FOCH DENIS ITALIE +FOCH SERGE JARDIN +FOCH FRANCK JEANPIERRE +FOCH JOCELYNE KENNEDY +FOCH FRANCK LABBE +FOCH DENIS LACATE +FOCH FRANCK LACOMBE +FOCH ROBERT LAMOTHE +FOCH BERNADETTE LATECOERE +FOCH BERNADETTE LEGER +FOCH SERGE LEONIE +FOCH FRANCK LEROY +FOCH SERGE LOZERE +FOCH DENIS MAROLLES +FOCH ROBERT MARRONIERS +FOCH SERGE MARSAT +FOCH SERGE MONTAGNE +FOCH FRANCK MONTALEIGNE +FOCH DENIS MONTELIER +FOCH DENIS MONTILS +FOCH BERNADETTE MONTJUSTIN +FOCH SERGE MORIZET +FOCH ROBERT NIMES +FOCH ROBERT NORD +FOCH SERGE NOVEMBRE +FOCH BERNADETTE ONZE +FOCH SERGE ORANGERIE +FOCH FRANCK ORVEAU +FOCH BERNADETTE PALMAROLE +FOCH JOCELYNE PEYBERT +FOCH ROBERT PEYNIBLOU +FOCH ROBERT PIECE +FOCH JOCELYNE PIED +FOCH ROBERT PLAGNE +FOCH SERGE PLAISANCE +FOCH BERNADETTE PLOUHARNEL +FOCH DENIS POINTE +FOCH ROBERT POMMERY +FOCH JOCELYNE PONTAROUX +FOCH DENIS PORTO +FOCH ROBERT PRESIDENT +FOCH ROBERT PUJADE +FOCH FRANCK PURPAN +FOCH ROBERT QUILICHINI +FOCH DENIS REINOTS +FOCH DENIS REMPART +FOCH SERGE RESISTANCE +FOCH SERGE RESTANQUES +FOCH ROBERT RIOU +FOCH FRANCK ROCQUENCOURT +FOCH ROBERT ROLL +FOCH ROBERT ROSSA +FOCH SERGE ROSSAYS +FOCH DENIS ROUSSIER +FOCH FRANCK RUSSIE +FOCH ROBERT SABLONS +FOCH SERGE SARTRE +FOCH SERGE SAVIGNAC +FOCH SERGE SEGUR +FOCH ROBERT STRASBOURG +FOCH ROBERT TIRE +FOCH DENIS TORTE +FOCH DENIS TOULON +FOCH ROBERT TUBY +FOCH DENIS VALMANTE +FOCH SERGE VANOEL +FOCH ROBERT VIARMES +FOCH SERGE WILSON +DROP TABLE t2; +DROP TABLE t1; diff --git a/storage/connect/mysql-test/connect/t/mysql_index.test b/storage/connect/mysql-test/connect/t/mysql_index.test index 9a162b4d8e3..81fdcad9330 100644 --- a/storage/connect/mysql-test/connect/t/mysql_index.test +++ b/storage/connect/mysql-test/connect/t/mysql_index.test @@ -64,3 +64,70 @@ SELECT * FROM t2; DROP TABLE t2; DROP TABLE t1; + +let $MYSQLD_DATADIR= `select @@datadir`; +--copy_file $MTR_SUITE_DIR/std_data/emp.txt $MYSQLD_DATADIR/test/emp.txt + +--echo # +--echo # Make local FIX table with indices matricule and nom/prenom +--echo # +CREATE TABLE t1 +( + matricule INT(4) KEY NOT NULL field_format='Z', + nom VARCHAR(16) NOT NULL, + prenom VARCHAR(20) NOT NULL, + sexe SMALLINT(1) NOT NULL COMMENT 'sexe 1:M 2:F', + aanais INT(4) NOT NULL, + mmnais INT(2) NOT NULL, + ddentree DATE NOT NULL date_format='YYYYMM', + ddnom DATE NOT NULL date_format='YYYYMM', + brut INT(5) NOT NULL, + net DOUBLE(8,2) NOT NULL, + service INT(2) NOT NULL, + sitmat CHAR(1) NOT NULL, + formation CHAR(5) NOT NULL, + INDEX NP(nom,prenom) +) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='emp.txt' ENDING=2; + +--echo # +--echo # Make MYSQL table with same indices +--echo # +CREATE TABLE t2 +( + matricule INT(4) KEY NOT NULL, + nom VARCHAR(16) NOT NULL, + prenom VARCHAR(20) NOT NULL, + sexe SMALLINT(1) NOT NULL, + aanais INT(4) NOT NULL, + mmnais INT(2) NOT NULL, + ddentree DATE NOT NULL date_format='YYYYMM', + ddnom DATE NOT NULL date_format='YYYYMM', + brut INT(5) NOT NULL, + net DOUBLE(8,2) NOT NULL, + service INT(2) NOT NULL, + sitmat CHAR(1) NOT NULL, + formation CHAR(5) NOT NULL, + INDEX NP(nom,prenom) +) ENGINE=CONNECT TABLE_TYPE=MYSQL CONNECTIOn='mysql://root@localhost/test/t1'; +SELECT * FROM t2 limit 10; +SELECT matricule, nom, prenom FROM t2 WHERE nom IN ('FOCH','MOGADOR'); +SELECT matricule, nom, prenom FROM t2 WHERE nom = 'FOCH' OR nom = 'MOGADOR'; +SELECT matricule, nom, prenom FROM t2 WHERE nom < 'ADDAX'; +SELECT matricule, nom, prenom FROM t2 WHERE nom <= 'ABEL'; +SELECT matricule, nom, prenom FROM t2 WHERE nom > 'YVON'; +SELECT matricule, nom, prenom FROM t2 WHERE nom >= 'YVON'; +SELECT matricule, nom, prenom FROM t2 WHERE nom <= 'ABEL' OR nom > 'YVON'; +SELECT matricule, nom, prenom FROM t2 WHERE nom > 'HELEN' AND nom < 'HEROS'; +SELECT matricule, nom, prenom FROM t2 WHERE nom BETWEEN 'HELEN' AND 'HEROS'; +SELECT matricule, nom, prenom FROM t2 WHERE nom BETWEEN 'HELEN' AND 'HEROS' AND prenom = 'PHILIPPE'; +SELECT matricule, nom, prenom FROM t2 ORDER BY nom LIMIT 10; +SELECT a.nom, a.prenom, b.nom FROM t1 a STRAIGHT_JOIN t2 b ON a.prenom = b.prenom WHERE a.nom = 'FOCH' AND a.nom != b.nom; + +DROP TABLE t2; +DROP TABLE t1; + +# +# Clean up +# +--remove_file $MYSQLD_DATADIR/test/emp.txt +--remove_file $MYSQLD_DATADIR/test/emp.fnx diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index ed474de036a..b704e1c758b 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -19,7 +19,7 @@ /* --------------- */ /* TABMYSQL.CPP - Source code */ /* PLGDBSEM.H - DB application declaration file */ -/* TABMYSQL.H - TABODBC classes declaration file */ +/* TABMYSQL.H - TABMYSQL classes declaration file */ /* GLOBAL.H - Global declaration file */ /* */ /* REQUIRED LIBRARIES: */ @@ -857,7 +857,9 @@ bool TDBMYSQL::OpenDB(PGLOBAL g) /*******************************************************************/ /* Table already open, just replace it at its beginning. */ /*******************************************************************/ - Myc.Rewind(); + if (Myc.Rewind(g, (Mode == MODE_READX) ? Query->GetStr() : NULL) != RC_OK) + return true; + N = -1; return false; } // endif use diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index 70201167fde..dc524d3466a 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -566,17 +566,17 @@ int get_connection(MEM_ROOT *mem_root, FEDERATEDX_SHARE *share) at the address of the share. */ share->server_name_length= server->server_name_length; - share->server_name= server->server_name; - share->username= server->username; - share->password= server->password; - share->database= server->db; + share->server_name= const_cast(server->server_name); + share->username= const_cast(server->username); + share->password= const_cast(server->password); + share->database= const_cast(server->db); share->port= server->port > MIN_PORT && server->port < 65536 ? (ushort) server->port : MYSQL_PORT; - share->hostname= server->host; - if (!(share->socket= server->socket) && + share->hostname= const_cast(server->host); + if (!(share->socket= const_cast(server->socket)) && !strcmp(share->hostname, my_localhost)) share->socket= (char *) MYSQL_UNIX_ADDR; - share->scheme= server->scheme; + share->scheme= const_cast(server->scheme); DBUG_PRINT("info", ("share->username: %s", share->username)); DBUG_PRINT("info", ("share->password: %s", share->password)); @@ -1319,7 +1319,7 @@ bool ha_federatedx::create_where_from_key(String *to, break; } DBUG_PRINT("info", ("federatedx HA_READ_AFTER_KEY %d", i)); - if (store_length >= length) /* end key */ + if (store_length >= length || i > 0) /* end key */ { if (emit_key_part_name(&tmp, key_part)) goto err; @@ -2555,9 +2555,7 @@ int ha_federatedx::index_read_idx(uchar *buf, uint index, const uchar *key, RESULT 0 ok In this case *result will contain the result set - table->status == 0 # error In this case *result will contain 0 - table->status == STATUS_NOT_FOUND */ int ha_federatedx::index_read_idx_with_result_set(uchar *buf, uint index, @@ -2614,11 +2612,9 @@ int ha_federatedx::index_read_idx_with_result_set(uchar *buf, uint index, insert_dynamic(&results, (uchar*) result); *result= 0; - table->status= STATUS_NOT_FOUND; DBUG_RETURN(retval); error: - table->status= STATUS_NOT_FOUND; my_error(retval, MYF(0), error_buffer); DBUG_RETURN(retval); } @@ -2699,7 +2695,6 @@ int ha_federatedx::read_range_first(const key_range *start_key, DBUG_RETURN(retval); error: - table->status= STATUS_NOT_FOUND; DBUG_RETURN(retval); } @@ -2904,8 +2899,6 @@ int ha_federatedx::read_next(uchar *buf, FEDERATEDX_IO_RESULT *result) FEDERATEDX_IO_ROW *row; DBUG_ENTER("ha_federatedx::read_next"); - table->status= STATUS_NOT_FOUND; // For easier return - if ((retval= txn->acquire(share, TRUE, &io))) DBUG_RETURN(retval); @@ -2990,7 +2983,6 @@ int ha_federatedx::rnd_pos(uchar *buf, uchar *pos) DBUG_RETURN(retval); error: - table->status= STATUS_NOT_FOUND; DBUG_RETURN(retval); } @@ -3093,7 +3085,7 @@ error: else if (remote_error_number != -1 /* error already reported */) { error_code= remote_error_number; - my_error(error_code, MYF(0), ER(error_code)); + my_error(error_code, MYF(0), ER_THD(thd, error_code)); } fail: tmp_txn->release(&tmp_io); From f6cc7f1bdc56e57cf441f99f2c88ca92aeeebc11 Mon Sep 17 00:00:00 2001 From: Monty Date: Mon, 25 Apr 2016 15:37:24 +0300 Subject: [PATCH 75/91] Fixed failing test cases and compiler warnings - Fixed wait condition in kill_processlist-6619 - Updated Ssl_chiper for openssl tests - Added supression for valgrinds when using libcrypto - Fixed wrong argument to pthread_mutex in server_audit.c when compiling with debug - Adding missing debug_sync_update() to debug_sync.h - Added initializers to some variables and fixed error handling in jsonudf.cpp - Fixed cluster_filter_unpack_varchar which doesn't have a stable index type. - Updated compiler_warnings.supp --- mysql-test/t/kill_processlist-6619.test | 9 ++++++++- mysql-test/t/openssl_1.test | 4 ++-- mysql-test/t/openssl_6975.test | 1 + mysql-test/t/ssl.test | 4 ++-- mysql-test/t/ssl_compress.test | 4 ++-- mysql-test/t/ssl_timeout.test | 2 +- mysql-test/valgrind.supp | 7 +++++++ plugin/server_audit/server_audit.c | 10 ++++------ sql/debug_sync.h | 1 + sql/sys_vars.h | 2 +- storage/connect/jsonudf.cpp | 11 ++++++----- .../tokudb/r/cluster_filter_unpack_varchar.result | 4 ++-- .../tokudb/t/cluster_filter_unpack_varchar.test | 4 ++-- support-files/compiler_warnings.supp | 6 +++--- 14 files changed, 42 insertions(+), 27 deletions(-) diff --git a/mysql-test/t/kill_processlist-6619.test b/mysql-test/t/kill_processlist-6619.test index 95af83be56d..d599d204dda 100644 --- a/mysql-test/t/kill_processlist-6619.test +++ b/mysql-test/t/kill_processlist-6619.test @@ -1,5 +1,5 @@ # -# MDEV-6619 SHOW PROCESSLIST returns empty result set after KILL QUERY +# 6619 SHOW PROCESSLIST returns empty result set after KILL QUERY # --source include/not_embedded.inc --source include/have_debug_sync.inc @@ -23,5 +23,12 @@ SET DEBUG_SYNC='now SIGNAL go'; --error ER_QUERY_INTERRUPTED reap; SET DEBUG_SYNC='reset'; + +# Wait until default connection has reset query string +let $wait_condition= + SELECT COUNT(*) = 1 from information_schema.processlist + WHERE info is NULL; +--source include/wait_condition.inc + --replace_column 1 # 3 # 6 # 7 # SHOW PROCESSLIST; diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test index e36f106a5be..4578a05be36 100644 --- a/mysql-test/t/openssl_1.test +++ b/mysql-test/t/openssl_1.test @@ -132,7 +132,7 @@ drop table t1; # verification of servers certificate by setting both ca certificate # and ca path to NULL # ---replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA +--replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-SHA --exec $MYSQL --ssl --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem -e "SHOW STATUS LIKE 'ssl_Cipher'" 2>&1 --echo End of 5.0 tests @@ -257,7 +257,7 @@ select 'is still running; no cipher request crashed the server' as result from d GRANT SELECT ON test.* TO bug42158@localhost REQUIRE X509; FLUSH PRIVILEGES; connect(con1,localhost,bug42158,,,,,SSL); ---replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA +--replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-SHA SHOW STATUS LIKE 'Ssl_cipher'; disconnect con1; connection default; diff --git a/mysql-test/t/openssl_6975.test b/mysql-test/t/openssl_6975.test index bc6397c5c28..89e6983cf47 100644 --- a/mysql-test/t/openssl_6975.test +++ b/mysql-test/t/openssl_6975.test @@ -15,6 +15,7 @@ let $mysql=$MYSQL --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$ disable_abort_on_error; echo TLS1.2 ciphers: user is ok with any cipher; exec $mysql --ssl-cipher=AES128-SHA256; +--replace_result DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-GCM-SHA384 exec $mysql --ssl-cipher=TLSv1.2; echo TLS1.2 ciphers: user requires SSLv3 cipher RC4-SHA; exec $mysql --user ssl_sslv3 --ssl-cipher=AES128-SHA256; diff --git a/mysql-test/t/ssl.test b/mysql-test/t/ssl.test index 0d14ad82692..21733f7e594 100644 --- a/mysql-test/t/ssl.test +++ b/mysql-test/t/ssl.test @@ -11,7 +11,7 @@ connect (ssl_con,localhost,root,,,,,SSL); # Check ssl turned on ---replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA +--replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-SHA SHOW STATUS LIKE 'Ssl_cipher'; # Check ssl expiration @@ -22,7 +22,7 @@ SHOW STATUS LIKE 'Ssl_server_not_after'; -- source include/common-tests.inc # Check ssl turned on ---replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA +--replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-SHA SHOW STATUS LIKE 'Ssl_cipher'; # diff --git a/mysql-test/t/ssl_compress.test b/mysql-test/t/ssl_compress.test index 5e45e3824a2..28f3453c23e 100644 --- a/mysql-test/t/ssl_compress.test +++ b/mysql-test/t/ssl_compress.test @@ -11,7 +11,7 @@ connect (ssl_compress_con,localhost,root,,,,,SSL COMPRESS); # Check ssl turned on ---replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA +--replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-SHA SHOW STATUS LIKE 'Ssl_cipher'; # Check compression turned on @@ -21,7 +21,7 @@ SHOW STATUS LIKE 'Compression'; -- source include/common-tests.inc # Check ssl turned on ---replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA +--replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-SHA SHOW STATUS LIKE 'Ssl_cipher'; # Check compression turned on diff --git a/mysql-test/t/ssl_timeout.test b/mysql-test/t/ssl_timeout.test index 0d96b3f6601..806b928aca0 100644 --- a/mysql-test/t/ssl_timeout.test +++ b/mysql-test/t/ssl_timeout.test @@ -7,7 +7,7 @@ connect (ssl_con,localhost,root,,,,,SSL read_timeout=5); --echo # Check ssl turned on ---replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA +--replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-SHA SHOW STATUS LIKE 'Ssl_cipher'; # --error CR_SERVER_LOST diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index e8eb47eb1cb..d83bb1d206c 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -1158,6 +1158,13 @@ fun:SSL_library_init } +{ + libcrypto 2.2.1 leak + Memcheck:Leak + fun:malloc + ... + fun:ERR_get_state +} { Problem with udf and libresolve diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index 30b7cdb5dcb..b84f2b94806 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -97,13 +97,11 @@ static void closelog() {} #define FLOGGER_NO_PSI /* How to access the pthread_mutex in mysql_mutex_t */ -//#ifdef SAFE_MUTEX -//#define mysql_mutex_real_mutex(A) &(A)->m_mutex.mutex -//#elif defined(MY_PTHREAD_FASTMUTEX) -//#define mysql_mutex_real_mutex(A) &(A)->m_mutex.mutex -//#else +#if defined(SAFE_MUTEX) || defined(MY_PTHREAD_FASTMUTEX) +#define mysql_mutex_real_mutex(A) &(A)->m_mutex.mutex +#else #define mysql_mutex_real_mutex(A) &(A)->m_mutex -//#endif +#endif #define flogger_mutex_init(A,B,C) do{}while(0) #define flogger_mutex_destroy(A) do{}while(0) diff --git a/sql/debug_sync.h b/sql/debug_sync.h index bf1b3167dbc..25b379e5892 100644 --- a/sql/debug_sync.h +++ b/sql/debug_sync.h @@ -44,6 +44,7 @@ extern void debug_sync_end(void); extern void debug_sync_init_thread(THD *thd); extern void debug_sync_end_thread(THD *thd); extern bool debug_sync_set_action(THD *thd, const char *action_str, size_t len); +extern bool debug_sync_update(THD *thd, char *val_str); #endif /* defined(ENABLED_DEBUG_SYNC) */ diff --git a/sql/sys_vars.h b/sql/sys_vars.h index 36067c50cc1..79b67d3b45c 100644 --- a/sql/sys_vars.h +++ b/sql/sys_vars.h @@ -30,6 +30,7 @@ #include "strfunc.h" #include "tztime.h" // my_tz_find, my_tz_SYSTEM, struct Time_zone #include "rpl_mi.h" // For Multi-Source Replication +#include "debug_sync.h" /* a set of mostly trivial (as in f(X)=X) defines below to make system variable @@ -1455,7 +1456,6 @@ public: } bool session_update(THD *thd, set_var *var) { - extern bool debug_sync_update(THD *thd, char *val_str); return debug_sync_update(thd, var->save_result.string_value.str); } bool global_update(THD *thd, set_var *var) diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index 25c77cea534..7b82ba2d627 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -533,7 +533,7 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n) /*********************************************************************************/ my_bool JSNX::CheckPath(PGLOBAL g) { - PJVAL val; + PJVAL val= NULL; PJSON row = Row; for (int i = 0; i < Nod && row; i++) { @@ -1302,7 +1302,7 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj, { char fn[_MAX_PATH]; unsigned long i, k, m, n; - long fl, j = -1; + long fl= 0, j = -1; reslen = args->arg_count + 2; @@ -2087,7 +2087,7 @@ my_bool json_object_nonull_init(UDF_INIT *initid, UDF_ARGS *args, char *json_object_nonull(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *res_length, char *, char *) { - char *str; + char *str= 0; PGLOBAL g = (PGLOBAL)initid->ptr; if (!g->Xchk) { @@ -2621,7 +2621,7 @@ char *json_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result, } // endif Xchk if (!CheckMemory(g, initid, args, 2, false, false, true)) { - PJSON top; + PJSON top= 0; PJVAL jvp; PJSON jsp[2] = {NULL, NULL}; @@ -4721,7 +4721,7 @@ char *jbin_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result, my_bool b = true; PJSON jsp; PJSNX jsx; - PJVAL jvp; + PJVAL jvp= 0; PBSON bsp = NULL; PGLOBAL g = (PGLOBAL)initid->ptr; PGLOBAL gb = GetMemPtr(g, args, 0); @@ -4742,6 +4742,7 @@ char *jbin_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result, if (!g->Xchk) { if (CheckMemory(g, initid, args, 1, true, false, true)) { PUSH_WARNING("CheckMemory error"); + goto fin; } else jvp = MakeValue(g, args, 0); diff --git a/storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar.result b/storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar.result index d3273437f77..9faf04b6a10 100644 --- a/storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar.result +++ b/storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar.result @@ -182,14 +182,14 @@ a b c d e f 3 30 200 2000 20000 200000 explain select * from t1 where b > "0"; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index b b NULL NULL NULL; Using where; Using index +1 SIMPLE t1 # b b NULL NULL NULL; Using where; Using index select * from t1 where b > "0"; a b c d e f 2 20 100 1000 10000 100000 3 30 200 2000 20000 200000 explain select * from t1 where d > "0"; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index d d NULL NULL NULL; Using where; Using index +1 SIMPLE t1 # d d NULL NULL NULL; Using where; Using index select * from t1 where d > "0"; a b c d e f 2 20 100 1000 10000 100000 diff --git a/storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar.test b/storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar.test index 3a30919a8ff..f3e494e0dd4 100644 --- a/storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar.test +++ b/storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar.test @@ -82,11 +82,11 @@ alter table t1 add key d(d,a) clustering=yes, add key b(b) clustering=yes; explain select * from t1 where c > "0"; select * from t1 where c > "0"; ---replace_column 7 NULL 9 NULL; +--replace_column 4 # 7 NULL 9 NULL; explain select * from t1 where b > "0"; select * from t1 where b > "0"; ---replace_column 7 NULL 9 NULL; +--replace_column 4 # 7 NULL 9 NULL; explain select * from t1 where d > "0"; select * from t1 where d > "0"; diff --git a/support-files/compiler_warnings.supp b/support-files/compiler_warnings.supp index 47eb8a827f1..9f9215704ec 100644 --- a/support-files/compiler_warnings.supp +++ b/support-files/compiler_warnings.supp @@ -184,10 +184,10 @@ jemalloc/src/jemalloc\.c: set but not used # # Connect engine # -storage/connect/ha_connect\.cc: might be clobbered by ~longjmp~ -storage/connect/connect\.cc: might be clobbered by ~longjmp~ +storage/connect/ha_connect\.cc: might be clobbered by .*longjmp +storage/connect/connect\.cc: might be clobbered by .*longjmp storage/connect/filamvct\.cpp: ignoring return value of -storage/connect/filamvct\.cpp: might be clobbered by ~longjmp~ +storage/connect/filamvct\.cpp: might be clobbered by .*longjmp storage/connect/xindex\.cpp: ignoring return value of storage/connect/value\.cpp: always false From a98ecc2aafcbc08f27a2f7faba872e7a0d25fee2 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 23 Apr 2016 12:19:40 +0200 Subject: [PATCH 76/91] support SEARCH_RANGE in search_pattern_in_file.inc Backport a part of commit 439f75f Author: Kristian Nielsen Date: Mon Jun 30 13:59:21 2014 +0200 Fix test failures in rpl.rpl_checksum and rpl.rpl_gtid_errorlog. --- mysql-test/include/search_pattern_in_file.inc | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/mysql-test/include/search_pattern_in_file.inc b/mysql-test/include/search_pattern_in_file.inc index c047b5bc499..0d09cdcd36e 100644 --- a/mysql-test/include/search_pattern_in_file.inc +++ b/mysql-test/include/search_pattern_in_file.inc @@ -10,6 +10,10 @@ # The environment variables SEARCH_FILE and SEARCH_PATTERN must be set # before sourcing this routine. # +# Optionally, SEARCH_RANGE can be set to the max number of bytes of the file +# to search. If negative, it will search that many bytes at the end of the +# file. The default is to search only the first 50000 bytes of the file. +# # In case of # - SEARCH_FILE and/or SEARCH_PATTERN is not set # - SEARCH_FILE cannot be opened @@ -38,6 +42,7 @@ # --error 0,1 # --remove_file $error_log # let SEARCH_FILE= $error_log; +# let SEARCH_RANGE= -50000; # # Stop the server # let $restart_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect; # --exec echo "wait" > $restart_file @@ -57,8 +62,18 @@ perl; use strict; my $search_file= $ENV{'SEARCH_FILE'} or die "SEARCH_FILE not set"; my $search_pattern= $ENV{'SEARCH_PATTERN'} or die "SEARCH_PATTERN not set"; + my $search_range= $ENV{'SEARCH_RANGE'}; + my $file_content; + $search_range= 50000 unless $search_range =~ /-?[0-9]+/; open(FILE, "$search_file") or die("Unable to open '$search_file': $!\n"); - read(FILE, my $file_content, 50000, 0); + if ($search_range >= 0) { + read(FILE, $file_content, $search_range, 0); + } else { + my $size= -s $search_file; + $search_range = -$size if $size > -$search_range; + seek(FILE, $search_range, 2); + read(FILE, $file_content, -$search_range, 0); + } close(FILE); if ( not $file_content =~ m{$search_pattern} ) { die("# ERROR: The file '$search_file' does not contain the expected pattern $search_pattern\n->$file_content<-\n"); From 22204807317c467b2f09dd0dcd13898a48501b10 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 25 Apr 2016 18:59:41 +0200 Subject: [PATCH 77/91] MDEV-7775 Wrong error message (Unknown error) when idle sessions are killed after wait_timeout restore the error message that was removed by mistake in ec38c1bbd709 --- mysql-test/r/wait_timeout_not_windows.result | 3 +++ mysql-test/t/wait_timeout_not_windows.test | 15 +++++++++++++++ sql/sql_connect.cc | 3 ++- 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 mysql-test/r/wait_timeout_not_windows.result create mode 100644 mysql-test/t/wait_timeout_not_windows.test diff --git a/mysql-test/r/wait_timeout_not_windows.result b/mysql-test/r/wait_timeout_not_windows.result new file mode 100644 index 00000000000..df70aa99221 --- /dev/null +++ b/mysql-test/r/wait_timeout_not_windows.result @@ -0,0 +1,3 @@ +set global log_warnings=2; +set @@wait_timeout=1; +set global log_warnings=@@log_warnings; diff --git a/mysql-test/t/wait_timeout_not_windows.test b/mysql-test/t/wait_timeout_not_windows.test new file mode 100644 index 00000000000..43ba48e4c43 --- /dev/null +++ b/mysql-test/t/wait_timeout_not_windows.test @@ -0,0 +1,15 @@ +source include/not_windows.inc; + +# +# MDEV-7775 Wrong error message (Unknown error) when idle sessions are killed after wait_timeout +# +set global log_warnings=2; +connect (foo,localhost,root); +set @@wait_timeout=1; +sleep 2; +connection default; +let SEARCH_FILE=$MYSQLTEST_VARDIR/log/mysqld.1.err; +let SEARCH_RANGE= -50; +let SEARCH_PATTERN= Aborted.*Got timeout reading communication packets; +source include/search_pattern_in_file.inc; +set global log_warnings=@@log_warnings; diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 16b53da1ebd..61f8b4081eb 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1092,7 +1092,8 @@ void end_connection(THD *thd) } if (!thd->killed && (net->error && net->vio != 0)) - thd->print_aborted_warning(1, ER(ER_UNKNOWN_ERROR)); + thd->print_aborted_warning(1, + thd->stmt_da->is_error() ? thd->stmt_da->message() : ER(ER_UNKNOWN_ERROR)); } From 0dbc66498d9222d91b73d4c0a8a40c96bd3dc296 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 26 Apr 2016 12:22:02 +0300 Subject: [PATCH 78/91] Fix for MDEV-9679 main.delayed fails sporadically Problem was that notify_shared_lock() didn't abort an insert delayed thread if it was in thr_upgrade_write_delay_lock(). ALTER TABLE first takes a weak_mdl_lock, then a thr_lock and then tries to upgrade the mdl_lock. Delayed insert thread first takes a mdl lock followed by a thr_upgrade_write_delay_lock() This caused insert delay to wait for alter table in thr_lock, while alter table was waiting for the mdl lock by insert delay. Fixed by telling mdl to run thr_lock_abort() for the insert delay thread table. We also set thd->mysys_var->abort to 1 for the delay thread when it's killed by alter table to ensure it doesn't ever get locked in thr_lock. --- sql/sql_class.cc | 55 +++++++++++++++++++++++++++++++---------------- sql/sql_insert.cc | 30 ++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 21 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 271c44e1948..9cd4258c0df 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1878,38 +1878,55 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use, { THD *in_use= ctx_in_use->get_thd(); bool signalled= FALSE; + DBUG_ENTER("THD::notify_shared_lock"); + DBUG_PRINT("enter",("needs_thr_lock_abort: %d", needs_thr_lock_abort)); if ((in_use->system_thread & SYSTEM_THREAD_DELAYED_INSERT) && !in_use->killed) { - in_use->killed= KILL_CONNECTION; - mysql_mutex_lock(&in_use->mysys_var->mutex); - if (in_use->mysys_var->current_cond) - mysql_cond_broadcast(in_use->mysys_var->current_cond); - mysql_mutex_unlock(&in_use->mysys_var->mutex); + /* This code is similar to kill_delayed_threads() */ + DBUG_PRINT("info", ("kill delayed thread")); + mysql_mutex_lock(&in_use->LOCK_thd_data); + if (in_use->killed < KILL_CONNECTION) + in_use->killed= KILL_CONNECTION; + if (in_use->mysys_var) + { + mysql_mutex_lock(&in_use->mysys_var->mutex); + if (in_use->mysys_var->current_cond) + mysql_cond_broadcast(in_use->mysys_var->current_cond); + + /* Abort if about to wait in thr_upgrade_write_delay_lock */ + in_use->mysys_var->abort= 1; + mysql_mutex_unlock(&in_use->mysys_var->mutex); + } + mysql_mutex_unlock(&in_use->LOCK_thd_data); signalled= TRUE; } if (needs_thr_lock_abort) { mysql_mutex_lock(&in_use->LOCK_thd_data); - for (TABLE *thd_table= in_use->open_tables; - thd_table ; - thd_table= thd_table->next) + /* If not already dying */ + if (in_use->killed != KILL_CONNECTION_HARD) { - /* - Check for TABLE::needs_reopen() is needed since in some places we call - handler::close() for table instance (and set TABLE::db_stat to 0) - and do not remove such instances from the THD::open_tables - for some time, during which other thread can see those instances - (e.g. see partitioning code). - */ - if (!thd_table->needs_reopen()) - signalled|= mysql_lock_abort_for_thread(this, thd_table); + for (TABLE *thd_table= in_use->open_tables; + thd_table ; + thd_table= thd_table->next) + { + /* + Check for TABLE::needs_reopen() is needed since in some + places we call handler::close() for table instance (and set + TABLE::db_stat to 0) and do not remove such instances from + the THD::open_tables for some time, during which other + thread can see those instances (e.g. see partitioning code). + */ + if (!thd_table->needs_reopen()) + signalled|= mysql_lock_abort_for_thread(this, thd_table); + } + mysql_mutex_unlock(&in_use->LOCK_thd_data); } - mysql_mutex_unlock(&in_use->LOCK_thd_data); } - return signalled; + DBUG_RETURN(signalled); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index b0151182a88..def5560a011 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2620,14 +2620,16 @@ static void end_delayed_insert(THD *thd) void kill_delayed_threads(void) { + DBUG_ENTER("kill_delayed_threads"); mysql_mutex_lock(&LOCK_delayed_insert); // For unlink from list I_List_iterator it(delayed_threads); Delayed_insert *di; while ((di= it++)) { - di->thd.killed= KILL_CONNECTION; mysql_mutex_lock(&di->thd.LOCK_thd_data); + if (di->thd.killed < KILL_CONNECTION) + di->thd.killed= KILL_CONNECTION; if (di->thd.mysys_var) { mysql_mutex_lock(&di->thd.mysys_var->mutex); @@ -2648,6 +2650,7 @@ void kill_delayed_threads(void) mysql_mutex_unlock(&di->thd.LOCK_thd_data); } mysql_mutex_unlock(&LOCK_delayed_insert); // For unlink from list + DBUG_VOID_RETURN; } @@ -2845,6 +2848,12 @@ pthread_handler_t handle_delayed_insert(void *arg) /* Tell client that the thread is initialized */ mysql_cond_signal(&di->cond_client); + /* + Inform mdl that it needs to call mysql_lock_abort to abort locks + for delayed insert. + */ + thd->mdl_context.set_needs_thr_lock_abort(TRUE); + /* Now wait until we get an insert or lock to handle */ /* We will not abort as long as a client thread uses this thread */ @@ -2853,6 +2862,7 @@ pthread_handler_t handle_delayed_insert(void *arg) if (thd->killed) { uint lock_count; + DBUG_PRINT("delayed", ("Insert delayed killed")); /* Remove this from delay insert list so that no one can request a table from this @@ -2869,6 +2879,9 @@ pthread_handler_t handle_delayed_insert(void *arg) } /* Shouldn't wait if killed or an insert is waiting. */ + DBUG_PRINT("delayed", + ("thd->killed: %d di->status: %d di->stacked_inserts: %d", + thd->killed, di->status, di->stacked_inserts)); if (!thd->killed && !di->status && !di->stacked_inserts) { struct timespec abstime; @@ -2908,6 +2921,9 @@ pthread_handler_t handle_delayed_insert(void *arg) mysql_mutex_unlock(&di->thd.mysys_var->mutex); mysql_mutex_lock(&di->mutex); } + DBUG_PRINT("delayed", + ("thd->killed: %d di->tables_in_use: %d thd->lock: %d", + thd->killed, di->tables_in_use, thd->lock != 0)); if (di->tables_in_use && ! thd->lock && !thd->killed) { @@ -2968,9 +2984,19 @@ pthread_handler_t handle_delayed_insert(void *arg) { DBUG_ENTER("handle_delayed_insert-cleanup"); di->table=0; - thd->killed= KILL_CONNECTION; // If error mysql_mutex_unlock(&di->mutex); + /* + Protect against mdl_locks trying to access open tables + We use KILL_CONNECTION_HARD here to ensure that + THD::notify_shared_lock() dosn't try to access open tables after + this. + */ + mysql_mutex_lock(&thd->LOCK_thd_data); + thd->killed= KILL_CONNECTION_HARD; // If error + thd->mdl_context.set_needs_thr_lock_abort(0); + mysql_mutex_unlock(&thd->LOCK_thd_data); + close_thread_tables(thd); // Free the table thd->mdl_context.release_transactional_locks(); mysql_cond_broadcast(&di->cond_client); // Safety From 7f5ceb77689d4858875bfae7c4f2abc11534b7f1 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 26 Apr 2016 11:49:35 +0200 Subject: [PATCH 79/91] disable main.wait_timeout_not_windows for embedded --- mysql-test/t/wait_timeout_not_windows.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/wait_timeout_not_windows.test b/mysql-test/t/wait_timeout_not_windows.test index 43ba48e4c43..de4904fada2 100644 --- a/mysql-test/t/wait_timeout_not_windows.test +++ b/mysql-test/t/wait_timeout_not_windows.test @@ -1,3 +1,4 @@ +source include/not_embedded.inc; source include/not_windows.inc; # From 44554d611194e2ac02e5beaf4b88ffe5a349ebb4 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 26 Apr 2016 14:37:19 +0400 Subject: [PATCH 80/91] MDEV-9605 mysqlbinlog does not accept ssl-ca option as expected. Added SSL support to the mysqlbinlog. --- client/mysqlbinlog.cc | 15 +++++++++++++++ mysql-test/r/openssl_1.result | 9 +++++++++ mysql-test/t/openssl_1.test | 7 +++++++ 3 files changed, 31 insertions(+) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 315fdcd22dc..4be31421f9b 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -34,6 +34,7 @@ #define TABLE TABLE_CLIENT #include "client_priv.h" #include +#include /* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */ #include "sql_priv.h" #include "log_event.h" @@ -1392,6 +1393,7 @@ static struct my_option my_options[] = {"socket", 'S', "The socket file to use for connection.", &sock, &sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#include {"start-datetime", OPT_START_DATETIME, "Start reading the binlog at first event having a datetime equal or " "posterior to the argument; the argument must be a date and time " @@ -1599,6 +1601,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), DBUG_PUSH(argument ? argument : default_dbug_option); break; #endif +#include case 'd': one_database = 1; break; @@ -1748,6 +1751,18 @@ static Exit_status safe_connect() return ERROR_STOP; } +#ifdef HAVE_OPENSSL + if (opt_use_ssl) + { + mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, + opt_ssl_capath, opt_ssl_cipher); + mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); + mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); + } + mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + (char*)&opt_ssl_verify_server_cert); +#endif /*HAVE_OPENSSL*/ + if (opt_plugindir && *opt_plugindir) mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugindir); diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result index c5dd1500110..dd78b1967c4 100644 --- a/mysql-test/r/openssl_1.result +++ b/mysql-test/r/openssl_1.result @@ -207,3 +207,12 @@ Variable_name Value Ssl_cipher DHE-RSA-AES256-SHA DROP USER bug42158@localhost; End of 5.1 tests +/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/; +/*!40019 SET @@session.max_insert_delayed_threads=0*/; +/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; +DELIMITER /*!*/; +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/; diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test index 4578a05be36..91a8cc57b1b 100644 --- a/mysql-test/t/openssl_1.test +++ b/mysql-test/t/openssl_1.test @@ -265,5 +265,12 @@ DROP USER bug42158@localhost; --echo End of 5.1 tests +# +# MDEV-9605 mysqlbinlog does not accept ssl-ca option as expected. +# + +--error 1 +--exec $MYSQL_BINLOG --read-from-remote-server --ssl-ca --user=root --host=localhost nobinlog.111111 + # Wait till we reached the initial number of concurrent sessions --source include/wait_until_count_sessions.inc From 29868de2fff62c3ebd8af5cf533d3d224da1b332 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 26 Apr 2016 12:58:14 +0200 Subject: [PATCH 81/91] MDEV-9986 Full-text search of the utf8mb4 column causes crash take into account that agg_arg_charsets_for_comparison() can replace Item_field's with Item_func_conv_charset --- mysql-test/r/fulltext3.result | 12 ++++++++++++ mysql-test/t/fulltext3.test | 15 +++++++++++++++ sql/item_func.cc | 2 ++ 3 files changed, 29 insertions(+) diff --git a/mysql-test/r/fulltext3.result b/mysql-test/r/fulltext3.result index 4ec48369ad1..c0b871cd5a7 100644 --- a/mysql-test/r/fulltext3.result +++ b/mysql-test/r/fulltext3.result @@ -15,3 +15,15 @@ CREATE TABLE t1(a VARCHAR(2) CHARACTER SET big5 COLLATE big5_chinese_ci, FULLTEXT(a)); INSERT INTO t1 VALUES(0xA3C2); DROP TABLE t1; +create table t1 ( +id varchar(255), +business_name text null collate utf8mb4_unicode_ci, +street_address text, +fulltext index ft (business_name), +fulltext index ft2 (street_address) +); +select * from t1 where match (business_name, street_address) against ('some business name and address here'); +ERROR HY000: Can't find FULLTEXT index matching the column list +select * from t1 where match (business_name, street_address) against ('some business name and address here' in boolean mode); +id business_name street_address +drop table t1; diff --git a/mysql-test/t/fulltext3.test b/mysql-test/t/fulltext3.test index 1b6a07c540f..66f940b495e 100644 --- a/mysql-test/t/fulltext3.test +++ b/mysql-test/t/fulltext3.test @@ -32,3 +32,18 @@ INSERT INTO t1 VALUES(0xA3C2); DROP TABLE t1; # End of 5.1 tests + +# +# MDEV-9986 Full-text search of the utf8mb4 column causes crash +# +create table t1 ( + id varchar(255), + business_name text null collate utf8mb4_unicode_ci, + street_address text, + fulltext index ft (business_name), + fulltext index ft2 (street_address) +); +--error ER_FT_MATCHING_KEY_NOT_FOUND +select * from t1 where match (business_name, street_address) against ('some business name and address here'); +select * from t1 where match (business_name, street_address) against ('some business name and address here' in boolean mode); +drop table t1; diff --git a/sql/item_func.cc b/sql/item_func.cc index bd6553d45d4..cabba7a666c 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -6366,6 +6366,8 @@ bool Item_func_match::fix_index() for (i=1; i < arg_count; i++) { + if (args[i]->type() != FIELD_ITEM) + goto err; item=(Item_field*)args[i]; for (keynr=0 ; keynr < fts ; keynr++) { From 4f1ad43992d75676687f29da96dd7c4147247a8f Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Tue, 26 Apr 2016 16:15:15 +0400 Subject: [PATCH 82/91] MDEV-9987 - gen_lex_hash leaks memory, making LeakSanitizer builds fail Fixed memory leaks in gen_lex_hash. --- sql/gen_lex_hash.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc index c37f4f145cf..3a3273d279b 100644 --- a/sql/gen_lex_hash.cc +++ b/sql/gen_lex_hash.cc @@ -310,6 +310,7 @@ void print_find_structs() add_structs_to_map(root_by_len,max_len); set_links(root_by_len,max_len); print_hash_map("sql_functions_map"); + free(hash_map); hash_map= 0; size_hash_map= 0; @@ -319,6 +320,7 @@ void print_find_structs() add_structs_to_map(root_by_len2,max_len2); set_links(root_by_len2,max_len2); print_hash_map("symbols_map"); + free(hash_map); } From f1aae861eee711cc718ca8fe52cc08d326b948cf Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 26 Apr 2016 19:05:10 +0200 Subject: [PATCH 83/91] 5.6.30 --- storage/innobase/fil/fil0fil.cc | 37 ++-- storage/innobase/fts/fts0fts.cc | 266 ++++++++++++++++++++------ storage/innobase/fts/fts0opt.cc | 81 ++++++-- storage/innobase/handler/ha_innodb.cc | 14 +- storage/innobase/include/fts0fts.h | 24 ++- storage/innobase/include/fts0types.h | 10 +- storage/innobase/include/os0sync.h | 46 ++--- storage/innobase/row/row0merge.cc | 5 +- 8 files changed, 354 insertions(+), 129 deletions(-) diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index a4e7c6f2ef2..77c1353843c 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2016, 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 @@ -3216,8 +3216,6 @@ fil_create_link_file( const char* tablename, /*!< in: tablename */ const char* filepath) /*!< in: pathname of tablespace */ { - os_file_t file; - ibool success; dberr_t err = DB_SUCCESS; char* link_filepath; char* prev_filepath = fil_read_link_file(tablename); @@ -3236,13 +3234,24 @@ fil_create_link_file( link_filepath = fil_make_isl_name(tablename); - file = os_file_create_simple_no_error_handling( - innodb_file_data_key, link_filepath, - OS_FILE_CREATE, OS_FILE_READ_WRITE, &success); + /** Check if the file already exists. */ + FILE* file = NULL; + ibool exists; + os_file_type_t ftype; - if (!success) { - /* The following call will print an error message */ - ulint error = os_file_get_last_error(true); + bool success = os_file_status(link_filepath, &exists, &ftype); + + ulint error = 0; + if (success && !exists) { + file = fopen(link_filepath, "w"); + if (file == NULL) { + /* This call will print its own error message */ + error = os_file_get_last_error(true); + } + } else { + error = OS_FILE_ALREADY_EXISTS; + } + if (error != 0) { ut_print_timestamp(stderr); fputs(" InnoDB: Cannot create file ", stderr); @@ -3267,13 +3276,17 @@ fil_create_link_file( return(err); } - if (!os_file_write(link_filepath, file, filepath, 0, - strlen(filepath))) { + ulint rbytes = fwrite(filepath, 1, strlen(filepath), file); + if (rbytes != strlen(filepath)) { + os_file_get_last_error(true); + ib_logf(IB_LOG_LEVEL_ERROR, + "cannot write link file " + "%s",filepath); err = DB_ERROR; } /* Close the file, we only need it at startup */ - os_file_close(file); + fclose(file); mem_free(link_filepath); diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 5d6d5ae7cf9..25047b38b9d 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2011, 2016, 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 @@ -260,16 +260,18 @@ static const char* fts_config_table_insert_values_sql = "INSERT INTO \"%s\" VALUES ('" FTS_TABLE_STATE "', '0');\n"; -/****************************************************************//** -Run SYNC on the table, i.e., write out data from the cache to the +/** Run SYNC on the table, i.e., write out data from the cache to the FTS auxiliary INDEX table and clear the cache at the end. -@return DB_SUCCESS if all OK */ +@param[in,out] sync sync state +@param[in] unlock_cache whether unlock cache lock when write node +@param[in] wait whether wait when a sync is in progress +@return DB_SUCCESS if all OK */ static dberr_t fts_sync( -/*=====*/ - fts_sync_t* sync) /*!< in: sync state */ - __attribute__((nonnull)); + fts_sync_t* sync, + bool unlock_cache, + bool wait); /****************************************************************//** Release all resources help by the words rb tree e.g., the node ilist. */ @@ -653,6 +655,7 @@ fts_cache_create( mem_heap_zalloc(heap, sizeof(fts_sync_t))); cache->sync->table = table; + cache->sync->event = os_event_create(); /* Create the index cache vector that will hold the inverted indexes. */ cache->indexes = ib_vector_create( @@ -1207,6 +1210,7 @@ fts_cache_destroy( mutex_free(&cache->optimize_lock); mutex_free(&cache->deleted_lock); mutex_free(&cache->doc_id_lock); + os_event_free(cache->sync->event); if (cache->stopword_info.cached_stopword) { rbt_free(cache->stopword_info.cached_stopword); @@ -1435,7 +1439,7 @@ fts_cache_add_doc( ib_vector_last(word->nodes)); } - if (fts_node == NULL + if (fts_node == NULL || fts_node->synced || fts_node->ilist_size > FTS_ILIST_MAX_SIZE || doc_id < fts_node->last_doc_id) { @@ -2886,35 +2890,28 @@ fts_doc_ids_free( } /*********************************************************************//** -Do commit-phase steps necessary for the insertion of a new row. -@return DB_SUCCESS or error code */ -static __attribute__((nonnull, warn_unused_result)) -dberr_t +Do commit-phase steps necessary for the insertion of a new row. */ +void fts_add( /*====*/ fts_trx_table_t*ftt, /*!< in: FTS trx table */ fts_trx_row_t* row) /*!< in: row */ { dict_table_t* table = ftt->table; - dberr_t error = DB_SUCCESS; doc_id_t doc_id = row->doc_id; ut_a(row->state == FTS_INSERT || row->state == FTS_MODIFY); fts_add_doc_by_id(ftt, doc_id, row->fts_indexes); - if (error == DB_SUCCESS) { - mutex_enter(&table->fts->cache->deleted_lock); - ++table->fts->cache->added; - mutex_exit(&table->fts->cache->deleted_lock); + mutex_enter(&table->fts->cache->deleted_lock); + ++table->fts->cache->added; + mutex_exit(&table->fts->cache->deleted_lock); - if (!DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID) - && doc_id >= table->fts->cache->next_doc_id) { - table->fts->cache->next_doc_id = doc_id + 1; - } + if (!DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID) + && doc_id >= table->fts->cache->next_doc_id) { + table->fts->cache->next_doc_id = doc_id + 1; } - - return(error); } /*********************************************************************//** @@ -3025,7 +3022,7 @@ fts_modify( error = fts_delete(ftt, row); if (error == DB_SUCCESS) { - error = fts_add(ftt, row); + fts_add(ftt, row); } return(error); @@ -3114,7 +3111,7 @@ fts_commit_table( switch (row->state) { case FTS_INSERT: - error = fts_add(ftt, row); + fts_add(ftt, row); break; case FTS_MODIFY: @@ -3553,16 +3550,34 @@ fts_add_doc_by_id( get_doc->index_cache, doc_id, doc.tokens); + bool need_sync = false; + if ((cache->total_size > fts_max_cache_size / 10 + || fts_need_sync) + && !cache->sync->in_progress) { + need_sync = true; + } + rw_lock_x_unlock(&table->fts->cache->lock); DBUG_EXECUTE_IF( "fts_instrument_sync", - fts_sync(cache->sync); + fts_optimize_request_sync_table(table); + os_event_wait(cache->sync->event); ); - if (cache->total_size > fts_max_cache_size - || fts_need_sync) { - fts_sync(cache->sync); + DBUG_EXECUTE_IF( + "fts_instrument_sync_debug", + fts_sync(cache->sync, true, true); + ); + + DEBUG_SYNC_C("fts_instrument_sync_request"); + DBUG_EXECUTE_IF( + "fts_instrument_sync_request", + fts_optimize_request_sync_table(table); + ); + + if (need_sync) { + fts_optimize_request_sync_table(table); } mtr_start(&mtr); @@ -3933,16 +3948,17 @@ fts_sync_add_deleted_cache( return(error); } -/*********************************************************************//** -Write the words and ilist to disk. +/** Write the words and ilist to disk. +@param[in,out] trx transaction +@param[in] index_cache index cache +@param[in] unlock_cache whether unlock cache when write node @return DB_SUCCESS if all went well else error code */ static __attribute__((nonnull, warn_unused_result)) dberr_t fts_sync_write_words( -/*=================*/ - trx_t* trx, /*!< in: transaction */ - fts_index_cache_t* - index_cache) /*!< in: index cache */ + trx_t* trx, + fts_index_cache_t* index_cache, + bool unlock_cache) { fts_table_t fts_table; ulint n_nodes = 0; @@ -3950,8 +3966,8 @@ fts_sync_write_words( const ib_rbt_node_t* rbt_node; dberr_t error = DB_SUCCESS; ibool print_error = FALSE; -#ifdef FTS_DOC_STATS_DEBUG dict_table_t* table = index_cache->index->table; +#ifdef FTS_DOC_STATS_DEBUG ulint n_new_words = 0; #endif /* FTS_DOC_STATS_DEBUG */ @@ -3964,7 +3980,7 @@ fts_sync_write_words( since we want to free the memory used during caching. */ for (rbt_node = rbt_first(index_cache->words); rbt_node; - rbt_node = rbt_first(index_cache->words)) { + rbt_node = rbt_next(index_cache->words, rbt_node)) { ulint i; ulint selected; @@ -3997,27 +4013,47 @@ fts_sync_write_words( } #endif /* FTS_DOC_STATS_DEBUG */ - n_nodes += ib_vector_size(word->nodes); - - /* We iterate over all the nodes even if there was an error, - this is to free the memory of the fts_node_t elements. */ + /* We iterate over all the nodes even if there was an error */ for (i = 0; i < ib_vector_size(word->nodes); ++i) { fts_node_t* fts_node = static_cast( ib_vector_get(word->nodes, i)); + if (fts_node->synced) { + continue; + } else { + fts_node->synced = true; + } + + /*FIXME: we need to handle the error properly. */ if (error == DB_SUCCESS) { + if (unlock_cache) { + rw_lock_x_unlock( + &table->fts->cache->lock); + } error = fts_write_node( trx, &index_cache->ins_graph[selected], &fts_table, &word->text, fts_node); - } - ut_free(fts_node->ilist); - fts_node->ilist = NULL; + DEBUG_SYNC_C("fts_write_node"); + DBUG_EXECUTE_IF("fts_write_node_crash", + DBUG_SUICIDE();); + + DBUG_EXECUTE_IF("fts_instrument_sync_sleep", + os_thread_sleep(1000000); + ); + + if (unlock_cache) { + rw_lock_x_lock( + &table->fts->cache->lock); + } + } } + n_nodes += ib_vector_size(word->nodes); + if (error != DB_SUCCESS && !print_error) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Error (%s) writing " @@ -4026,9 +4062,6 @@ fts_sync_write_words( print_error = TRUE; } - - /* NOTE: We are responsible for free'ing the node */ - ut_free(rbt_remove_node(index_cache->words, rbt_node)); } #ifdef FTS_DOC_STATS_DEBUG @@ -4329,7 +4362,7 @@ fts_sync_index( ut_ad(rbt_validate(index_cache->words)); - error = fts_sync_write_words(trx, index_cache); + error = fts_sync_write_words(sync->trx, index_cache, sync->unlock_cache); #ifdef FTS_DOC_STATS_DEBUG /* FTS_RESOLVE: the word counter info in auxiliary table "DOC_ID" @@ -4345,6 +4378,36 @@ fts_sync_index( return(error); } +/** Check if index cache has been synced completely +@param[in,out] sync sync state +@param[in,out] index_cache index cache +@return true if index is synced, otherwise false. */ +static +bool +fts_sync_index_check( + fts_sync_t* sync, + fts_index_cache_t* index_cache) +{ + const ib_rbt_node_t* rbt_node; + + for (rbt_node = rbt_first(index_cache->words); + rbt_node != NULL; + rbt_node = rbt_next(index_cache->words, rbt_node)) { + + fts_tokenizer_word_t* word; + word = rbt_value(fts_tokenizer_word_t, rbt_node); + + fts_node_t* fts_node; + fts_node = static_cast(ib_vector_last(word->nodes)); + + if (!fts_node->synced) { + return(false); + } + } + + return(true); +} + /*********************************************************************//** Commit the SYNC, change state of processed doc ids etc. @return DB_SUCCESS if all OK */ @@ -4421,21 +4484,53 @@ fts_sync_rollback( trx_t* trx = sync->trx; fts_cache_t* cache = sync->table->fts->cache; + for (ulint i = 0; i < ib_vector_size(cache->indexes); ++i) { + ulint j; + fts_index_cache_t* index_cache; + + index_cache = static_cast( + ib_vector_get(cache->indexes, i)); + + for (j = 0; fts_index_selector[j].value; ++j) { + + if (index_cache->ins_graph[j] != NULL) { + + fts_que_graph_free_check_lock( + NULL, index_cache, + index_cache->ins_graph[j]); + + index_cache->ins_graph[j] = NULL; + } + + if (index_cache->sel_graph[j] != NULL) { + + fts_que_graph_free_check_lock( + NULL, index_cache, + index_cache->sel_graph[j]); + + index_cache->sel_graph[j] = NULL; + } + } + } + rw_lock_x_unlock(&cache->lock); fts_sql_rollback(trx); trx_free_for_background(trx); } -/****************************************************************//** -Run SYNC on the table, i.e., write out data from the cache to the +/** Run SYNC on the table, i.e., write out data from the cache to the FTS auxiliary INDEX table and clear the cache at the end. +@param[in,out] sync sync state +@param[in] unlock_cache whether unlock cache lock when write node +@param[in] wait whether wait when a sync is in progress @return DB_SUCCESS if all OK */ static dberr_t fts_sync( -/*=====*/ - fts_sync_t* sync) /*!< in: sync state */ + fts_sync_t* sync, + bool unlock_cache, + bool wait) { ulint i; dberr_t error = DB_SUCCESS; @@ -4443,8 +4538,35 @@ fts_sync( rw_lock_x_lock(&cache->lock); + /* Check if cache is being synced. + Note: we release cache lock in fts_sync_write_words() to + avoid long wait for the lock by other threads. */ + while (sync->in_progress) { + rw_lock_x_unlock(&cache->lock); + + if (wait) { + os_event_wait(sync->event); + } else { + return(DB_SUCCESS); + } + + rw_lock_x_lock(&cache->lock); + } + + sync->unlock_cache = unlock_cache; + sync->in_progress = true; + + DEBUG_SYNC_C("fts_sync_begin"); fts_sync_begin(sync); +begin_sync: + if (cache->total_size > fts_max_cache_size) { + /* Avoid the case: sync never finish when + insert/update keeps comming. */ + ut_ad(sync->unlock_cache); + sync->unlock_cache = false; + } + for (i = 0; i < ib_vector_size(cache->indexes); ++i) { fts_index_cache_t* index_cache; @@ -4459,21 +4581,43 @@ fts_sync( if (error != DB_SUCCESS && !sync->interrupted) { - break; + goto end_sync; } } DBUG_EXECUTE_IF("fts_instrument_sync_interrupted", sync->interrupted = true; error = DB_INTERRUPTED; + goto end_sync; ); + /* Make sure all the caches are synced. */ + for (i = 0; i < ib_vector_size(cache->indexes); ++i) { + fts_index_cache_t* index_cache; + + index_cache = static_cast( + ib_vector_get(cache->indexes, i)); + + if (index_cache->index->to_be_dropped + || fts_sync_index_check(sync, index_cache)) { + continue; + } + + goto begin_sync; + } + +end_sync: if (error == DB_SUCCESS && !sync->interrupted) { error = fts_sync_commit(sync); } else { fts_sync_rollback(sync); } + rw_lock_x_lock(&cache->lock); + sync->in_progress = false; + os_event_set(sync->event); + rw_lock_x_unlock(&cache->lock); + /* We need to check whether an optimize is required, for that we make copies of the two variables that control the trigger. These variables can change behind our back and we don't want to hold the @@ -4488,21 +4632,25 @@ fts_sync( return(error); } -/****************************************************************//** -Run SYNC on the table, i.e., write out data from the cache to the -FTS auxiliary INDEX table and clear the cache at the end. */ +/** Run SYNC on the table, i.e., write out data from the cache to the +FTS auxiliary INDEX table and clear the cache at the end. +@param[in,out] table fts table +@param[in] unlock_cache whether unlock cache when write node +@param[in] wait whether wait for existing sync to finish +@return DB_SUCCESS on success, error code on failure. */ UNIV_INTERN dberr_t fts_sync_table( -/*===========*/ - dict_table_t* table) /*!< in: table */ + dict_table_t* table, + bool unlock_cache, + bool wait) { dberr_t err = DB_SUCCESS; ut_ad(table->fts); if (!dict_table_is_discarded(table) && table->fts->cache) { - err = fts_sync(table->fts->cache->sync); + err = fts_sync(table->fts->cache->sync, unlock_cache, wait); } return(err); diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc index 2a0aa4daf12..711c5f53d01 100644 --- a/storage/innobase/fts/fts0opt.cc +++ b/storage/innobase/fts/fts0opt.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2007, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2007, 2016, 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 @@ -87,6 +87,7 @@ enum fts_msg_type_t { FTS_MSG_DEL_TABLE, /*!< Remove a table from the optimize threads work queue */ + FTS_MSG_SYNC_TABLE /*!< Sync fts cache of a table */ }; /** Compressed list of words that have been read from FTS INDEX @@ -2652,6 +2653,39 @@ fts_optimize_remove_table( os_event_free(event); } +/** Send sync fts cache for the table. +@param[in] table table to sync */ +UNIV_INTERN +void +fts_optimize_request_sync_table( + dict_table_t* table) +{ + fts_msg_t* msg; + table_id_t* table_id; + + /* if the optimize system not yet initialized, return */ + if (!fts_optimize_wq) { + return; + } + + /* FTS optimizer thread is already exited */ + if (fts_opt_start_shutdown) { + ib_logf(IB_LOG_LEVEL_INFO, + "Try to sync table %s after FTS optimize" + " thread exiting.", table->name); + return; + } + + msg = fts_optimize_create_msg(FTS_MSG_SYNC_TABLE, NULL); + + table_id = static_cast( + mem_heap_alloc(msg->heap, sizeof(table_id_t))); + *table_id = table->id; + msg->ptr = table_id; + + ib_wqueue_add(fts_optimize_wq, msg, msg->heap); +} + /**********************************************************************//** Find the slot for a particular table. @return slot if found else NULL. */ @@ -2932,6 +2966,25 @@ fts_optimize_need_sync( } #endif +/** Sync fts cache of a table +@param[in] table_id table id */ +void +fts_optimize_sync_table( + table_id_t table_id) +{ + dict_table_t* table = NULL; + + table = dict_table_open_on_id(table_id, FALSE, DICT_TABLE_OP_NORMAL); + + if (table) { + if (dict_table_has_fts_index(table) && table->fts->cache) { + fts_sync_table(table, true, false); + } + + dict_table_close(table, FALSE, FALSE); + } +} + /**********************************************************************//** Optimize all FTS tables. @return Dummy return */ @@ -3053,6 +3106,11 @@ fts_optimize_thread( ((fts_msg_del_t*) msg->ptr)->event); break; + case FTS_MSG_SYNC_TABLE: + fts_optimize_sync_table( + *static_cast(msg->ptr)); + break; + default: ut_error; } @@ -3079,26 +3137,7 @@ fts_optimize_thread( ib_vector_get(tables, i)); if (slot->state != FTS_STATE_EMPTY) { - dict_table_t* table = NULL; - - /*slot->table may be freed, so we try to open - table by slot->table_id.*/ - table = dict_table_open_on_id( - slot->table_id, FALSE, - DICT_TABLE_OP_NORMAL); - - if (table) { - - if (dict_table_has_fts_index(table)) { - fts_sync_table(table); - } - - if (table->fts) { - fts_free(table); - } - - dict_table_close(table, FALSE, FALSE); - } + fts_optimize_sync_table(slot->table_id); } } } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 53a60bb341a..3a9c3a44e73 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, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. @@ -3344,6 +3344,16 @@ innobase_change_buffering_inited_ok: innobase_open_files = table_cache_size; } } + + if (innobase_open_files > (long) open_files_limit) { + fprintf(stderr, + "innodb_open_files should not be greater" + " than the open_files_limit.\n"); + if (innobase_open_files > (long) table_cache_size) { + innobase_open_files = table_cache_size; + } + } + srv_max_n_open_files = (ulint) innobase_open_files; srv_innodb_status = (ibool) innobase_create_status_file; @@ -11363,7 +11373,7 @@ ha_innobase::optimize( if (innodb_optimize_fulltext_only) { if (prebuilt->table->fts && prebuilt->table->fts->cache && !dict_table_is_discarded(prebuilt->table)) { - fts_sync_table(prebuilt->table); + fts_sync_table(prebuilt->table, false, true); fts_optimize_table(prebuilt->table); } return(HA_ADMIN_OK); diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h index d54ed281d9a..9f7b0216d9b 100644 --- a/storage/innobase/include/fts0fts.h +++ b/storage/innobase/include/fts0fts.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2011, 2016, 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 @@ -724,6 +724,13 @@ fts_optimize_remove_table( /*======================*/ dict_table_t* table); /*!< in: table to remove */ +/** Send sync fts cache for the table. +@param[in] table table to sync */ +UNIV_INTERN +void +fts_optimize_request_sync_table( + dict_table_t* table); + /**********************************************************************//** Signal the optimize thread to prepare for shutdown. */ UNIV_INTERN @@ -826,15 +833,18 @@ fts_drop_index_split_tables( dict_index_t* index) /*!< in: fts instance */ __attribute__((nonnull, warn_unused_result)); -/****************************************************************//** -Run SYNC on the table, i.e., write out data from the cache to the -FTS auxiliary INDEX table and clear the cache at the end. */ +/** Run SYNC on the table, i.e., write out data from the cache to the +FTS auxiliary INDEX table and clear the cache at the end. +@param[in,out] table fts table +@param[in] unlock_cache whether unlock cache when write node +@param[in] wait whether wait for existing sync to finish +@return DB_SUCCESS on success, error code on failure. */ UNIV_INTERN dberr_t fts_sync_table( -/*===========*/ - dict_table_t* table) /*!< in: table */ - __attribute__((nonnull)); + dict_table_t* table, + bool unlock_cache, + bool wait); /****************************************************************//** Free the query graph but check whether dict_sys->mutex is already diff --git a/storage/innobase/include/fts0types.h b/storage/innobase/include/fts0types.h index 64677428331..e495fe72a60 100644 --- a/storage/innobase/include/fts0types.h +++ b/storage/innobase/include/fts0types.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2007, 2016, 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 @@ -122,7 +122,11 @@ struct fts_sync_t { doc_id_t max_doc_id; /*!< The doc id at which the cache was noted as being full, we use this to set the upper_limit field */ - ib_time_t start_time; /*!< SYNC start time */ + ib_time_t start_time; /*!< SYNC start time */ + bool in_progress; /*!< flag whether sync is in progress.*/ + bool unlock_cache; /*!< flag whether unlock cache when + write fts node */ + os_event_t event; /*!< sync finish event */ }; /** The cache for the FTS system. It is a memory-based inverted index @@ -165,7 +169,6 @@ struct fts_cache_t { objects, they are recreated after a SYNC is completed */ - ib_alloc_t* self_heap; /*!< This heap is the heap out of which an instance of the cache itself was created. Objects created using @@ -212,6 +215,7 @@ struct fts_node_t { ulint ilist_size_alloc; /*!< Allocated size of ilist in bytes */ + bool synced; /*!< flag whether the node is synced */ }; /** A tokenizer word. Contains information about one word. */ diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h index 9329a0effb4..367c2a31924 100644 --- a/storage/innobase/include/os0sync.h +++ b/storage/innobase/include/os0sync.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -449,28 +449,7 @@ amount to decrement. */ # define os_atomic_decrement_uint64(ptr, amount) \ os_atomic_decrement(ptr, amount) -# if defined(HAVE_IB_GCC_ATOMIC_TEST_AND_SET) - -/** Do an atomic test-and-set. -@param[in,out] ptr Memory location to set to non-zero -@return the previous value */ -inline -lock_word_t -os_atomic_test_and_set(volatile lock_word_t* ptr) -{ - return(__atomic_test_and_set(ptr, __ATOMIC_ACQUIRE)); -} - -/** Do an atomic clear. -@param[in,out] ptr Memory location to set to zero */ -inline -void -os_atomic_clear(volatile lock_word_t* ptr) -{ - __atomic_clear(ptr, __ATOMIC_RELEASE); -} - -# elif defined(IB_STRONG_MEMORY_MODEL) +# if defined(IB_STRONG_MEMORY_MODEL) /** Do an atomic test and set. @param[in,out] ptr Memory location to set to non-zero @@ -499,6 +478,27 @@ os_atomic_clear(volatile lock_word_t* ptr) return(__sync_lock_test_and_set(ptr, 0)); } +# elif defined(HAVE_IB_GCC_ATOMIC_TEST_AND_SET) + +/** Do an atomic test-and-set. +@param[in,out] ptr Memory location to set to non-zero +@return the previous value */ +inline +lock_word_t +os_atomic_test_and_set(volatile lock_word_t* ptr) +{ + return(__atomic_test_and_set(ptr, __ATOMIC_ACQUIRE)); +} + +/** Do an atomic clear. +@param[in,out] ptr Memory location to set to zero */ +inline +void +os_atomic_clear(volatile lock_word_t* ptr) +{ + __atomic_clear(ptr, __ATOMIC_RELEASE); +} + # else # error "Unsupported platform" diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index e9be0b1157c..20a73a9ba33 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2005, 2016, 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 @@ -1986,7 +1986,8 @@ wait_again: if (max_doc_id && err == DB_SUCCESS) { /* Sync fts cache for other fts indexes to keep all fts indexes consistent in sync_doc_id. */ - err = fts_sync_table(const_cast(new_table)); + err = fts_sync_table(const_cast(new_table), + false, true); if (err == DB_SUCCESS) { fts_update_next_doc_id( From 5b8ac23030a59a8ed3636d441180fec571dbe3d1 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 26 Apr 2016 19:07:11 +0200 Subject: [PATCH 84/91] 5.6.29-76.2 --- storage/xtradb/buf/buf0dump.cc | 25 ++- storage/xtradb/buf/buf0flu.cc | 6 - storage/xtradb/dict/dict0dict.cc | 2 +- storage/xtradb/dict/dict0stats.cc | 19 +- storage/xtradb/fts/fts0opt.cc | 11 +- storage/xtradb/handler/ha_innodb.cc | 274 +++++++++++++++++++++++- storage/xtradb/handler/ha_innodb.h | 23 ++ storage/xtradb/handler/handler0alter.cc | 26 ++- storage/xtradb/include/buf0flu.h | 6 + storage/xtradb/include/ha_prototypes.h | 11 +- storage/xtradb/include/os0file.h | 29 +-- storage/xtradb/include/row0log.h | 5 +- storage/xtradb/include/row0merge.h | 24 ++- storage/xtradb/include/univ.i | 2 +- storage/xtradb/lock/lock0lock.cc | 2 +- storage/xtradb/os/os0file.cc | 18 +- storage/xtradb/row/row0ftsort.cc | 16 +- storage/xtradb/row/row0log.cc | 46 +++- storage/xtradb/row/row0merge.cc | 182 ++++++++++------ storage/xtradb/srv/srv0srv.cc | 30 +-- storage/xtradb/srv/srv0start.cc | 6 +- 21 files changed, 601 insertions(+), 162 deletions(-) diff --git a/storage/xtradb/buf/buf0dump.cc b/storage/xtradb/buf/buf0dump.cc index 090e8cac63b..bd2343c223d 100644 --- a/storage/xtradb/buf/buf0dump.cc +++ b/storage/xtradb/buf/buf0dump.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2011, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2011, 2015, 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 @@ -167,6 +167,25 @@ buf_load_status( va_end(ap); } +/** Returns the directory path where the buffer pool dump file will be created. +@return directory path */ +static +const char* +get_buf_dump_dir() +{ + const char* dump_dir; + + /* The dump file should be created in the default data directory if + innodb_data_home_dir is set as an empty string. */ + if (strcmp(srv_data_home, "") == 0) { + dump_dir = fil_path_to_mysql_datadir; + } else { + dump_dir = srv_data_home; + } + + return(dump_dir); +} + /*****************************************************************//** Perform a buffer pool dump into the file specified by innodb_buffer_pool_filename. If any errors occur then the value of @@ -190,7 +209,7 @@ buf_dump( int ret; ut_snprintf(full_filename, sizeof(full_filename), - "%s%c%s", srv_data_home, SRV_PATH_SEPARATOR, + "%s%c%s", get_buf_dump_dir(), SRV_PATH_SEPARATOR, srv_buf_dump_filename); ut_snprintf(tmp_filename, sizeof(tmp_filename), @@ -387,7 +406,7 @@ buf_load() buf_load_abort_flag = FALSE; ut_snprintf(full_filename, sizeof(full_filename), - "%s%c%s", srv_data_home, SRV_PATH_SEPARATOR, + "%s%c%s", get_buf_dump_dir(), SRV_PATH_SEPARATOR, srv_buf_dump_filename); buf_load_status(STATUS_NOTICE, diff --git a/storage/xtradb/buf/buf0flu.cc b/storage/xtradb/buf/buf0flu.cc index 97c86ee7ed8..e151ca47c2b 100644 --- a/storage/xtradb/buf/buf0flu.cc +++ b/storage/xtradb/buf/buf0flu.cc @@ -67,12 +67,6 @@ UNIV_INTERN mysql_pfs_key_t buf_page_cleaner_thread_key; UNIV_INTERN mysql_pfs_key_t buf_lru_manager_thread_key; #endif /* UNIV_PFS_THREAD */ -/** If LRU list of a buf_pool is less than this size then LRU eviction -should not happen. This is because when we do LRU flushing we also put -the blocks on free list. If LRU list is very small then we can end up -in thrashing. */ -#define BUF_LRU_MIN_LEN 256 - /* @} */ /** Handled page counters for a single flush */ diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc index 8b65b769444..d5fd3722ba1 100644 --- a/storage/xtradb/dict/dict0dict.cc +++ b/storage/xtradb/dict/dict0dict.cc @@ -1066,7 +1066,7 @@ dict_init(void) &dict_operation_lock, SYNC_DICT_OPERATION); if (!srv_read_only_mode) { - dict_foreign_err_file = os_file_create_tmpfile(); + dict_foreign_err_file = os_file_create_tmpfile(NULL); ut_a(dict_foreign_err_file); mutex_create(dict_foreign_err_mutex_key, diff --git a/storage/xtradb/dict/dict0stats.cc b/storage/xtradb/dict/dict0stats.cc index 9cd909686ed..9aa63caa579 100644 --- a/storage/xtradb/dict/dict0stats.cc +++ b/storage/xtradb/dict/dict0stats.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2009, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2009, 2015, 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 @@ -1434,7 +1434,6 @@ on the leaf page. when comparing records @param[out] n_diff number of distinct records @param[out] n_external_pages number of external pages -@param[in,out] mtr mini-transaction @return number of distinct records on the leaf page */ static void @@ -1442,8 +1441,7 @@ dict_stats_analyze_index_below_cur( const btr_cur_t* cur, ulint n_prefix, ib_uint64_t* n_diff, - ib_uint64_t* n_external_pages, - mtr_t* mtr) + ib_uint64_t* n_external_pages) { dict_index_t* index; ulint space; @@ -1457,6 +1455,7 @@ dict_stats_analyze_index_below_cur( ulint* offsets2; ulint* offsets_rec; ulint size; + mtr_t mtr; index = btr_cur_get_index(cur); @@ -1495,12 +1494,14 @@ dict_stats_analyze_index_below_cur( function without analyzing any leaf pages */ *n_external_pages = 0; + mtr_start(&mtr); + /* descend to the leaf level on the B-tree */ for (;;) { block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH, NULL /* no guessed block */, - BUF_GET, __FILE__, __LINE__, mtr); + BUF_GET, __FILE__, __LINE__, &mtr); page = buf_block_get_frame(block); @@ -1522,6 +1523,8 @@ dict_stats_analyze_index_below_cur( ut_a(*n_diff > 0); if (*n_diff == 1) { + mtr_commit(&mtr); + /* page has all keys equal and the end of the page was reached by dict_stats_scan_page(), no need to descend to the leaf level */ @@ -1546,7 +1549,7 @@ dict_stats_analyze_index_below_cur( } /* make sure we got a leaf page as a result from the above loop */ - ut_ad(btr_page_get_level(page, mtr) == 0); + ut_ad(btr_page_get_level(page, &mtr) == 0); /* scan the leaf page and find the number of distinct keys, when looking only at the first n_prefix columns; also estimate @@ -1563,6 +1566,7 @@ dict_stats_analyze_index_below_cur( __func__, page_no, n_diff); #endif + mtr_commit(&mtr); mem_heap_free(heap); } @@ -1772,8 +1776,7 @@ dict_stats_analyze_index_for_n_prefix( dict_stats_analyze_index_below_cur(btr_pcur_get_btr_cur(&pcur), n_prefix, &n_diff_on_leaf_page, - &n_external_pages, - mtr); + &n_external_pages); /* We adjust n_diff_on_leaf_page here to avoid counting one record twice - once as the last on some page and once diff --git a/storage/xtradb/fts/fts0opt.cc b/storage/xtradb/fts/fts0opt.cc index e096b8bf6d6..2a0aa4daf12 100644 --- a/storage/xtradb/fts/fts0opt.cc +++ b/storage/xtradb/fts/fts0opt.cc @@ -580,7 +580,7 @@ fts_zip_read_word( #ifdef UNIV_DEBUG ulint i; #endif - byte len = 0; + short len = 0; void* null = NULL; byte* ptr = word->f_str; int flush = Z_NO_FLUSH; @@ -590,7 +590,7 @@ fts_zip_read_word( return(NULL); } - zip->zp->next_out = &len; + zip->zp->next_out = reinterpret_cast(&len); zip->zp->avail_out = sizeof(len); while (zip->status == Z_OK && zip->zp->avail_out > 0) { @@ -688,11 +688,12 @@ fts_fetch_index_words( fts_zip_t* zip = static_cast(user_arg); que_node_t* exp = sel_node->select_list; dfield_t* dfield = que_node_get_val(exp); - byte len = (byte) dfield_get_len(dfield); + short len = static_cast(dfield_get_len(dfield)); void* data = dfield_get_data(dfield); /* Skip the duplicate words. */ - if (zip->word.f_len == len && !memcmp(zip->word.f_str, data, len)) { + if (zip->word.f_len == static_cast(len) + && !memcmp(zip->word.f_str, data, len)) { return(TRUE); } @@ -706,7 +707,7 @@ fts_fetch_index_words( ut_a(zip->zp->next_in == NULL); /* The string is prefixed by len. */ - zip->zp->next_in = &len; + zip->zp->next_in = reinterpret_cast(&len); zip->zp->avail_in = sizeof(len); /* Compress the word, create output blocks as necessary. */ diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 4ce9df722c1..3d10f04fe07 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -564,6 +564,108 @@ innodb_stopword_table_validate( for update function */ struct st_mysql_value* value); /*!< in: incoming string */ +/** Validate passed-in "value" is a valid directory name. +This function is registered as a callback with MySQL. +@param[in,out] thd thread handle +@param[in] var pointer to system variable +@param[out] save immediate result for update +@param[in] value incoming string +@return 0 for valid name */ +static +int +innodb_tmpdir_validate( + THD* thd, + struct st_mysql_sys_var* var, + void* save, + struct st_mysql_value* value) +{ + + char* alter_tmp_dir; + char* innodb_tmp_dir; + char buff[OS_FILE_MAX_PATH]; + int len = sizeof(buff); + char tmp_abs_path[FN_REFLEN + 2]; + + ut_ad(save != NULL); + ut_ad(value != NULL); + + if (check_global_access(thd, FILE_ACL)) { + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "InnoDB: FILE Permissions required"); + *static_cast(save) = NULL; + return(1); + } + + alter_tmp_dir = (char*) value->val_str(value, buff, &len); + + if (!alter_tmp_dir) { + *static_cast(save) = alter_tmp_dir; + return(0); + } + + if (strlen(alter_tmp_dir) > FN_REFLEN) { + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "Path length should not exceed %d bytes", FN_REFLEN); + *static_cast(save) = NULL; + return(1); + } + + my_realpath(tmp_abs_path, alter_tmp_dir, 0); + size_t tmp_abs_len = strlen(tmp_abs_path); + + if (my_access(tmp_abs_path, F_OK)) { + + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "InnoDB: Path doesn't exist."); + *static_cast(save) = NULL; + return(1); + } else if (my_access(tmp_abs_path, R_OK | W_OK)) { + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "InnoDB: Server doesn't have permission in " + "the given location."); + *static_cast(save) = NULL; + return(1); + } + + MY_STAT stat_info_dir; + + if (my_stat(tmp_abs_path, &stat_info_dir, MYF(0))) { + if ((stat_info_dir.st_mode & S_IFDIR) != S_IFDIR) { + + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "Given path is not a directory. "); + *static_cast(save) = NULL; + return(1); + } + } + + if (!is_mysql_datadir_path(tmp_abs_path)) { + + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "InnoDB: Path Location should not be same as " + "mysql data directory location."); + *static_cast(save) = NULL; + return(1); + } + + innodb_tmp_dir = static_cast( + thd_memdup(thd, tmp_abs_path, tmp_abs_len + 1)); + *static_cast(save) = innodb_tmp_dir; + return(0); +} + /** "GEN_CLUST_INDEX" is the name reserved for InnoDB default system clustered index when there is no primary key. */ const char innobase_index_reserve_name[] = "GEN_CLUST_INDEX"; @@ -651,6 +753,10 @@ static MYSQL_THDVAR_BOOL(fake_changes, PLUGIN_VAR_OPCMDARG, "This is to cause replication prefetch IO. ATTENTION: the transaction started after enabled is affected.", NULL, NULL, FALSE); +static MYSQL_THDVAR_STR(tmpdir, + PLUGIN_VAR_OPCMDARG|PLUGIN_VAR_MEMALLOC, + "Directory for temporary non-tablespace files.", + innodb_tmpdir_validate, NULL, NULL); static SHOW_VAR innodb_status_variables[]= { {"buffer_pool_dump_status", @@ -1242,6 +1348,28 @@ normalize_table_name_low( ibool set_lower_case); /* in: TRUE if we want to set name to lower case */ +/*************************************************************//** +Checks if buffer pool is big enough to enable backoff algorithm. +InnoDB empty free list algorithm backoff requires free pages +from LRU for the best performance. +buf_LRU_buf_pool_running_out cancels query if 1/4 of +buffer pool belongs to LRU or freelist. +At the same time buf_flush_LRU_list_batch +keeps up to BUF_LRU_MIN_LEN in LRU. +In order to avoid deadlock baclkoff requires buffer pool +to be at least 4*BUF_LRU_MIN_LEN, +but flush peformance is bad because of trashing +and additional BUF_LRU_MIN_LEN pages are requested. +@return true if it's possible to enable backoff. */ +static +bool +innodb_empty_free_list_algorithm_backoff_allowed( + srv_empty_free_list_t + algorithm, /*!< in: desired algorithm + from srv_empty_free_list_t */ + long long buf_pool_pages); /*!< in: total number + of pages inside buffer pool */ + /*************************************************************//** Removes old archived transaction log files. @return true on error */ @@ -1520,6 +1648,26 @@ thd_supports_xa( return(THDVAR(thd, support_xa)); } +/** Get the value of innodb_tmpdir. +@param[in] thd thread handle, or NULL to query + the global innodb_tmpdir. +@retval NULL if innodb_tmpdir="" */ +UNIV_INTERN +const char* +thd_innodb_tmpdir( + THD* thd) +{ +#ifdef UNIV_SYNC_DEBUG + ut_ad(!sync_thread_levels_nonempty_trx(false)); +#endif /* UNIV_SYNC_DEBUG */ + + const char* tmp_dir = THDVAR(thd, tmpdir); + if (tmp_dir != NULL && *tmp_dir == '\0') { + tmp_dir = NULL; + } + + return(tmp_dir); +} /******************************************************************//** Check the status of fake changes mode (innodb_fake_changes) @return true if fake change mode is enabled. */ @@ -2096,13 +2244,14 @@ innobase_get_lower_case_table_names(void) return(lower_case_table_names); } -/*********************************************************************//** -Creates a temporary file. +/** Create a temporary file in the location specified by the parameter +path. If the path is null, then it will be created in tmpdir. +@param[in] path location for creating temporary file @return temporary file descriptor, or < 0 on error */ UNIV_INTERN int -innobase_mysql_tmpfile(void) -/*========================*/ +innobase_mysql_tmpfile( + const char* path) { int fd2 = -1; File fd; @@ -2112,7 +2261,11 @@ innobase_mysql_tmpfile(void) return(-1); ); - fd = mysql_tmpfile("ib"); + if (path == NULL) { + fd = mysql_tmpfile("ib"); + } else { + fd = mysql_tmpfile_path(path, "ib"); + } if (fd >= 0) { /* Copy the file descriptor, so that the additional resources @@ -3110,6 +3263,13 @@ ha_innobase::reset_template(void) ut_ad(prebuilt->magic_n == ROW_PREBUILT_ALLOCATED); ut_ad(prebuilt->magic_n2 == prebuilt->magic_n); + /* Force table to be freed in close_thread_table(). */ + DBUG_EXECUTE_IF("free_table_in_fts_query", + if (prebuilt->in_fts_query) { + table->m_needs_reopen = true; + } + ); + prebuilt->keep_other_fields_on_keyread = 0; prebuilt->read_just_key = 0; prebuilt->in_fts_query = 0; @@ -3691,6 +3851,22 @@ innobase_change_buffering_inited_ok: srv_kill_idle_transaction = 0; #endif + + /* Do not enable backoff algorithm for small buffer pool. */ + if (!innodb_empty_free_list_algorithm_backoff_allowed( + static_cast( + srv_empty_free_list_algorithm), + innobase_buffer_pool_size / srv_page_size)) { + sql_print_information( + "InnoDB: innodb_empty_free_list_algorithm " + "has been changed to legacy " + "because of small buffer pool size. " + "In order to use backoff, " + "increase buffer pool at least up to 20MB.\n"); + srv_empty_free_list_algorithm + = SRV_EMPTY_FREE_LIST_LEGACY; + } + srv_use_atomic_writes = (ibool) innobase_use_atomic_writes; if (innobase_use_atomic_writes) { ib_logf(IB_LOG_LEVEL_INFO, "using atomic writes."); @@ -5145,7 +5321,7 @@ building based on the assumption that there is no concurrent index creation/drop and DMLs that requires index lookup. All table handle will be closed before the index creation/drop. @return TRUE if index translation table built successfully */ -static +UNIV_INTERN ibool innobase_build_index_translation( /*=============================*/ @@ -16539,8 +16715,6 @@ innobase_fts_close_ranking( { fts_result_t* result; - ((NEW_FT_INFO*) fts_hdl)->ft_prebuilt->in_fts_query = false; - result = ((NEW_FT_INFO*) fts_hdl)->ft_result; fts_query_free_result(result); @@ -16892,6 +17066,87 @@ innodb_status_output_update( os_event_set(lock_sys->timeout_event); } +/*************************************************************//** +Empty free list algorithm. +Checks if buffer pool is big enough to enable backoff algorithm. +InnoDB empty free list algorithm backoff requires free pages +from LRU for the best performance. +buf_LRU_buf_pool_running_out cancels query if 1/4 of +buffer pool belongs to LRU or freelist. +At the same time buf_flush_LRU_list_batch +keeps up to BUF_LRU_MIN_LEN in LRU. +In order to avoid deadlock baclkoff requires buffer pool +to be at least 4*BUF_LRU_MIN_LEN, +but flush peformance is bad because of trashing +and additional BUF_LRU_MIN_LEN pages are requested. +@return true if it's possible to enable backoff. */ +static +bool +innodb_empty_free_list_algorithm_backoff_allowed( + srv_empty_free_list_t algorithm, /*!< in: desired algorithm + from srv_empty_free_list_t */ + long long buf_pool_pages) /*!< in: total number + of pages inside buffer pool */ +{ + return(buf_pool_pages >= BUF_LRU_MIN_LEN * (4 + 1) + || algorithm != SRV_EMPTY_FREE_LIST_BACKOFF); +} + +/*************************************************************//** +Empty free list algorithm. This function is registered as +a callback with MySQL. +@return 0 for valid algorithm */ +static +int +innodb_srv_empty_free_list_algorithm_validate( +/*===========================*/ + THD* thd, /*!< in: thread handle */ + struct st_mysql_sys_var* var, /*!< in: pointer to system + variable */ + void* save, /*!< out: immediate result + for update function */ + struct st_mysql_value* value) /*!< in: incoming string */ +{ + const char* algorithm_name; + char buff[STRING_BUFFER_USUAL_SIZE]; + int len = sizeof(buff); + ulint algo; + srv_empty_free_list_t algorithm; + + algorithm_name = value->val_str(value, buff, &len); + + if (!algorithm_name) { + return(1); + } + + for (algo = 0; algo < array_elements( + innodb_empty_free_list_algorithm_names + ) - 1; + algo++) { + if (!innobase_strcasecmp( + algorithm_name, + innodb_empty_free_list_algorithm_names[algo])) + break; + } + + if (algo == array_elements( innodb_empty_free_list_algorithm_names) - 1) + return(1); + + algorithm = static_cast(algo); + if (!innodb_empty_free_list_algorithm_backoff_allowed( + algorithm, + innobase_buffer_pool_size / srv_page_size)) { + sql_print_warning( + "InnoDB: innodb_empty_free_list_algorithm " + "= 'backoff' requires at least" + " 20MB buffer pool.\n"); + return(1); + } + + *reinterpret_cast(save) = static_cast(algorithm); + return(0); +} + static SHOW_VAR innodb_status_variables_export[]= { {"Innodb", (char*) &show_innodb_vars, SHOW_FUNC}, {NullS, NullS, SHOW_LONG} @@ -17436,7 +17691,7 @@ static MYSQL_SYSVAR_ENUM(empty_free_list_algorithm, "The algorithm to use for empty free list handling. Allowed values: " "LEGACY: Original Oracle MySQL 5.6 handling with single page flushes; " "BACKOFF: (default) Wait until cleaner produces a free page.", - NULL, NULL, SRV_EMPTY_FREE_LIST_BACKOFF, + innodb_srv_empty_free_list_algorithm_validate, NULL, SRV_EMPTY_FREE_LIST_BACKOFF, &innodb_empty_free_list_algorithm_typelib); static MYSQL_SYSVAR_LONG(buffer_pool_instances, innobase_buffer_pool_instances, @@ -18177,6 +18432,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(corrupt_table_action), MYSQL_SYSVAR(fake_changes), MYSQL_SYSVAR(locking_fake_changes), + MYSQL_SYSVAR(tmpdir), NULL }; diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h index d49a7c228f7..b4c0e0b7cf4 100644 --- a/storage/xtradb/handler/ha_innodb.h +++ b/storage/xtradb/handler/ha_innodb.h @@ -642,3 +642,26 @@ innobase_copy_frm_flags_from_table_share( /*=====================================*/ dict_table_t* innodb_table, /*!< in/out: InnoDB table */ const TABLE_SHARE* table_share); /*!< in: table share */ + +/*******************************************************************//** +This function builds a translation table in INNOBASE_SHARE +structure for fast index location with mysql array number from its +table->key_info structure. This also provides the necessary translation +between the key order in mysql key_info and Innodb ib_table->indexes if +they are not fully matched with each other. +Note we do not have any mutex protecting the translation table +building based on the assumption that there is no concurrent +index creation/drop and DMLs that requires index lookup. All table +handle will be closed before the index creation/drop. +@return TRUE if index translation table built successfully */ +UNIV_INTERN +ibool +innobase_build_index_translation( +/*=============================*/ + const TABLE* table, /*!< in: table in MySQL data + dictionary */ + dict_table_t* ib_table, /*!< in: table in Innodb data + dictionary */ + INNOBASE_SHARE* share); /*!< in/out: share structure + where index translation table + will be constructed in. */ diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index 49ae7c19cc5..cc016d8cb6d 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -2613,6 +2613,10 @@ prepare_inplace_alter_table_dict( ctx->num_to_add_index = ha_alter_info->index_add_count; + ut_ad(ctx->prebuilt->trx->mysql_thd != NULL); + const char* path = thd_innodb_tmpdir( + ctx->prebuilt->trx->mysql_thd); + index_defs = innobase_create_key_defs( ctx->heap, ha_alter_info, altered_table, ctx->num_to_add_index, num_fts_index, @@ -2951,8 +2955,10 @@ prepare_inplace_alter_table_dict( error = DB_OUT_OF_MEMORY; goto error_handling;); rw_lock_x_lock(&ctx->add_index[a]->lock); + bool ok = row_log_allocate(ctx->add_index[a], - NULL, true, NULL, NULL); + NULL, true, NULL, + NULL, path); rw_lock_x_unlock(&ctx->add_index[a]->lock); if (!ok) { @@ -2978,7 +2984,7 @@ prepare_inplace_alter_table_dict( clust_index, ctx->new_table, !(ha_alter_info->handler_flags & Alter_inplace_info::ADD_PK_INDEX), - ctx->add_cols, ctx->col_map); + ctx->add_cols, ctx->col_map, path); rw_lock_x_unlock(&clust_index->lock); if (!ok) { @@ -3951,6 +3957,7 @@ ok_exit: files and merge sort. */ DBUG_EXECUTE_IF("innodb_OOM_inplace_alter", error = DB_OUT_OF_MEMORY; goto oom;); + error = row_merge_build_indexes( prebuilt->trx, prebuilt->table, ctx->new_table, @@ -5971,6 +5978,21 @@ foreign_fail: row_mysql_unlock_data_dictionary(trx); trx_free_for_mysql(trx); + /* Rebuild index translation table now for temporary tables if we are + restoring secondary keys, as ha_innobase::open will not be called for + the next access. */ + if (dict_table_is_temporary(ctx0->new_table) + && ctx0->num_to_add_index > 0) { + ut_ad(!ctx0->num_to_drop_index); + ut_ad(!ctx0->num_to_drop_fk); + if (!innobase_build_index_translation(altered_table, + ctx0->new_table, + share)) { + MONITOR_ATOMIC_DEC(MONITOR_PENDING_ALTER_TABLE); + DBUG_RETURN(true); + } + } + /* TODO: The following code could be executed while allowing concurrent access to the table (MDL downgrade). */ diff --git a/storage/xtradb/include/buf0flu.h b/storage/xtradb/include/buf0flu.h index 2cd8eefb79d..83f1275e4d2 100644 --- a/storage/xtradb/include/buf0flu.h +++ b/storage/xtradb/include/buf0flu.h @@ -304,6 +304,12 @@ buf_flush_flush_list_in_progress(void) /*==================================*/ __attribute__((warn_unused_result)); +/** If LRU list of a buf_pool is less than this size then LRU eviction +should not happen. This is because when we do LRU flushing we also put +the blocks on free list. If LRU list is very small then we can end up +in thrashing. */ +#define BUF_LRU_MIN_LEN 256 + #ifndef UNIV_NONINL #include "buf0flu.ic" #endif diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h index 74832b59b7f..5a7e24c6b4a 100644 --- a/storage/xtradb/include/ha_prototypes.h +++ b/storage/xtradb/include/ha_prototypes.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2006, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2006, 2015, 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 @@ -335,6 +335,15 @@ thd_supports_xa( THD* thd); /*!< in: thread handle, or NULL to query the global innodb_supports_xa */ +/** Get status of innodb_tmpdir. +@param[in] thd thread handle, or NULL to query + the global innodb_tmpdir. +@retval NULL if innodb_tmpdir="" */ +UNIV_INTERN +const char* +thd_innodb_tmpdir( + THD* thd); + /******************************************************************//** Check the status of fake changes mode (innodb_fake_changes) @return true if fake change mode is enabled. */ diff --git a/storage/xtradb/include/os0file.h b/storage/xtradb/include/os0file.h index de5ef1b59fb..330067576f6 100644 --- a/storage/xtradb/include/os0file.h +++ b/storage/xtradb/include/os0file.h @@ -455,14 +455,19 @@ UNIV_INTERN void os_io_init_simple(void); /*===================*/ -/***********************************************************************//** -Creates a temporary file. This function is like tmpfile(3), but -the temporary file is created in the MySQL temporary directory. -@return temporary file handle, or NULL on error */ + +/** Create a temporary file. This function is like tmpfile(3), but +the temporary file is created in the given parameter path. If the path +is null then it will create the file in the mysql server configuration +parameter (--tmpdir). +@param[in] path location for creating temporary file +@return temporary file handle, or NULL on error */ +UNIV_INTERN FILE* -os_file_create_tmpfile(void); -/*========================*/ +os_file_create_tmpfile( + const char* path); + #endif /* !UNIV_HOTBACKUP */ /***********************************************************************//** The os_file_opendir() function opens a directory stream corresponding to the @@ -1284,14 +1289,14 @@ os_file_get_status( file can be opened in RW mode */ #if !defined(UNIV_HOTBACKUP) -/*********************************************************************//** -Creates a temporary file that will be deleted on close. -This function is defined in ha_innodb.cc. -@return temporary file descriptor, or < 0 on error */ +/** Create a temporary file in the location specified by the parameter +path. If the path is null, then it will be created in tmpdir. +@param[in] path location for creating temporary file +@return temporary file descriptor, or < 0 on error */ UNIV_INTERN int -innobase_mysql_tmpfile(void); -/*========================*/ +innobase_mysql_tmpfile( + const char* path); #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/xtradb/include/row0log.h b/storage/xtradb/include/row0log.h index 62715fe8808..5eed390aced 100644 --- a/storage/xtradb/include/row0log.h +++ b/storage/xtradb/include/row0log.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2011, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2011, 2015, 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 @@ -51,8 +51,9 @@ row_log_allocate( const dtuple_t* add_cols, /*!< in: default values of added columns, or NULL */ - const ulint* col_map)/*!< in: mapping of old column + const ulint* col_map,/*!< in: mapping of old column numbers to new ones, or NULL if !table */ + const char* path) /*!< in: where to create temporary file */ __attribute__((nonnull(1), warn_unused_result)); /******************************************************//** diff --git a/storage/xtradb/include/row0merge.h b/storage/xtradb/include/row0merge.h index 2b9e9f7711c..06e9fec544b 100644 --- a/storage/xtradb/include/row0merge.h +++ b/storage/xtradb/include/row0merge.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2005, 2015, 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 @@ -170,14 +170,14 @@ void row_merge_drop_temp_indexes(void); /*=============================*/ -/*********************************************************************//** -Creates temporary merge files, and if UNIV_PFS_IO defined, register -the file descriptor with Performance Schema. +/** Create temporary merge files in the given paramater path, and if +UNIV_PFS_IO defined, register the file descriptor with Performance Schema. +@param[in] path location for creating temporary merge files. @return File descriptor */ UNIV_INTERN int -row_merge_file_create_low(void) -/*===========================*/ +row_merge_file_create_low( + const char* path) __attribute__((warn_unused_result)); /*********************************************************************//** Destroy a merge file. And de-register the file from Performance Schema @@ -348,15 +348,17 @@ row_merge_buf_empty( /*================*/ row_merge_buf_t* buf) /*!< in,own: sort buffer */ __attribute__((warn_unused_result, nonnull)); -/*********************************************************************//** -Create a merge file. + +/** Create a merge file in the given location. +@param[out] merge_file merge file structure +@param[in] path location for creating temporary file @return file descriptor, or -1 on failure */ UNIV_INTERN int row_merge_file_create( -/*==================*/ - merge_file_t* merge_file) /*!< out: merge file structure */ - __attribute__((nonnull)); + merge_file_t* merge_file, + const char* path); + /*********************************************************************//** Merge disk files. @return DB_SUCCESS or error code */ diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index 28a100ee757..6db589355e2 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -47,7 +47,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_BUGFIX MYSQL_VERSION_PATCH #ifndef PERCONA_INNODB_VERSION -#define PERCONA_INNODB_VERSION 76.1 +#define PERCONA_INNODB_VERSION 76.2 #endif /* Enable UNIV_LOG_ARCHIVE in XtraDB */ diff --git a/storage/xtradb/lock/lock0lock.cc b/storage/xtradb/lock/lock0lock.cc index cc23b2b25df..c523b09afc6 100644 --- a/storage/xtradb/lock/lock0lock.cc +++ b/storage/xtradb/lock/lock0lock.cc @@ -619,7 +619,7 @@ lock_sys_create( lock_sys->rec_num = 0; if (!srv_read_only_mode) { - lock_latest_err_file = os_file_create_tmpfile(); + lock_latest_err_file = os_file_create_tmpfile(NULL); ut_a(lock_latest_err_file); } } diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc index 4dbd3ba9433..a28555821b7 100644 --- a/storage/xtradb/os/os0file.cc +++ b/storage/xtradb/os/os0file.cc @@ -764,17 +764,19 @@ os_io_init_simple(void) } } -/***********************************************************************//** -Creates a temporary file. This function is like tmpfile(3), but -the temporary file is created in the MySQL temporary directory. -@return temporary file handle, or NULL on error */ +/** Create a temporary file. This function is like tmpfile(3), but +the temporary file is created in the given parameter path. If the path +is null then it will create the file in the mysql server configuration +parameter (--tmpdir). +@param[in] path location for creating temporary file +@return temporary file handle, or NULL on error */ UNIV_INTERN FILE* -os_file_create_tmpfile(void) -/*========================*/ +os_file_create_tmpfile( + const char* path) { FILE* file = NULL; - int fd = innobase_mysql_tmpfile(); + int fd = innobase_mysql_tmpfile(path); ut_ad(!srv_read_only_mode); @@ -3815,7 +3817,7 @@ os_aio_native_aio_supported(void) return(FALSE); } else if (!srv_read_only_mode) { /* Now check if tmpdir supports native aio ops. */ - fd = innobase_mysql_tmpfile(); + fd = innobase_mysql_tmpfile(NULL); if (fd < 0) { ib_logf(IB_LOG_LEVEL_WARN, diff --git a/storage/xtradb/row/row0ftsort.cc b/storage/xtradb/row/row0ftsort.cc index f3f540ba230..37706898e65 100644 --- a/storage/xtradb/row/row0ftsort.cc +++ b/storage/xtradb/row/row0ftsort.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2010, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2010, 2015, 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 @@ -223,6 +223,9 @@ row_fts_psort_info_init( common_info->merge_event = os_event_create(); common_info->opt_doc_id_size = opt_doc_id_size; + ut_ad(trx->mysql_thd != NULL); + const char* path = thd_innodb_tmpdir(trx->mysql_thd); + /* There will be FTS_NUM_AUX_INDEX number of "sort buckets" for each parallel sort thread. Each "sort bucket" holds records for a particular "FTS index partition" */ @@ -244,8 +247,8 @@ row_fts_psort_info_init( psort_info[j].merge_buf[i] = row_merge_buf_create( dup->index); - if (row_merge_file_create(psort_info[j].merge_file[i]) - < 0) { + if (row_merge_file_create(psort_info[j].merge_file[i], + path) < 0) { goto func_exit; } @@ -613,6 +616,11 @@ fts_parallel_tokenization( ulint retried = 0; dberr_t error = DB_SUCCESS; + ut_ad(psort_info->psort_common->trx->mysql_thd != NULL); + + const char* path = thd_innodb_tmpdir( + psort_info->psort_common->trx->mysql_thd); + ut_ad(psort_info); buf = psort_info->merge_buf; @@ -842,7 +850,7 @@ exit: continue; } - tmpfd[i] = row_merge_file_create_low(); + tmpfd[i] = row_merge_file_create_low(path); if (tmpfd[i] < 0) { error = DB_OUT_OF_MEMORY; goto func_exit; diff --git a/storage/xtradb/row/row0log.cc b/storage/xtradb/row/row0log.cc index 3989b669c28..bb473ca92cf 100644 --- a/storage/xtradb/row/row0log.cc +++ b/storage/xtradb/row/row0log.cc @@ -194,8 +194,25 @@ struct row_log_t { or by index->lock X-latch only */ row_log_buf_t head; /*!< reader context; protected by MDL only; modifiable by row_log_apply_ops() */ + const char* path; /*!< where to create temporary file during + log operation */ }; +/** Create the file or online log if it does not exist. +@param[in,out] log online rebuild log +@return file descriptor. */ +static __attribute__((warn_unused_result)) +int +row_log_tmpfile( + row_log_t* log) +{ + DBUG_ENTER("row_log_tmpfile"); + if (log->fd < 0) { + log->fd = row_merge_file_create_low(log->path); + } + + DBUG_RETURN(log->fd); +} /** Allocate the memory for the log buffer. @param[in,out] log_buf Buffer used for log operation @@ -340,6 +357,12 @@ row_log_online_op( log->tail.buf, avail_size); } UNIV_MEM_ASSERT_RW(log->tail.block, srv_sort_buf_size); + + if (row_log_tmpfile(log) < 0) { + log->error = DB_OUT_OF_MEMORY; + goto err_exit; + } + ret = os_file_write( "(modification log)", OS_FILE_FROM_FD(log->fd), @@ -450,6 +473,12 @@ row_log_table_close_func( log->tail.buf, avail); } UNIV_MEM_ASSERT_RW(log->tail.block, srv_sort_buf_size); + + if (row_log_tmpfile(log) < 0) { + log->error = DB_OUT_OF_MEMORY; + goto err_exit; + } + ret = os_file_write( "(modification log)", OS_FILE_FROM_FD(log->fd), @@ -469,6 +498,7 @@ write_failed: log->tail.total += size; UNIV_MEM_INVALID(log->tail.buf, sizeof log->tail.buf); +err_exit: mutex_exit(&log->mutex); } @@ -2536,7 +2566,8 @@ corruption: if (index->online_log->head.blocks) { #ifdef HAVE_FTRUNCATE /* Truncate the file in order to save space. */ - if (ftruncate(index->online_log->fd, 0) == -1) { + if (index->online_log->fd != -1 + && ftruncate(index->online_log->fd, 0) == -1) { perror("ftruncate"); } #endif /* HAVE_FTRUNCATE */ @@ -2852,8 +2883,9 @@ row_log_allocate( const dtuple_t* add_cols, /*!< in: default values of added columns, or NULL */ - const ulint* col_map)/*!< in: mapping of old column + const ulint* col_map,/*!< in: mapping of old column numbers to new ones, or NULL if !table */ + const char* path) /*!< in: where to create temporary file */ { row_log_t* log; DBUG_ENTER("row_log_allocate"); @@ -2872,11 +2904,7 @@ row_log_allocate( DBUG_RETURN(false); } - log->fd = row_merge_file_create_low(); - if (log->fd < 0) { - ut_free(log); - DBUG_RETURN(false); - } + log->fd = -1; mutex_create(index_online_log_key, &log->mutex, SYNC_INDEX_ONLINE_LOG); log->blobs = NULL; @@ -2891,6 +2919,7 @@ row_log_allocate( log->tail.block = log->head.block = NULL; log->head.blocks = log->head.bytes = 0; log->head.total = 0; + log->path = path; dict_index_set_online_status(index, ONLINE_INDEX_CREATION); index->online_log = log; @@ -3368,7 +3397,8 @@ corruption: if (index->online_log->head.blocks) { #ifdef HAVE_FTRUNCATE /* Truncate the file in order to save space. */ - if (ftruncate(index->online_log->fd, 0) == -1) { + if (index->online_log->fd != -1 + && ftruncate(index->online_log->fd, 0) == -1) { perror("ftruncate"); } #endif /* HAVE_FTRUNCATE */ diff --git a/storage/xtradb/row/row0merge.cc b/storage/xtradb/row/row0merge.cc index 6304f0f7266..ecf7e5bb116 100644 --- a/storage/xtradb/row/row0merge.cc +++ b/storage/xtradb/row/row0merge.cc @@ -1241,47 +1241,95 @@ row_merge_write_eof( return(&block[0]); } -/********************************************************************//** -Reads clustered index of the table and create temporary files +/** Create a temporary file if it has not been created already. +@param[in,out] tmpfd temporary file handle +@param[in] path path to create temporary file +@return file descriptor, or -1 on failure */ +static __attribute__((warn_unused_result)) +int +row_merge_tmpfile_if_needed( + int* tmpfd, + const char* path) +{ + if (*tmpfd < 0) { + *tmpfd = row_merge_file_create_low(path); + } + + return(*tmpfd); +} + +/** Create a temporary file for merge sort if it was not created already. +@param[in,out] file merge file structure +@param[in,out] tmpfd temporary file structure +@param[in] nrec number of records in the file +@param[in] path path to create temporary files +@return file descriptor, or -1 on failure */ +static __attribute__((warn_unused_result)) +int +row_merge_file_create_if_needed( + merge_file_t* file, + int* tmpfd, + ulint nrec, + const char* path) +{ + ut_ad(file->fd < 0 || *tmpfd >=0); + if (file->fd < 0 && row_merge_file_create(file, path) >= 0) { + if (row_merge_tmpfile_if_needed(tmpfd, path) < 0) { + return(-1); + } + + file->n_rec = nrec; + } + + ut_ad(file->fd < 0 || *tmpfd >=0); + return(file->fd); +} + +/** Reads clustered index of the table and create temporary files containing the index entries for the indexes to be built. -@return DB_SUCCESS or error */ +@param[in] trx transaction +@param[in,out] table MySQL table object, for reporting erroneous + records +@param[in] old_table table where rows are read from +@param[in] new_table table where indexes are created; identical to + old_table unless creating a PRIMARY KEY +@param[in] online true if creating indexes online +@param[in] index indexes to be created +@param[in] fts_sort_idx full-text index to be created, or NULL +@param[in] psort_info parallel sort info for fts_sort_idx creation, + or NULL +@param[in] files temporary files +@param[in] key_numbers MySQL key numbers to create +@param[in] n_index number of indexes to create +@param[in] add_cols default values of added columns, or NULL +@param[in] col_map mapping of old column numbers to new ones, or + NULL if old_table == new_table +@param[in] add_autoinc number of added AUTO_INCREMENT columns, or + ULINT_UNDEFINED if none is added +@param[in,out] sequence autoinc sequence +@param[in,out] block file buffer +@param[in,out] tmpfd temporary file handle +return DB_SUCCESS or error */ static __attribute__((nonnull(1,2,3,4,6,9,10,16), warn_unused_result)) dberr_t row_merge_read_clustered_index( -/*===========================*/ - trx_t* trx, /*!< in: transaction */ - struct TABLE* table, /*!< in/out: MySQL table object, - for reporting erroneous records */ - const dict_table_t* old_table,/*!< in: table where rows are - read from */ - const dict_table_t* new_table,/*!< in: table where indexes are - created; identical to old_table - unless creating a PRIMARY KEY */ - bool online, /*!< in: true if creating indexes - online */ - dict_index_t** index, /*!< in: indexes to be created */ + trx_t* trx, + struct TABLE* table, + const dict_table_t* old_table, + const dict_table_t* new_table, + bool online, + dict_index_t** index, dict_index_t* fts_sort_idx, - /*!< in: full-text index to be created, - or NULL */ fts_psort_t* psort_info, - /*!< in: parallel sort info for - fts_sort_idx creation, or NULL */ - merge_file_t* files, /*!< in: temporary files */ + merge_file_t* files, const ulint* key_numbers, - /*!< in: MySQL key numbers to create */ - ulint n_index,/*!< in: number of indexes to create */ + ulint n_index, const dtuple_t* add_cols, - /*!< in: default values of - added columns, or NULL */ - const ulint* col_map,/*!< in: mapping of old column - numbers to new ones, or NULL - if old_table == new_table */ + const ulint* col_map, ulint add_autoinc, - /*!< in: number of added - AUTO_INCREMENT column, or - ULINT_UNDEFINED if none is added */ - ib_sequence_t& sequence,/*!< in/out: autoinc sequence */ - row_merge_block_t* block) /*!< in/out: file buffer */ + ib_sequence_t& sequence, + row_merge_block_t* block, + int* tmpfd) { dict_index_t* clust_index; /* Clustered index */ mem_heap_t* row_heap; /* Heap memory to create @@ -1313,6 +1361,9 @@ row_merge_read_clustered_index( DEBUG_FTS_SORT_PRINT("FTS_SORT: Start Create Index\n"); #endif + ut_ad(trx->mysql_thd != NULL); + const char* path = thd_innodb_tmpdir(trx->mysql_thd); + /* Create and initialize memory for record buffers */ merge_buf = static_cast( @@ -1783,13 +1834,25 @@ write_buffers: dict_index_get_lock(buf->index)); } - row_merge_buf_write(buf, file, block); + if (buf->n_tuples > 0) { - if (!row_merge_write(file->fd, file->offset++, - block)) { - err = DB_TEMP_FILE_WRITE_FAILURE; - trx->error_key_num = i; - break; + if (row_merge_file_create_if_needed( + file, tmpfd, buf->n_tuples, path) < 0) { + err = DB_OUT_OF_MEMORY; + trx->error_key_num = i; + break; + } + + ut_ad(file->n_rec > 0); + + row_merge_buf_write(buf, file, block); + + if (!row_merge_write(file->fd, file->offset++, + block)) { + err = DB_TEMP_FILE_WRITE_FAILURE; + trx->error_key_num = i; + break; + } } UNIV_MEM_INVALID(&block[0], srv_sort_buf_size); @@ -1833,6 +1896,7 @@ write_buffers: func_exit: mtr_commit(&mtr); + mem_heap_free(row_heap); if (nonnull) { @@ -3045,14 +3109,15 @@ row_merge_drop_temp_indexes(void) trx_free_for_background(trx); } -/*********************************************************************//** -Creates temporary merge files, and if UNIV_PFS_IO defined, register -the file descriptor with Performance Schema. -@return file descriptor, or -1 on failure */ + +/** Create temporary merge files in the given paramater path, and if +UNIV_PFS_IO defined, register the file descriptor with Performance Schema. +@param[in] path location for creating temporary merge files. +@return File descriptor */ UNIV_INTERN int -row_merge_file_create_low(void) -/*===========================*/ +row_merge_file_create_low( + const char* path) { int fd; #ifdef UNIV_PFS_IO @@ -3066,7 +3131,7 @@ row_merge_file_create_low(void) "Innodb Merge Temp File", __FILE__, __LINE__); #endif - fd = innobase_mysql_tmpfile(); + fd = innobase_mysql_tmpfile(path); #ifdef UNIV_PFS_IO register_pfs_file_open_end(locker, fd); #endif @@ -3079,16 +3144,18 @@ row_merge_file_create_low(void) return(fd); } -/*********************************************************************//** -Create a merge file. + +/** Create a merge file in the given location. +@param[out] merge_file merge file structure +@param[in] path location for creating temporary file @return file descriptor, or -1 on failure */ UNIV_INTERN int row_merge_file_create( -/*==================*/ - merge_file_t* merge_file) /*!< out: merge file structure */ + merge_file_t* merge_file, + const char* path) { - merge_file->fd = row_merge_file_create_low(); + merge_file->fd = row_merge_file_create_low(path); merge_file->offset = 0; merge_file->n_rec = 0; @@ -3604,10 +3671,6 @@ row_merge_build_indexes( } for (i = 0; i < n_indexes; i++) { - if (row_merge_file_create(&merge_files[i]) < 0) { - error = DB_OUT_OF_MEMORY; - goto func_exit; - } if (indexes[i]->type & DICT_FTS) { ibool opt_doc_id_size = FALSE; @@ -3636,13 +3699,6 @@ row_merge_build_indexes( } } - tmpfd = row_merge_file_create_low(); - - if (tmpfd < 0) { - error = DB_OUT_OF_MEMORY; - goto func_exit; - } - /* Reset the MySQL row buffer that is used when reporting duplicate keys. */ innobase_rec_reset(table); @@ -3654,7 +3710,7 @@ row_merge_build_indexes( trx, table, old_table, new_table, online, indexes, fts_sort_idx, psort_info, merge_files, key_numbers, n_indexes, add_cols, col_map, - add_autoinc, sequence, block); + add_autoinc, sequence, block, &tmpfd); if (error != DB_SUCCESS) { @@ -3735,7 +3791,7 @@ wait_again: #ifdef FTS_INTERNAL_DIAG_PRINT DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Insert\n"); #endif - } else { + } else if (merge_files[i].fd != -1) { row_merge_dup_t dup = { sort_idx, table, col_map, 0}; diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc index 96827558876..2b086a2fb1f 100644 --- a/storage/xtradb/srv/srv0srv.cc +++ b/storage/xtradb/srv/srv0srv.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. @@ -2043,6 +2043,8 @@ exit_func: /*********************************************************************//** A thread which prints warnings about semaphore waits which have lasted too long. These can be used to track bugs which cause hangs. +Note: In order to make sync_arr_wake_threads_if_sema_free work as expected, +we should avoid waiting any mutexes in this function! @return a dummy parameter */ extern "C" UNIV_INTERN os_thread_ret_t @@ -2082,22 +2084,22 @@ loop: /* Try to track a strange bug reported by Harald Fuchs and others, where the lsn seems to decrease at times */ - new_lsn = log_get_lsn(); + if (log_peek_lsn(&new_lsn)) { + if (new_lsn < old_lsn) { + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Error: old log sequence number " LSN_PF + " was greater\n" + "InnoDB: than the new log sequence number " LSN_PF "!\n" + "InnoDB: Please submit a bug report" + " to http://bugs.mysql.com\n", + old_lsn, new_lsn); + ut_ad(0); + } - if (new_lsn < old_lsn) { - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: old log sequence number " LSN_PF - " was greater\n" - "InnoDB: than the new log sequence number " LSN_PF "!\n" - "InnoDB: Please submit a bug report" - " to http://bugs.mysql.com\n", - old_lsn, new_lsn); - ut_ad(0); + old_lsn = new_lsn; } - old_lsn = new_lsn; - if (difftime(time(NULL), srv_last_monitor_time) > 60) { /* We referesh InnoDB Monitor values so that averages are printed from at most 60 last seconds */ diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc index 0d3f4691a50..f4d404e43a5 100644 --- a/storage/xtradb/srv/srv0start.cc +++ b/storage/xtradb/srv/srv0start.cc @@ -1938,7 +1938,7 @@ innobase_start_or_create_for_mysql(void) } } else { srv_monitor_file_name = NULL; - srv_monitor_file = os_file_create_tmpfile(); + srv_monitor_file = os_file_create_tmpfile(NULL); if (!srv_monitor_file) { return(DB_ERROR); @@ -1948,7 +1948,7 @@ innobase_start_or_create_for_mysql(void) mutex_create(srv_dict_tmpfile_mutex_key, &srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION); - srv_dict_tmpfile = os_file_create_tmpfile(); + srv_dict_tmpfile = os_file_create_tmpfile(NULL); if (!srv_dict_tmpfile) { return(DB_ERROR); @@ -1957,7 +1957,7 @@ innobase_start_or_create_for_mysql(void) mutex_create(srv_misc_tmpfile_mutex_key, &srv_misc_tmpfile_mutex, SYNC_ANY_LATCH); - srv_misc_tmpfile = os_file_create_tmpfile(); + srv_misc_tmpfile = os_file_create_tmpfile(NULL); if (!srv_misc_tmpfile) { return(DB_ERROR); From b7ad1ba5d121d4fe4b0655e46076b6e50754b4e9 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 26 Apr 2016 20:11:40 +0300 Subject: [PATCH 85/91] Fixed mutex that wasn't properly unlocked (typo in last patch) --- sql/sql_class.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 9cd4258c0df..1ee5e4b4113 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1923,8 +1923,8 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use, if (!thd_table->needs_reopen()) signalled|= mysql_lock_abort_for_thread(this, thd_table); } - mysql_mutex_unlock(&in_use->LOCK_thd_data); } + mysql_mutex_unlock(&in_use->LOCK_thd_data); } DBUG_RETURN(signalled); } From 4995bcffaded6a02106632fb8f259cd3d9048dc4 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 26 Apr 2016 17:00:47 +0200 Subject: [PATCH 86/91] MDEV-9610 Trigger on normal table can't insert into CONNECT engine table - Access Denied in case of prelocking, don't check table->grant.privilege in handler::external_lock(), do it in handler::start_stmt(). --- storage/connect/ha_connect.cc | 13 ++++++++++--- storage/connect/ha_connect.h | 2 +- storage/connect/mysql-test/connect/r/grant3.result | 5 +++++ storage/connect/mysql-test/connect/t/grant3.test | 11 +++++++++++ 4 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 storage/connect/mysql-test/connect/r/grant3.result create mode 100644 storage/connect/mysql-test/connect/t/grant3.test diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 645d0003c47..dc9bf47244f 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -4054,7 +4054,7 @@ int ha_connect::delete_all_rows() } // end of delete_all_rows -bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn) +bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick) { const char *db= (dbn && *dbn) ? dbn : NULL; TABTYPE type=GetRealType(options); @@ -4081,6 +4081,7 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn) case TAB_VEC: case TAB_JSON: if (options->filename && *options->filename) { + if (!quick) { char *s, path[FN_REFLEN], dbpath[FN_REFLEN]; #if defined(__WIN__) s= "\\"; @@ -4099,7 +4100,7 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn) my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv"); return true; } // endif path - + } } else return false; @@ -4121,10 +4122,13 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn) Otherwise it's a DML, the table was normally opened, locked, privilege were already checked, and table->grant.privilege is set. With SQL SECURITY DEFINER, table->grant.privilege has definer's privileges. + + Unless we're in prelocking mode, in this case table->grant.privilege + is only checked in start_stmt(), not in external_lock(). */ if (!table || !table->mdl_ticket || table->mdl_ticket->get_type() == MDL_EXCLUSIVE) return check_access(thd, FILE_ACL, db, NULL, NULL, 0, 0); - if (table->grant.privilege & FILE_ACL) + if ((!quick && thd->lex->requires_prelocking()) || table->grant.privilege & FILE_ACL) return false; status_var_increment(thd->status_var.access_denied_errors); my_error(access_denied_error_code(thd->password), MYF(0), @@ -4308,6 +4312,9 @@ int ha_connect::start_stmt(THD *thd, thr_lock_type lock_type) PGLOBAL g= GetPlug(thd, xp); DBUG_ENTER("ha_connect::start_stmt"); + if (check_privileges(thd, GetTableOptionStruct(), table->s->db.str, true)) + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); + // Action will depend on lock_type switch (lock_type) { case TL_WRITE_ALLOW_WRITE: diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h index 05cc872fa2a..6d491b6ddd3 100644 --- a/storage/connect/ha_connect.h +++ b/storage/connect/ha_connect.h @@ -536,7 +536,7 @@ private: DsMrr_impl ds_mrr; protected: - bool check_privileges(THD *thd, PTOS options, char *dbn); + bool check_privileges(THD *thd, PTOS options, char *dbn, bool quick=false); MODE CheckMode(PGLOBAL g, THD *thd, MODE newmode, bool *chk, bool *cras); char *GetDBfromName(const char *name); diff --git a/storage/connect/mysql-test/connect/r/grant3.result b/storage/connect/mysql-test/connect/r/grant3.result new file mode 100644 index 00000000000..2f9d37bdb35 --- /dev/null +++ b/storage/connect/mysql-test/connect/r/grant3.result @@ -0,0 +1,5 @@ +create table tcon (i int) engine=Connect table_type=DOS file_name='tcon.dos'; +create table tin (i int); +create trigger tr after insert on tin for each row insert into tcon values (new.i); +insert into tin values (1); +drop table tin,tcon; diff --git a/storage/connect/mysql-test/connect/t/grant3.test b/storage/connect/mysql-test/connect/t/grant3.test new file mode 100644 index 00000000000..9f05ca796c5 --- /dev/null +++ b/storage/connect/mysql-test/connect/t/grant3.test @@ -0,0 +1,11 @@ +# +# MDEV-9610 Trigger on normal table can't insert into CONNECT engine table - Access Denied +# +create table tcon (i int) engine=Connect table_type=DOS file_name='tcon.dos'; +create table tin (i int); +create trigger tr after insert on tin for each row insert into tcon values (new.i); +insert into tin values (1); +drop table tin,tcon; + +let datadir=`select @@datadir`; +remove_file $datadir/test/tcon.dos; From cf225145912508644fe00100afbc957aeff8aa87 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 27 Apr 2016 08:34:35 +0200 Subject: [PATCH 87/91] after-merge fixes for failures in buildbot --- .../sys_vars/t/innodb_empty_free_list_algorithm_basic.opt | 1 + storage/innobase/handler/ha_innodb.cc | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) create mode 100644 mysql-test/suite/sys_vars/t/innodb_empty_free_list_algorithm_basic.opt diff --git a/mysql-test/suite/sys_vars/t/innodb_empty_free_list_algorithm_basic.opt b/mysql-test/suite/sys_vars/t/innodb_empty_free_list_algorithm_basic.opt new file mode 100644 index 00000000000..c788dc76ac7 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/innodb_empty_free_list_algorithm_basic.opt @@ -0,0 +1 @@ +--loose-innodb-buffer-pool-size=20M diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 0c3a04fe753..99ca76e2269 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3498,13 +3498,11 @@ innobase_change_buffering_inited_ok: } } - if (innobase_open_files > (long) open_files_limit) { + if (innobase_open_files > (long) tc_size) { fprintf(stderr, "innodb_open_files should not be greater" " than the open_files_limit.\n"); - if (innobase_open_files > (long) tc_size) { - innobase_open_files = tc_size; - } + innobase_open_files = tc_size; } srv_max_n_open_files = (ulint) innobase_open_files; From e5810727a95659c3cd841d1dd070a19bd011ccd5 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 27 Apr 2016 18:16:03 +0200 Subject: [PATCH 88/91] Fix msxml6 search in Connect engine on Windows, as it fails on new builders. msxml6 is found on all Windows we support, thus there is no reason to search for it. --- storage/connect/CMakeLists.txt | 35 ++++------------------------------ 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index 0702e44bcf2..6ef8b45daf9 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -128,37 +128,10 @@ IF(WIN32) OPTION(CONNECT_WITH_MSXML "Compile CONNECT storage engine with MSXML support" ON) IF(CONNECT_WITH_MSXML) - find_library(MSXML_LIBRARY - NAMES msxml6 msxml4 msxml3 msxml2 - PATHS - "C:/Program Files/Microsoft SDKs/Windows/v7.0A/Lib" - "C:/Program Files/Microsoft SDKs/Windows/v6.0A/Lib" - "C:/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/Lib" - DOC "Specify the MSXML? library here." - ) - IF(MSXML_LIBRARY MATCHES .*msxml6[.].*) - add_definitions(-DMSX6 -DDOMDOC_SUPPORT) - message(STATUS "MSXML library version: msxml6") - SET(MSXML_FOUND 1) - SET(CONNECT_SOURCES ${CONNECT_SOURCES} domdoc.cpp domdoc.h) - ELSEIF(MSXML_LIBRARY MATCHES .*msxml4[.].*) - add_definitions(-DMSX4 -DDOMDOC_SUPPORT) - message("MSXML library version: msxml4") - SET(MSXML_FOUND 1) - SET(CONNECT_SOURCES ${CONNECT_SOURCES} domdoc.cpp domdoc.h) - ELSEIF(MSXML_LIBRARY MATCHES .*msxml3[.].*) - message("MSXML library version: msxml3") - add_definitions(-DMSX3 -DDOMDOC_SUPPORT) - SET(MSXML_FOUND 1) - SET(CONNECT_SOURCES ${CONNECT_SOURCES} domdoc.cpp domdoc.h) - ELSEIF(MSXML_LIBRARY MATCHES .*msxml2[.].*) - message("MSXML library version: msxml2") - add_definitions(-DMXS2 -DDOMDOC_SUPPORT) - SET(MSXML_FOUND 1) - SET(CONNECT_SOURCES ${CONNECT_SOURCES} domdoc.cpp domdoc.h) - ELSE() - message(STATUS "msxml? library not found") - ENDIF() + add_definitions(-DMSX6 -DDOMDOC_SUPPORT) + message(STATUS "MSXML library version: msxml6") + SET(MSXML_FOUND 1) + SET(CONNECT_SOURCES ${CONNECT_SOURCES} domdoc.cpp domdoc.h) ENDIF(CONNECT_WITH_MSXML) ENDIF(WIN32) From 94bad73dd1dd563a3a324dcd519975f6d995dc88 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Thu, 28 Apr 2016 21:59:23 +0400 Subject: [PATCH 89/91] MDEV-9988 - Insert cast to suppress -Wdynamic-class-memaccess Clang warns on this code because it is memsetting over a vtable contained in a struct in the best_positions array. The diagnostic text is: mariadb/sql/sql_select.cc:24462:10: error: destination for this 'memset' call is a pointer to class containing a dynamic class 'Duplicate_weedout_picker'; vtable pointer will be overwritten [-Werror,-Wdynamic-class-memaccess] memset(best_positions, 0, sizeof(POSITION) * (table_count + 1)); ~~~~~~ ^ Patch contributed by David Gow. --- sql/opt_subselect.cc | 9 +++++---- sql/sql_select.cc | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index de57143e61d..a81b091461f 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -2243,7 +2243,8 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map) rows *= join->map2table[tableno]->table->quick_condition_rows; sjm->rows= MY_MIN(sjm->rows, rows); } - memcpy(sjm->positions, join->best_positions + join->const_tables, + memcpy((uchar*) sjm->positions, + (uchar*) (join->best_positions + join->const_tables), sizeof(POSITION) * n_tables); /* @@ -3347,7 +3348,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join) SJ_MATERIALIZATION_INFO *sjm= s->emb_sj_nest->sj_mat_info; sjm->is_used= TRUE; sjm->is_sj_scan= FALSE; - memcpy(pos - sjm->tables + 1, sjm->positions, + memcpy((uchar*) (pos - sjm->tables + 1), (uchar*) sjm->positions, sizeof(POSITION) * sjm->tables); recalculate_prefix_record_count(join, tablenr - sjm->tables + 1, tablenr); @@ -3363,8 +3364,8 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join) sjm->is_used= TRUE; sjm->is_sj_scan= TRUE; first= pos->sjmat_picker.sjm_scan_last_inner - sjm->tables + 1; - memcpy(join->best_positions + first, - sjm->positions, sizeof(POSITION) * sjm->tables); + memcpy((uchar*) (join->best_positions + first), + (uchar*) sjm->positions, sizeof(POSITION) * sjm->tables); recalculate_prefix_record_count(join, first, first + sjm->tables); join->best_positions[first].sj_strategy= SJ_OPT_MATERIALIZE_SCAN; join->best_positions[first].n_sj_tables= sjm->tables; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f58738a4539..c2b25d812fb 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -24672,7 +24672,7 @@ void JOIN::save_query_plan(Join_plan_state *save_to) } memcpy((uchar*) save_to->best_positions, (uchar*) best_positions, sizeof(POSITION) * (table_count + 1)); - memset(best_positions, 0, sizeof(POSITION) * (table_count + 1)); + memset((uchar*) best_positions, 0, sizeof(POSITION) * (table_count + 1)); /* Save SJM nests */ List_iterator it(select_lex->sj_nests); From 9eba34f08675c31b0796eeb127582be827773070 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 28 Apr 2016 22:18:15 +0200 Subject: [PATCH 90/91] Fix crash due to heap corruption in main.shm --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 177018dd171..4dfe45683d6 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -6642,7 +6642,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg) thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); /* Host is unknown */ create_new_thread(thd); connect_number++; - set_current_thd(thd); + set_current_thd(0); continue; errorconn: From cee9ab9d85a8d75290b0d60bc7af26c8cf179a1d Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Sat, 30 Apr 2016 11:23:46 -0400 Subject: [PATCH 91/91] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 159e62bbc32..14d24a318d1 100644 --- a/VERSION +++ b/VERSION @@ -1,3 +1,3 @@ MYSQL_VERSION_MAJOR=10 MYSQL_VERSION_MINOR=0 -MYSQL_VERSION_PATCH=25 +MYSQL_VERSION_PATCH=26