From 3dfe14807424d5008969f5e0bd212dd3a70368ea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= <vicentiu@mariadb.org>
Date: Tue, 23 Jan 2018 17:43:37 +0200
Subject: [PATCH] 5.6.39

---
 storage/innobase/CMakeLists.txt       |  4 +-
 storage/innobase/dict/dict0dict.cc    | 66 ++++++++++++++-------------
 storage/innobase/dict/dict0mem.cc     | 13 +++++-
 storage/innobase/fts/fts0fts.cc       | 14 ++++--
 storage/innobase/fts/fts0que.cc       | 17 +++++--
 storage/innobase/handler/ha_innodb.cc |  8 ++++
 storage/innobase/include/ut0ut.h      | 11 ++++-
 storage/innobase/row/row0sel.cc       |  2 +-
 storage/innobase/trx/trx0purge.cc     | 15 ++++--
 storage/innobase/ut/ut0ut.cc          | 30 +++++++++++-
 10 files changed, 130 insertions(+), 50 deletions(-)

diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt
index 2e939899d24..1177256b366 100644
--- a/storage/innobase/CMakeLists.txt
+++ b/storage/innobase/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -450,3 +450,5 @@ MYSQL_ADD_PLUGIN(innobase ${INNOBASE_SOURCES} STORAGE_ENGINE
   DEFAULT
   MODULE_OUTPUT_NAME ha_innodb
   LINK_LIBRARIES ${ZLIB_LIBRARY})
+
+ADD_DEPENDENCIES(innobase GenError)
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index ae4cb0b845a..b2def1edffe 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
 Copyright (c) 2012, Facebook Inc.
 
 This program is free software; you can redistribute it and/or modify it under
@@ -556,6 +556,8 @@ dict_table_close(
 					indexes after an aborted online
 					index creation */
 {
+
+	ibool		drop_aborted;
 	if (!dict_locked) {
 		mutex_enter(&dict_sys->mutex);
 	}
@@ -563,6 +565,11 @@ dict_table_close(
 	ut_ad(mutex_own(&dict_sys->mutex));
 	ut_a(table->n_ref_count > 0);
 
+	drop_aborted = try_drop
+			&& table->drop_aborted
+			&& table->n_ref_count == 1
+			&& dict_table_get_first_index(table);
+
 	--table->n_ref_count;
 
 	/* Force persistent stats re-read upon next open of the table
@@ -591,12 +598,6 @@ dict_table_close(
 
 	if (!dict_locked) {
 		table_id_t	table_id	= table->id;
-		ibool		drop_aborted;
-
-		drop_aborted = try_drop
-			&& table->drop_aborted
-			&& table->n_ref_count == 1
-			&& dict_table_get_first_index(table);
 
 		mutex_exit(&dict_sys->mutex);
 
@@ -2054,6 +2055,33 @@ dict_table_remove_from_cache_low(
 		foreign->referenced_index = NULL;
 	}
 
+	/* The check for dropped index should happen before we release
+	   all the indexes */
+
+	if (lru_evict && table->drop_aborted) {
+		/* Do as dict_table_try_drop_aborted() does. */
+
+		trx_t* trx = trx_allocate_for_background();
+
+		ut_ad(mutex_own(&dict_sys->mutex));
+#ifdef UNIV_SYNC_DEBUG
+		ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+		/* Mimic row_mysql_lock_data_dictionary(). */
+		trx->dict_operation_lock_mode = RW_X_LATCH;
+
+		trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
+
+		/* Silence a debug assertion in row_merge_drop_indexes(). */
+		ut_d(table->n_ref_count++);
+		row_merge_drop_indexes(trx, table, TRUE);
+		ut_d(table->n_ref_count--);
+		ut_ad(table->n_ref_count == 0);
+		trx_commit_for_mysql(trx);
+		trx->dict_operation_lock_mode = 0;
+		trx_free_for_background(trx);
+	}
+
 	/* Remove the indexes from the cache */
 
 	for (index = UT_LIST_GET_LAST(table->indexes);
@@ -2086,30 +2114,6 @@ dict_table_remove_from_cache_low(
 		dict_table_autoinc_store(table);
 	}
 
-	if (lru_evict && table->drop_aborted) {
-		/* Do as dict_table_try_drop_aborted() does. */
-
-		trx_t* trx = trx_allocate_for_background();
-
-		ut_ad(mutex_own(&dict_sys->mutex));
-#ifdef UNIV_SYNC_DEBUG
-		ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
-#endif /* UNIV_SYNC_DEBUG */
-		/* Mimic row_mysql_lock_data_dictionary(). */
-		trx->dict_operation_lock_mode = RW_X_LATCH;
-
-		trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
-
-		/* Silence a debug assertion in row_merge_drop_indexes(). */
-		ut_d(table->n_ref_count++);
-		row_merge_drop_indexes(trx, table, TRUE);
-		ut_d(table->n_ref_count--);
-		ut_ad(table->n_ref_count == 0);
-		trx_commit_for_mysql(trx);
-		trx->dict_operation_lock_mode = 0;
-		trx_free_for_background(trx);
-	}
-
 	size = mem_heap_get_size(table->heap) + strlen(table->name) + 1;
 
 	ut_ad(dict_sys->size >= size);
diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc
index b39e1e171ee..f5bfd49e9f6 100644
--- a/storage/innobase/dict/dict0mem.cc
+++ b/storage/innobase/dict/dict0mem.cc
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
 Copyright (c) 2012, Facebook Inc.
 
 This program is free software; you can redistribute it and/or modify it under
@@ -300,11 +300,20 @@ dict_mem_table_col_rename_low(
 		char*	col_names;
 
 		if (to_len > from_len) {
+			ulint table_size_before_rename_col
+                                = mem_heap_get_size(table->heap);
 			col_names = static_cast<char*>(
 				mem_heap_alloc(
 					table->heap,
 					full_len + to_len - from_len));
-
+			ulint table_size_after_rename_col
+                                = mem_heap_get_size(table->heap);
+			if (table_size_before_rename_col
+                                != table_size_after_rename_col) {
+                                dict_sys->size +=
+                                        table_size_after_rename_col
+                                                - table_size_before_rename_col;
+                        }
 			memcpy(col_names, table->col_names, prefix_len);
 		} else {
 			col_names = const_cast<char*>(table->col_names);
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index a29e046eb84..f3fa6e52d0d 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -4804,9 +4804,17 @@ fts_process_token(
 		t_str.f_str = static_cast<byte*>(
 			mem_heap_alloc(heap, t_str.f_len));
 
-		newlen = innobase_fts_casedn_str(
-			doc->charset, (char*) str.f_str, str.f_len,
-			(char*) t_str.f_str, t_str.f_len);
+		/* For binary collations, a case sensitive search is
+		performed. Hence don't convert to lower case. */
+		if (my_binary_compare(result_doc->charset)) {
+			memcpy(t_str.f_str, str.f_str, str.f_len);
+			t_str.f_str[str.f_len]= 0;
+			newlen= str.f_len;
+		} else {
+			newlen = innobase_fts_casedn_str(
+				doc->charset, (char*) str.f_str, str.f_len,
+				(char*) t_str.f_str, t_str.f_len);
+		}
 
 		t_str.f_len = newlen;
 		t_str.f_str[newlen] = 0;
diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc
index fd1199ac434..d20ff345dc6 100644
--- a/storage/innobase/fts/fts0que.cc
+++ b/storage/innobase/fts/fts0que.cc
@@ -3764,10 +3764,19 @@ fts_query_str_preprocess(
 	str_len = query_len * charset->casedn_multiply + 1;
 	str_ptr = static_cast<byte*>(ut_malloc(str_len));
 
-	*result_len = innobase_fts_casedn_str(
-		charset, const_cast<char*>(reinterpret_cast<const char*>(
-			query_str)), query_len,
-		reinterpret_cast<char*>(str_ptr), str_len);
+	/* For binary collations, a case sensitive search is
+	performed. Hence don't convert to lower case. */
+	if (my_binary_compare(charset)) {
+		memcpy(str_ptr, query_str, query_len);
+		str_ptr[query_len]= 0;
+		*result_len= query_len;
+	} else {
+		*result_len = innobase_fts_casedn_str(
+				charset, const_cast<char*>
+				(reinterpret_cast<const char*>( query_str)),
+				query_len,
+				reinterpret_cast<char*>(str_ptr), str_len);
+	}
 
 	ut_ad(*result_len < str_len);
 
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 142f1b94a1e..2b41c3db344 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -3473,6 +3473,14 @@ innobase_init(
 	/* Turn on monitor counters that are default on */
 	srv_mon_default_on();
 
+#ifndef UNIV_HOTBACKUP
+#ifdef _WIN32
+	if (ut_win_init_time()) {
+		goto mem_free_and_error;
+	}
+#endif /* _WIN32 */
+#endif /* !UNIV_HOTBACKUP */
+
 	DBUG_RETURN(FALSE);
 error:
 	DBUG_RETURN(TRUE);
diff --git a/storage/innobase/include/ut0ut.h b/storage/innobase/include/ut0ut.h
index ef887ed5e58..7c28081dd70 100644
--- a/storage/innobase/include/ut0ut.h
+++ b/storage/innobase/include/ut0ut.h
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2017, Oracle and/or its affiliates. All Rights Reserved.
 
 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
@@ -266,6 +266,15 @@ UNIV_INTERN
 ulint
 ut_time_ms(void);
 /*============*/
+#ifdef _WIN32
+/**********************************************************//**
+Initialise highest available time resolution API on Windows
+@return 0 if all OK else -1 */
+int
+ut_win_init_time();
+
+#endif /* _WIN32 */
+
 #endif /* !UNIV_HOTBACKUP */
 
 /**********************************************************//**
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index bd311a99b77..706b5436981 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -2796,7 +2796,7 @@ row_sel_store_mysql_field_func(
 {
 	const byte*	data;
 	ulint		len;
-	ulint		clust_field_no;
+	ulint		clust_field_no = 0;
 	bool		clust_templ_for_sec = (sec_field_no != ULINT_UNDEFINED);
 
 	ut_ad(prebuilt->default_rec);
diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc
index 55af54991c6..35f4127a31f 100644
--- a/storage/innobase/trx/trx0purge.cc
+++ b/storage/innobase/trx/trx0purge.cc
@@ -579,6 +579,7 @@ trx_purge_rseg_get_next_history_log(
 		mutex_exit(&(rseg->mutex));
 		mtr_commit(&mtr);
 
+#ifdef UNIV_DEBUG
 		mutex_enter(&trx_sys->mutex);
 
 		/* Add debug code to track history list corruption reported
@@ -595,15 +596,19 @@ trx_purge_rseg_get_next_history_log(
 				"  InnoDB: Warning: purge reached the"
 				" head of the history list,\n"
 				"InnoDB: but its length is still"
-				" reported as %lu! Make a detailed bug\n"
-				"InnoDB: report, and submit it"
-				" to http://bugs.mysql.com\n",
+				" reported as %lu!.\n"
+				"This can happen for multiple reasons\n"
+				"1. A long running transaction is"
+				" withholding purging of undo logs or a read"
+				" view is open. Please try to commit the long"
+				" running transaction.\n"
+				"2. Try increasing the number of purge"
+				" threads to expedite purging of undo logs.",
 				(ulong) trx_sys->rseg_history_len);
-			ut_ad(0);
 		}
 
 		mutex_exit(&trx_sys->mutex);
-
+#endif
 		return;
 	}
 
diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc
index 68446cc85ef..82979b5bcc8 100644
--- a/storage/innobase/ut/ut0ut.cc
+++ b/storage/innobase/ut/ut0ut.cc
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2017, Oracle and/or its affiliates. All Rights Reserved.
 
 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
@@ -48,6 +48,10 @@ Created 5/11/1994 Heikki Tuuri
 UNIV_INTERN ibool	ut_always_false	= FALSE;
 
 #ifdef __WIN__
+#include <mysql/innodb_priv.h> /* For sql_print_error */
+typedef VOID(WINAPI *time_fn)(LPFILETIME);
+static time_fn ut_get_system_time_as_file_time = GetSystemTimeAsFileTime;
+
 /*****************************************************************//**
 NOTE: The Windows epoch starts from 1601/01/01 whereas the Unix
 epoch starts from 1970/1/1. For selection of constant see:
@@ -55,6 +59,28 @@ epoch starts from 1970/1/1. For selection of constant see:
 #define WIN_TO_UNIX_DELTA_USEC  ((ib_int64_t) 11644473600000000ULL)
 
 
+/**
+Initialise highest available time resolution API on Windows
+@return 0 if all OK else -1 */
+int
+ut_win_init_time()
+{
+	HMODULE h = LoadLibrary("kernel32.dll");
+	if (h != NULL)
+	{
+		time_fn pfn = (time_fn)GetProcAddress(h, "GetSystemTimePreciseAsFileTime");
+		if (pfn != NULL)
+		{
+			ut_get_system_time_as_file_time = pfn;
+		}
+		return false;
+	}
+	DWORD error = GetLastError();
+  sql_print_error(
+		"LoadLibrary(\"kernel32.dll\") failed: GetLastError returns %lu", error);
+	return(-1);
+}
+
 /*****************************************************************//**
 This is the Windows version of gettimeofday(2).
 @return	0 if all OK else -1 */
@@ -73,7 +99,7 @@ ut_gettimeofday(
 		return(-1);
 	}
 
-	GetSystemTimeAsFileTime(&ft);
+	ut_get_system_time_as_file_time(&ft);
 
 	tm = (ib_int64_t) ft.dwHighDateTime << 32;
 	tm |= ft.dwLowDateTime;
-- 
2.30.9