summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeppo Jaakola <seppo.jaakola@codership.com>2012-11-30 13:36:29 +0200
committerSeppo Jaakola <seppo.jaakola@codership.com>2012-11-30 13:36:29 +0200
commit4df29fef362389f3fe64da4880af7050396baa94 (patch)
tree473488ed8a09fc3cc857fbfa1872013cfeaf8c52
parentfc6cd855e9dd1b89a45f6584b3bd21ddc1f60607 (diff)
parent7c5f62a313d7dd3047ed29f4007c73b53541c482 (diff)
downloadmariadb-git-4df29fef362389f3fe64da4880af7050396baa94.tar.gz
References: lp:1066784 - Merged with MariaDB 5.5.28a
bzr merge -r tag:mariadb-5.5.28a lp:maria/5.5 ...no conflicts
-rw-r--r--VERSION2
-rw-r--r--client/mysqlshow.c3
-rw-r--r--cmake/mysql_version.cmake2
-rw-r--r--extra/perror.c2
-rw-r--r--include/my_base.h3
-rw-r--r--include/mysql.h11
-rw-r--r--include/mysql_com.h3
-rw-r--r--include/violite.h6
-rw-r--r--include/welcome_copyright_notice.h3
-rw-r--r--mysql-test/include/have_innodb.combinations9
-rw-r--r--mysql-test/include/mtr_warnings.sql1
-rw-r--r--mysql-test/r/derived_opt.result70
-rw-r--r--mysql-test/r/group_by.result11
-rw-r--r--mysql-test/r/information_schema.result6
-rw-r--r--mysql-test/r/innodb_ext_key.result20
-rw-r--r--mysql-test/r/limit_rows_examined.result4
-rw-r--r--mysql-test/r/order_by.result76
-rw-r--r--mysql-test/r/partition.result6
-rw-r--r--mysql-test/r/range_vs_index_merge.result147
-rw-r--r--mysql-test/r/range_vs_index_merge_innodb,innodb_plugin.rdiff13
-rw-r--r--mysql-test/r/range_vs_index_merge_innodb.result147
-rw-r--r--mysql-test/r/subselect.result114
-rw-r--r--mysql-test/r/subselect2.result99
-rw-r--r--mysql-test/r/subselect3.result2
-rw-r--r--mysql-test/r/subselect3_jcl6.result2
-rw-r--r--mysql-test/r/subselect_no_mat.result114
-rw-r--r--mysql-test/r/subselect_no_opts.result114
-rw-r--r--mysql-test/r/subselect_no_scache.result114
-rw-r--r--mysql-test/r/subselect_no_semijoin.result114
-rw-r--r--mysql-test/r/user_var.result32
-rw-r--r--mysql-test/suite/federated/federatedx.test2
-rw-r--r--mysql-test/suite/heap/heap_hash.result20
-rw-r--r--mysql-test/suite/heap/heap_hash.test17
-rw-r--r--mysql-test/suite/innodb/t/innodb_information_schema_buffer.test5
-rw-r--r--mysql-test/suite/plugins/r/audit_null.result29
-rw-r--r--mysql-test/suite/plugins/t/audit_null.test30
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_buffer_pool_populate_basic.result1
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_buffer_pool_populate_basic.test1
-rw-r--r--mysql-test/suite/vcol/inc/vcol_trigger_sp.inc41
-rw-r--r--mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result40
-rw-r--r--mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result40
-rw-r--r--mysql-test/t/derived_opt.test60
-rw-r--r--mysql-test/t/group_by.test14
-rw-r--r--mysql-test/t/information_schema.test11
-rw-r--r--mysql-test/t/information_schema_all_engines.test2
-rw-r--r--mysql-test/t/innodb_ext_key.test21
-rw-r--r--mysql-test/t/mysqlshow.test2
-rw-r--r--mysql-test/t/order_by.test65
-rw-r--r--mysql-test/t/partition.test8
-rwxr-xr-xmysql-test/t/range_vs_index_merge.test58
-rw-r--r--mysql-test/t/subselect.test76
-rw-r--r--mysql-test/t/subselect2.test96
-rw-r--r--mysql-test/t/user_var.test28
-rw-r--r--mysys/mf_pack.c15
-rw-r--r--mysys/my_context.c23
-rw-r--r--plugin/audit_null/audit_null.c2
-rw-r--r--plugin/feedback/CMakeLists.txt12
-rw-r--r--plugin/feedback/url_http.cc36
-rw-r--r--scripts/mysql_config.sh11
-rwxr-xr-xscripts/mysql_secure_installation.pl.in2
-rw-r--r--scripts/mysql_secure_installation.sh2
-rwxr-xr-xsql-bench/test-table-elimination.sh9
-rw-r--r--sql/ha_partition.cc4
-rw-r--r--sql/item_func.h9
-rw-r--r--sql/item_subselect.cc19
-rw-r--r--sql/item_subselect.h5
-rw-r--r--sql/item_sum.cc6
-rw-r--r--sql/log.cc54
-rw-r--r--sql/log.h2
-rw-r--r--sql/opt_range.cc7
-rw-r--r--sql/scheduler.cc24
-rw-r--r--sql/scheduler.h2
-rw-r--r--sql/sp_head.cc3
-rw-r--r--sql/sql_acl.cc20
-rw-r--r--sql/sql_audit.h18
-rw-r--r--sql/sql_base.cc17
-rw-r--r--sql/sql_base.h3
-rw-r--r--sql/sql_delete.cc4
-rw-r--r--sql/sql_parse.cc4
-rw-r--r--sql/sql_prepare.cc14
-rw-r--r--sql/sql_select.cc317
-rw-r--r--sql/sql_select.h10
-rw-r--r--sql/sql_show.cc5
-rw-r--r--sql/sql_table.cc2
-rw-r--r--sql/sql_update.cc8
-rw-r--r--sql/table.cc26
-rw-r--r--sql/table.h7
-rw-r--r--sql/threadpool_common.cc2
-rw-r--r--sql/threadpool_unix.cc18
-rw-r--r--sql/threadpool_win.cc16
-rw-r--r--storage/heap/CMakeLists.txt10
-rw-r--r--storage/heap/hp_rkey.c2
-rw-r--r--storage/innobase/btr/btr0btr.c26
-rw-r--r--storage/innobase/page/page0cur.c1
-rw-r--r--storage/innobase/page/page0page.c10
-rw-r--r--storage/maria/CMakeLists.txt6
-rw-r--r--storage/maria/ha_maria.cc7
-rw-r--r--storage/maria/ma_blockrec.c8
-rw-r--r--storage/maria/ma_rrnd.c4
-rw-r--r--storage/maria/ma_test2.c65
-rw-r--r--storage/pbxt/mysql-test/main/r/rpl_mmap.result16
-rw-r--r--storage/pbxt/mysql-test/main/t/rpl_mmap.test21
-rw-r--r--storage/perfschema/CMakeLists.txt2
-rw-r--r--storage/xtradb/btr/btr0btr.c21
-rw-r--r--storage/xtradb/btr/btr0cur.c39
-rw-r--r--storage/xtradb/btr/btr0pcur.c67
-rw-r--r--storage/xtradb/buf/buf0buf.c22
-rw-r--r--storage/xtradb/buf/buf0lru.c2
-rw-r--r--storage/xtradb/buf/buf0rea.c4
-rw-r--r--storage/xtradb/handler/ha_innodb.cc341
-rw-r--r--storage/xtradb/handler/i_s.cc1836
-rw-r--r--storage/xtradb/handler/i_s.h3
-rw-r--r--storage/xtradb/ibuf/ibuf0ibuf.c17
-rw-r--r--storage/xtradb/include/buf0buf.h34
-rw-r--r--storage/xtradb/include/buf0buf.ic19
-rw-r--r--storage/xtradb/include/fil0fil.h2
-rw-r--r--storage/xtradb/include/ha_prototypes.h2
-rw-r--r--storage/xtradb/include/log0log.h3
-rw-r--r--storage/xtradb/include/os0proc.h3
-rw-r--r--storage/xtradb/include/srv0srv.h1
-rw-r--r--storage/xtradb/include/trx0sys.h16
-rw-r--r--storage/xtradb/include/univ.i2
-rw-r--r--storage/xtradb/os/os0file.c2
-rw-r--r--storage/xtradb/os/os0proc.c58
-rw-r--r--storage/xtradb/page/page0page.c21
-rw-r--r--storage/xtradb/row/row0ins.c9
-rw-r--r--storage/xtradb/row/row0merge.c16
-rw-r--r--storage/xtradb/srv/srv0srv.c2
-rw-r--r--storage/xtradb/srv/srv0start.c3
-rw-r--r--storage/xtradb/trx/trx0sys.c132
-rw-r--r--storage/xtradb/trx/trx0trx.c21
-rw-r--r--strings/decimal.c2
-rw-r--r--tests/mysql_client_test.c17
133 files changed, 4964 insertions, 586 deletions
diff --git a/VERSION b/VERSION
index 4ed7f1471fd..70bdfecc0c6 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
MYSQL_VERSION_MAJOR=5
MYSQL_VERSION_MINOR=5
MYSQL_VERSION_PATCH=28
-MYSQL_VERSION_EXTRA=
+MYSQL_VERSION_EXTRA=a
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index 5cf2be1160c..323c4282ff4 100644
--- a/client/mysqlshow.c
+++ b/client/mysqlshow.c
@@ -1,5 +1,6 @@
/*
- Copyright (c) 2000, 2011, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2012, Monty Program Ab
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
diff --git a/cmake/mysql_version.cmake b/cmake/mysql_version.cmake
index e6b9d3e7edf..33aa33c9e5b 100644
--- a/cmake/mysql_version.cmake
+++ b/cmake/mysql_version.cmake
@@ -65,7 +65,7 @@ MACRO(GET_MYSQL_VERSION)
MARK_AS_ADVANCED(VERSION MYSQL_VERSION_ID MYSQL_BASE_VERSION)
SET(CPACK_PACKAGE_VERSION_MAJOR ${MAJOR_VERSION})
SET(CPACK_PACKAGE_VERSION_MINOR ${MINOR_VERSION})
- SET(CPACK_PACKAGE_VERSION_PATCH ${PATCH_VERSION})
+ SET(CPACK_PACKAGE_VERSION_PATCH ${PATCH_VERSION}${EXTRA_VERSION})
ENDMACRO()
# Get mysql version and other interesting variables
diff --git a/extra/perror.c b/extra/perror.c
index fbea21f9091..de8a9b8a0c3 100644
--- a/extra/perror.c
+++ b/extra/perror.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2011, Oracle and/or its affiliates
+ Copyright (c) 2000, 2012, Oracle and/or its affiliates.
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
diff --git a/include/my_base.h b/include/my_base.h
index 905e4535360..e072bb7e2b1 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -282,6 +282,9 @@ enum ha_base_keytype {
#define HA_USES_BLOCK_SIZE ((uint) 32768)
#define HA_SORT_ALLOWS_SAME 512 /* Intern bit when sorting records */
+/* This flag can be used only in KEY::ext_key_flags */
+#define HA_EXT_NOSAME 131072
+
/* These flags can be added to key-seg-flag */
#define HA_SPACE_PACK 1 /* Pack space in key-seg */
diff --git a/include/mysql.h b/include/mysql.h
index 1fc164f62b2..fa62026b44a 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -47,9 +47,6 @@ extern "C" {
#ifndef MYSQL_ABI_CHECK
#include <sys/types.h>
#endif
-#ifdef __LCC__
-#include <winsock2.h> /* For windows */
-#endif
typedef char my_bool;
#if (defined(_WIN32) || defined(_WIN64)) && !defined(__WIN__)
#define __WIN__
@@ -61,11 +58,13 @@ typedef char my_bool;
#endif
#ifndef my_socket_defined
-#ifdef __WIN__
-#define my_socket SOCKET
+#if defined (_WIN64)
+#define my_socket unsigned long long
+#elif defined (_WIN32)
+#define my_socket unsigned int
#else
typedef int my_socket;
-#endif /* __WIN__ */
+#endif /* _WIN64 */
#endif /* my_socket_defined */
#endif /* _global_h */
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 0988d20f97f..6e8a2b23de0 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -57,9 +57,6 @@
#define LOCAL_HOST "localhost"
#define LOCAL_HOST_NAMEDPIPE "."
-#ifdef _WIN32
-#include <ws2tcpip.h>
-#endif
#if defined(__WIN__) && !defined( _CUSTOMCONFIG_)
#define MYSQL_NAMEDPIPE "MySQL"
diff --git a/include/violite.h b/include/violite.h
index 18df848d8b8..14c99e8d8fe 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -177,6 +177,12 @@ void vio_end(void);
#endif /* !defined(DONT_MAP_VIO) */
#ifdef _WIN32
+
+/* shutdown(2) flags */
+#ifndef SHUT_RD
+#define SHUT_RD SD_BOTH
+#endif
+
/*
Set thread id for io cancellation (required on Windows XP only,
and should to be removed if XP is no more supported)
diff --git a/include/welcome_copyright_notice.h b/include/welcome_copyright_notice.h
index adb7b9f9c20..01139677b7d 100644
--- a/include/welcome_copyright_notice.h
+++ b/include/welcome_copyright_notice.h
@@ -1,4 +1,5 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates.
+/* Copyright (c) 2011, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2011, 2012, Monty Program Ab
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
diff --git a/mysql-test/include/have_innodb.combinations b/mysql-test/include/have_innodb.combinations
index 117bf2216a1..93c39fd1a98 100644
--- a/mysql-test/include/have_innodb.combinations
+++ b/mysql-test/include/have_innodb.combinations
@@ -4,6 +4,9 @@ plugin-load=$HA_INNODB_SO
innodb
innodb-cmpmem
innodb-trx
+innodb-buffer-pool-stats
+innodb-buffer-page
+innodb-buffer-page-lru
[xtradb_plugin]
ignore-builtin-innodb
@@ -11,8 +14,14 @@ plugin-load=$HA_XTRADB_SO
innodb
innodb-cmpmem
innodb-trx
+innodb-buffer-pool-stats
+innodb-buffer-page
+innodb-buffer-page-lru
[xtradb]
innodb
innodb-cmpmem
innodb-trx
+innodb-buffer-pool-stats
+innodb-buffer-page
+innodb-buffer-page-lru
diff --git a/mysql-test/include/mtr_warnings.sql b/mysql-test/include/mtr_warnings.sql
index a690ca4b334..37a17a8133e 100644
--- a/mysql-test/include/mtr_warnings.sql
+++ b/mysql-test/include/mtr_warnings.sql
@@ -97,7 +97,6 @@ INSERT INTO global_suppressions VALUES
("Failed to open log"),
("Failed to open the existing master info file"),
("Forcing shutdown of [0-9]* plugins"),
- ("Forcing close of thread"),
/*
Due to timing issues, it might be that this warning
diff --git a/mysql-test/r/derived_opt.result b/mysql-test/r/derived_opt.result
index 11216a32e61..22e2ab8d676 100644
--- a/mysql-test/r/derived_opt.result
+++ b/mysql-test/r/derived_opt.result
@@ -282,4 +282,74 @@ CREATE TABLE t1 ( i INT );
INSERT INTO t1 VALUES ( (SELECT 1 FROM ( SELECT * FROM t1 ) as a) );
drop table t1;
set optimizer_switch=@save_optimizer_switch;
+#
+# MDEV-3801 Reproducible sub select join crash on 5.3.8 and 5.3.9
+#
+CREATE TABLE t1 (
+pk int(10) unsigned NOT NULL AUTO_INCREMENT,
+a char(2) DEFAULT NULL,
+PRIMARY KEY (pk),
+KEY a (a)
+) ENGINE=MyISAM;
+INSERT INTO t1 (a)
+VALUES (NULL),(NULL),(NULL),('AB'),(NULL),('CD'),(NULL),(NULL);
+INSERT INTO t1 SELECT NULL, a1.a FROM t1 a1, t1 a2, t1 a3, t1 a4, t1 a5;
+CREATE TABLE t2 (
+pk int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
+INSERT INTO t2 SELECT NULL FROM t2 a1, t2 a2, t2 a3, t2 a4, t2 a5;
+CREATE TABLE t3 (
+pk int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY
+) ENGINE=MyISAM;
+INSERT INTO t3 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
+INSERT INTO t3 SELECT NULL FROM t3 a1, t3 a2, t3 a3, t3 a4, t3 a5;
+CREATE TABLE t4 (
+a char(2) NOT NULL DEFAULT '',
+PRIMARY KEY (a)
+) ENGINE=MyISAM;
+INSERT INTO t4 VALUES ('CD');
+set @@tmp_table_size=8192;
+EXPLAIN
+SELECT * FROM t3 AS tx JOIN t2 AS ty ON (tx.pk = ty.pk)
+WHERE
+tx.pk IN
+(SELECT *
+FROM (SELECT DISTINCT ta.pk
+FROM t3 AS ta
+JOIN t2 AS tb ON (ta.pk = tb.pk)
+JOIN t1 AS tc ON (tb.pk = tc.pk)
+JOIN t4 AS td ON tc.a = td.a) tu)
+limit 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL #
+1 PRIMARY tx eq_ref PRIMARY PRIMARY 4 tu.pk # Using index
+1 PRIMARY ty eq_ref PRIMARY PRIMARY 4 tu.pk # Using index
+2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL #
+3 DERIVED td system PRIMARY NULL NULL NULL # Using temporary
+3 DERIVED tc ref PRIMARY,a a 3 const #
+3 DERIVED ta eq_ref PRIMARY PRIMARY 4 test.tc.pk # Using index
+3 DERIVED tb eq_ref PRIMARY PRIMARY 4 test.tc.pk # Using index; Distinct
+SELECT * FROM t3 AS tX JOIN t2 AS tY ON (tX.pk = tY.pk)
+WHERE
+tX.pk IN
+(SELECT *
+FROM (SELECT DISTINCT tA.pk
+FROM t3 AS tA
+JOIN t2 AS tB ON (tA.pk = tB.pk)
+JOIN t1 AS tC ON (tB.pk = tC.pk)
+JOIN t4 AS tD ON tC.a = tD.a) tU)
+limit 10;
+pk pk
+6 6
+16 16
+24 24
+32 32
+40 40
+48 48
+56 56
+64 64
+72 72
+80 80
+drop table t1, t2, t3, t4;
set optimizer_switch=@exit_optimizer_switch;
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 222977e5106..9f942747594 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -2119,6 +2119,17 @@ FROM t2
GROUP BY 1;
a
DROP TABLE t1, t2;
+FLUSH STATUS;
+CREATE TABLE t1 (f1 INT, f2 decimal(20,1), f3 blob);
+INSERT INTO t1 values(11,NULL,'blob'),(11,NULL,'blob');
+SELECT f3, MIN(f2) FROM t1 GROUP BY f1 LIMIT 1;
+f3 MIN(f2)
+blob NULL
+DROP TABLE t1;
+the value below *must* be 1
+show status like 'Created_tmp_disk_tables';
+Variable_name Value
+Created_tmp_disk_tables 1
# End of 5.3 tests
#
# Bug#49771: Incorrect MIN (date) when minimum value is 0000-00-00
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
index fcb40dae4ff..9d993e723c2 100644
--- a/mysql-test/r/information_schema.result
+++ b/mysql-test/r/information_schema.result
@@ -1678,6 +1678,12 @@ SELECT length(CAST(b AS CHAR)) FROM ubig;
length(CAST(b AS CHAR))
20
DROP TABLE ubig;
+select 1 from information_schema.tables where table_schema=repeat('a', 2000);
+1
+grant usage on *.* to mysqltest_1@localhost;
+select 1 from information_schema.tables where table_schema=repeat('a', 2000);
+1
+drop user mysqltest_1@localhost;
End of 5.1 tests.
#
# Additional test for WL#3726 "DDL locking for all metadata objects"
diff --git a/mysql-test/r/innodb_ext_key.result b/mysql-test/r/innodb_ext_key.result
index d2fb29a023c..0b7b042a0b2 100644
--- a/mysql-test/r/innodb_ext_key.result
+++ b/mysql-test/r/innodb_ext_key.result
@@ -613,6 +613,26 @@ Handler_read_prev 0
Handler_read_rnd 0
Handler_read_rnd_deleted 0
Handler_read_rnd_next 0
+#
+# Bug mdev-3851: ref access used instead of expected eq_ref access
+# when extended_keys=on
+#
+create table t0 (a int);
+insert into t0 values (1), (2), (3), (4), (5);
+create index i_p_size on part(p_size);
+set optimizer_switch='extended_keys=on';
+explain
+select * from t0, part ignore index (primary)
+where p_partkey=t0.a and p_size=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ALL NULL NULL NULL NULL 5 Using where
+1 SIMPLE part eq_ref i_p_size i_p_size 9 const,dbt3_s001.t0.a 1
+select * from t0, part ignore index (primary)
+where p_partkey=t0.a and p_size=1;
+a p_partkey p_name p_mfgr p_brand p_type p_size p_container p_retailprice p_comment
+2 2 blush rosy metallic lemon navajo Manufacturer#1 Brand#13 LARGE BRUSHED BRASS 1 LG CASE 902 final platelets hang f
+drop table t0;
+drop index i_p_size on part;
DROP DATABASE dbt3_s001;
use test;
#
diff --git a/mysql-test/r/limit_rows_examined.result b/mysql-test/r/limit_rows_examined.result
index f4242f17a14..a51798a5883 100644
--- a/mysql-test/r/limit_rows_examined.result
+++ b/mysql-test/r/limit_rows_examined.result
@@ -318,7 +318,7 @@ LIMIT ROWS EXAMINED 9;
c1
bb
Warnings:
-Warning 1931 Query execution was interrupted. The query examined at least 10 rows, which exceeds LIMIT ROWS EXAMINED (9). The query result may be incomplete.
+Warning 1931 Query execution was interrupted. The query examined at least 12 rows, which exceeds LIMIT ROWS EXAMINED (9). The query result may be incomplete.
Same as above, without subquery cache
set @@optimizer_switch='subquery_cache=off';
select * from t1
@@ -347,7 +347,7 @@ LIMIT ROWS EXAMINED 5;
c1
bb
Warnings:
-Warning 1931 Query execution was interrupted. The query examined at least 6 rows, which exceeds LIMIT ROWS EXAMINED (5). The query result may be incomplete.
+Warning 1931 Query execution was interrupted. The query examined at least 7 rows, which exceeds LIMIT ROWS EXAMINED (5). The query result may be incomplete.
Subqueries with materialization
set @@optimizer_switch='semijoin=off,in_to_exists=off,materialization=on,subquery_cache=on';
explain
diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index 53fed519a15..94e7d5e757a 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -1945,3 +1945,79 @@ f0 f1 f2
set sort_buffer_size= @save_sort_buffer_size;
DROP TABLE t1;
End of 5.3 tests
+#
+# Bug 54599: discarded fast range scan for query with
+# GROUP BY + ORDER BY + LIMIT
+#
+create table t0 (a int);
+insert into t0 values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);
+create table t1 (a int, b int, index idx1(a,b), index idx2(b,a));
+insert into t1
+select 1000*s4.a+100*s3.a+10*s2.a + s1.a, 1000*s4.a+100*s3.a+10*s2.a+s1.a
+from t0 s1, t0 s2, t0 s3, t0 s4;
+analyze table t1;
+explain
+select b, count(*) num_cnt from t1
+where a > 9750 group by b order by num_cnt;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx1 idx1 5 NULL 502 Using where; Using index; Using temporary; Using filesort
+flush status;
+select b, count(*) num_cnt from t1
+where a > 9750 group by b order by num_cnt;
+show status like '%Handler_read%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 250
+Handler_read_last 0
+Handler_read_next 249
+Handler_read_prev 0
+Handler_read_rnd 249
+Handler_read_rnd_deleted 0
+Handler_read_rnd_next 250
+explain
+select b, count(*) num_cnt from t1
+where a > 9750 group by b order by num_cnt limit 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx1 idx1 5 NULL 502 Using where; Using index; Using temporary; Using filesort
+flush status;
+select b, count(*) num_cnt from t1
+where a > 9750 group by b order by num_cnt limit 1;
+show status like '%Handler_read%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 250
+Handler_read_last 0
+Handler_read_next 249
+Handler_read_prev 0
+Handler_read_rnd 1
+Handler_read_rnd_deleted 0
+Handler_read_rnd_next 250
+drop table t0, t1;
+#
+# LP bug #1002508 : the number of expected rows to be examined is off
+# (bug #13528826)
+#
+CREATE TABLE t1(a int PRIMARY KEY, b int) ENGINE=myisam;
+INSERT INTO t1 VALUES
+(5, 10), (2, 70), (7, 80), (6, 20), (1, 50), (9, 40), (8, 30), (3, 60);
+CREATE TABLE t2 (p int, a int, INDEX i_a(a)) ENGINE=myisam;
+INSERT INTO t2 VALUES
+(103, 7), (109, 3), (102, 3), (108, 1), (106, 3),
+(107, 7), (105, 1), (101, 3), (100, 7), (110, 1);
+EXPLAIN
+SELECT t1.a FROM t1 LEFT JOIN t2 ON t1.a=t2.a ORDER BY t1.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL PRIMARY 4 NULL 8 Using index
+1 SIMPLE t2 ref i_a i_a 5 test.t1.a 2 Using index
+EXPLAIN
+SELECT t1.a FROM t1 LEFT JOIN t2 ON t1.a=t2.a ORDER BY t1.a LIMIT 8;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL PRIMARY 4 NULL 4 Using index
+1 SIMPLE t2 ref i_a i_a 5 test.t1.a 2 Using index
+EXPLAIN
+SELECT t1.a FROM t1 LEFT JOIN t2 ON t1.a=t2.a ORDER BY t1.a LIMIT 100;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL PRIMARY 4 NULL 8 Using index
+1 SIMPLE t2 ref i_a i_a 5 test.t1.a 2 Using index
+DROP TABLE t1,t2;
+End of 5.5 tests
diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result
index 40586b8d54b..86425825601 100644
--- a/mysql-test/r/partition.result
+++ b/mysql-test/r/partition.result
@@ -2394,6 +2394,12 @@ HAVING b > geomfromtext("")
);
1
DROP TABLE t1;
+
+MDEV-612 Valgrind error in ha_maria::check_if_incompatible_data
+
+CREATE TABLE t1 (a INT, b INT, KEY(a)) ENGINE=Aria PARTITION BY KEY(a) PARTITIONS 2;
+ALTER TABLE t1 ADD KEY (b);
+drop table t1;
End of 5.1 tests
#
# BUG#55385: UPDATE statement throws an error, but still updates
diff --git a/mysql-test/r/range_vs_index_merge.result b/mysql-test/r/range_vs_index_merge.result
index faaa6d2429e..cc8a345a2ff 100644
--- a/mysql-test/r/range_vs_index_merge.result
+++ b/mysql-test/r/range_vs_index_merge.result
@@ -1221,6 +1221,153 @@ Lugansk UKR 469000
Seattle USA 563374
Caracas VEN 1975294
set optimizer_switch=@save_optimizer_switch;
+#
+# Bug mdev-585: range vs index-merge with ORDER BY ... LIMIT n
+# (LP bug #637962)
+#
+DROP INDEX CountryPopulation ON City;
+DROP INDEX CountryName ON City;
+DROP INDEX CityName on City;
+CREATE INDEX Name ON City(Name);
+CREATE INDEX Population ON City(Population);
+EXPLAIN
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE City index_merge Country,Name,Population Name,Country 35,3 NULL # Using sort_union(Name,Country); Using where
+FLUSH STATUS;
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000);
+ID Name Country Population
+384 Cabo Frio BRA 119503
+387 Camaragibe BRA 118968
+403 Catanduva BRA 107761
+412 Cachoeirinha BRA 103240
+508 Watford GBR 113080
+509 Ipswich GBR 114000
+510 Slough GBR 112000
+511 Exeter GBR 111000
+512 Cheltenham GBR 106000
+513 Gloucester GBR 107000
+514 Saint Helens GBR 106293
+515 Sutton Coldfield GBR 106001
+516 York GBR 104425
+517 Oldham GBR 103931
+518 Basildon GBR 100924
+519 Worthing GBR 100000
+635 Mallawi EGY 119283
+636 Bilbays EGY 113608
+637 Mit Ghamr EGY 101801
+638 al-Arish EGY 100447
+701 Tarragona ESP 113016
+702 Lleida (Lérida) ESP 112207
+703 Jaén ESP 109247
+704 Ourense (Orense) ESP 109120
+705 Mataró ESP 104095
+706 Algeciras ESP 103106
+707 Marbella ESP 101144
+759 Gonder ETH 112249
+869 Cabuyao PHL 106630
+870 Calapan PHL 105910
+873 Cauayan PHL 103952
+903 Serekunda GMB 102600
+909 Sohumi GEO 111700
+913 Tema GHA 109975
+914 Sekondi-Takoradi GHA 103653
+924 Villa Nueva GTM 101295
+1844 Cape Breton CAN 114733
+1847 Cambridge CAN 109186
+2406 Herakleion GRC 116178
+2407 Kallithea GRC 114233
+2408 Larisa GRC 113090
+2908 Cajamarca PER 108009
+3002 Besançon FRA 117733
+3003 Caen FRA 113987
+3004 Orléans FRA 113126
+3005 Mulhouse FRA 110359
+3006 Rouen FRA 106592
+3007 Boulogne-Billancourt FRA 106367
+3008 Perpignan FRA 105115
+3009 Nancy FRA 103605
+3411 Ceyhan TUR 102412
+3567 Carúpano VEN 119639
+3568 Catia La Mar VEN 117012
+3571 Calabozo VEN 107146
+3786 Cam Ranh VNM 114041
+3792 Tartu EST 101246
+4002 Carrollton USA 109576
+4027 Cape Coral USA 102286
+4032 Cambridge USA 101355
+SHOW STATUS LIKE 'Handler_read_%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 2
+Handler_read_last 0
+Handler_read_next 385
+Handler_read_prev 0
+Handler_read_rnd 377
+Handler_read_rnd_deleted 0
+Handler_read_rnd_next 0
+EXPLAIN
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE City range Country,Name,Population Population 4 NULL # Using where
+FLUSH STATUS;
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+ID Name Country Population
+519 Worthing GBR 100000
+638 al-Arish EGY 100447
+518 Basildon GBR 100924
+707 Marbella ESP 101144
+3792 Tartu EST 101246
+SHOW STATUS LIKE 'Handler_read_%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 1
+Handler_read_last 0
+Handler_read_next 59
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_deleted 0
+Handler_read_rnd_next 0
+set optimizer_switch='index_merge=off';
+EXPLAIN
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE City range Country,Name,Population Population 4 NULL # Using index condition; Using where
+FLUSH STATUS;
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+ID Name Country Population
+519 Worthing GBR 100000
+638 al-Arish EGY 100447
+518 Basildon GBR 100924
+707 Marbella ESP 101144
+3792 Tartu EST 101246
+SHOW STATUS LIKE 'Handler_read_%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 1
+Handler_read_last 0
+Handler_read_next 59
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_deleted 0
+Handler_read_rnd_next 0
+set optimizer_switch=@save_optimizer_switch;
DROP DATABASE world;
use test;
CREATE TABLE t1 (
diff --git a/mysql-test/r/range_vs_index_merge_innodb,innodb_plugin.rdiff b/mysql-test/r/range_vs_index_merge_innodb,innodb_plugin.rdiff
index 5913434caae..ecae2c809c1 100644
--- a/mysql-test/r/range_vs_index_merge_innodb,innodb_plugin.rdiff
+++ b/mysql-test/r/range_vs_index_merge_innodb,innodb_plugin.rdiff
@@ -1,5 +1,5 @@
---- r/range_vs_index_merge_innodb.result 2012-03-24 17:12:02.124422000 +0100
-+++ r/range_vs_index_merge_innodb,innodb_plugin.reject 2012-03-24 18:00:13.647902620 +0100
+--- ./r/range_vs_index_merge_innodb.result 2012-11-21 19:35:14.000000000 +0100
++++ ./r/range_vs_index_merge_innodb,innodb_plugin.reject 2012-11-21 20:56:00.000000000 +0100
@@ -50,14 +50,14 @@
WHERE (Population >= 100000 OR Name LIKE 'P%') AND Country='CAN' OR
(Population < 100000 OR Name Like 'T%') AND Country='ARG';
@@ -269,3 +269,12 @@
SELECT Name, Country, Population FROM City WHERE
(Name='Manila' AND Country='PHL') OR
(Name='Addis Abeba' AND Country='ETH') OR
+@@ -1346,7 +1346,7 @@
+ AND (Population >= 100000 AND Population < 120000)
+ ORDER BY Population LIMIT 5;
+ id select_type table type possible_keys key key_len ref rows Extra
+-1 SIMPLE City range Country,Name,Population Population 4 NULL # Using index condition; Using where
++1 SIMPLE City range Country,Name,Population Population 4 NULL # Using where
+ FLUSH STATUS;
+ SELECT * FROM City
+ WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
diff --git a/mysql-test/r/range_vs_index_merge_innodb.result b/mysql-test/r/range_vs_index_merge_innodb.result
index df3a2af0753..67e341192da 100644
--- a/mysql-test/r/range_vs_index_merge_innodb.result
+++ b/mysql-test/r/range_vs_index_merge_innodb.result
@@ -1222,6 +1222,153 @@ Lugansk UKR 469000
Seattle USA 563374
Caracas VEN 1975294
set optimizer_switch=@save_optimizer_switch;
+#
+# Bug mdev-585: range vs index-merge with ORDER BY ... LIMIT n
+# (LP bug #637962)
+#
+DROP INDEX CountryPopulation ON City;
+DROP INDEX CountryName ON City;
+DROP INDEX CityName on City;
+CREATE INDEX Name ON City(Name);
+CREATE INDEX Population ON City(Population);
+EXPLAIN
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE City index_merge Country,Name,Population Name,Country 35,3 NULL # Using sort_union(Name,Country); Using where
+FLUSH STATUS;
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000);
+ID Name Country Population
+384 Cabo Frio BRA 119503
+387 Camaragibe BRA 118968
+403 Catanduva BRA 107761
+412 Cachoeirinha BRA 103240
+508 Watford GBR 113080
+509 Ipswich GBR 114000
+510 Slough GBR 112000
+511 Exeter GBR 111000
+512 Cheltenham GBR 106000
+513 Gloucester GBR 107000
+514 Saint Helens GBR 106293
+515 Sutton Coldfield GBR 106001
+516 York GBR 104425
+517 Oldham GBR 103931
+518 Basildon GBR 100924
+519 Worthing GBR 100000
+635 Mallawi EGY 119283
+636 Bilbays EGY 113608
+637 Mit Ghamr EGY 101801
+638 al-Arish EGY 100447
+701 Tarragona ESP 113016
+702 Lleida (Lérida) ESP 112207
+703 Jaén ESP 109247
+704 Ourense (Orense) ESP 109120
+705 Mataró ESP 104095
+706 Algeciras ESP 103106
+707 Marbella ESP 101144
+759 Gonder ETH 112249
+869 Cabuyao PHL 106630
+870 Calapan PHL 105910
+873 Cauayan PHL 103952
+903 Serekunda GMB 102600
+909 Sohumi GEO 111700
+913 Tema GHA 109975
+914 Sekondi-Takoradi GHA 103653
+924 Villa Nueva GTM 101295
+1844 Cape Breton CAN 114733
+1847 Cambridge CAN 109186
+2406 Herakleion GRC 116178
+2407 Kallithea GRC 114233
+2408 Larisa GRC 113090
+2908 Cajamarca PER 108009
+3002 Besançon FRA 117733
+3003 Caen FRA 113987
+3004 Orléans FRA 113126
+3005 Mulhouse FRA 110359
+3006 Rouen FRA 106592
+3007 Boulogne-Billancourt FRA 106367
+3008 Perpignan FRA 105115
+3009 Nancy FRA 103605
+3411 Ceyhan TUR 102412
+3567 Carúpano VEN 119639
+3568 Catia La Mar VEN 117012
+3571 Calabozo VEN 107146
+3786 Cam Ranh VNM 114041
+3792 Tartu EST 101246
+4002 Carrollton USA 109576
+4027 Cape Coral USA 102286
+4032 Cambridge USA 101355
+SHOW STATUS LIKE 'Handler_read_%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 2
+Handler_read_last 0
+Handler_read_next 385
+Handler_read_prev 0
+Handler_read_rnd 377
+Handler_read_rnd_deleted 0
+Handler_read_rnd_next 0
+EXPLAIN
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE City range Country,Name,Population Population 4 NULL # Using where
+FLUSH STATUS;
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+ID Name Country Population
+519 Worthing GBR 100000
+638 al-Arish EGY 100447
+518 Basildon GBR 100924
+707 Marbella ESP 101144
+3792 Tartu EST 101246
+SHOW STATUS LIKE 'Handler_read_%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 1
+Handler_read_last 0
+Handler_read_next 59
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_deleted 0
+Handler_read_rnd_next 0
+set optimizer_switch='index_merge=off';
+EXPLAIN
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE City range Country,Name,Population Population 4 NULL # Using index condition; Using where
+FLUSH STATUS;
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+ID Name Country Population
+519 Worthing GBR 100000
+638 al-Arish EGY 100447
+518 Basildon GBR 100924
+707 Marbella ESP 101144
+3792 Tartu EST 101246
+SHOW STATUS LIKE 'Handler_read_%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 1
+Handler_read_last 0
+Handler_read_next 59
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_deleted 0
+Handler_read_rnd_next 0
+set optimizer_switch=@save_optimizer_switch;
DROP DATABASE world;
use test;
CREATE TABLE t1 (
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index a4bad836d1f..14347e9b899 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -6060,6 +6060,116 @@ WHERE (col_varchar_nokey, 'x') IN
col_int_nokey
1
DROP TABLE ot,it1,it2;
+#
+# MDEV-746
+# Bug#13651009 WRONG RESULT FROM DERIVED TABLE IF THE SUBQUERY
+# HAS AN EMPTY RESULT
+#
+CREATE TABLE t1 (
+pk int NOT NULL,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+CREATE TABLE t2 (
+pk int NOT NULL AUTO_INCREMENT,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,4,4,'00:00:00','b','b');
+SET @var2:=4, @var3:=8;
+
+Testcase without inner subquery
+EXPLAIN SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+EXPLAIN SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE <derived2> system NULL NULL NULL NULL 0 const row not found
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+
+Testcase with inner subquery; crashed WL#6095
+SET @var3=8;
+EXPLAIN SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+EXPLAIN SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+3 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+DROP TABLE t1,t2;
End of 5.2 tests
#
# BUG#779885: Crash in eliminate_item_equal with materialization=on in
@@ -6860,7 +6970,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
@@ -6894,6 +7004,6 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
diff --git a/mysql-test/r/subselect2.result b/mysql-test/r/subselect2.result
index 7eff7f949a8..4fd303dfd44 100644
--- a/mysql-test/r/subselect2.result
+++ b/mysql-test/r/subselect2.result
@@ -180,6 +180,32 @@ SET optimizer_switch=@tmp_optimizer_switch;
DROP VIEW v1;
DROP TABLE t1,t2,t3;
#
+# MDEV-536: LP:1050806 - different result for a query using subquery
+#
+DROP TABLE IF EXISTS `t1`;
+Warnings:
+Note 1051 Unknown table 't1'
+CREATE TABLE `t1` (
+`node_uid` bigint(20) unsigned DEFAULT NULL,
+`date` datetime DEFAULT NULL,
+`mirror_date` datetime DEFAULT NULL,
+KEY `date` (`date`)
+) ENGINE=MyISAM;
+INSERT INTO `t1` VALUES (2085,'2012-01-01 00:00:00','2013-01-01 00:00:00');
+INSERT INTO `t1` VALUES (2084,'2012-02-01 00:00:00','2013-01-01 00:00:00');
+INSERT INTO `t1` VALUES (2088,'2012-03-01 00:00:00','2013-01-01 00:00:00');
+SELECT * FROM (
+SELECT node_uid, date, mirror_date, @result := 0 AS result
+FROM t1
+WHERE date < '2012-12-12 12:12:12'
+ AND node_uid in (2085, 2084)
+ORDER BY mirror_date ASC
+) AS calculated_result;
+node_uid date mirror_date result
+2085 2012-01-01 00:00:00 2013-01-01 00:00:00 0
+2084 2012-02-01 00:00:00 2013-01-01 00:00:00 0
+DROP TABLE t1;
+#
# MDEV-567: Wrong result from a query with correlated subquery if ICP is allowed
#
CREATE TABLE t1 (a int, b int, INDEX idx(a));
@@ -197,5 +223,76 @@ a b
1 0
1 1
1 3
-DROP TABLE t1, t2, t3;
+set @tmp_mdev567=@@optimizer_switch;
+set optimizer_switch='mrr=off';
+SELECT * FROM t3
+WHERE a = (SELECT COUNT(DISTINCT t2.b) FROM t1, t2
+WHERE t1.a = t2.a AND t2.a BETWEEN 7 AND 9
+AND t3.b = t1.b
+GROUP BY t1.b);
+a b
+1 0
+1 1
+1 3
+DROP TABLE t1,t2,t3;
+set optimizer_switch=@tmp_mdev567;
+#
+# MDEV-614, also MDEV-536, also LP:1050806:
+# different result for a query using subquery between 5.5.25 and 5.5.27
+#
+CREATE TABLE `t1` (
+`node_uid` bigint(20) unsigned DEFAULT NULL,
+`date` datetime DEFAULT NULL,
+`mirror_date` datetime DEFAULT NULL,
+KEY `date` (`date`)
+) ENGINE=MyISAM;
+INSERT INTO `t1` VALUES (2085,'2012-01-01 00:00:00','2013-01-01 00:00:00');
+INSERT INTO `t1` VALUES (2084,'2012-02-01 00:00:00','2013-01-01 00:00:00');
+INSERT INTO `t1` VALUES (2088,'2012-03-01 00:00:00','2013-01-01 00:00:00');
+explain
+SELECT * FROM (
+SELECT node_uid, date, mirror_date, @result := 0 AS result
+FROM t1
+WHERE date < '2012-12-12 12:12:12'
+ AND node_uid in (2085, 2084)
+ORDER BY mirror_date ASC
+) AS calculated_result;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE <derived2> ALL NULL NULL NULL NULL 2
+2 DERIVED t1 range date date 9 NULL 2 Using index condition; Using where; Rowid-ordered scan; Using filesort
+SELECT * FROM (
+SELECT node_uid, date, mirror_date, @result := 0 AS result
+FROM t1
+WHERE date < '2012-12-12 12:12:12'
+ AND node_uid in (2085, 2084)
+ORDER BY mirror_date ASC
+) AS calculated_result;
+node_uid date mirror_date result
+2085 2012-01-01 00:00:00 2013-01-01 00:00:00 0
+2084 2012-02-01 00:00:00 2013-01-01 00:00:00 0
+set @tmp_mdev614=@@optimizer_switch;
+set optimizer_switch='mrr=off';
+explain
+SELECT * FROM (
+SELECT node_uid, date, mirror_date, @result := 0 AS result
+FROM t1
+WHERE date < '2012-12-12 12:12:12'
+ AND node_uid in (2085, 2084)
+ORDER BY mirror_date ASC
+) AS calculated_result;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE <derived2> ALL NULL NULL NULL NULL 2
+2 DERIVED t1 range date date 9 NULL 2 Using index condition; Using where; Using filesort
+SELECT * FROM (
+SELECT node_uid, date, mirror_date, @result := 0 AS result
+FROM t1
+WHERE date < '2012-12-12 12:12:12'
+ AND node_uid in (2085, 2084)
+ORDER BY mirror_date ASC
+) AS calculated_result;
+node_uid date mirror_date result
+2085 2012-01-01 00:00:00 2013-01-01 00:00:00 0
+2084 2012-02-01 00:00:00 2013-01-01 00:00:00 0
+set optimizer_switch=@tmp_mdev614;
+DROP TABLE t1;
set optimizer_switch=@subselect2_test_tmp;
diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result
index b33e7e113f2..049c4d14b1a 100644
--- a/mysql-test/r/subselect3.result
+++ b/mysql-test/r/subselect3.result
@@ -126,7 +126,7 @@ Handler_read_next 0
Handler_read_prev 0
Handler_read_rnd 0
Handler_read_rnd_deleted 0
-Handler_read_rnd_next 50
+Handler_read_rnd_next 41
select 'No key lookups, seq reads: 29= 5 reads from t2 + 4 * 6 reads from t1.' Z;
Z
No key lookups, seq reads: 29= 5 reads from t2 + 4 * 6 reads from t1.
diff --git a/mysql-test/r/subselect3_jcl6.result b/mysql-test/r/subselect3_jcl6.result
index 4660cd60603..815a8985d44 100644
--- a/mysql-test/r/subselect3_jcl6.result
+++ b/mysql-test/r/subselect3_jcl6.result
@@ -136,7 +136,7 @@ Handler_read_next 0
Handler_read_prev 0
Handler_read_rnd 0
Handler_read_rnd_deleted 0
-Handler_read_rnd_next 50
+Handler_read_rnd_next 41
select 'No key lookups, seq reads: 29= 5 reads from t2 + 4 * 6 reads from t1.' Z;
Z
No key lookups, seq reads: 29= 5 reads from t2 + 4 * 6 reads from t1.
diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result
index cb9847a0d99..c307a68f64d 100644
--- a/mysql-test/r/subselect_no_mat.result
+++ b/mysql-test/r/subselect_no_mat.result
@@ -6059,6 +6059,116 @@ WHERE (col_varchar_nokey, 'x') IN
col_int_nokey
1
DROP TABLE ot,it1,it2;
+#
+# MDEV-746
+# Bug#13651009 WRONG RESULT FROM DERIVED TABLE IF THE SUBQUERY
+# HAS AN EMPTY RESULT
+#
+CREATE TABLE t1 (
+pk int NOT NULL,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+CREATE TABLE t2 (
+pk int NOT NULL AUTO_INCREMENT,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,4,4,'00:00:00','b','b');
+SET @var2:=4, @var3:=8;
+
+Testcase without inner subquery
+EXPLAIN SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+EXPLAIN SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE <derived2> system NULL NULL NULL NULL 0 const row not found
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+
+Testcase with inner subquery; crashed WL#6095
+SET @var3=8;
+EXPLAIN SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+EXPLAIN SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+3 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+DROP TABLE t1,t2;
End of 5.2 tests
#
# BUG#779885: Crash in eliminate_item_equal with materialization=on in
@@ -6858,7 +6968,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
@@ -6891,7 +7001,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
set optimizer_switch=default;
diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result
index 63eeb816b38..d1590b0df51 100644
--- a/mysql-test/r/subselect_no_opts.result
+++ b/mysql-test/r/subselect_no_opts.result
@@ -6055,6 +6055,116 @@ WHERE (col_varchar_nokey, 'x') IN
col_int_nokey
1
DROP TABLE ot,it1,it2;
+#
+# MDEV-746
+# Bug#13651009 WRONG RESULT FROM DERIVED TABLE IF THE SUBQUERY
+# HAS AN EMPTY RESULT
+#
+CREATE TABLE t1 (
+pk int NOT NULL,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+CREATE TABLE t2 (
+pk int NOT NULL AUTO_INCREMENT,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,4,4,'00:00:00','b','b');
+SET @var2:=4, @var3:=8;
+
+Testcase without inner subquery
+EXPLAIN SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+EXPLAIN SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE <derived2> system NULL NULL NULL NULL 0 const row not found
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+
+Testcase with inner subquery; crashed WL#6095
+SET @var3=8;
+EXPLAIN SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+EXPLAIN SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+3 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+DROP TABLE t1,t2;
End of 5.2 tests
#
# BUG#779885: Crash in eliminate_item_equal with materialization=on in
@@ -6855,7 +6965,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
@@ -6889,7 +6999,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
set @optimizer_switch_for_subselect_test=null;
diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result
index 6fd21f8d0b0..b6b5572815a 100644
--- a/mysql-test/r/subselect_no_scache.result
+++ b/mysql-test/r/subselect_no_scache.result
@@ -6066,6 +6066,116 @@ WHERE (col_varchar_nokey, 'x') IN
col_int_nokey
1
DROP TABLE ot,it1,it2;
+#
+# MDEV-746
+# Bug#13651009 WRONG RESULT FROM DERIVED TABLE IF THE SUBQUERY
+# HAS AN EMPTY RESULT
+#
+CREATE TABLE t1 (
+pk int NOT NULL,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+CREATE TABLE t2 (
+pk int NOT NULL AUTO_INCREMENT,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,4,4,'00:00:00','b','b');
+SET @var2:=4, @var3:=8;
+
+Testcase without inner subquery
+EXPLAIN SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+EXPLAIN SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE <derived2> system NULL NULL NULL NULL 0 const row not found
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+
+Testcase with inner subquery; crashed WL#6095
+SET @var3=8;
+EXPLAIN SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+EXPLAIN SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+3 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+DROP TABLE t1,t2;
End of 5.2 tests
#
# BUG#779885: Crash in eliminate_item_equal with materialization=on in
@@ -6866,7 +6976,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
@@ -6900,7 +7010,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
set optimizer_switch=default;
diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result
index b924a18ca8f..34cdb17e23e 100644
--- a/mysql-test/r/subselect_no_semijoin.result
+++ b/mysql-test/r/subselect_no_semijoin.result
@@ -6055,6 +6055,116 @@ WHERE (col_varchar_nokey, 'x') IN
col_int_nokey
1
DROP TABLE ot,it1,it2;
+#
+# MDEV-746
+# Bug#13651009 WRONG RESULT FROM DERIVED TABLE IF THE SUBQUERY
+# HAS AN EMPTY RESULT
+#
+CREATE TABLE t1 (
+pk int NOT NULL,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+CREATE TABLE t2 (
+pk int NOT NULL AUTO_INCREMENT,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,4,4,'00:00:00','b','b');
+SET @var2:=4, @var3:=8;
+
+Testcase without inner subquery
+EXPLAIN SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+EXPLAIN SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE <derived2> system NULL NULL NULL NULL 0 const row not found
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+
+Testcase with inner subquery; crashed WL#6095
+SET @var3=8;
+EXPLAIN SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+EXPLAIN SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+3 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+DROP TABLE t1,t2;
End of 5.2 tests
#
# BUG#779885: Crash in eliminate_item_equal with materialization=on in
@@ -6855,7 +6965,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
@@ -6889,7 +6999,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
set @optimizer_switch_for_subselect_test=null;
diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result
index e98dda46061..9c4fd02fcdd 100644
--- a/mysql-test/r/user_var.result
+++ b/mysql-test/r/user_var.result
@@ -498,4 +498,36 @@ DROP TABLE t1;
#
SET @bug12408412=1;
SELECT GROUP_CONCAT(@bug12408412 ORDER BY 1) INTO @bug12408412;
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES (0);
+SELECT DISTINCT POW(COUNT(*), @a:=(SELECT 1 FROM t1 LEFT JOIN t1 AS t2 ON @a))
+AS b FROM t1 GROUP BY a;
+b
+1
+SELECT @a;
+@a
+1
+DROP TABLE t1;
+CREATE TABLE t1(f1 INT, f2 INT);
+INSERT INTO t1 VALUES (1,2),(2,3),(3,1);
+CREATE TABLE t2(a INT);
+INSERT INTO t2 VALUES (1);
+SET @var=NULL;
+SELECT @var:=(SELECT f2 FROM t2 WHERE @var) FROM t1 GROUP BY f1 ORDER BY f2 DESC
+LIMIT 1;
+@var:=(SELECT f2 FROM t2 WHERE @var)
+NULL
+SELECT @var;
+@var
+NULL
+DROP TABLE t1, t2;
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES (0),(1),(3);
+SELECT DISTINCT POW(COUNT(distinct a), @a:=(SELECT 1 FROM t1 LEFT JOIN t1 AS t2 ON @a limit 1)) AS b FROM t1 GROUP BY a;
+b
+1
+SELECT @a;
+@a
+1
+DROP TABLE t1;
End of 5.5 tests
diff --git a/mysql-test/suite/federated/federatedx.test b/mysql-test/suite/federated/federatedx.test
index fd2f363ff90..15fdd47c4da 100644
--- a/mysql-test/suite/federated/federatedx.test
+++ b/mysql-test/suite/federated/federatedx.test
@@ -1999,4 +1999,4 @@ connection slave;
SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT;
connection default;
-source suite/federated/include/federated_cleanup.inc;
+source include/federated_cleanup.inc;
diff --git a/mysql-test/suite/heap/heap_hash.result b/mysql-test/suite/heap/heap_hash.result
index ac62427c81c..55d43588403 100644
--- a/mysql-test/suite/heap/heap_hash.result
+++ b/mysql-test/suite/heap/heap_hash.result
@@ -382,6 +382,26 @@ INSERT INTO t1 VALUES('A ', 'A ');
ERROR 23000: Duplicate entry 'A -A ' for key 'key1'
DROP TABLE t1;
End of 5.0 tests
+#
+# MDEV-568 (AKA LP BUG#1007981, AKA MySQL bug#44771)
+# Wrong result for a hash index look-up if the index is unique and
+# the key is NULL
+#
+CREATE TABLE t1 ( pk INT PRIMARY KEY, val INT, UNIQUE KEY USING HASH(val)) ENGINE=MEMORY;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (2, NULL);
+INSERT INTO t1 VALUES (3, 1);
+INSERT INTO t1 VALUES (4, NULL);
+EXPLAIN SELECT * FROM t1 WHERE val IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref val val 5 const 1 Using where
+SELECT * FROM t1 WHERE val IS NULL;
+pk val
+4 NULL
+2 NULL
+1 NULL
+drop table t1;
+End of 5.2 tests
# bit index in heap tables
create table t1 (a bit(63) not null) engine=heap;
insert into t1 values (869751),(736494),(226312),(802616),(728912);
diff --git a/mysql-test/suite/heap/heap_hash.test b/mysql-test/suite/heap/heap_hash.test
index 80d6ef9c8f2..3fe95e14205 100644
--- a/mysql-test/suite/heap/heap_hash.test
+++ b/mysql-test/suite/heap/heap_hash.test
@@ -285,6 +285,23 @@ DROP TABLE t1;
--echo End of 5.0 tests
+--echo #
+--echo # MDEV-568 (AKA LP BUG#1007981, AKA MySQL bug#44771)
+--echo # Wrong result for a hash index look-up if the index is unique and
+--echo # the key is NULL
+--echo #
+CREATE TABLE t1 ( pk INT PRIMARY KEY, val INT, UNIQUE KEY USING HASH(val)) ENGINE=MEMORY;
+
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (2, NULL);
+INSERT INTO t1 VALUES (3, 1);
+INSERT INTO t1 VALUES (4, NULL);
+EXPLAIN SELECT * FROM t1 WHERE val IS NULL;
+SELECT * FROM t1 WHERE val IS NULL;
+drop table t1;
+
+--echo End of 5.2 tests
+
-- echo # bit index in heap tables
create table t1 (a bit(63) not null) engine=heap;
diff --git a/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test b/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test
index b9c6aecd177..751a2bd6b5e 100644
--- a/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test
+++ b/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test
@@ -3,11 +3,6 @@
-- source include/have_innodb.inc
-if (`select plugin_auth_version <= "1.1.8-29.0" from information_schema.plugins where plugin_name='innodb'`)
-{
- --skip Not fixed in XtraDB 1.1.8-29.0 or earlier
-}
-
-- disable_result_log
SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS;
diff --git a/mysql-test/suite/plugins/r/audit_null.result b/mysql-test/suite/plugins/r/audit_null.result
new file mode 100644
index 00000000000..4cf648510e6
--- /dev/null
+++ b/mysql-test/suite/plugins/r/audit_null.result
@@ -0,0 +1,29 @@
+set @old_global_general_log=@@global.general_log;
+set global general_log=OFF;
+install plugin audit_null soname 'adt_null';
+select 1;
+1
+1
+select foobar;
+ERROR 42S22: Unknown column 'foobar' in 'field list'
+show status like 'audit_null%';
+Variable_name Value
+Audit_null_called 9
+Audit_null_general_error 1
+Audit_null_general_log 3
+Audit_null_general_result 2
+create procedure au1(x char(16)) select concat("test1", x);
+call au1("-12");
+concat("test1", x)
+test1-12
+show status like 'audit_null%';
+Variable_name Value
+Audit_null_called 19
+Audit_null_general_error 1
+Audit_null_general_log 7
+Audit_null_general_result 5
+uninstall plugin audit_null;
+Warnings:
+Warning 1620 Plugin is busy and will be uninstalled on shutdown
+drop procedure au1;
+set global general_log=@old_global_general_log;
diff --git a/mysql-test/suite/plugins/t/audit_null.test b/mysql-test/suite/plugins/t/audit_null.test
new file mode 100644
index 00000000000..428fd0c276e
--- /dev/null
+++ b/mysql-test/suite/plugins/t/audit_null.test
@@ -0,0 +1,30 @@
+
+--source include/not_embedded.inc
+
+if (!$ADT_NULL_SO) {
+ skip No NULL_AUDIT plugin;
+}
+
+set @old_global_general_log=@@global.general_log;
+set global general_log=OFF;
+
+--disable_ps_protocol
+install plugin audit_null soname 'adt_null';
+
+select 1;
+--error 1054
+select foobar;
+
+show status like 'audit_null%';
+
+create procedure au1(x char(16)) select concat("test1", x);
+call au1("-12");
+
+show status like 'audit_null%';
+
+uninstall plugin audit_null;
+--enable_ps_protocol
+
+drop procedure au1;
+set global general_log=@old_global_general_log;
+
diff --git a/mysql-test/suite/sys_vars/r/innodb_buffer_pool_populate_basic.result b/mysql-test/suite/sys_vars/r/innodb_buffer_pool_populate_basic.result
new file mode 100644
index 00000000000..d9d067c2cf9
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/innodb_buffer_pool_populate_basic.result
@@ -0,0 +1 @@
+XtraDB extension
diff --git a/mysql-test/suite/sys_vars/t/innodb_buffer_pool_populate_basic.test b/mysql-test/suite/sys_vars/t/innodb_buffer_pool_populate_basic.test
new file mode 100644
index 00000000000..00aa476e8d2
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/innodb_buffer_pool_populate_basic.test
@@ -0,0 +1 @@
+--echo XtraDB extension
diff --git a/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc b/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc
index ddf13fef6a1..eb7e6ad32b9 100644
--- a/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc
+++ b/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc
@@ -108,3 +108,44 @@ select * from t1;
drop table t1,t2;
drop procedure p1;
+
+--echo #
+--echo # Bug mdev-3845: values of virtual columns are not computed for triggers
+--echo #
+
+CREATE TABLE t1 (
+ a INTEGER UNSIGNED NULL DEFAULT NULL,
+ b INTEGER UNSIGNED GENERATED ALWAYS AS (a) VIRTUAL
+);
+
+CREATE TABLE t2 (c INTEGER UNSIGNED NOT NULL);
+
+DELIMITER |;
+
+CREATE TRIGGER t1_ins_aft
+ AFTER INSERT
+ ON t1
+ FOR EACH ROW
+BEGIN
+ INSERT INTO t2 (c) VALUES (NEW.b);
+END |
+
+CREATE TRIGGER t1_del_bef
+ BEFORE DELETE
+ ON t1
+ FOR EACH ROW
+BEGIN
+ INSERT INTO t2 (c) VALUES (OLD.b);
+END |
+
+DELIMITER ;|
+
+INSERT INTO t1 (a) VALUES (1), (2), (3);
+SELECT * FROM t2;
+DELETE FROM t1;
+SELECT * FROM t2;
+
+DROP TRIGGER t1_ins_aft;
+DROP TRIGGER t1_del_bef;
+DROP TABLE t1,t2;
+
diff --git a/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result b/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result
index e903bc4eafd..1d78bbf50e4 100644
--- a/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result
+++ b/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result
@@ -85,3 +85,43 @@ a b c
300 30 30
drop table t1,t2;
drop procedure p1;
+#
+# Bug mdev-3845: values of virtual columns are not computed for triggers
+#
+CREATE TABLE t1 (
+a INTEGER UNSIGNED NULL DEFAULT NULL,
+b INTEGER UNSIGNED GENERATED ALWAYS AS (a) VIRTUAL
+);
+CREATE TABLE t2 (c INTEGER UNSIGNED NOT NULL);
+CREATE TRIGGER t1_ins_aft
+AFTER INSERT
+ON t1
+FOR EACH ROW
+BEGIN
+INSERT INTO t2 (c) VALUES (NEW.b);
+END |
+CREATE TRIGGER t1_del_bef
+BEFORE DELETE
+ON t1
+FOR EACH ROW
+BEGIN
+INSERT INTO t2 (c) VALUES (OLD.b);
+END |
+INSERT INTO t1 (a) VALUES (1), (2), (3);
+SELECT * FROM t2;
+c
+1
+2
+3
+DELETE FROM t1;
+SELECT * FROM t2;
+c
+1
+2
+3
+1
+2
+3
+DROP TRIGGER t1_ins_aft;
+DROP TRIGGER t1_del_bef;
+DROP TABLE t1,t2;
diff --git a/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result b/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result
index c2a66d656b5..77efa8fe6b9 100644
--- a/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result
+++ b/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result
@@ -85,3 +85,43 @@ a b c
300 30 30
drop table t1,t2;
drop procedure p1;
+#
+# Bug mdev-3845: values of virtual columns are not computed for triggers
+#
+CREATE TABLE t1 (
+a INTEGER UNSIGNED NULL DEFAULT NULL,
+b INTEGER UNSIGNED GENERATED ALWAYS AS (a) VIRTUAL
+);
+CREATE TABLE t2 (c INTEGER UNSIGNED NOT NULL);
+CREATE TRIGGER t1_ins_aft
+AFTER INSERT
+ON t1
+FOR EACH ROW
+BEGIN
+INSERT INTO t2 (c) VALUES (NEW.b);
+END |
+CREATE TRIGGER t1_del_bef
+BEFORE DELETE
+ON t1
+FOR EACH ROW
+BEGIN
+INSERT INTO t2 (c) VALUES (OLD.b);
+END |
+INSERT INTO t1 (a) VALUES (1), (2), (3);
+SELECT * FROM t2;
+c
+1
+2
+3
+DELETE FROM t1;
+SELECT * FROM t2;
+c
+1
+2
+3
+1
+2
+3
+DROP TRIGGER t1_ins_aft;
+DROP TRIGGER t1_del_bef;
+DROP TABLE t1,t2;
diff --git a/mysql-test/t/derived_opt.test b/mysql-test/t/derived_opt.test
index c2f831036e1..b01c479111b 100644
--- a/mysql-test/t/derived_opt.test
+++ b/mysql-test/t/derived_opt.test
@@ -212,5 +212,65 @@ INSERT INTO t1 VALUES ( (SELECT 1 FROM ( SELECT * FROM t1 ) as a) );
drop table t1;
set optimizer_switch=@save_optimizer_switch;
+--echo #
+--echo # MDEV-3801 Reproducible sub select join crash on 5.3.8 and 5.3.9
+--echo #
+
+CREATE TABLE t1 (
+ pk int(10) unsigned NOT NULL AUTO_INCREMENT,
+ a char(2) DEFAULT NULL,
+ PRIMARY KEY (pk),
+ KEY a (a)
+) ENGINE=MyISAM;
+INSERT INTO t1 (a)
+VALUES (NULL),(NULL),(NULL),('AB'),(NULL),('CD'),(NULL),(NULL);
+INSERT INTO t1 SELECT NULL, a1.a FROM t1 a1, t1 a2, t1 a3, t1 a4, t1 a5;
+
+CREATE TABLE t2 (
+ pk int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
+INSERT INTO t2 SELECT NULL FROM t2 a1, t2 a2, t2 a3, t2 a4, t2 a5;
+
+CREATE TABLE t3 (
+ pk int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY
+) ENGINE=MyISAM;
+INSERT INTO t3 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
+INSERT INTO t3 SELECT NULL FROM t3 a1, t3 a2, t3 a3, t3 a4, t3 a5;
+
+CREATE TABLE t4 (
+ a char(2) NOT NULL DEFAULT '',
+ PRIMARY KEY (a)
+) ENGINE=MyISAM;
+INSERT INTO t4 VALUES ('CD');
+
+set @@tmp_table_size=8192;
+
+--replace_column 9 #
+EXPLAIN
+SELECT * FROM t3 AS tx JOIN t2 AS ty ON (tx.pk = ty.pk)
+WHERE
+ tx.pk IN
+ (SELECT *
+ FROM (SELECT DISTINCT ta.pk
+ FROM t3 AS ta
+ JOIN t2 AS tb ON (ta.pk = tb.pk)
+ JOIN t1 AS tc ON (tb.pk = tc.pk)
+ JOIN t4 AS td ON tc.a = td.a) tu)
+limit 10;
+
+SELECT * FROM t3 AS tX JOIN t2 AS tY ON (tX.pk = tY.pk)
+WHERE
+ tX.pk IN
+ (SELECT *
+ FROM (SELECT DISTINCT tA.pk
+ FROM t3 AS tA
+ JOIN t2 AS tB ON (tA.pk = tB.pk)
+ JOIN t1 AS tC ON (tB.pk = tC.pk)
+ JOIN t4 AS tD ON tC.a = tD.a) tU)
+limit 10;
+
+drop table t1, t2, t3, t4;
+
# The following command must be the last one the file
set optimizer_switch=@exit_optimizer_switch;
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index 1226683ba03..3af531418c5 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -1469,6 +1469,20 @@ WHERE a = (
GROUP BY 1;
DROP TABLE t1, t2;
+#
+# MDEV-736 LP:1004615 - Unexpected warnings "Encountered illegal value '' when converting to DECIMAL" on a query with aggregate functions and GROUP BY
+#
+
+FLUSH STATUS; # this test case *must* use Aria temp tables
+
+CREATE TABLE t1 (f1 INT, f2 decimal(20,1), f3 blob);
+INSERT INTO t1 values(11,NULL,'blob'),(11,NULL,'blob');
+SELECT f3, MIN(f2) FROM t1 GROUP BY f1 LIMIT 1;
+DROP TABLE t1;
+
+--echo the value below *must* be 1
+show status like 'Created_tmp_disk_tables';
+
--echo # End of 5.3 tests
--echo #
diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test
index b0f8ddd375f..e95f41f6c8d 100644
--- a/mysql-test/t/information_schema.test
+++ b/mysql-test/t/information_schema.test
@@ -1444,6 +1444,17 @@ SELECT length(CAST(b AS CHAR)) FROM ubig;
DROP TABLE ubig;
+#
+# Bug #13889741: HANDLE_FATAL_SIGNAL IN _DB_ENTER_ | HANDLE_FATAL_SIGNAL IN STRNLEN
+#
+select 1 from information_schema.tables where table_schema=repeat('a', 2000);
+grant usage on *.* to mysqltest_1@localhost;
+connect (con1, localhost, mysqltest_1,,);
+connection con1;
+select 1 from information_schema.tables where table_schema=repeat('a', 2000);
+connection default;
+disconnect con1;
+drop user mysqltest_1@localhost;
--echo End of 5.1 tests.
diff --git a/mysql-test/t/information_schema_all_engines.test b/mysql-test/t/information_schema_all_engines.test
index a5400e8287a..553367d2b9a 100644
--- a/mysql-test/t/information_schema_all_engines.test
+++ b/mysql-test/t/information_schema_all_engines.test
@@ -15,6 +15,7 @@ show tables;
# Bug#18925: subqueries with MIN/MAX functions on INFORMATION_SCHEMA
#
+--sorted_result
SELECT t.table_name, c1.column_name
FROM information_schema.tables t
INNER JOIN
@@ -29,6 +30,7 @@ SELECT t.table_name, c1.column_name
c2.table_name = t.table_name AND
c2.column_name LIKE '%SCHEMA%'
) order by t.table_name;
+--sorted_result
SELECT t.table_name, c1.column_name
FROM information_schema.tables t
INNER JOIN
diff --git a/mysql-test/t/innodb_ext_key.test b/mysql-test/t/innodb_ext_key.test
index 58d692f720d..f5b5df527a3 100644
--- a/mysql-test/t/innodb_ext_key.test
+++ b/mysql-test/t/innodb_ext_key.test
@@ -287,6 +287,27 @@ select o_orderkey, p_partkey
and o_orderkey=l_orderkey and p_partkey=l_partkey;
show status like 'handler_read%';
+--echo #
+--echo # Bug mdev-3851: ref access used instead of expected eq_ref access
+--echo # when extended_keys=on
+--echo #
+
+create table t0 (a int);
+insert into t0 values (1), (2), (3), (4), (5);
+create index i_p_size on part(p_size);
+
+set optimizer_switch='extended_keys=on';
+
+explain
+select * from t0, part ignore index (primary)
+ where p_partkey=t0.a and p_size=1;
+
+select * from t0, part ignore index (primary)
+ where p_partkey=t0.a and p_size=1;
+
+drop table t0;
+drop index i_p_size on part;
+
DROP DATABASE dbt3_s001;
use test;
diff --git a/mysql-test/t/mysqlshow.test b/mysql-test/t/mysqlshow.test
index 2b6b5b631b2..5dba7fa5b85 100644
--- a/mysql-test/t/mysqlshow.test
+++ b/mysql-test/t/mysqlshow.test
@@ -29,7 +29,7 @@ select "---- -v -v -t ------" as "";
DROP TABLE t1, t2;
-if (`select count(*) from information_schema.plugins where plugin_name='innodb' and plugin_auth_version > "1.1.8-29.0"`)
+if (`select count(*) from information_schema.plugins where plugin_name='innodb' and plugin_auth_version > "1.1.8-29.1"`)
{
# because of lp:1066512 this test shows xtradb I_S plugins, even when
# xtradb is supposed to be disabled
diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test
index 2912e190af8..3e20d22d726 100644
--- a/mysql-test/t/order_by.test
+++ b/mysql-test/t/order_by.test
@@ -1652,3 +1652,68 @@ DROP TABLE t1;
--echo End of 5.3 tests
+--echo #
+--echo # Bug 54599: discarded fast range scan for query with
+--echo # GROUP BY + ORDER BY + LIMIT
+--echo #
+
+create table t0 (a int);
+insert into t0 values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);
+
+create table t1 (a int, b int, index idx1(a,b), index idx2(b,a));
+insert into t1
+ select 1000*s4.a+100*s3.a+10*s2.a + s1.a, 1000*s4.a+100*s3.a+10*s2.a+s1.a
+ from t0 s1, t0 s2, t0 s3, t0 s4;
+--disable_result_log
+analyze table t1;
+--enable_result_log
+
+explain
+select b, count(*) num_cnt from t1
+ where a > 9750 group by b order by num_cnt;
+flush status;
+--disable_result_log
+select b, count(*) num_cnt from t1
+ where a > 9750 group by b order by num_cnt;
+--enable_result_log
+show status like '%Handler_read%';
+
+explain
+select b, count(*) num_cnt from t1
+ where a > 9750 group by b order by num_cnt limit 1;
+flush status;
+--disable_result_log
+select b, count(*) num_cnt from t1
+ where a > 9750 group by b order by num_cnt limit 1;
+--enable_result_log
+show status like '%Handler_read%';
+
+drop table t0, t1;
+
+--echo #
+--echo # LP bug #1002508 : the number of expected rows to be examined is off
+--echo # (bug #13528826)
+--echo #
+
+CREATE TABLE t1(a int PRIMARY KEY, b int) ENGINE=myisam;
+INSERT INTO t1 VALUES
+ (5, 10), (2, 70), (7, 80), (6, 20), (1, 50), (9, 40), (8, 30), (3, 60);
+CREATE TABLE t2 (p int, a int, INDEX i_a(a)) ENGINE=myisam;
+INSERT INTO t2 VALUES
+ (103, 7), (109, 3), (102, 3), (108, 1), (106, 3),
+ (107, 7), (105, 1), (101, 3), (100, 7), (110, 1);
+
+EXPLAIN
+SELECT t1.a FROM t1 LEFT JOIN t2 ON t1.a=t2.a ORDER BY t1.a;
+
+EXPLAIN
+SELECT t1.a FROM t1 LEFT JOIN t2 ON t1.a=t2.a ORDER BY t1.a LIMIT 8;
+
+EXPLAIN
+SELECT t1.a FROM t1 LEFT JOIN t2 ON t1.a=t2.a ORDER BY t1.a LIMIT 100;
+
+DROP TABLE t1,t2;
+
+--echo End of 5.5 tests
+
+
diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test
index ef0d3df6661..038907702d5 100644
--- a/mysql-test/t/partition.test
+++ b/mysql-test/t/partition.test
@@ -2395,6 +2395,14 @@ SELECT 1 FROM t1 WHERE b < SOME
DROP TABLE t1;
+--echo
+--echo MDEV-612 Valgrind error in ha_maria::check_if_incompatible_data
+--echo
+
+CREATE TABLE t1 (a INT, b INT, KEY(a)) ENGINE=Aria PARTITION BY KEY(a) PARTITIONS 2;
+ALTER TABLE t1 ADD KEY (b);
+drop table t1;
+
--echo End of 5.1 tests
--echo #
diff --git a/mysql-test/t/range_vs_index_merge.test b/mysql-test/t/range_vs_index_merge.test
index 613a7cf5760..fb8fd778559 100755
--- a/mysql-test/t/range_vs_index_merge.test
+++ b/mysql-test/t/range_vs_index_merge.test
@@ -675,6 +675,64 @@ SELECT Name, Country, Population FROM City WHERE
$cond;
set optimizer_switch=@save_optimizer_switch;
+
+--echo #
+--echo # Bug mdev-585: range vs index-merge with ORDER BY ... LIMIT n
+--echo # (LP bug #637962)
+--echo #
+
+DROP INDEX CountryPopulation ON City;
+DROP INDEX CountryName ON City;
+DROP INDEX CityName on City;
+
+CREATE INDEX Name ON City(Name);
+CREATE INDEX Population ON City(Population);
+
+
+--replace_column 9 #
+EXPLAIN
+SELECT * FROM City
+ WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+ AND (Population >= 100000 AND Population < 120000);
+FLUSH STATUS;
+SELECT * FROM City
+ WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+ AND (Population >= 100000 AND Population < 120000);
+SHOW STATUS LIKE 'Handler_read_%';
+
+
+--replace_column 9 #
+EXPLAIN
+SELECT * FROM City
+ WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+ AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+
+FLUSH STATUS;
+SELECT * FROM City
+ WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+ AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+SHOW STATUS LIKE 'Handler_read_%';
+
+
+set optimizer_switch='index_merge=off';
+
+--replace_column 9 #
+EXPLAIN
+SELECT * FROM City
+ WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+ AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+
+FLUSH STATUS;
+SELECT * FROM City
+ WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+ AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+SHOW STATUS LIKE 'Handler_read_%';
+
+set optimizer_switch=@save_optimizer_switch;
DROP DATABASE world;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 07f0084e7ab..e7cb505b19f 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -5078,6 +5078,82 @@ SELECT col_int_nokey FROM ot
DROP TABLE ot,it1,it2;
+--echo #
+--echo # MDEV-746
+--echo # Bug#13651009 WRONG RESULT FROM DERIVED TABLE IF THE SUBQUERY
+--echo # HAS AN EMPTY RESULT
+--echo #
+
+CREATE TABLE t1 (
+ pk int NOT NULL,
+ col_int_nokey int NOT NULL,
+ col_int_key int NOT NULL,
+ col_time_key time NOT NULL,
+ col_varchar_key varchar(1) NOT NULL,
+ col_varchar_nokey varchar(1) NOT NULL,
+ PRIMARY KEY (pk),
+ KEY col_int_key (col_int_key),
+ KEY col_time_key (col_time_key),
+ KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+
+CREATE TABLE t2 (
+ pk int NOT NULL AUTO_INCREMENT,
+ col_int_nokey int NOT NULL,
+ col_int_key int NOT NULL,
+ col_time_key time NOT NULL,
+ col_varchar_key varchar(1) NOT NULL,
+ col_varchar_nokey varchar(1) NOT NULL,
+ PRIMARY KEY (pk),
+ KEY col_int_key (col_int_key),
+ KEY col_time_key (col_time_key),
+ KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+
+INSERT INTO t2 VALUES (1,4,4,'00:00:00','b','b');
+
+SET @var2:=4, @var3:=8;
+
+--echo
+--echo Testcase without inner subquery
+
+let $subq=
+SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+ sq4_alias1.col_varchar_key = @var3;
+
+eval EXPLAIN $subq;
+eval $subq;
+SELECT @var3;
+
+# Now as derived table:
+eval EXPLAIN SELECT * FROM ( $subq ) AS alias3;
+eval SELECT * FROM ( $subq ) AS alias3;
+SELECT @var3;
+
+--echo
+--echo Testcase with inner subquery; crashed WL#6095
+SET @var3=8;
+let $subq=
+SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+ NOT IN
+ (SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+ c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+ FROM t2 AS c_sq1_alias1
+ WHERE (c_sq1_alias1.col_int_nokey != @var2
+ OR c_sq1_alias1.pk != @var3));
+
+eval EXPLAIN $subq;
+eval $subq;
+# Now as derived table:
+eval EXPLAIN SELECT * FROM ( $subq ) AS alias3;
+eval SELECT * FROM ( $subq ) AS alias3;
+
+DROP TABLE t1,t2;
+
--echo End of 5.2 tests
--echo #
diff --git a/mysql-test/t/subselect2.test b/mysql-test/t/subselect2.test
index 75cf842fbdb..68894ad18cb 100644
--- a/mysql-test/t/subselect2.test
+++ b/mysql-test/t/subselect2.test
@@ -204,6 +204,32 @@ DROP VIEW v1;
DROP TABLE t1,t2,t3;
--echo #
+--echo # MDEV-536: LP:1050806 - different result for a query using subquery
+--echo #
+DROP TABLE IF EXISTS `t1`;
+
+CREATE TABLE `t1` (
+ `node_uid` bigint(20) unsigned DEFAULT NULL,
+ `date` datetime DEFAULT NULL,
+ `mirror_date` datetime DEFAULT NULL,
+ KEY `date` (`date`)
+) ENGINE=MyISAM;
+
+INSERT INTO `t1` VALUES (2085,'2012-01-01 00:00:00','2013-01-01 00:00:00');
+INSERT INTO `t1` VALUES (2084,'2012-02-01 00:00:00','2013-01-01 00:00:00');
+INSERT INTO `t1` VALUES (2088,'2012-03-01 00:00:00','2013-01-01 00:00:00');
+
+SELECT * FROM (
+ SELECT node_uid, date, mirror_date, @result := 0 AS result
+ FROM t1
+ WHERE date < '2012-12-12 12:12:12'
+ AND node_uid in (2085, 2084)
+ ORDER BY mirror_date ASC
+) AS calculated_result;
+
+DROP TABLE t1;
+
+--echo #
--echo # MDEV-567: Wrong result from a query with correlated subquery if ICP is allowed
--echo #
CREATE TABLE t1 (a int, b int, INDEX idx(a));
@@ -220,7 +246,75 @@ SELECT * FROM t3
WHERE t1.a = t2.a AND t2.a BETWEEN 7 AND 9
AND t3.b = t1.b
GROUP BY t1.b);
-DROP TABLE t1, t2, t3;
+
+
+set @tmp_mdev567=@@optimizer_switch;
+set optimizer_switch='mrr=off';
+SELECT * FROM t3
+ WHERE a = (SELECT COUNT(DISTINCT t2.b) FROM t1, t2
+ WHERE t1.a = t2.a AND t2.a BETWEEN 7 AND 9
+ AND t3.b = t1.b
+ GROUP BY t1.b);
+
+DROP TABLE t1,t2,t3;
+set optimizer_switch=@tmp_mdev567;
+
+--echo #
+--echo # MDEV-614, also MDEV-536, also LP:1050806:
+--echo # different result for a query using subquery between 5.5.25 and 5.5.27
+--echo #
+
+CREATE TABLE `t1` (
+ `node_uid` bigint(20) unsigned DEFAULT NULL,
+ `date` datetime DEFAULT NULL,
+ `mirror_date` datetime DEFAULT NULL,
+ KEY `date` (`date`)
+) ENGINE=MyISAM;
+
+INSERT INTO `t1` VALUES (2085,'2012-01-01 00:00:00','2013-01-01 00:00:00');
+INSERT INTO `t1` VALUES (2084,'2012-02-01 00:00:00','2013-01-01 00:00:00');
+INSERT INTO `t1` VALUES (2088,'2012-03-01 00:00:00','2013-01-01 00:00:00');
+
+explain
+SELECT * FROM (
+ SELECT node_uid, date, mirror_date, @result := 0 AS result
+ FROM t1
+ WHERE date < '2012-12-12 12:12:12'
+ AND node_uid in (2085, 2084)
+ ORDER BY mirror_date ASC
+) AS calculated_result;
+
+SELECT * FROM (
+ SELECT node_uid, date, mirror_date, @result := 0 AS result
+ FROM t1
+ WHERE date < '2012-12-12 12:12:12'
+ AND node_uid in (2085, 2084)
+ ORDER BY mirror_date ASC
+) AS calculated_result;
+
+set @tmp_mdev614=@@optimizer_switch;
+set optimizer_switch='mrr=off';
+explain
+SELECT * FROM (
+ SELECT node_uid, date, mirror_date, @result := 0 AS result
+ FROM t1
+ WHERE date < '2012-12-12 12:12:12'
+ AND node_uid in (2085, 2084)
+ ORDER BY mirror_date ASC
+) AS calculated_result;
+
+SELECT * FROM (
+ SELECT node_uid, date, mirror_date, @result := 0 AS result
+ FROM t1
+ WHERE date < '2012-12-12 12:12:12'
+ AND node_uid in (2085, 2084)
+ ORDER BY mirror_date ASC
+) AS calculated_result;
+
+set optimizer_switch=@tmp_mdev614;
+
+DROP TABLE t1;
+
set optimizer_switch=@subselect2_test_tmp;
diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test
index f509a1ad0f2..c6c4e4d9d2f 100644
--- a/mysql-test/t/user_var.test
+++ b/mysql-test/t/user_var.test
@@ -424,4 +424,32 @@ DROP TABLE t1;
SET @bug12408412=1;
SELECT GROUP_CONCAT(@bug12408412 ORDER BY 1) INTO @bug12408412;
+#
+# MDEV-616 LP BUG#1002126
+# Bug #11764371 57196: MORE FUN WITH ASSERTION: !TABLE->FILE ||
+# TABLE->FILE->INITED == HANDLER::
+#
+
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES (0);
+SELECT DISTINCT POW(COUNT(*), @a:=(SELECT 1 FROM t1 LEFT JOIN t1 AS t2 ON @a))
+AS b FROM t1 GROUP BY a;
+SELECT @a;
+DROP TABLE t1;
+CREATE TABLE t1(f1 INT, f2 INT);
+INSERT INTO t1 VALUES (1,2),(2,3),(3,1);
+CREATE TABLE t2(a INT);
+INSERT INTO t2 VALUES (1);
+SET @var=NULL;
+SELECT @var:=(SELECT f2 FROM t2 WHERE @var) FROM t1 GROUP BY f1 ORDER BY f2 DESC
+LIMIT 1;
+SELECT @var;
+DROP TABLE t1, t2;
+
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES (0),(1),(3);
+SELECT DISTINCT POW(COUNT(distinct a), @a:=(SELECT 1 FROM t1 LEFT JOIN t1 AS t2 ON @a limit 1)) AS b FROM t1 GROUP BY a;
+SELECT @a;
+DROP TABLE t1;
+
--echo End of 5.5 tests
diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c
index 18c9a38f0db..a51d94f8e73 100644
--- a/mysys/mf_pack.c
+++ b/mysys/mf_pack.c
@@ -1,4 +1,5 @@
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates.
+ Copyright (c) 2012, Monty Program Ab
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
@@ -30,7 +31,7 @@ void pack_dirname(char * to, const char *from)
int cwd_err;
size_t d_length,length,UNINIT_VAR(buff_length);
char * start;
- char buff[FN_REFLEN];
+ char buff[FN_REFLEN + 1];
DBUG_ENTER("pack_dirname");
(void) intern_filename(to,from); /* Change to intern name */
@@ -127,7 +128,7 @@ size_t cleanup_dirname(register char *to, const char *from)
reg3 char * from_ptr;
reg4 char * start;
char parent[5], /* for "FN_PARENTDIR" */
- buff[FN_REFLEN+1],*end_parentdir;
+ buff[FN_REFLEN + 1],*end_parentdir;
#ifdef BACKSLASH_MBTAIL
CHARSET_INFO *fs= fs_character_set();
#endif
@@ -241,7 +242,7 @@ my_bool my_use_symdir=0; /* Set this if you want to use symdirs */
#ifdef USE_SYMDIR
void symdirget(char *dir)
{
- char buff[FN_REFLEN+1];
+ char buff[FN_REFLEN + 1];
char *pos=strend(dir);
if (dir[0] && pos[-1] != FN_DEVCHAR && my_access(dir, F_OK))
{
@@ -291,7 +292,7 @@ void symdirget(char *dir)
size_t normalize_dirname(char *to, const char *from)
{
size_t length;
- char buff[FN_REFLEN];
+ char buff[FN_REFLEN + 1];
DBUG_ENTER("normalize_dirname");
/*
@@ -418,7 +419,7 @@ static char * expand_tilde(char **path)
size_t unpack_filename(char * to, const char *from)
{
size_t length, n_length, buff_length;
- char buff[FN_REFLEN];
+ char buff[FN_REFLEN + 1];
DBUG_ENTER("unpack_filename");
length=dirname_part(buff, from, &buff_length);/* copy & convert dirname */
@@ -448,7 +449,7 @@ size_t system_filename(char *to, const char *from)
char *intern_filename(char *to, const char *from)
{
size_t length, to_length;
- char buff[FN_REFLEN];
+ char buff[FN_REFLEN + 1];
if (from == to)
{ /* Dirname may destroy from */
strmov(buff,from);
diff --git a/mysys/my_context.c b/mysys/my_context.c
index d2374391a39..08dc0920f21 100644
--- a/mysys/my_context.c
+++ b/mysys/my_context.c
@@ -206,7 +206,7 @@ my_context_spawn(struct my_context *c, void (*f)(void *), void *d)
(
"movq %%rsp, (%[save])\n\t"
"movq %[stack], %%rsp\n\t"
-#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4
+#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 && !defined(__INTEL_COMPILER)
/*
This emits a DWARF DW_CFA_undefined directive to make the return address
undefined. This indicates that this is the top of the stack frame, and
@@ -437,6 +437,8 @@ my_context_destroy(struct my_context *c)
int
my_context_spawn(struct my_context *c, void (*f)(void *), void *d)
{
+ void (*tmp_f)(void *)= f;
+ void *tmp_d= d;
int ret;
DBUG_SWAP_CODE_STATE(&c->dbug_state);
@@ -454,6 +456,15 @@ my_context_spawn(struct my_context *c, void (*f)(void *), void *d)
(
"movl %%esp, (%[save])\n\t"
"movl %[stack], %%esp\n\t"
+#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 && !defined(__INTEL_COMPILER)
+ /*
+ This emits a DWARF DW_CFA_undefined directive to make the return address
+ undefined. This indicates that this is the top of the stack frame, and
+ helps tools that use DWARF stack unwinding to obtain stack traces.
+ (I use numeric constant to avoid a dependency on libdwarf includes).
+ */
+ ".cfi_escape 0x07, 8\n\t"
+#endif
/* Push the parameter on the stack. */
"pushl %[d]\n\t"
"movl %%ebp, 4(%[save])\n\t"
@@ -483,13 +494,13 @@ my_context_spawn(struct my_context *c, void (*f)(void *), void *d)
"3:\n\t"
"movl $1, %[ret]\n"
"4:\n"
- : [ret] "=a" (ret)
+ : [ret] "=a" (ret),
+ [f] "+c" (tmp_f),
+ [d] "+d" (tmp_d)
: [stack] "a" (c->stack_top),
/* Need this in callee-save register to preserve across function call. */
- [save] "D" (&c->save[0]),
- [f] "m" (f),
- [d] "m" (d)
- : "ecx", "edx", "memory", "cc"
+ [save] "D" (&c->save[0])
+ : "memory", "cc"
);
DBUG_SWAP_CODE_STATE(&c->dbug_state);
diff --git a/plugin/audit_null/audit_null.c b/plugin/audit_null/audit_null.c
index 469e5ae494c..be0c70fbd35 100644
--- a/plugin/audit_null/audit_null.c
+++ b/plugin/audit_null/audit_null.c
@@ -145,7 +145,7 @@ mysql_declare_plugin(audit_null)
{
MYSQL_AUDIT_PLUGIN, /* type */
&audit_null_descriptor, /* descriptor */
- "NULL_AUDIT", /* name */
+ "AUDIT_NULL", /* name */
"Oracle Corp", /* author */
"Simple NULL Audit", /* description */
PLUGIN_LICENSE_GPL,
diff --git a/plugin/feedback/CMakeLists.txt b/plugin/feedback/CMakeLists.txt
index 627e4d643fb..3e14ef3918b 100644
--- a/plugin/feedback/CMakeLists.txt
+++ b/plugin/feedback/CMakeLists.txt
@@ -1,9 +1,11 @@
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql ${CMAKE_SOURCE_DIR}/regex
- ${CMAKE_SOURCE_DIR}/extra/yassl/include)
+ ${SSL_INCLUDE_DIRS})
SET(FEEDBACK_SOURCES feedback.cc sender_thread.cc
url_base.cc url_http.cc utils.cc)
+ADD_DEFINITIONS(${SSL_DEFINES})
+
INCLUDE (CheckIncludeFiles)
CHECK_INCLUDE_FILES (netdb.h HAVE_NETDB_H)
IF(HAVE_NETDB_H)
@@ -11,8 +13,10 @@ IF(HAVE_NETDB_H)
ENDIF(HAVE_NETDB_H)
IF(WIN32)
- #SET(FEEDBACK_LIBS Ws2_32)
- MYSQL_ADD_PLUGIN(FEEDBACK ${FEEDBACK_SOURCES} STATIC_ONLY DEFAULT)
+ MYSQL_ADD_PLUGIN(FEEDBACK ${FEEDBACK_SOURCES}
+ LINK_LIBRARIES ${SSL_LIBRARIES}
+ STATIC_ONLY DEFAULT)
ELSE(WIN32)
- MYSQL_ADD_PLUGIN(FEEDBACK ${FEEDBACK_SOURCES})
+ MYSQL_ADD_PLUGIN(FEEDBACK ${FEEDBACK_SOURCES}
+ LINK_LIBRARIES ${SSL_LIBRARIES})
ENDIF(WIN32)
diff --git a/plugin/feedback/url_http.cc b/plugin/feedback/url_http.cc
index a9d4c5bbbaf..dd39adbf7a7 100644
--- a/plugin/feedback/url_http.cc
+++ b/plugin/feedback/url_http.cc
@@ -29,12 +29,6 @@ namespace feedback {
static const uint FOR_READING= 0;
static const uint FOR_WRITING= 1;
-#ifdef MARIADB_BASE_VERSION
-#define ssl_connect(A,B,C,D) sslconnect(A,B,C,D)
-#else
-#define ssl_connect(A,B,C,D) sslconnect(A,B,C)
-#endif
-
/**
implementation of the Url class that sends the data via HTTP POST request.
@@ -199,12 +193,23 @@ int Url_http::send(const char* data, size_t data_length)
struct st_VioSSLFd *UNINIT_VAR(ssl_fd);
if (ssl)
{
- buf[0]= 0;
- if (!(ssl_fd= new_VioSSLConnectorFd(0, 0, 0, 0, 0)) ||
- ssl_connect(ssl_fd, vio, send_timeout, buf))
+ enum enum_ssl_init_error ssl_init_error= SSL_INITERR_NOERROR;
+ ulong ssl_error= 0;
+ if (!(ssl_fd= new_VioSSLConnectorFd(0, 0, 0, 0, 0, &ssl_init_error)) ||
+ sslconnect(ssl_fd, vio, send_timeout, &ssl_error))
{
+ const char *err;
+ if (ssl_init_error != SSL_INITERR_NOERROR)
+ err= sslGetErrString(ssl_init_error);
+ else
+ {
+ ERR_error_string_n(ssl_error, buf, sizeof(buf));
+ buf[sizeof(buf)-1]= 0;
+ err= buf;
+ }
+
sql_print_error("feedback plugin: ssl failed for url '%s' %s",
- full_url.str, buf);
+ full_url.str, err);
if (ssl_fd)
free_vio_ssl_acceptor_fd(ssl_fd);
closesocket(fd);
@@ -256,18 +261,21 @@ int Url_http::send(const char* data, size_t data_length)
Extract the first string between <h1>...</h1> tags
and put it as a server reply into the error log.
*/
+ len= 0;
for (;;)
{
- size_t i= vio_read(vio, (uchar*)buf + len, sizeof(buf) - len - 1);
+ size_t i= sizeof(buf) - len - 1;
+ if (i)
+ i= vio_read(vio, (uchar*)buf + len, i);
if ((int)i <= 0)
break;
len+= i;
}
- if (len && len < sizeof(buf))
+ if (len)
{
char *from;
- buf[len+1]= 0; // safety
+ buf[len]= 0; // safety
if ((from= strstr(buf, "<h1>")))
{
@@ -296,7 +304,7 @@ int Url_http::send(const char* data, size_t data_length)
if (ssl)
{
SSL_CTX_free(ssl_fd->ssl_context);
- my_free(ssl_fd, MYF(0));
+ my_free(ssl_fd);
}
#endif
diff --git a/scripts/mysql_config.sh b/scripts/mysql_config.sh
index fd15d7ac746..38cd2b6b910 100644
--- a/scripts/mysql_config.sh
+++ b/scripts/mysql_config.sh
@@ -92,11 +92,7 @@ plugindir_rel=`echo $plugindir | sed -e "s;^$basedir/;;"`
fix_path plugindir $plugindir_rel lib/mysql/plugin lib/plugin
pkgincludedir='@pkgincludedir@'
-if [ -f "$basedir/include/mysql/mysql.h" ]; then
- pkgincludedir="$basedir/include/mysql"
-elif [ -f "$basedir/include/mysql.h" ]; then
- pkgincludedir="$basedir/include"
-fi
+fix_path pkgincludedir include/mysql
version='@VERSION@'
socket='@MYSQL_UNIX_ADDR@'
@@ -125,8 +121,11 @@ if [ -r "$pkglibdir/libmygcc.a" ]; then
embedded_libs="$embedded_libs -lmygcc "
fi
-cflags="-I$pkgincludedir @CFLAGS@ " #note: end space!
include="-I$pkgincludedir"
+if [ "$basedir" != "/usr" ]; then
+ include="$include -I$pkgincludedir/.."
+fi
+cflags="$include @CFLAGS@ " #note: end space!
# Remove some options that a client doesn't have to care about
# FIXME until we have a --cxxflags, we need to remove -Xa
diff --git a/scripts/mysql_secure_installation.pl.in b/scripts/mysql_secure_installation.pl.in
index de549add904..188a6bd7104 100755
--- a/scripts/mysql_secure_installation.pl.in
+++ b/scripts/mysql_secure_installation.pl.in
@@ -1,7 +1,7 @@
#!/usr/bin/perl
# -*- cperl -*-
#
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates
+# Copyright (c) 2007, 2012, Oracle and/or its affiliates.
#
# 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
diff --git a/scripts/mysql_secure_installation.sh b/scripts/mysql_secure_installation.sh
index 28c631a46d5..9e9bce9fa87 100644
--- a/scripts/mysql_secure_installation.sh
+++ b/scripts/mysql_secure_installation.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-# Copyright (c) 2002, 2012, Oracle and/or its affiliates
+# Copyright (c) 2002, 2012, Oracle and/or its affiliates.
#
# 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
diff --git a/sql-bench/test-table-elimination.sh b/sql-bench/test-table-elimination.sh
index 0dcfe975486..5b494688bec 100755
--- a/sql-bench/test-table-elimination.sh
+++ b/sql-bench/test-table-elimination.sh
@@ -1,4 +1,3 @@
-
#!@PERL@
# Test of table elimination feature
@@ -93,7 +92,7 @@ $dbh->do("create view elim_current_facts as $select_current_full_facts");
if ($opt_lock_tables)
{
- do_query($dbh,"LOCK TABLES elim_facts, elim_attr1, elim_attr2 WRITE");
+ do_query($dbh,"LOCK TABLES elim_current_facts WRITE, elim_facts WRITE, elim_attr1 WRITE, elim_attr2 WRITE");
}
if ($opt_fast && defined($server->{vacuum}))
@@ -200,12 +199,14 @@ if ($opt_lock_tables)
if ($opt_fast && defined($server->{vacuum}))
{
- $server->vacuum(0,\$dbh,["elim_facts", "elim_attr1", "elim_attr2"]);
+ $server->vacuum(1,\$dbh,"elim_facts");
+ $server->vacuum(1,\$dbh,"elim_attr1");
+ $server->vacuum(1,\$dbh,"elim_attr2");
}
if ($opt_lock_tables)
{
- do_query($dbh,"LOCK TABLES elim_facts, elim_attr1, elim_attr2 WRITE");
+ do_query($dbh,"LOCK TABLES elim_current_facts READ, elim_facts READ, elim_attr1 READ, elim_attr2 READ");
}
####
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index afd773faf32..9cbb8e16f8a 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -4651,8 +4651,8 @@ int ha_partition::common_index_read(uchar *buf, bool have_start_key)
bool reverse_order= FALSE;
DBUG_ENTER("ha_partition::common_index_read");
- DBUG_PRINT("info", ("m_ordered %u m_ordered_scan_ong %u have_start_key %u",
- m_ordered, m_ordered_scan_ongoing, have_start_key));
+ DBUG_PRINT("info", ("m_ordered: %u have_start_key: %u",
+ m_ordered, have_start_key));
if (have_start_key)
{
diff --git a/sql/item_func.h b/sql/item_func.h
index 586444e0e4e..f1b97151cbe 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1569,6 +1569,15 @@ public:
:Item_func(b), cached_result_type(INT_RESULT),
entry(NULL), entry_thread_id(0), name(a)
{}
+ Item_func_set_user_var(Item_func_set_user_var *item)
+ :Item_func(item), cached_result_type(item->cached_result_type),
+ entry(item->entry), entry_thread_id(item->entry_thread_id),
+ value(item->value), decimal_buff(item->decimal_buff),
+ null_item(item->null_item), save_result(item->save_result),
+ name(item->name)
+ {
+ //fixed= 1;
+ }
enum Functype functype() const { return SUSERVAR_FUNC; }
double val_real();
longlong val_int();
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index e26c3a47912..265db0055ad 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -49,7 +49,7 @@ Item_subselect::Item_subselect():
used_tables_cache(0), have_to_be_excluded(0), const_item_cache(1),
inside_first_fix_fields(0), done_first_fix_fields(FALSE),
expr_cache(0), forced_const(FALSE), substitution(0), engine(0), eliminated(FALSE),
- engine_changed(0), changed(0), is_correlated(FALSE)
+ changed(0), is_correlated(FALSE)
{
DBUG_ENTER("Item_subselect::Item_subselect");
DBUG_PRINT("enter", ("this: 0x%lx", (ulong) this));
@@ -623,6 +623,8 @@ bool Item_subselect::walk(Item_processor processor, bool walk_subquery,
bool Item_subselect::exec()
{
+ subselect_engine *org_engine= engine;
+
DBUG_ENTER("Item_subselect::exec");
/*
@@ -644,11 +646,14 @@ bool Item_subselect::exec()
#ifndef DBUG_OFF
++exec_counter;
#endif
- if (engine_changed)
+ if (engine != org_engine)
{
- engine_changed= 0;
- res= exec();
- DBUG_RETURN(res);
+ /*
+ If the subquery engine changed during execution due to lazy subquery
+ optimization, or because the original engine found a more efficient other
+ engine, re-execute the subquery with the new engine.
+ */
+ DBUG_RETURN(exec());
}
DBUG_RETURN(res);
}
@@ -3141,10 +3146,8 @@ int subselect_single_select_engine::exec()
DBUG_RETURN(1); /* purecov: inspected */
}
}
- if (item->engine_changed)
- {
+ if (item->engine_changed(this))
DBUG_RETURN(1);
- }
}
if (select_lex->uncacheable &&
select_lex->uncacheable != UNCACHEABLE_EXPLAIN
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 2a64c63a1be..1da129380e7 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -122,8 +122,6 @@ public:
*/
bool eliminated;
- /* changed engine indicator */
- bool engine_changed;
/* subquery is transformed */
bool changed;
@@ -200,9 +198,9 @@ public:
{
old_engine= engine;
engine= eng;
- engine_changed= 1;
return eng == 0;
}
+ bool engine_changed(subselect_engine *eng) { return engine != eng; }
/*
True if this subquery has been already evaluated. Implemented only for
single select and union subqueries only.
@@ -260,7 +258,6 @@ public:
st_select_lex*, st_select_lex*,
Field*, Item*, Item_ident*);
friend bool convert_join_subqueries_to_semijoins(JOIN *join);
-
};
/* single value subselect */
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 0b21ba92558..b04fda55736 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -2510,9 +2510,8 @@ Item_sum_hybrid::min_max_update_int_field()
void
Item_sum_hybrid::min_max_update_decimal_field()
{
- /* TODO: optimize: do not get result_field in case of args[0] is NULL */
my_decimal old_val, nr_val;
- const my_decimal *old_nr= result_field->val_decimal(&old_val);
+ const my_decimal *old_nr;
const my_decimal *nr= args[0]->val_decimal(&nr_val);
if (!args[0]->null_value)
{
@@ -2520,16 +2519,17 @@ Item_sum_hybrid::min_max_update_decimal_field()
old_nr=nr;
else
{
+ old_nr= result_field->val_decimal(&old_val);
bool res= my_decimal_cmp(old_nr, nr) > 0;
/* (cmp_sign > 0 && res) || (!(cmp_sign > 0) && !res) */
if ((cmp_sign > 0) ^ (!res))
old_nr=nr;
}
result_field->set_notnull();
+ result_field->store_decimal(old_nr);
}
else if (result_field->is_null(0))
result_field->set_null();
- result_field->store_decimal(old_nr);
}
diff --git a/sql/log.cc b/sql/log.cc
index a0207510fbe..964120e6b51 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1413,12 +1413,6 @@ bool LOGGER::general_log_write(THD *thd, enum enum_server_command command,
DBUG_ASSERT(thd);
- lock_shared();
- if (!opt_log)
- {
- unlock();
- return 0;
- }
user_host_len= make_user_name(thd, user_host_buff);
current_time= my_hrtime();
@@ -1429,15 +1423,19 @@ bool LOGGER::general_log_write(THD *thd, enum enum_server_command command,
command_name[(uint) command].length,
query, query_length);
- while (*current_handler)
- error|= (*current_handler++)->
- log_general(thd, current_time, user_host_buff,
- user_host_len, thd->thread_id,
- command_name[(uint) command].str,
- command_name[(uint) command].length,
- query, query_length,
- thd->variables.character_set_client) || error;
- unlock();
+ if (opt_log && log_command(thd, command))
+ {
+ lock_shared();
+ while (*current_handler)
+ error|= (*current_handler++)->
+ log_general(thd, current_time, user_host_buff,
+ user_host_len, thd->thread_id,
+ command_name[(uint) command].str,
+ command_name[(uint) command].length,
+ query, query_length,
+ thd->variables.character_set_client) || error;
+ unlock();
+ }
return error;
}
@@ -5547,7 +5545,7 @@ bool general_log_write(THD *thd, enum enum_server_command command,
const char *query, uint query_length)
{
/* Write the message to the log if we want to log this king of commands */
- if (logger.log_command(thd, command))
+ if (logger.log_command(thd, command) || mysql_audit_general_enabled())
return logger.general_log_write(thd, command, query, query_length);
return FALSE;
@@ -7188,8 +7186,9 @@ int TC_LOG_MMAP::open(const char *opt_name)
syncing= 0;
active=pages;
+ DBUG_ASSERT(npages >= 2);
pool=pages+1;
- pool_last=pages+npages-1;
+ pool_last_ptr= &((pages+npages-1)->next);
commit_ordered_queue= NULL;
commit_ordered_queue_busy= false;
@@ -7222,8 +7221,8 @@ void TC_LOG_MMAP::get_active_from_pool()
do
{
best_p= p= &pool;
- if ((*p)->waiters == 0) // can the first page be used ?
- break; // yes - take it.
+ if ((*p)->waiters == 0 && (*p)->free > 0) // can the first page be used ?
+ break; // yes - take it.
best_free=0; // no - trying second strategy
for (p=&(*p)->next; *p; p=&(*p)->next)
@@ -7240,10 +7239,10 @@ void TC_LOG_MMAP::get_active_from_pool()
mysql_mutex_assert_owner(&LOCK_active);
active=*best_p;
- if ((*best_p)->next) // unlink the page from the pool
- *best_p=(*best_p)->next;
- else
- pool_last=*best_p;
+ /* Unlink the page from the pool. */
+ if (!(*best_p)->next)
+ pool_last_ptr= best_p;
+ *best_p=(*best_p)->next;
mysql_mutex_unlock(&LOCK_pool);
mysql_mutex_lock(&active->lock);
@@ -7350,12 +7349,9 @@ int TC_LOG_MMAP::log_one_transaction(my_xid xid)
mysql_mutex_unlock(&LOCK_active);
mysql_mutex_lock(&p->lock);
p->waiters++;
- for (;;)
+ while (p->state == PS_DIRTY && syncing)
{
- int not_dirty = p->state != PS_DIRTY;
mysql_mutex_unlock(&p->lock);
- if (not_dirty || !syncing)
- break;
mysql_cond_wait(&p->cond, &LOCK_sync);
mysql_mutex_lock(&p->lock);
}
@@ -7407,8 +7403,8 @@ int TC_LOG_MMAP::sync()
/* page is synced. let's move it to the pool */
mysql_mutex_lock(&LOCK_pool);
- pool_last->next=syncing;
- pool_last=syncing;
+ (*pool_last_ptr)=syncing;
+ pool_last_ptr=&(syncing->next);
syncing->next=0;
syncing->state= err ? PS_ERROR : PS_POOL;
mysql_cond_signal(&COND_pool); // in case somebody's waiting
diff --git a/sql/log.h b/sql/log.h
index c911b281f05..0e189a789db 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -134,7 +134,7 @@ class TC_LOG_MMAP: public TC_LOG
my_off_t file_length;
uint npages, inited;
uchar *data;
- struct st_page *pages, *syncing, *active, *pool, *pool_last;
+ struct st_page *pages, *syncing, *active, *pool, **pool_last_ptr;
/*
note that, e.g. LOCK_active is only used to protect
'active' pointer, to protect the content of the active page
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 791af42521a..b98edeb15db 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -10944,6 +10944,13 @@ int QUICK_RANGE_SELECT::reset()
DBUG_ENTER("QUICK_RANGE_SELECT::reset");
last_range= NULL;
cur_range= (QUICK_RANGE**) ranges.buffer;
+
+ if (file->inited == handler::RND)
+ {
+ /* Handler could be left in this state by MRR */
+ if ((error= file->ha_rnd_end()))
+ DBUG_RETURN(error);
+ }
if (file->inited == handler::NONE)
{
diff --git a/sql/scheduler.cc b/sql/scheduler.cc
index 78a1a2a32bb..0ae4121ef4c 100644
--- a/sql/scheduler.cc
+++ b/sql/scheduler.cc
@@ -79,11 +79,34 @@ void scheduler_init() {
scheduler_wait_sync_end);
}
+
+/**
+ Kill notification callback, used by one-thread-per-connection
+ and threadpool scheduler.
+
+ Wakes up a thread that is stuck in read/poll/epoll/event-poll
+ routines used by threadpool, such that subsequent attempt to
+ read from client connection will result in IO error.
+*/
+
+void post_kill_notification(THD *thd)
+{
+ DBUG_ENTER("post_kill_notification");
+ if (current_thd == thd || thd->system_thread)
+ DBUG_VOID_RETURN;
+
+ if (thd->net.vio)
+ vio_shutdown(thd->net.vio, SHUT_RD);
+ DBUG_VOID_RETURN;
+}
+
/*
Initialize scheduler for --thread-handling=one-thread-per-connection
*/
#ifndef EMBEDDED_LIBRARY
+
+
void one_thread_per_connection_scheduler(scheduler_functions *func,
ulong *arg_max_connections,
uint *arg_connection_count)
@@ -95,6 +118,7 @@ void one_thread_per_connection_scheduler(scheduler_functions *func,
func->init_new_connection_thread= init_new_connection_handler_thread;
func->add_connection= create_thread_to_handle_connection;
func->end_thread= one_thread_per_connection_end;
+ func->post_kill_notification= post_kill_notification;
}
#endif
diff --git a/sql/scheduler.h b/sql/scheduler.h
index 82bba5abe65..4e200e86d74 100644
--- a/sql/scheduler.h
+++ b/sql/scheduler.h
@@ -78,7 +78,7 @@ void one_thread_per_connection_scheduler(scheduler_functions *func,
void one_thread_scheduler(scheduler_functions *func);
extern void scheduler_init();
-
+extern void post_kill_notification(THD *);
/*
To be used for pool-of-threads (implemeneted differently on various OSs)
*/
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index f3ba0073c69..0d92a68a2d4 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -3113,8 +3113,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
(the order of query cache and subst_spvars calls is irrelevant because
queries with SP vars can't be cached)
*/
- if (unlikely((thd->variables.option_bits & OPTION_LOG_OFF)==0))
- general_log_write(thd, COM_QUERY, thd->query(), thd->query_length());
+ general_log_write(thd, COM_QUERY, thd->query(), thd->query_length());
if (query_cache_send_result_to_client(thd, thd->query(),
thd->query_length()) <= 0)
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 22fb5ee74cd..b35ab76f3d2 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1633,14 +1633,20 @@ ulong acl_get(const char *host, const char *ip,
acl_entry *entry;
DBUG_ENTER("acl_get");
- mysql_mutex_lock(&acl_cache->lock);
- end=strmov((tmp_db=strmov(strmov(key, ip ? ip : "")+1,user)+1),db);
+ tmp_db= strmov(strmov(key, ip ? ip : "") + 1, user) + 1;
+ end= strnmov(tmp_db, db, key + sizeof(key) - tmp_db);
+
+ if (end >= key + sizeof(key)) // db name was truncated
+ DBUG_RETURN(0); // no privileges for an invalid db name
+
if (lower_case_table_names)
{
my_casedn_str(files_charset_info, tmp_db);
db=tmp_db;
}
key_length= (size_t) (end-key);
+
+ mysql_mutex_lock(&acl_cache->lock);
if (!db_is_pattern && (entry=(acl_entry*) acl_cache->search((uchar*) key,
key_length)))
{
@@ -4990,11 +4996,17 @@ static bool check_grant_db_routine(THD *thd, const char *db, HASH *hash)
bool check_grant_db(THD *thd,const char *db)
{
Security_context *sctx= thd->security_ctx;
- char helping [SAFE_NAME_LEN + USERNAME_LENGTH+2];
+ char helping [SAFE_NAME_LEN + USERNAME_LENGTH+2], *end;
uint len;
bool error= TRUE;
- len= (uint) (strmov(strmov(helping, sctx->priv_user) + 1, db) - helping) + 1;
+ end= strmov(helping, sctx->priv_user) + 1;
+ end= strnmov(end, db, helping + sizeof(helping) - end);
+
+ if (end >= helping + sizeof(helping)) // db name was truncated
+ return 1; // no privileges for an invalid db name
+
+ len= (uint) (end - helping) + 1;
mysql_rwlock_rdlock(&LOCK_grant);
diff --git a/sql/sql_audit.h b/sql/sql_audit.h
index 51c695d091d..b2ce31f1d26 100644
--- a/sql/sql_audit.h
+++ b/sql/sql_audit.h
@@ -37,8 +37,16 @@ extern void mysql_audit_acquire_plugins(THD *thd, uint event_class);
#ifndef EMBEDDED_LIBRARY
extern void mysql_audit_notify(THD *thd, uint event_class,
uint event_subtype, ...);
+
+static inline bool mysql_audit_general_enabled()
+{
+ return mysql_global_audit_mask[0] & MYSQL_AUDIT_GENERAL_CLASSMASK;
+}
+
#else
-#define mysql_audit_notify(...)
+static inline void mysql_audit_notify(THD *thd, uint event_class,
+ uint event_subtype, ...) { }
+#define mysql_audit_general_enabled() 0
#endif
extern void mysql_audit_release(THD *thd);
@@ -72,8 +80,7 @@ void mysql_audit_general_log(THD *thd, time_t time,
const char *cmd, uint cmdlen,
const char *query, uint querylen)
{
-#ifndef EMBEDDED_LIBRARY
- if (mysql_global_audit_mask[0] & MYSQL_AUDIT_GENERAL_CLASSMASK)
+ if (mysql_audit_general_enabled())
{
CHARSET_INFO *clientcs= thd ? thd->variables.character_set_client
: global_system_variables.character_set_client;
@@ -82,7 +89,6 @@ void mysql_audit_general_log(THD *thd, time_t time,
0, time, user, userlen, cmd, cmdlen,
query, querylen, clientcs, 0);
}
-#endif
}
/**
@@ -101,8 +107,7 @@ static inline
void mysql_audit_general(THD *thd, uint event_subtype,
int error_code, const char *msg)
{
-#ifndef EMBEDDED_LIBRARY
- if (mysql_global_audit_mask[0] & MYSQL_AUDIT_GENERAL_CLASSMASK)
+ if (mysql_audit_general_enabled())
{
time_t time= my_time(0);
uint msglen= msg ? strlen(msg) : 0;
@@ -130,7 +135,6 @@ void mysql_audit_general(THD *thd, uint event_subtype,
error_code, time, user, userlen, msg, msglen,
query.str(), query.length(), query.charset(), rows);
}
-#endif
}
#define MYSQL_AUDIT_NOTIFY_CONNECTION_CONNECT(thd) mysql_audit_notify(\
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 07bdb93930c..ac247e11e88 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -8908,7 +8908,9 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
/* Update virtual fields*/
thd->abort_on_warning= FALSE;
if (vcol_table && vcol_table->vfield &&
- update_virtual_fields(thd, vcol_table, TRUE))
+ update_virtual_fields(thd, vcol_table,
+ vcol_table->triggers ? VCOL_UPDATE_ALL :
+ VCOL_UPDATE_FOR_WRITE))
goto err;
thd->abort_on_warning= save_abort_on_warning;
thd->no_errors= save_no_errors;
@@ -8972,7 +8974,9 @@ fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
if (item_field && item_field->field &&
(table= item_field->field->table) &&
table->vfield)
- result= update_virtual_fields(thd, table, TRUE);
+ result= update_virtual_fields(thd, table,
+ table->triggers ? VCOL_UPDATE_ALL :
+ VCOL_UPDATE_FOR_WRITE);
}
}
return result;
@@ -9056,7 +9060,10 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors,
}
/* Update virtual fields*/
thd->abort_on_warning= FALSE;
- if (table->vfield && update_virtual_fields(thd, table, TRUE))
+ if (table->vfield &&
+ update_virtual_fields(thd, table,
+ table->triggers ? VCOL_UPDATE_ALL :
+ VCOL_UPDATE_FOR_WRITE))
goto err;
thd->abort_on_warning= abort_on_warning_saved;
DBUG_RETURN(thd->is_error());
@@ -9109,7 +9116,9 @@ fill_record_n_invoke_before_triggers(THD *thd, Field **ptr,
{
TABLE *table= (*ptr)->table;
if (table->vfield)
- result= update_virtual_fields(thd, table, TRUE);
+ result= update_virtual_fields(thd, table,
+ table->triggers ? VCOL_UPDATE_ALL :
+ VCOL_UPDATE_FOR_WRITE);
}
return result;
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 3deb97c9730..6ec998c44f8 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -303,7 +303,8 @@ TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
bool no_error);
void mark_tmp_table_for_reuse(TABLE *table);
bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists);
-int update_virtual_fields(THD *thd, TABLE *table, bool ignore_stored= FALSE);
+int update_virtual_fields(THD *thd, TABLE *table,
+ enum enum_vcol_update_mode vcol_update_mode= VCOL_UPDATE_FOR_READ);
int dynamic_column_error_message(enum_dyncol_func_result rc);
extern TABLE *unused_tables;
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index b863f3c7bb5..a3d68f54c9c 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -328,7 +328,9 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
! thd->is_error())
{
if (table->vfield)
- update_virtual_fields(thd, table);
+ update_virtual_fields(thd, table,
+ table->triggers ? VCOL_UPDATE_ALL :
+ VCOL_UPDATE_FOR_READ);
thd->examined_row_count++;
// thd->is_error() is tested to disallow delete row on error
if (!select || select->skip_record(thd) > 0)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 03398987818..4bf1183e9da 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -7264,8 +7264,10 @@ void sql_kill(THD *thd, ulong id, killed_state state)
uint error;
if (!(error= kill_one_thread(thd, id, state)))
{
- if (! thd->killed)
+ if ((!thd->killed))
my_ok(thd);
+ else
+ my_error(killed_errno(thd->killed), MYF(0), id);
}
else
my_error(error, MYF(0), id);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 114de41f83a..c1f07581106 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2505,14 +2505,24 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
*/
if (sl->prep_where)
{
- sl->where= sl->prep_where->copy_andor_structure(thd);
+ /*
+ We need this rollback because memory allocated in
+ copy_andor_structure() will be freed
+ */
+ thd->change_item_tree((Item**)&sl->where,
+ sl->prep_where->copy_andor_structure(thd));
sl->where->cleanup();
}
else
sl->where= NULL;
if (sl->prep_having)
{
- sl->having= sl->prep_having->copy_andor_structure(thd);
+ /*
+ We need this rollback because memory allocated in
+ copy_andor_structure() will be freed
+ */
+ thd->change_item_tree((Item**)&sl->having,
+ sl->prep_having->copy_andor_structure(thd));
sl->having->cleanup();
}
else
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index a4b2d376e05..ceb8827c790 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1232,11 +1232,9 @@ JOIN::optimize()
DBUG_RETURN(1); // error == -1
}
if (const_table_map != found_const_table_map &&
- !(select_options & SELECT_DESCRIBE) &&
- (!conds ||
- !(conds->used_tables() & RAND_TABLE_BIT) ||
- select_lex->master_unit() == &thd->lex->unit)) // upper level SELECT
+ !(select_options & SELECT_DESCRIBE))
{
+ // There is at least one empty const table
zero_result_cause= "no matching row in const table";
DBUG_PRINT("error",("Error: %s", zero_result_cause));
error= 0;
@@ -5378,7 +5376,8 @@ best_access_path(JOIN *join,
!ref_or_null_part)
{ /* use eq key */
max_key_part= (uint) ~0;
- if ((key_flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME)
+ if ((key_flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME ||
+ test(key_flags & HA_EXT_NOSAME))
{
tmp = prev_record_reads(join->positions, idx, found_ref);
records=1.0;
@@ -7966,18 +7965,23 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j,
*ref_key=0; // end_marker
if (j->type == JT_FT)
DBUG_RETURN(0);
+ ulong key_flags= j->table->actual_key_flags(keyinfo);
if (j->type == JT_CONST)
j->table->const_table= 1;
- else if (((j->table->actual_key_flags(keyinfo) &
- (HA_NOSAME | HA_NULL_PART_KEY))
- != HA_NOSAME) ||
+ else if (((key_flags & (HA_NOSAME | HA_NULL_PART_KEY))!= HA_NOSAME) ||
keyparts != j->table->actual_n_key_parts(keyinfo) ||
null_ref_key)
{
- /* Must read with repeat */
- j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF;
- j->ref.null_ref_key= null_ref_key;
- j->ref.null_ref_part= null_ref_part;
+ if (test(key_flags & HA_EXT_NOSAME) && keyparts == keyinfo->ext_key_parts &&
+ !null_ref_key)
+ j->type= JT_EQ_REF;
+ else
+ {
+ /* Must read with repeat */
+ j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF;
+ j->ref.null_ref_key= null_ref_key;
+ j->ref.null_ref_part= null_ref_part;
+ }
}
else if (keyuse_uses_no_tables)
{
@@ -9137,7 +9141,7 @@ void JOIN::drop_unused_derived_keys()
JOIN_TAB *tab;
for (tab= first_linear_tab(this, WITHOUT_CONST_TABLES);
tab;
- tab= next_linear_tab(this, tab, WITHOUT_BUSH_ROOTS))
+ tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS))
{
TABLE *table=tab->table;
@@ -10603,9 +10607,22 @@ void JOIN::cleanup(bool full)
if (full)
{
+ JOIN_TAB *sort_tab= first_linear_tab(this, WITHOUT_CONST_TABLES);
+ if (pre_sort_join_tab)
+ {
+ if (sort_tab && sort_tab->select == pre_sort_join_tab->select)
+ {
+ pre_sort_join_tab->select= NULL;
+ }
+ else
+ clean_pre_sort_join_tab();
+ }
+
for (tab= first_linear_tab(this, WITH_CONST_TABLES); tab;
tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS))
+ {
tab->cleanup();
+ }
}
else
{
@@ -16479,6 +16496,17 @@ int safe_index_read(JOIN_TAB *tab)
}
+/**
+ Reads content of constant table
+
+ @param tab table
+ @param pos position of table in query plan
+
+ @retval 0 ok, one row was found or one NULL-complemented row was created
+ @retval -1 ok, no row was found and no NULL-complemented row was created
+ @retval 1 error
+*/
+
static int
join_read_const_table(JOIN_TAB *tab, POSITION *pos)
{
@@ -16597,6 +16625,16 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
}
+/**
+ Read a constant table when there is at most one matching row, using a table
+ scan.
+
+ @param tab Table to read
+
+ @retval 0 Row was found
+ @retval -1 Row was not found
+ @retval 1 Got an error (other than row not found) during read
+*/
static int
join_read_system(JOIN_TAB *tab)
{
@@ -16629,12 +16667,9 @@ join_read_system(JOIN_TAB *tab)
@param tab Table to read
- @retval
- 0 Row was found
- @retval
- -1 Row was not found
- @retval
- 1 Got an error (other than row not found) during read
+ @retval 0 Row was found
+ @retval -1 Row was not found
+ @retval 1 Got an error (other than row not found) during read
*/
static int
@@ -18469,15 +18504,18 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
*/
if (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE ||
- quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_INTERSECT ||
+ quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_INTERSECT ||
quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT)
- goto use_filesort;
- ref_key= select->quick->index;
- ref_key_parts= select->quick->used_key_parts;
+ ref_key= MAX_KEY;
+ else
+ {
+ ref_key= select->quick->index;
+ ref_key_parts= select->quick->used_key_parts;
+ }
}
- if (ref_key >= 0)
+ if (ref_key >= 0 && ref_key != MAX_KEY)
{
/*
We come here when there is a REF key.
@@ -18849,6 +18887,8 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
TABLE *table;
SQL_SELECT *select;
JOIN_TAB *tab;
+ int err= 0;
+ bool quick_created= FALSE;
DBUG_ENTER("create_sort_index");
if (join->table_count == join->const_tables)
@@ -18856,18 +18896,61 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
tab= join->join_tab + join->const_tables;
table= tab->table;
select= tab->select;
+
+ JOIN_TAB *save_pre_sort_join_tab= NULL;
+ if (join->pre_sort_join_tab)
+ {
+ /*
+ we've already been in this function, and stashed away the original access
+ method in join->pre_sort_join_tab, restore it now.
+ */
+
+ /* First, restore state of the handler */
+ if (join->pre_sort_index != MAX_KEY)
+ {
+ if (table->file->ha_index_or_rnd_end())
+ goto err;
+ if (join->pre_sort_idx_pushed_cond)
+ {
+ table->file->idx_cond_push(join->pre_sort_index,
+ join->pre_sort_idx_pushed_cond);
+ }
+ }
+ else
+ {
+ if (table->file->ha_index_or_rnd_end() ||
+ table->file->ha_rnd_init(TRUE))
+ goto err;
+ }
+
+ /* Second, restore access method parameters */
+ tab->records= join->pre_sort_join_tab->records;
+ tab->select= join->pre_sort_join_tab->select;
+ tab->select_cond= join->pre_sort_join_tab->select_cond;
+ tab->type= join->pre_sort_join_tab->type;
+ tab->read_first_record= join->pre_sort_join_tab->read_first_record;
+
+ save_pre_sort_join_tab= join->pre_sort_join_tab;
+ join->pre_sort_join_tab= NULL;
+ }
+ else
+ {
+ /*
+ Save index #, save index condition. Do it right now, because MRR may
+ */
+ if (table->file->inited == handler::INDEX)
+ {
+ join->pre_sort_index= table->file->active_index;
+ join->pre_sort_idx_pushed_cond= table->file->pushed_idx_cond;
+ // no need to save key_read
+ }
+ else
+ join->pre_sort_index= MAX_KEY;
+ }
/* Currently ORDER BY ... LIMIT is not supported in subqueries. */
DBUG_ASSERT(join->group_list || !join->is_in_subquery());
- /*
- If we have a select->quick object that is created outside of
- create_sort_index() and this is part of a subquery that
- potentially can be executed multiple times then we should not
- delete the quick object on exit from this function.
- */
- bool keep_quick= select && select->quick && join->join_tab_save;
-
/*
When there is SQL_BIG_RESULT do not sort using index for GROUP BY,
and thus force sorting on disk unless a group min-max optimization
@@ -18919,7 +19002,7 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
get_quick_select_for_ref(thd, table, &tab->ref,
tab->found_records))))
goto err;
- DBUG_ASSERT(!keep_quick);
+ quick_created= TRUE;
}
}
@@ -18935,7 +19018,27 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
table->sort.found_records=filesort(thd, table,join->sortorder, length,
select, filesort_limit, 0,
&examined_rows);
+
+ if (quick_created)
+ {
+ /* This will delete the quick select. */
+ select->cleanup();
+ }
+
+ if (!join->pre_sort_join_tab)
+ {
+ if (save_pre_sort_join_tab)
+ join->pre_sort_join_tab= save_pre_sort_join_tab;
+ else if (!(join->pre_sort_join_tab= (JOIN_TAB*)thd->alloc(sizeof(JOIN_TAB))))
+ goto err;
+ }
+
+ *(join->pre_sort_join_tab)= *tab;
+
+ /*TODO: here, close the index scan, cancel index-only read. */
tab->records= table->sort.found_records; // For SQL_CALC_ROWS
+#if 0
+ /* MariaDB doesn't need the following: */
if (select)
{
/*
@@ -18952,6 +19055,7 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
tablesort_result_cache= table->sort.io_cache;
table->sort.io_cache= NULL;
+ // select->cleanup(); // filesort did select
/*
If a quick object was created outside of create_sort_index()
that might be reused, then do not call select->cleanup() since
@@ -18974,18 +19078,61 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
// Restore the output resultset
table->sort.io_cache= tablesort_result_cache;
}
+#endif
+ tab->select=NULL;
tab->set_select_cond(NULL, __LINE__);
- tab->last_inner= 0;
- tab->first_unmatched= 0;
tab->type=JT_ALL; // Read with normal read_record
tab->read_first_record= join_init_read_record;
+ tab->table->file->ha_index_or_rnd_end();
+
+ if (err)
+ goto err;
+
tab->join->examined_rows+=examined_rows;
- table->disable_keyread(); // Restore if we used indexes
DBUG_RETURN(table->sort.found_records == HA_POS_ERROR);
err:
DBUG_RETURN(-1);
}
+
+void JOIN::clean_pre_sort_join_tab()
+{
+ //TABLE *table= pre_sort_join_tab->table;
+ /*
+ Note: we can come here for fake_select_lex object. That object will have
+ the table already deleted by st_select_lex_unit::cleanup().
+ We rely on that fake_select_lex didn't have quick select.
+ */
+#if 0
+ if (pre_sort_join_tab->select && pre_sort_join_tab->select->quick)
+ {
+ /*
+ We need to preserve tablesort's output resultset here, because
+ QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT (called by
+ SQL_SELECT::cleanup()) may free it assuming it's the result of the quick
+ select operation that we no longer need. Note that all the other parts of
+ this data structure are cleaned up when
+ QUICK_INDEX_MERGE_SELECT::get_next encounters end of data, so the next
+ SQL_SELECT::cleanup() call changes sort.io_cache alone.
+ */
+ IO_CACHE *tablesort_result_cache;
+
+ tablesort_result_cache= table->sort.io_cache;
+ table->sort.io_cache= NULL;
+ pre_sort_join_tab->select->cleanup();
+ table->quick_keys.clear_all(); // as far as we cleanup select->quick
+ table->intersect_keys.clear_all();
+ table->sort.io_cache= tablesort_result_cache;
+ }
+#endif
+ //table->disable_keyread(); // Restore if we used indexes
+ if (pre_sort_join_tab->select && pre_sort_join_tab->select->quick)
+ {
+ pre_sort_join_tab->select->cleanup();
+ }
+}
+
+
/*****************************************************************************
Remove duplicates from tmp table
This should be recoded to add a unique index to the table and remove
@@ -20465,40 +20612,66 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
res_selected_fields.empty();
res_all_fields.empty();
- uint i, border= all_fields.elements - elements;
- for (i= 0; (item= it++); i++)
+ uint border= all_fields.elements - elements;
+ for (uint i= 0; (item= it++); i++)
{
Field *field;
-
- if ((item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) ||
- (item->type() == Item::FUNC_ITEM &&
- ((Item_func*)item)->functype() == Item_func::SUSERVAR_FUNC))
+ if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
item_field= item;
- else
+ else if (item->type() == Item::FIELD_ITEM)
+ item_field= item->get_tmp_table_item(thd);
+ else if (item->type() == Item::FUNC_ITEM &&
+ ((Item_func*)item)->functype() == Item_func::SUSERVAR_FUNC)
{
- if (item->type() == Item::FIELD_ITEM)
+ field= item->get_tmp_table_field();
+ if (field != NULL)
{
- item_field= item->get_tmp_table_item(thd);
+ /*
+ Replace "@:=<expression>" with "@:=<tmp table column>". Otherwise,
+ we would re-evaluate <expression>, and if expression were
+ a subquery, this would access already-unlocked tables.
+ */
+ Item_func_set_user_var* suv=
+ new Item_func_set_user_var((Item_func_set_user_var*) item);
+ Item_field *new_field= new Item_field(field);
+ if (!suv || !new_field || suv->fix_fields(thd, (Item**)&suv))
+ DBUG_RETURN(true); // Fatal error
+ ((Item *)suv)->name= item->name;
+ /*
+ We are replacing the argument of Item_func_set_user_var after its
+ value has been read. The argument's null_value should be set by
+ now, so we must set it explicitly for the replacement argument
+ since the null_value may be read without any preceeding call to
+ val_*().
+ */
+ new_field->update_null_value();
+ List<Item> list;
+ list.push_back(new_field);
+ suv->set_arguments(list);
+ item_field= suv;
}
- else if ((field= item->get_tmp_table_field()))
+ else
+ item_field= item;
+ }
+ else if ((field= item->get_tmp_table_field()))
+ {
+ if (item->type() == Item::SUM_FUNC_ITEM && field->table->group)
+ item_field= ((Item_sum*) item)->result_item(field);
+ else
+ item_field= (Item*) new Item_field(field);
+ if (!item_field)
+ DBUG_RETURN(true); // Fatal error
+
+ if (item->real_item()->type() != Item::FIELD_ITEM)
+ field->orig_table= 0;
+ item_field->name= item->name;
+ if (item->type() == Item::REF_ITEM)
{
- if (item->type() == Item::SUM_FUNC_ITEM && field->table->group)
- item_field= ((Item_sum*) item)->result_item(field);
- else
- item_field= (Item*) new Item_field(field);
- if (!item_field)
- DBUG_RETURN(TRUE); // Fatal error
-
- if (item->real_item()->type() != Item::FIELD_ITEM)
- field->orig_table= 0;
- item_field->name= item->name;
- if (item->type() == Item::REF_ITEM)
- {
- Item_field *ifield= (Item_field *) item_field;
- Item_ref *iref= (Item_ref *) item;
- ifield->table_name= iref->table_name;
- ifield->db_name= iref->db_name;
- }
+ Item_field *ifield= (Item_field *) item_field;
+ Item_ref *iref= (Item_ref *) item;
+ ifield->table_name= iref->table_name;
+ ifield->db_name= iref->db_name;
+ }
#ifndef DBUG_OFF
if (!item_field->name)
{
@@ -20510,20 +20683,20 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
item_field->name= sql_strmake(str.ptr(),str.length());
}
#endif
- }
- else
- item_field= item;
}
+ else
+ item_field= item;
+
res_all_fields.push_back(item_field);
ref_pointer_array[((i < border)? all_fields.elements-i-1 : i-border)]=
item_field;
}
List_iterator_fast<Item> itr(res_all_fields);
- for (i= 0; i < border; i++)
+ for (uint i= 0; i < border; i++)
itr++;
itr.sublist(res_selected_fields, elements);
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(false);
}
@@ -22703,6 +22876,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
ha_rows table_records= table->file->stats.records;
bool group= join && join->group && order == join->group_list;
ha_rows ref_key_quick_rows= HA_POS_ERROR;
+ const bool has_limit= (select_limit_arg != HA_POS_ERROR);
/*
If not used with LIMIT, only use keys if the whole query can be
@@ -22727,7 +22901,8 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
else
keys= usable_keys;
- if (ref_key >= 0 && table->covering_keys.is_set(ref_key))
+ if (ref_key >= 0 && ref_key != MAX_KEY &&
+ table->covering_keys.is_set(ref_key))
ref_key_quick_rows= table->quick_rows[ref_key];
if (join)
@@ -22834,7 +23009,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
be included into the result set.
*/
if (select_limit > table_records/rec_per_key)
- select_limit= table_records;
+ select_limit= table_records;
else
select_limit= (ha_rows) (select_limit*rec_per_key);
} /* group */
@@ -22916,7 +23091,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
*new_key= best_key;
*new_key_direction= best_key_direction;
- *new_select_limit= best_select_limit;
+ *new_select_limit= has_limit ? best_select_limit : table_records;
if (new_used_key_parts != NULL)
*new_used_key_parts= best_key_parts;
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 118a684ab62..e4687b4f00c 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -897,6 +897,14 @@ protected:
public:
JOIN_TAB *join_tab, **best_ref;
+
+ /*
+ Saved join_tab for pre_sorting. create_sort_index() will save here..
+ */
+ JOIN_TAB *pre_sort_join_tab;
+ uint pre_sort_index;
+ Item *pre_sort_idx_pushed_cond;
+ void clean_pre_sort_join_tab();
/*
For "Using temporary+Using filesort" queries, JOIN::join_tab can point to
@@ -1279,6 +1287,8 @@ public:
outer_ref_cond= pseudo_bits_cond= NULL;
in_to_exists_where= NULL;
in_to_exists_having= NULL;
+
+ pre_sort_join_tab= NULL;
}
int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 1952a0c58b3..d585521fc99 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -3883,8 +3883,9 @@ end:
/* Restore original LEX value, statement's arena and THD arena values. */
lex_end(thd->lex);
- if (i_s_arena.free_list)
- i_s_arena.free_items();
+ // Free items, before restoring backup_arena below.
+ DBUG_ASSERT(i_s_arena.free_list == NULL);
+ thd->free_items();
/*
For safety reset list of open temporary tables before closing
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 5e8b182e3e8..5eec93f3254 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -7462,7 +7462,7 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to,
}
prev_insert_id= to->file->next_insert_id;
if (to->vfield)
- update_virtual_fields(thd, to, TRUE);
+ update_virtual_fields(thd, to, VCOL_UPDATE_FOR_WRITE);
if (thd->is_error())
{
error= 1;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 6fb01899da2..241e332736a 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -560,7 +560,9 @@ int mysql_update(THD *thd,
while (!(error=info.read_record(&info)) && !thd->killed)
{
if (table->vfield)
- update_virtual_fields(thd, table);
+ update_virtual_fields(thd, table,
+ table->triggers ? VCOL_UPDATE_ALL :
+ VCOL_UPDATE_FOR_READ);
thd->examined_row_count++;
if (!select || (error= select->skip_record(thd)) > 0)
{
@@ -676,7 +678,9 @@ int mysql_update(THD *thd,
while (!(error=info.read_record(&info)) && !thd->killed)
{
if (table->vfield)
- update_virtual_fields(thd, table);
+ update_virtual_fields(thd, table,
+ table->triggers ? VCOL_UPDATE_ALL :
+ VCOL_UPDATE_FOR_READ);
thd->examined_row_count++;
if (!select || select->skip_record(thd) > 0)
{
diff --git a/sql/table.cc b/sql/table.cc
index c0e27b9a962..cc3ab6f8c36 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -981,7 +981,6 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
keyinfo->ext_key_part_map= 0;
if (share->use_ext_keys && i)
{
- keyinfo->ext_key_flags= keyinfo->flags | HA_NOSAME;
keyinfo->ext_key_part_map= 0;
for (j= 0;
j < first_key_parts && keyinfo->ext_key_parts < MAX_REF_PARTS;
@@ -1002,7 +1001,9 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
keyinfo->ext_key_parts++;
keyinfo->ext_key_part_map|= 1 << j;
}
- }
+ }
+ if (j == first_key_parts)
+ keyinfo->ext_key_flags= keyinfo->flags | HA_NOSAME | HA_EXT_NOSAME;
}
share->ext_key_parts+= keyinfo->ext_key_parts;
}
@@ -6415,22 +6416,25 @@ bool is_simple_order(ORDER *order)
@param thd Thread handle
@param table The TABLE object
- @param for_write Requests to compute only fields needed for write
+ @param vcol_update_mode Specifies what virtual column are computed
@details
The function computes the values of the virtual columns of the table and
stores them in the table record buffer.
- Only fields from vcol_set are computed, and, when the flag for_write is not
- set to TRUE, a virtual field is computed only if it's not stored.
- The flag for_write is set to TRUE for row insert/update operations.
-
+ If vcol_update_mode is set to VCOL_UPDATE_ALL then all virtual column are
+ computed. Otherwise, only fields from vcol_set are computed: all of them,
+ if vcol_update_mode is set to VCOL_UPDATE_FOR_WRITE, and, only those with
+ the stored_in_db flag set to false, if vcol_update_mode is equal to
+ VCOL_UPDATE_FOR_READ.
+
@retval
0 Success
@retval
>0 Error occurred when storing a virtual field value
*/
-int update_virtual_fields(THD *thd, TABLE *table, bool for_write)
+int update_virtual_fields(THD *thd, TABLE *table,
+ enum enum_vcol_update_mode vcol_update_mode)
{
DBUG_ENTER("update_virtual_fields");
Field **vfield_ptr, *vfield;
@@ -6443,9 +6447,9 @@ int update_virtual_fields(THD *thd, TABLE *table, bool for_write)
{
vfield= (*vfield_ptr);
DBUG_ASSERT(vfield->vcol_info && vfield->vcol_info->expr_item);
- /* Only update those fields that are marked in the vcol_set bitmap */
- if (bitmap_is_set(table->vcol_set, vfield->field_index) &&
- (for_write || !vfield->stored_in_db))
+ if ((bitmap_is_set(table->vcol_set, vfield->field_index) &&
+ (vcol_update_mode == VCOL_UPDATE_FOR_WRITE || !vfield->stored_in_db)) ||
+ vcol_update_mode == VCOL_UPDATE_ALL)
{
/* Compute the actual value of the virtual fields */
error= vfield->vcol_info->expr_item->save_in_field(vfield, 0);
diff --git a/sql/table.h b/sql/table.h
index 1a24fde6111..59e142eaa20 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -299,6 +299,13 @@ enum tmp_table_type
};
enum release_type { RELEASE_NORMAL, RELEASE_WAIT_FOR_DROP };
+enum enum_vcol_update_mode
+{
+ VCOL_UPDATE_FOR_READ= 0,
+ VCOL_UPDATE_FOR_WRITE,
+ VCOL_UPDATE_ALL
+};
+
typedef struct st_filesort_info
{
IO_CACHE *io_cache; /* If sorted through filesort */
diff --git a/sql/threadpool_common.cc b/sql/threadpool_common.cc
index 7e5bbd11c69..6b956768287 100644
--- a/sql/threadpool_common.cc
+++ b/sql/threadpool_common.cc
@@ -257,7 +257,7 @@ static scheduler_functions tp_scheduler_functions=
tp_add_connection, // add_connection
tp_wait_begin, // thd_wait_begin
tp_wait_end, // thd_wait_end
- tp_post_kill_notification, // post_kill_notification
+ post_kill_notification, // post_kill_notification
NULL, // end_thread
tp_end // end
};
diff --git a/sql/threadpool_unix.cc b/sql/threadpool_unix.cc
index f5ea771883d..da38d64fa4d 100644
--- a/sql/threadpool_unix.cc
+++ b/sql/threadpool_unix.cc
@@ -173,7 +173,6 @@ static int create_worker(thread_group_t *thread_group);
static void *worker_main(void *param);
static void check_stall(thread_group_t *thread_group);
static void connection_abort(connection_t *connection);
-void tp_post_kill_notification(THD *thd);
static void set_wait_timeout(connection_t *connection);
static void set_next_timeout_check(ulonglong abstime);
static void print_pool_blocked_message(bool);
@@ -444,7 +443,7 @@ static void timeout_check(pool_timer_t *timer)
/* Wait timeout exceeded, kill connection. */
mysql_mutex_lock(&thd->LOCK_thd_data);
thd->killed = KILL_CONNECTION;
- tp_post_kill_notification(thd);
+ post_kill_notification(thd);
mysql_mutex_unlock(&thd->LOCK_thd_data);
}
else
@@ -1259,21 +1258,6 @@ static void connection_abort(connection_t *connection)
/**
- MySQL scheduler callback : kill connection
-*/
-
-void tp_post_kill_notification(THD *thd)
-{
- DBUG_ENTER("tp_post_kill_notification");
- if (current_thd == thd || thd->system_thread)
- DBUG_VOID_RETURN;
-
- if (thd->net.vio)
- vio_shutdown(thd->net.vio, SHUT_RD);
- DBUG_VOID_RETURN;
-}
-
-/**
MySQL scheduler callback: wait begin
*/
diff --git a/sql/threadpool_win.cc b/sql/threadpool_win.cc
index 6359f81cd2b..72e03da2453 100644
--- a/sql/threadpool_win.cc
+++ b/sql/threadpool_win.cc
@@ -544,22 +544,6 @@ void tp_end(void)
}
}
-/**
- Notify pool about connection being killed.
-*/
-void tp_post_kill_notification(THD *thd)
-{
- if (current_thd == thd)
- return; /* There is nothing to do.*/
-
- if (thd->system_thread)
- return; /* Will crash if we attempt to kill system thread. */
-
- Vio *vio= thd->net.vio;
-
- vio_shutdown(vio, SD_BOTH);
-
-}
/*
Handle read completion/notification.
diff --git a/storage/heap/CMakeLists.txt b/storage/heap/CMakeLists.txt
index 0b9372bf224..3a0c2e7271c 100644
--- a/storage/heap/CMakeLists.txt
+++ b/storage/heap/CMakeLists.txt
@@ -21,8 +21,10 @@ SET(HEAP_SOURCES _check.c _rectest.c hp_block.c hp_clear.c hp_close.c hp_create
MYSQL_ADD_PLUGIN(heap ${HEAP_SOURCES} STORAGE_ENGINE MANDATORY RECOMPILE_FOR_EMBEDDED)
-ADD_EXECUTABLE(hp_test1 hp_test1.c)
-TARGET_LINK_LIBRARIES(hp_test1 heap mysys dbug strings)
+IF(WITH_UNIT_TESTS)
+ ADD_EXECUTABLE(hp_test1 hp_test1.c)
+ TARGET_LINK_LIBRARIES(hp_test1 heap mysys dbug strings)
-ADD_EXECUTABLE(hp_test2 hp_test2.c)
-TARGET_LINK_LIBRARIES(hp_test2 heap mysys dbug strings)
+ ADD_EXECUTABLE(hp_test2 hp_test2.c)
+ TARGET_LINK_LIBRARIES(hp_test2 heap mysys dbug strings)
+ENDIF() \ No newline at end of file
diff --git a/storage/heap/hp_rkey.c b/storage/heap/hp_rkey.c
index d0cbb94eb0e..138d65f9d25 100644
--- a/storage/heap/hp_rkey.c
+++ b/storage/heap/hp_rkey.c
@@ -65,7 +65,7 @@ int heap_rkey(HP_INFO *info, uchar *record, int inx, const uchar *key,
info->update= HA_STATE_NO_KEY;
DBUG_RETURN(my_errno);
}
- if (!(keyinfo->flag & HA_NOSAME))
+ if ((keyinfo->flag & (HA_NOSAME | HA_NULL_PART_KEY)) != HA_NOSAME)
memcpy(info->lastkey, key, (size_t) keyinfo->length);
}
memcpy(record, pos, (size_t) share->reclength);
diff --git a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c
index c9dc9e20072..a6fdff72f50 100644
--- a/storage/innobase/btr/btr0btr.c
+++ b/storage/innobase/btr/btr0btr.c
@@ -3263,6 +3263,7 @@ btr_compress(
if (adjust) {
nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor));
+ ut_ad(nth_rec > 0);
}
/* Decide the page to which we try to merge and which will inherit
@@ -3498,6 +3499,7 @@ func_exit:
mem_heap_free(heap);
if (adjust) {
+ ut_ad(nth_rec > 0);
btr_cur_position(
index,
page_rec_get_nth(merge_block->frame, nth_rec),
@@ -4011,8 +4013,22 @@ btr_index_page_validate(
{
page_cur_t cur;
ibool ret = TRUE;
+#ifndef DBUG_OFF
+ ulint nth = 1;
+#endif /* !DBUG_OFF */
page_cur_set_before_first(block, &cur);
+
+ /* Directory slot 0 should only contain the infimum record. */
+ DBUG_EXECUTE_IF("check_table_rec_next",
+ ut_a(page_rec_get_nth_const(
+ page_cur_get_page(&cur), 0)
+ == cur.rec);
+ ut_a(page_dir_slot_get_n_owned(
+ page_dir_get_nth_slot(
+ page_cur_get_page(&cur), 0))
+ == 1););
+
page_cur_move_to_next(&cur);
for (;;) {
@@ -4026,6 +4042,16 @@ btr_index_page_validate(
return(FALSE);
}
+ /* Verify that page_rec_get_nth_const() is correctly
+ retrieving each record. */
+ DBUG_EXECUTE_IF("check_table_rec_next",
+ ut_a(cur.rec == page_rec_get_nth_const(
+ page_cur_get_page(&cur),
+ page_rec_get_n_recs_before(
+ cur.rec)));
+ ut_a(nth++ == page_rec_get_n_recs_before(
+ cur.rec)););
+
page_cur_move_to_next(&cur);
}
diff --git a/storage/innobase/page/page0cur.c b/storage/innobase/page/page0cur.c
index d49b121afab..55ba72b4fe9 100644
--- a/storage/innobase/page/page0cur.c
+++ b/storage/innobase/page/page0cur.c
@@ -1902,6 +1902,7 @@ page_cur_delete_rec(
/* Save to local variables some data associated with current_rec */
cur_slot_no = page_dir_find_owner_slot(current_rec);
+ ut_ad(cur_slot_no > 0);
cur_dir_slot = page_dir_get_nth_slot(page, cur_slot_no);
cur_n_owned = page_dir_slot_get_n_owned(cur_dir_slot);
diff --git a/storage/innobase/page/page0page.c b/storage/innobase/page/page0page.c
index 946ec0e1c43..78135b0aff2 100644
--- a/storage/innobase/page/page0page.c
+++ b/storage/innobase/page/page0page.c
@@ -796,8 +796,8 @@ zip_reorganize:
/* Before copying, "ret" was the predecessor
of the predefined supremum record. If it was
the predefined infimum record, then it would
- still be the infimum. Thus, the assertion
- ut_a(ret_pos > 0) would fail here. */
+ still be the infimum, and we would have
+ ret_pos == 0. */
if (UNIV_UNLIKELY
(!page_zip_reorganize(new_block, index, mtr))) {
@@ -1052,6 +1052,7 @@ page_delete_rec_list_end(
n_owned = rec_get_n_owned_new(rec2) - count;
slot_index = page_dir_find_owner_slot(rec2);
+ ut_ad(slot_index > 0);
slot = page_dir_get_nth_slot(page, slot_index);
} else {
rec_t* rec2 = rec;
@@ -1067,6 +1068,7 @@ page_delete_rec_list_end(
n_owned = rec_get_n_owned_old(rec2) - count;
slot_index = page_dir_find_owner_slot(rec2);
+ ut_ad(slot_index > 0);
slot = page_dir_get_nth_slot(page, slot_index);
}
@@ -1471,6 +1473,10 @@ page_rec_get_nth_const(
ulint n_owned;
const rec_t* rec;
+ if (nth == 0) {
+ return(page_get_infimum_rec(page));
+ }
+
ut_ad(nth < UNIV_PAGE_SIZE / (REC_N_NEW_EXTRA_BYTES + 1));
for (i = 0;; i++) {
diff --git a/storage/maria/CMakeLists.txt b/storage/maria/CMakeLists.txt
index 9ca198873d1..0f30f8f3156 100644
--- a/storage/maria/CMakeLists.txt
+++ b/storage/maria/CMakeLists.txt
@@ -50,6 +50,10 @@ MYSQL_ADD_PLUGIN(aria ${ARIA_SOURCES}
STORAGE_ENGINE STATIC_ONLY DEFAULT
RECOMPILE_FOR_EMBEDDED)
+IF(NOT WITH_ARIA_STORAGE_ENGINE)
+ RETURN()
+ENDIF()
+
TARGET_LINK_LIBRARIES(aria myisam)
MYSQL_ADD_EXECUTABLE(aria_ftdump maria_ftdump.c COMPONENT Server)
@@ -83,6 +87,7 @@ IF(WITH_UNIT_TESTS)
ADD_EXECUTABLE(ma_sp_test ma_sp_test.c)
TARGET_LINK_LIBRARIES(ma_sp_test aria)
+ ADD_SUBDIRECTORY(unittest)
ENDIF()
IF (MSVC)
@@ -92,4 +97,3 @@ ENDIF()
CMAKE_DEPENDENT_OPTION(USE_ARIA_FOR_TMP_TABLES "Use Aria for temporary tables" ON
"WITH_ARIA_STORAGE_ENGINE" OFF)
-ADD_SUBDIRECTORY(unittest)
diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc
index 785fe5d8226..1278d951a16 100644
--- a/storage/maria/ha_maria.cc
+++ b/storage/maria/ha_maria.cc
@@ -2484,9 +2484,10 @@ int ha_maria::info(uint flag)
errkey= maria_info.errkey;
my_store_ptr(dup_ref, ref_length, maria_info.dup_key_pos);
}
- /* Faster to always update, than to do it based on flag */
- stats.update_time= maria_info.update_time;
- stats.auto_increment_value= maria_info.auto_increment;
+ if (flag & HA_STATUS_TIME)
+ stats.update_time= maria_info.update_time;
+ if (flag & HA_STATUS_AUTO)
+ stats.auto_increment_value= maria_info.auto_increment;
return 0;
}
diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c
index 8e0407c9d7a..71faa11fd2b 100644
--- a/storage/maria/ma_blockrec.c
+++ b/storage/maria/ma_blockrec.c
@@ -4669,7 +4669,7 @@ int _ma_read_block_record2(MARIA_HA *info, uchar *record,
uchar *data, uchar *end_of_data)
{
MARIA_SHARE *share= info->s;
- uchar *UNINIT_VAR(field_length_data), *blob_buffer, *start_of_data;
+ uchar *UNINIT_VAR(field_length_data), *UNINIT_VAR(blob_buffer), *start_of_data;
uint flag, null_bytes, cur_null_bytes, row_extents, field_lengths;
my_bool found_blob= 0;
MARIA_EXTENT_CURSOR extent;
@@ -4677,8 +4677,6 @@ int _ma_read_block_record2(MARIA_HA *info, uchar *record,
MARIA_ROW *cur_row= &info->cur_row;
DBUG_ENTER("_ma_read_block_record2");
- LINT_INIT(blob_buffer);
-
start_of_data= data;
flag= (uint) (uchar) data[0];
cur_null_bytes= share->base.original_null_bytes;
@@ -5106,6 +5104,7 @@ int _ma_read_block_record(MARIA_HA *info, uchar *record,
uchar *data, *end_of_data, *buff;
uint offset;
uint block_size= share->block_size;
+ int ret;
DBUG_ENTER("_ma_read_block_record");
DBUG_PRINT("enter", ("rowid: %lu page: %lu rownr: %u",
(ulong) record_pos,
@@ -5127,7 +5126,8 @@ int _ma_read_block_record(MARIA_HA *info, uchar *record,
my_errno= HA_ERR_RECORD_DELETED; /* File crashed */
DBUG_RETURN(HA_ERR_RECORD_DELETED);
}
- DBUG_RETURN(_ma_read_block_record2(info, record, data, end_of_data));
+ ret= _ma_read_block_record2(info, record, data, end_of_data);
+ DBUG_RETURN(ret);
}
diff --git a/storage/maria/ma_rrnd.c b/storage/maria/ma_rrnd.c
index 24c4bfdd467..8c35c71c95e 100644
--- a/storage/maria/ma_rrnd.c
+++ b/storage/maria/ma_rrnd.c
@@ -30,6 +30,7 @@
int maria_rrnd(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS filepos)
{
+ int ret;
DBUG_ENTER("maria_rrnd");
DBUG_ASSERT(filepos != HA_OFFSET_ERROR);
@@ -40,5 +41,6 @@ int maria_rrnd(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS filepos)
DBUG_RETURN(my_errno);
info->cur_row.lastpos= filepos; /* Remember for update */
- DBUG_RETURN((*info->s->read_record)(info, buf, filepos));
+ ret= (*info->s->read_record)(info, buf, filepos);
+ DBUG_RETURN(ret);
}
diff --git a/storage/maria/ma_test2.c b/storage/maria/ma_test2.c
index 5d0882f3fcb..ea1978b4ee5 100644
--- a/storage/maria/ma_test2.c
+++ b/storage/maria/ma_test2.c
@@ -50,7 +50,7 @@ static ulong pagecache_size=8192*32;
static enum data_file_type record_type= DYNAMIC_RECORD;
static uint keys=MARIA_KEYS,recant=1000;
-static uint16 key1[1001],key3[5000];
+static uint16 key1[1001],key3[5001];
static uchar record[300],record2[300],key[100],key2[100];
static uchar read_record[300],read_record2[300],read_record3[300];
static HA_KEYSEG glob_keyseg[MARIA_KEYS][MAX_PARTS];
@@ -222,7 +222,7 @@ int main(int argc, char *argv[])
blob_buffer=0;
for (i=1000 ; i>0 ; i--) key1[i]=0;
- for (i=4999 ; i>0 ; i--) key3[i]=0;
+ for (i=5000 ; i>0 ; i--) key3[i]=0;
if (!silent)
printf("- Creating maria-file\n");
@@ -280,7 +280,7 @@ int main(int argc, char *argv[])
if (key3[n3] == 1 && first_key <3 && first_key+keys >= 3)
{
printf("Error: Didn't get error when writing second key: '%8d'\n",n3);
- goto err;
+ goto err2;
}
write_count++; key1[n1]++; key3[n3]=1;
}
@@ -341,7 +341,7 @@ int main(int argc, char *argv[])
key, keyinfo[0].seg[0].length))
{
printf("Found wrong record when searching for key: \"%s\"\n",key);
- goto err;
+ goto err2;
}
if (opt_delete == (uint) remove_count) /* While testing */
goto end;
@@ -394,7 +394,7 @@ int main(int argc, char *argv[])
printf("Found wrong record when searching for key: \"%s\"; Found \"%.*s\"\n",
key, keyinfo[0].seg[0].length,
read_record+keyinfo[0].seg[0].start);
- goto err;
+ goto err2;
}
if (use_blob)
{
@@ -455,7 +455,7 @@ int main(int argc, char *argv[])
if (memcmp(read_record,read_record2,reclength) != 0)
{
printf("maria_rsame didn't find same record\n");
- goto err;
+ goto err2;
}
info.recpos=maria_position(file);
if (maria_rfirst(file,read_record2,0) ||
@@ -463,7 +463,7 @@ int main(int argc, char *argv[])
memcmp(read_record,read_record2,reclength) != 0)
{
printf("maria_rsame_with_pos didn't find same record\n");
- goto err;
+ goto err2;
}
{
int skr;
@@ -484,7 +484,7 @@ int main(int argc, char *argv[])
if (ant != dupp_keys)
{
printf("next: Found: %d keys of %d\n",ant,dupp_keys);
- goto err;
+ goto err2;
}
ant=0;
while (maria_rprev(file,read_record3,0) == 0 &&
@@ -492,7 +492,7 @@ int main(int argc, char *argv[])
if (ant != dupp_keys)
{
printf("prev: Found: %d records of %d\n",ant,dupp_keys);
- goto err;
+ goto err2;
}
/* Check of maria_rnext_same */
@@ -504,7 +504,7 @@ int main(int argc, char *argv[])
if (ant != dupp_keys || my_errno != HA_ERR_END_OF_FILE)
{
printf("maria_rnext_same: Found: %d records of %d\n",ant,dupp_keys);
- goto err;
+ goto err2;
}
}
@@ -531,7 +531,7 @@ int main(int argc, char *argv[])
printf("Can't find last record\n");
DBUG_DUMP("record2", read_record2, reclength);
DBUG_DUMP("record3", read_record3, reclength);
- goto err;
+ goto err2;
}
ant=1;
while (maria_rprev(file,read_record3,0) == 0 && ant < write_count+10)
@@ -539,12 +539,12 @@ int main(int argc, char *argv[])
if (ant != write_count - opt_delete)
{
printf("prev: I found: %d records of %d\n",ant,write_count);
- goto err;
+ goto err2;
}
if (bcmp(read_record,read_record3,reclength))
{
printf("Can't find first record\n");
- goto err;
+ goto err2;
}
if (!silent)
@@ -585,7 +585,7 @@ int main(int argc, char *argv[])
if (bcmp(read_record+start,key,(uint) i))
{
puts("Didn't find right record");
- goto err;
+ goto err2;
}
}
#endif
@@ -605,7 +605,7 @@ int main(int argc, char *argv[])
if (ant != dupp_keys-1)
{
printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-1);
- goto err;
+ goto err2;
}
}
if (dupp_keys>4)
@@ -623,7 +623,7 @@ int main(int argc, char *argv[])
if (ant != dupp_keys-2)
{
printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-2);
- goto err;
+ goto err2;
}
}
if (dupp_keys > 6)
@@ -643,7 +643,7 @@ int main(int argc, char *argv[])
if (ant != dupp_keys-3)
{
printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-3);
- goto err;
+ goto err2;
}
if (!silent)
@@ -658,7 +658,7 @@ int main(int argc, char *argv[])
if (ant != dupp_keys-4)
{
printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-4);
- goto err;
+ goto err2;
}
}
@@ -687,7 +687,7 @@ int main(int argc, char *argv[])
if (i != write_count && i != write_count - opt_delete)
{
printf("Found wrong number of rows while scanning table\n");
- goto err;
+ goto err2;
}
if (maria_rsame_with_pos(file,read_record,0,info.recpos))
@@ -695,7 +695,7 @@ int main(int argc, char *argv[])
if (bcmp(read_record,read_record2,reclength) != 0)
{
printf("maria_rsame_with_pos didn't find same record\n");
- goto err;
+ goto err2;
}
for (i=min(2,keys) ; i-- > 0 ;)
@@ -704,7 +704,7 @@ int main(int argc, char *argv[])
if (bcmp(read_record,read_record2,reclength) != 0)
{
printf("maria_rsame didn't find same record\n");
- goto err;
+ goto err2;
}
}
if (!silent)
@@ -731,7 +731,7 @@ int main(int argc, char *argv[])
{
printf("maria_records_range returned %ld; Should be about %ld\n",
(long) range_records,(long) info.records);
- goto err;
+ goto err2;
}
if (verbose)
{
@@ -768,7 +768,7 @@ int main(int argc, char *argv[])
{
printf("maria_records_range for key: %d returned %lu; Should be about %lu\n",
i, (ulong) range_records, (ulong) records);
- goto err;
+ goto err2;
}
if (verbose && records)
{
@@ -783,13 +783,13 @@ int main(int argc, char *argv[])
if (!silent)
printf("- maria_info\n");
maria_status(file,&info,HA_STATUS_VARIABLE | HA_STATUS_CONST);
- if (info.records != write_count-opt_delete || info.deleted > opt_delete + update
- || info.keys != keys)
+ if (info.records != write_count-opt_delete ||
+ info.deleted > opt_delete + update || info.keys != keys)
{
puts("Wrong info from maria_info");
printf("Got: records: %lu delete: %lu i_keys: %d\n",
(ulong) info.records, (ulong) info.deleted, info.keys);
- goto err;
+ goto err2;
}
if (verbose)
{
@@ -828,7 +828,7 @@ int main(int argc, char *argv[])
printf("scan with cache: I can only find: %d records of %d\n",
ant,write_count-opt_delete);
maria_scan_end(file);
- goto err;
+ goto err2;
}
if (maria_extra(file,HA_EXTRA_NO_CACHE,0))
{
@@ -848,7 +848,7 @@ int main(int argc, char *argv[])
printf("scan with cache: I can only find: %d records of %d\n",
ant,write_count-opt_delete);
maria_scan_end(file);
- goto err;
+ goto err2;
}
maria_scan_end(file);
@@ -872,7 +872,7 @@ int main(int argc, char *argv[])
{
printf("maria_rrnd didn't advance filepointer; old: %ld, new: %ld\n",
(long) lastpos, (long) info.recpos);
- goto err;
+ goto err2;
}
lastpos=info.recpos;
if (error == 0)
@@ -897,7 +897,7 @@ int main(int argc, char *argv[])
printf("Found blob with wrong info at %ld\n",(long) lastpos);
maria_scan_end(file);
my_errno= 0;
- goto err;
+ goto err2;
}
}
}
@@ -920,7 +920,7 @@ int main(int argc, char *argv[])
printf("Deleted only %d of %d records (%d parts)\n",opt_delete,write_count,
found_parts);
maria_scan_end(file);
- goto err;
+ goto err2;
}
if (testflag == 6)
goto end;
@@ -1021,10 +1021,11 @@ reads: %10lu\n",
return(0);
err:
printf("got error: %d when using MARIA-database\n",my_errno);
+err2:
if (file)
{
if (maria_commit(file))
- goto err;
+ printf("got error: %d when using MARIA-database\n",my_errno);
maria_close(file);
}
maria_end();
diff --git a/storage/pbxt/mysql-test/main/r/rpl_mmap.result b/storage/pbxt/mysql-test/main/r/rpl_mmap.result
new file mode 100644
index 00000000000..b1f5f15d012
--- /dev/null
+++ b/storage/pbxt/mysql-test/main/r/rpl_mmap.result
@@ -0,0 +1,16 @@
+include/master-slave.inc
+[connection master]
+create table t1 (a int) engine=InnoDB;
+create table t2 (a int) engine=pbxt;
+begin;
+insert into t1 values (1);
+insert into t2 values (2);
+commit;
+select * from t1;
+a
+1
+select * from t2;
+a
+2
+drop table t1, t2;
+include/rpl_end.inc
diff --git a/storage/pbxt/mysql-test/main/t/rpl_mmap.test b/storage/pbxt/mysql-test/main/t/rpl_mmap.test
new file mode 100644
index 00000000000..a6f50e1b6b3
--- /dev/null
+++ b/storage/pbxt/mysql-test/main/t/rpl_mmap.test
@@ -0,0 +1,21 @@
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+create table t1 (a int) engine=InnoDB;
+create table t2 (a int) engine=pbxt;
+
+begin;
+insert into t1 values (1);
+insert into t2 values (2);
+commit;
+
+sync_slave_with_master;
+connection slave;
+
+select * from t1;
+select * from t2;
+
+connection master;
+drop table t1, t2;
+
+--source include/rpl_end.inc
diff --git a/storage/perfschema/CMakeLists.txt b/storage/perfschema/CMakeLists.txt
index 7702b7365af..528e7806755 100644
--- a/storage/perfschema/CMakeLists.txt
+++ b/storage/perfschema/CMakeLists.txt
@@ -74,6 +74,6 @@ SET(PERFSCHEMA_SOURCES ha_perfschema.h
)
MYSQL_ADD_PLUGIN(perfschema ${PERFSCHEMA_SOURCES} STORAGE_ENGINE DEFAULT STATIC_ONLY)
-IF(WITH_PERFSCHEMA_STORAGE_ENGINE)
+IF(WITH_PERFSCHEMA_STORAGE_ENGINE AND WITH_UNIT_TESTS)
ADD_SUBDIRECTORY(unittest)
ENDIF()
diff --git a/storage/xtradb/btr/btr0btr.c b/storage/xtradb/btr/btr0btr.c
index 3f11684cb34..ed97fc5bd58 100644
--- a/storage/xtradb/btr/btr0btr.c
+++ b/storage/xtradb/btr/btr0btr.c
@@ -1891,6 +1891,7 @@ btr_root_raise_and_insert(
root = btr_cur_get_page(cursor);
root_block = btr_cur_get_block(cursor);
root_page_zip = buf_block_get_page_zip(root_block);
+ ut_ad(page_get_n_recs(root) > 0);
#ifdef UNIV_ZIP_DEBUG
ut_a(!root_page_zip || page_zip_validate(root_page_zip, root));
#endif /* UNIV_ZIP_DEBUG */
@@ -2371,12 +2372,20 @@ btr_insert_on_non_leaf_level_func(
BTR_CONT_MODIFY_TREE,
&cursor, 0, file, line, mtr);
- err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG
- | BTR_KEEP_SYS_FLAG
- | BTR_NO_UNDO_LOG_FLAG,
- &cursor, tuple, &rec,
- &dummy_big_rec, 0, NULL, mtr);
- ut_a(err == DB_SUCCESS);
+ ut_ad(cursor.flag == BTR_CUR_BINARY);
+
+ err = btr_cur_optimistic_insert(
+ BTR_NO_LOCKING_FLAG | BTR_KEEP_SYS_FLAG
+ | BTR_NO_UNDO_LOG_FLAG, &cursor, tuple, &rec,
+ &dummy_big_rec, 0, NULL, mtr);
+
+ if (err == DB_FAIL) {
+ err = btr_cur_pessimistic_insert(
+ BTR_NO_LOCKING_FLAG | BTR_KEEP_SYS_FLAG
+ | BTR_NO_UNDO_LOG_FLAG,
+ &cursor, tuple, &rec, &dummy_big_rec, 0, NULL, mtr);
+ ut_a(err == DB_SUCCESS);
+ }
}
/**************************************************************//**
diff --git a/storage/xtradb/btr/btr0cur.c b/storage/xtradb/btr/btr0cur.c
index 26db7329b7e..61c07ac792e 100644
--- a/storage/xtradb/btr/btr0cur.c
+++ b/storage/xtradb/btr/btr0cur.c
@@ -1412,7 +1412,12 @@ fail_err:
if (UNIV_UNLIKELY(reorg)) {
ut_a(zip_size);
- ut_a(*rec);
+ /* It's possible for rec to be NULL if the
+ page is compressed. This is because a
+ reorganized page may become incompressible. */
+ if (!*rec) {
+ goto fail;
+ }
}
}
@@ -1548,20 +1553,9 @@ btr_cur_pessimistic_insert(
ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, btr_cur_get_block(cursor),
MTR_MEMO_PAGE_X_FIX));
- /* Try first an optimistic insert; reset the cursor flag: we do not
- assume anything of how it was positioned */
-
cursor->flag = BTR_CUR_BINARY;
- err = btr_cur_optimistic_insert(flags, cursor, entry, rec,
- big_rec, n_ext, thr, mtr);
- if (err != DB_FAIL) {
-
- return(err);
- }
-
- /* Retry with a pessimistic insert. Check locks and write to undo log,
- if specified */
+ /* Check locks and write to undo log, if specified */
err = btr_cur_ins_lock_and_undo(flags, cursor, entry,
thr, mtr, &dummy_inh);
@@ -2188,8 +2182,12 @@ any_extern:
goto err_exit;
}
- max_size = old_rec_size
- + page_get_max_insert_size_after_reorganize(page, 1);
+ /* We do not attempt to reorganize if the page is compressed.
+ This is because the page may fail to compress after reorganization. */
+ max_size = page_zip
+ ? page_get_max_insert_size(page, 1)
+ : (old_rec_size
+ + page_get_max_insert_size_after_reorganize(page, 1));
if (!(((max_size >= BTR_CUR_PAGE_REORGANIZE_LIMIT)
&& (max_size >= new_rec_size))
@@ -2559,7 +2557,12 @@ make_external:
err = DB_SUCCESS;
goto return_after_reservations;
} else {
- ut_a(optim_err != DB_UNDERFLOW);
+ /* If the page is compressed and it initially
+ compresses very well, and there is a subsequent insert
+ of a badly-compressing record, it is possible for
+ btr_cur_optimistic_update() to return DB_UNDERFLOW and
+ btr_cur_insert_if_possible() to return FALSE. */
+ ut_a(page_zip || optim_err != DB_UNDERFLOW);
/* Out of space: reset the free bits. */
if (!dict_index_is_clust(index)
@@ -2588,7 +2591,9 @@ make_external:
was_first = page_cur_is_before_first(page_cursor);
/* Lock checks and undo logging were already performed by
- btr_cur_upd_lock_and_undo(). */
+ btr_cur_upd_lock_and_undo(). We do not try
+ btr_cur_optimistic_insert() because
+ btr_cur_insert_if_possible() already failed above. */
err = btr_cur_pessimistic_insert(BTR_NO_UNDO_LOG_FLAG
| BTR_NO_LOCKING_FLAG
diff --git a/storage/xtradb/btr/btr0pcur.c b/storage/xtradb/btr/btr0pcur.c
index 0de7b63f92d..b335e2c8aee 100644
--- a/storage/xtradb/btr/btr0pcur.c
+++ b/storage/xtradb/btr/btr0pcur.c
@@ -354,44 +354,39 @@ btr_pcur_restore_position_func(
/* Restore the old search mode */
cursor->search_mode = old_mode;
- if (btr_pcur_is_on_user_rec(cursor)) {
- switch (cursor->rel_pos) {
- case BTR_PCUR_ON:
- if (!cmp_dtuple_rec(
- tuple, btr_pcur_get_rec(cursor),
- rec_get_offsets(btr_pcur_get_rec(cursor),
- index, NULL,
- ULINT_UNDEFINED, &heap))) {
-
- /* We have to store the NEW value for
- the modify clock, since the cursor can
- now be on a different page! But we can
- retain the value of old_rec */
-
- cursor->block_when_stored =
- btr_pcur_get_block(cursor);
- cursor->modify_clock =
- buf_block_get_modify_clock(
- cursor->block_when_stored);
- cursor->old_stored = BTR_PCUR_OLD_STORED;
-
- mem_heap_free(heap);
-
- return(TRUE);
- }
-
- break;
- case BTR_PCUR_BEFORE:
- page_cur_move_to_next(btr_pcur_get_page_cur(cursor));
- break;
- case BTR_PCUR_AFTER:
- page_cur_move_to_prev(btr_pcur_get_page_cur(cursor));
- break;
+ switch (cursor->rel_pos) {
+ case BTR_PCUR_ON:
+ if (btr_pcur_is_on_user_rec(cursor)
+ && !cmp_dtuple_rec(
+ tuple, btr_pcur_get_rec(cursor),
+ rec_get_offsets(btr_pcur_get_rec(cursor),
+ index, NULL,
+ ULINT_UNDEFINED, &heap))) {
+
+ /* We have to store the NEW value for
+ the modify clock, since the cursor can
+ now be on a different page! But we can
+ retain the value of old_rec */
+
+ cursor->block_when_stored =
+ btr_pcur_get_block(cursor);
+ cursor->modify_clock =
+ buf_block_get_modify_clock(
+ cursor->block_when_stored);
+ cursor->old_stored = BTR_PCUR_OLD_STORED;
+
+ mem_heap_free(heap);
+
+ return(TRUE);
+ }
#ifdef UNIV_DEBUG
- default:
- ut_error;
+ /* fall through */
+ case BTR_PCUR_BEFORE:
+ case BTR_PCUR_AFTER:
+ break;
+ default:
+ ut_error;
#endif /* UNIV_DEBUG */
- }
}
mem_heap_free(heap);
diff --git a/storage/xtradb/buf/buf0buf.c b/storage/xtradb/buf/buf0buf.c
index 6ce77372dac..bbc1042ca78 100644
--- a/storage/xtradb/buf/buf0buf.c
+++ b/storage/xtradb/buf/buf0buf.c
@@ -336,15 +336,6 @@ be effective only if PFS_GROUP_BUFFER_SYNC is defined. */
# endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
#endif /* UNIV_PFS_MUTEX || UNIV_PFS_RWLOCK */
-/** A chunk of buffers. The buffer pool is allocated in chunks. (moved to buf0buf.h)*/
-//struct buf_chunk_struct{
-// ulint mem_size; /*!< allocated size of the chunk */
-// ulint size; /*!< size of frames[] and blocks[] */
-// void* mem; /*!< pointer to the memory area which
-// was allocated for the frames */
-// buf_block_t* blocks; /*!< array of buffer control blocks */
-//};
-
/********************************************************************//**
Gets the smallest oldest_modification lsn for any page in the pool. Returns
zero if all modified pages have been flushed to disk.
@@ -1028,7 +1019,8 @@ buf_chunk_init(
/*===========*/
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
buf_chunk_t* chunk, /*!< out: chunk of buffers */
- ulint mem_size) /*!< in: requested size in bytes */
+ ulint mem_size, /*!< in: requested size in bytes */
+ ibool populate) /*!< in: virtual page preallocation */
{
buf_block_t* block;
byte* frame;
@@ -1044,7 +1036,7 @@ buf_chunk_init(
+ (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
chunk->mem_size = mem_size;
- chunk->mem = os_mem_alloc_large(&chunk->mem_size);
+ chunk->mem = os_mem_alloc_large(&chunk->mem_size, populate);
if (UNIV_UNLIKELY(chunk->mem == NULL)) {
@@ -1254,6 +1246,7 @@ buf_pool_init_instance(
/*===================*/
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
ulint buf_pool_size, /*!< in: size in bytes */
+ ibool populate, /*!< in: virtual page preallocation */
ulint instance_no) /*!< in: id of the instance */
{
ulint i;
@@ -1286,7 +1279,7 @@ buf_pool_init_instance(
UT_LIST_INIT(buf_pool->free);
- if (!buf_chunk_init(buf_pool, chunk, buf_pool_size)) {
+ if (!buf_chunk_init(buf_pool, chunk, buf_pool_size, populate)) {
mem_free(chunk);
mem_free(buf_pool);
@@ -1381,6 +1374,7 @@ ulint
buf_pool_init(
/*==========*/
ulint total_size, /*!< in: size of the total pool in bytes */
+ ibool populate, /*!< in: virtual page preallocation */
ulint n_instances) /*!< in: number of instances */
{
ulint i;
@@ -1398,7 +1392,7 @@ buf_pool_init(
for (i = 0; i < n_instances; i++) {
buf_pool_t* ptr = &buf_pool_ptr[i];
- if (buf_pool_init_instance(ptr, size, i) != DB_SUCCESS) {
+ if (buf_pool_init_instance(ptr, size, populate, i) != DB_SUCCESS) {
/* Free all the instances created so far. */
buf_pool_free(i);
@@ -4973,7 +4967,7 @@ buf_stats_aggregate_pool_info(
Collect buffer pool stats information for a buffer pool. Also
record aggregated stats if there are more than one buffer pool
in the server */
-static
+UNIV_INTERN
void
buf_stats_get_pool_info(
/*====================*/
diff --git a/storage/xtradb/buf/buf0lru.c b/storage/xtradb/buf/buf0lru.c
index e8300107f3d..a6a1f8dcf9c 100644
--- a/storage/xtradb/buf/buf0lru.c
+++ b/storage/xtradb/buf/buf0lru.c
@@ -2384,7 +2384,7 @@ buf_LRU_free_one_page(
#endif
mutex_t* block_mutex = buf_page_get_mutex(bpage);
- ut_ad(buf_pool_mutex_own(buf_pool));
+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
ut_ad(mutex_own(block_mutex));
if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
diff --git a/storage/xtradb/buf/buf0rea.c b/storage/xtradb/buf/buf0rea.c
index c29dcbf0444..67379d614a0 100644
--- a/storage/xtradb/buf/buf0rea.c
+++ b/storage/xtradb/buf/buf0rea.c
@@ -64,7 +64,7 @@ buf_read_page_handle_error(
== BUF_BLOCK_FILE_PAGE);
/* First unfix and release lock on the bpage */
- buf_pool_mutex_enter(buf_pool);
+ mutex_enter(&buf_pool->LRU_list_mutex);
mutex_enter(buf_page_get_mutex(bpage));
ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ);
ut_ad(bpage->buf_fix_count == 0);
@@ -85,7 +85,7 @@ buf_read_page_handle_error(
buf_pool->n_pend_reads--;
mutex_exit(buf_page_get_mutex(bpage));
- buf_pool_mutex_exit(buf_pool);
+ mutex_exit(&buf_pool->LRU_list_mutex);
}
/********************************************************************//**
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index b84de8f5787..59acbdb504d 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -906,7 +906,7 @@ extern "C" UNIV_INTERN
ibool
thd_is_replication_slave_thread(
/*============================*/
- void* thd) /*!< in: thread handle (THD*) */
+ const void* thd) /*!< in: thread handle (THD*) */
{
return((ibool) thd_slave_thread((THD*) thd));
}
@@ -2516,6 +2516,122 @@ ha_innobase::init_table_handle_for_HANDLER(void)
reset_template();
}
+#ifdef HAVE_REPLICATION
+/* The last read master log coordinates in the slave info file */
+static char master_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN] = "";
+static int master_log_pos;
+/* The slave relay log coordinates in the slave info file after startup */
+static char original_relay_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN] = "";
+static int original_relay_log_pos;
+/* The master log coordinates in the slave info file after startup */
+static char original_master_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN] = "";
+static int original_master_log_pos;
+#endif
+
+/*****************************************************************//**
+Overwrites the MySQL relay log info file with the current master and relay log
+coordinates from InnoDB. Skips overwrite if the master log position did not
+change from the last overwrite. If the InnoDB master log position is equal
+to position that was read from the info file on startup before any overwrites,
+restores the original positions. */
+static
+void
+innobase_do_overwrite_relay_log_info(void)
+/*======================================*/
+{
+#ifdef HAVE_REPLICATION
+ char info_fname[FN_REFLEN];
+ File info_fd = -1;
+ int error = 0;
+ char buff[FN_REFLEN*2+22*2+4];
+ char *relay_info_log_pos;
+ size_t buf_len;
+
+ if (master_log_fname[0] == '\0') {
+ fprintf(stderr,
+ "InnoDB: something wrong with relay-log.info. "
+ "InnoDB will not overwrite it.\n");
+ return;
+ }
+
+ if (strcmp(master_log_fname, trx_sys_mysql_master_log_name) == 0
+ && master_log_pos == trx_sys_mysql_master_log_pos) {
+ fprintf(stderr,
+ "InnoDB: InnoDB and relay-log.info are synchronized. "
+ "InnoDB will not overwrite it.\n");
+ return;
+ }
+
+ /* If we overwrite the file back to the original master log position,
+ restore the original relay log position too. This is required because
+ we might have rolled back a prepared transaction and restored the
+ original master log position from the InnoDB trx sys header, but the
+ corresponding relay log position points to an already-purged file. */
+ if (strcmp(original_master_log_fname, trx_sys_mysql_master_log_name)
+ == 0
+ && (original_master_log_pos == trx_sys_mysql_master_log_pos)) {
+
+ strncpy(trx_sys_mysql_relay_log_name, original_relay_log_fname,
+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+ trx_sys_mysql_relay_log_pos = original_relay_log_pos;
+ }
+
+ fn_format(info_fname, relay_log_info_file, mysql_data_home, "",
+ MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH);
+
+ if (access(info_fname, F_OK)) {
+ /* File does not exist */
+ error = 1;
+ goto skip_overwrite;
+ }
+
+ /* File exists */
+ info_fd = my_open(info_fname, O_RDWR|O_BINARY, MYF(MY_WME));
+ if (info_fd < 0) {
+ error = 1;
+ goto skip_overwrite;
+ }
+
+ relay_info_log_pos = strmov(buff, trx_sys_mysql_relay_log_name);
+ *relay_info_log_pos ++= '\n';
+ relay_info_log_pos = longlong2str(trx_sys_mysql_relay_log_pos,
+ relay_info_log_pos, 10);
+ *relay_info_log_pos ++= '\n';
+ relay_info_log_pos = strmov(relay_info_log_pos,
+ trx_sys_mysql_master_log_name);
+ *relay_info_log_pos ++= '\n';
+ relay_info_log_pos = longlong2str(trx_sys_mysql_master_log_pos,
+ relay_info_log_pos, 10);
+ *relay_info_log_pos = '\n';
+
+ buf_len = (relay_info_log_pos - buff) + 1;
+ if (my_write(info_fd, (uchar *)buff, buf_len, MY_WME) != buf_len) {
+ error = 1;
+ } else if (my_sync(info_fd, MY_WME)) {
+ error = 1;
+ }
+
+ if (info_fd >= 0) {
+ my_close(info_fd, MYF(0));
+ }
+
+ strncpy(master_log_fname, trx_sys_mysql_relay_log_name,
+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+ master_log_pos = trx_sys_mysql_master_log_pos;
+
+skip_overwrite:
+ if (error) {
+ fprintf(stderr,
+ "InnoDB: ERROR: error occured during overwriting "
+ "relay-log.info.\n");
+ } else {
+ fprintf(stderr,
+ "InnoDB: relay-log.info was overwritten.\n");
+ }
+#endif
+}
+
+
/*********************************************************************//**
Opens an InnoDB database.
@return 0 on success, error code on failure */
@@ -2654,12 +2770,13 @@ innobase_init(
#ifdef HAVE_REPLICATION
#ifdef MYSQL_SERVER
/* read master log position from relay-log.info if exists */
- char fname[FN_REFLEN+128];
- int pos;
+ char info_fname[FN_REFLEN];
+ char relay_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN];
+ int relay_log_pos;
int info_fd;
IO_CACHE info_file;
- fname[0] = '\0';
+ info_fname[0] = '\0';
if(innobase_overwrite_relay_log_info) {
@@ -2668,13 +2785,14 @@ innobase_init(
" Updates by other storage engines may not be synchronized.\n");
bzero((char*) &info_file, sizeof(info_file));
- fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
+ fn_format(info_fname, relay_log_info_file, mysql_data_home, "", 4+32);
int error=0;
- if (!access(fname,F_OK)) {
+ if (!access(info_fname,F_OK)) {
/* exist */
- if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
+ if ((info_fd = my_open(info_fname, O_RDWR | O_BINARY,
+ MYF(MY_WME))) < 0) {
error=1;
} else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
READ_CACHE, 0L, 0, MYF(MY_WME))) {
@@ -2685,16 +2803,18 @@ innobase_init(
relay_info_error:
if (info_fd >= 0)
my_close(info_fd, MYF(0));
- fname[0] = '\0';
+ master_log_fname[0] = '\0';
goto skip_relay;
}
} else {
- fname[0] = '\0';
+ master_log_fname[0] = '\0';
goto skip_relay;
}
- if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") || /* dummy (it is relay-log) */
- init_intvar_from_file(&pos, &info_file, BIN_LOG_HEADER_SIZE)) {
+ if (init_strvar_from_file(relay_log_fname, sizeof(relay_log_fname),
+ &info_file, "")
+ || /* dummy (it is relay-log) */ init_intvar_from_file(
+ &relay_log_pos, &info_file, BIN_LOG_HEADER_SIZE)) {
end_io_cache(&info_file);
error=1;
goto relay_info_error;
@@ -2703,13 +2823,19 @@ relay_info_error:
fprintf(stderr,
"InnoDB: relay-log.info is detected.\n"
"InnoDB: relay log: position %u, file name %s\n",
- pos, fname);
+ relay_log_pos, relay_log_fname);
+
+ strncpy(trx_sys_mysql_relay_log_name, relay_log_fname,
+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+ trx_sys_mysql_relay_log_pos = (ib_int64_t) relay_log_pos;
- strncpy(trx_sys_mysql_relay_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
- trx_sys_mysql_relay_log_pos = (ib_int64_t) pos;
+ strncpy(original_relay_log_fname, relay_log_fname,
+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+ original_relay_log_pos = relay_log_pos;
- if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") ||
- init_intvar_from_file(&pos, &info_file, 0)) {
+ if (init_strvar_from_file(master_log_fname, sizeof(master_log_fname),
+ &info_file, "")
+ || init_intvar_from_file(&master_log_pos, &info_file, 0)) {
end_io_cache(&info_file);
error=1;
goto relay_info_error;
@@ -2717,10 +2843,15 @@ relay_info_error:
fprintf(stderr,
"InnoDB: master log: position %u, file name %s\n",
- pos, fname);
+ master_log_pos, master_log_fname);
+
+ strncpy(trx_sys_mysql_master_log_name, master_log_fname,
+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+ trx_sys_mysql_master_log_pos = (ib_int64_t) master_log_pos;
- strncpy(trx_sys_mysql_master_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
- trx_sys_mysql_master_log_pos = (ib_int64_t) pos;
+ strncpy(original_master_log_fname, master_log_fname,
+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+ original_master_log_pos = master_log_pos;
end_io_cache(&info_file);
if (info_fd >= 0)
@@ -3055,75 +3186,9 @@ innobase_change_buffering_inited_ok:
goto mem_free_and_error;
}
-#ifdef HAVE_REPLICATION
-#ifdef MYSQL_SERVER
if(innobase_overwrite_relay_log_info) {
- /* If InnoDB progressed from relay-log.info, overwrite it */
- if (fname[0] == '\0') {
- fprintf(stderr,
- "InnoDB: Something is wrong with the file relay-info.log. InnoDB will not overwrite it.\n");
- } else if (0 != strcmp(fname, trx_sys_mysql_master_log_name)
- || pos != trx_sys_mysql_master_log_pos) {
- /* Overwrite relay-log.info */
- bzero((char*) &info_file, sizeof(info_file));
- fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
-
- int error = 0;
-
- if (!access(fname,F_OK)) {
- /* exist */
- if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
- error = 1;
- } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
- WRITE_CACHE, 0L, 0, MYF(MY_WME))) {
- error = 1;
- }
-
- if (error) {
- if (info_fd >= 0)
- my_close(info_fd, MYF(0));
- goto skip_overwrite;
- }
- } else {
- error = 1;
- goto skip_overwrite;
- }
-
- char buff[FN_REFLEN*2+22*2+4], *pos;
-
- my_b_seek(&info_file, 0L);
- pos=strmov(buff, trx_sys_mysql_relay_log_name);
- *pos++='\n';
- pos=longlong10_to_str(trx_sys_mysql_relay_log_pos, pos, 10);
- *pos++='\n';
- pos=strmov(pos, trx_sys_mysql_master_log_name);
- *pos++='\n';
- pos=longlong10_to_str(trx_sys_mysql_master_log_pos, pos, 10);
- *pos='\n';
-
- if (my_b_write(&info_file, (uchar*) buff, (size_t) (pos-buff)+1))
- error = 1;
- if (flush_io_cache(&info_file))
- error = 1;
-
- end_io_cache(&info_file);
- if (info_fd >= 0)
- my_close(info_fd, MYF(0));
-skip_overwrite:
- if (error) {
- fprintf(stderr,
- "InnoDB: ERROR: An error occurred while overwriting relay-log.info.\n");
- } else {
- fprintf(stderr,
- "InnoDB: The file relay-log.info was successfully overwritten.\n");
- }
- } else {
- fprintf(stderr,
- "InnoDB: InnoDB and relay-log.info are synchronized. InnoDB will not overwrite it.\n");
- }
+ innobase_do_overwrite_relay_log_info();
}
-#endif /* MYSQL_SERVER */
-#endif /* HAVE_REPLICATION */
innobase_old_blocks_pct = buf_LRU_old_ratio_update(
innobase_old_blocks_pct, TRUE);
@@ -3226,6 +3291,32 @@ innobase_alter_table_flags(
| HA_INPLACE_ADD_PK_INDEX_NO_READ_WRITE);
}
+/****************************************************************//**
+Copy the current replication position from MySQL to a transaction. */
+static
+void
+innobase_copy_repl_coords_to_trx(
+/*=============================*/
+ const THD* thd, /*!< in: thread handle */
+ trx_t* trx) /*!< in/out: transaction */
+{
+ if (thd && thd_is_replication_slave_thread(thd)) {
+ /* Update the replication position info inside InnoDB.
+ In embedded server, does nothing. */
+ const char *log_file_name, *group_relay_log_name;
+ ulonglong log_pos, relay_log_pos;
+ bool res = rpl_get_position_info(&log_file_name, &log_pos,
+ &group_relay_log_name,
+ &relay_log_pos);
+ if (res) {
+ trx->mysql_master_log_file_name = log_file_name;
+ trx->mysql_master_log_pos = (ib_int64_t)log_pos;
+ trx->mysql_relay_log_file_name = group_relay_log_name;
+ trx->mysql_relay_log_pos = (ib_int64_t)relay_log_pos;
+ }
+ }
+}
+
/*****************************************************************//**
Commits a transaction in an InnoDB database. */
static
@@ -3235,27 +3326,12 @@ innobase_commit_low(
trx_t* trx) /*!< in: transaction handle */
{
if (trx_is_started(trx)) {
-#ifdef HAVE_REPLICATION
-#ifdef MYSQL_SERVER
- THD *thd=current_thd;
-
- if (thd && thd_is_replication_slave_thread(thd)) {
- /* Update the replication position info inside InnoDB.
- In embedded server, does nothing. */
- const char *log_file_name, *group_relay_log_name;
- ulonglong log_pos, relay_log_pos;
- bool res = rpl_get_position_info(&log_file_name, &log_pos,
- &group_relay_log_name,
- &relay_log_pos);
- if (res) {
- trx->mysql_master_log_file_name = log_file_name;
- trx->mysql_master_log_pos = (ib_int64_t)log_pos;
- trx->mysql_relay_log_file_name = group_relay_log_name;
- trx->mysql_relay_log_pos = (ib_int64_t)relay_log_pos;
- }
- }
-#endif /* MYSQL_SERVER */
-#endif /* HAVE_REPLICATION */
+
+ /* Save the current replication position for write to trx sys
+ header for undo purposes, see the comment at corresponding call
+ at innobase_xa_prepare(). */
+
+ innobase_copy_repl_coords_to_trx(current_thd, trx);
trx_commit_for_mysql(trx);
}
@@ -3476,6 +3552,9 @@ innobase_commit(
if (all
|| (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
+ DBUG_EXECUTE_IF("crash_innodb_before_commit",
+ DBUG_SUICIDE(););
+
/* Run the fast part of commit if we did not already. */
if (!trx_is_active_commit_ordered(trx)) {
innobase_commit_ordered_2(trx, thd);
@@ -12417,7 +12496,27 @@ innobase_xa_prepare(
ut_ad(trx_is_registered_for_2pc(trx));
+ /* Update the replication position info in current trx. This
+ is different from the binlog position update that happens
+ during XA COMMIT. In contrast to that, the slave position is
+ an actual part of the changes made by this transaction and thus
+ must be updated in the XA PREPARE stage. Since the trx sys
+ header page changes are not undo-logged, again store this
+ position in a different field in the XA COMMIT stage, so that
+ it might be used in case of rollbacks. */
+
+ /* Since currently there might be only one slave SQL thread, we
+ don't need to take any precautions (e.g. prepare_commit_mutex)
+ to ensure position ordering. Revisit this in 5.6 which has
+ both the multi-threaded replication to cause us problems and
+ the group commit to solve them. */
+
+ innobase_copy_repl_coords_to_trx(thd, trx);
+
error = (int) trx_prepare_for_mysql(trx);
+
+ DBUG_EXECUTE_IF("crash_innodb_after_prepare",
+ DBUG_SUICIDE(););
} else {
/* We just mark the SQL statement ended and do not do a
transaction prepare */
@@ -12510,6 +12609,22 @@ innobase_rollback_by_xid(
if (trx) {
int ret = innobase_rollback_trx(trx);
trx_free_for_background(trx);
+
+ if (innobase_overwrite_relay_log_info) {
+
+ /* On rollback of a prepared transaction revert the
+ current slave positions to the ones recorded by the
+ last COMMITTed transaction. This has an effect of
+ undoing the position change caused by the transaction
+ being rolled back. Assumes single-threaded slave SQL
+ thread. If the server has non-master write traffic
+ with XA rollbacks, this will cause additional spurious
+ slave info log overwrites, which should be harmless. */
+
+ trx_sys_print_committed_mysql_master_log_pos();
+ innobase_do_overwrite_relay_log_info();
+ }
+
return(ret);
} else {
return(XAER_NOTA);
@@ -13781,6 +13896,12 @@ static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size,
"The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
NULL, NULL, 128*1024*1024L, 5*1024*1024L, LONGLONG_MAX, 1024*1024L);
+static MYSQL_SYSVAR_BOOL(buffer_pool_populate, srv_buf_pool_populate,
+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
+ "Preallocate (pre-fault) the page frames required for the mapping "
+ "established by the buffer pool memory region. Disabled by default.",
+ NULL, NULL, FALSE);
+
static MYSQL_SYSVAR_LONG(buffer_pool_instances, innobase_buffer_pool_instances,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Number of buffer pool instances, set to higher value on high-end machines to increase scalability",
@@ -14194,6 +14315,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(additional_mem_pool_size),
MYSQL_SYSVAR(autoextend_increment),
MYSQL_SYSVAR(buffer_pool_size),
+ MYSQL_SYSVAR(buffer_pool_populate),
MYSQL_SYSVAR(buffer_pool_instances),
MYSQL_SYSVAR(buffer_pool_shm_key),
MYSQL_SYSVAR(buffer_pool_shm_checksum),
@@ -14342,7 +14464,10 @@ i_s_innodb_buffer_pool_pages,
i_s_innodb_buffer_pool_pages_index,
i_s_innodb_buffer_pool_pages_blob,
i_s_innodb_admin_command,
-i_s_innodb_changed_pages
+i_s_innodb_changed_pages,
+i_s_innodb_buffer_page,
+i_s_innodb_buffer_page_lru,
+i_s_innodb_buffer_stats
maria_declare_plugin_end;
/** @brief Initialize the default value of innodb_commit_concurrency.
diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc
index 57a091ea80d..29a80594344 100644
--- a/storage/xtradb/handler/i_s.cc
+++ b/storage/xtradb/handler/i_s.cc
@@ -64,8 +64,93 @@ extern "C" {
#include "buf0lru.h" /* for XTRA_LRU_[DUMP/RESTORE] */
#include "btr0btr.h" /* for btr_page_get_index_id */
#include "log0online.h"
+#include "btr0btr.h"
+#include "page0zip.h"
+#include "log0log.h"
}
+/** structure associates a name string with a file page type and/or buffer
+page state. */
+struct buffer_page_desc_str_struct{
+ const char* type_str; /*!< String explain the page
+ type/state */
+ ulint type_value; /*!< Page type or page state */
+};
+
+typedef struct buffer_page_desc_str_struct buf_page_desc_str_t;
+
+/** Any states greater than FIL_PAGE_TYPE_LAST would be treated as unknown. */
+#define I_S_PAGE_TYPE_UNKNOWN (FIL_PAGE_TYPE_LAST + 1)
+
+/** We also define I_S_PAGE_TYPE_INDEX as the Index Page's position
+in i_s_page_type[] array */
+#define I_S_PAGE_TYPE_INDEX 1
+
+/** Name string for File Page Types */
+static buf_page_desc_str_t i_s_page_type[] = {
+ {"ALLOCATED", FIL_PAGE_TYPE_ALLOCATED},
+ {"INDEX", FIL_PAGE_INDEX},
+ {"UNDO_LOG", FIL_PAGE_UNDO_LOG},
+ {"INODE", FIL_PAGE_INODE},
+ {"IBUF_FREE_LIST", FIL_PAGE_IBUF_FREE_LIST},
+ {"IBUF_BITMAP", FIL_PAGE_IBUF_BITMAP},
+ {"SYSTEM", FIL_PAGE_TYPE_SYS},
+ {"TRX_SYSTEM", FIL_PAGE_TYPE_TRX_SYS},
+ {"FILE_SPACE_HEADER", FIL_PAGE_TYPE_FSP_HDR},
+ {"EXTENT_DESCRIPTOR", FIL_PAGE_TYPE_XDES},
+ {"BLOB", FIL_PAGE_TYPE_BLOB},
+ {"COMPRESSED_BLOB", FIL_PAGE_TYPE_ZBLOB},
+ {"COMPRESSED_BLOB2", FIL_PAGE_TYPE_ZBLOB2},
+ {"UNKNOWN", I_S_PAGE_TYPE_UNKNOWN}
+};
+
+/* Check if we can hold all page type in a 4 bit value */
+#if I_S_PAGE_TYPE_UNKNOWN > 1<<4
+# error "i_s_page_type[] is too large"
+#endif
+
+/** This structure defines information we will fetch from pages
+currently cached in the buffer pool. It will be used to populate
+table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE */
+struct buffer_page_info_struct{
+ ulint block_id; /*!< Buffer Pool block ID */
+ unsigned space_id:32; /*!< Tablespace ID */
+ unsigned page_num:32; /*!< Page number/offset */
+ unsigned access_time:32; /*!< Time of first access */
+ unsigned pool_id:MAX_BUFFER_POOLS_BITS;
+ /*!< Buffer Pool ID. Must be less than
+ MAX_BUFFER_POOLS */
+ unsigned flush_type:2; /*!< Flush type */
+ unsigned io_fix:2; /*!< type of pending I/O operation */
+ unsigned fix_count:19; /*!< Count of how manyfold this block
+ is bufferfixed */
+ unsigned hashed:1; /*!< Whether hash index has been
+ built on this page */
+ unsigned is_old:1; /*!< TRUE if the block is in the old
+ blocks in buf_pool->LRU_old */
+ unsigned freed_page_clock:31; /*!< the value of
+ buf_pool->freed_page_clock */
+ unsigned zip_ssize:PAGE_ZIP_SSIZE_BITS;
+ /*!< Compressed page size */
+ unsigned page_state:BUF_PAGE_STATE_BITS; /*!< Page state */
+ unsigned page_type:4; /*!< Page type */
+ unsigned num_recs;
+ /*!< Number of records on Page */
+ unsigned data_size;
+ /*!< Sum of the sizes of the records */
+ lsn_t newest_mod; /*!< Log sequence number of
+ the youngest modification */
+ lsn_t oldest_mod; /*!< Log sequence number of
+ the oldest modification */
+ index_id_t index_id; /*!< Index ID if a index page */
+};
+
+typedef struct buffer_page_info_struct buf_page_info_t;
+
+/** maximum number of buffer page info we would cache. */
+#define MAX_BUF_INFO_CACHED 10000
+
+
#define OK(expr) \
if ((expr) != 0) { \
DBUG_RETURN(1); \
@@ -1570,7 +1655,6 @@ i_s_cmpmem_fill_low(
buf_pool = buf_pool_from_array(i);
- //buf_pool_mutex_enter(buf_pool);
mutex_enter(&buf_pool->zip_free_mutex);
for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) {
@@ -1601,7 +1685,6 @@ i_s_cmpmem_fill_low(
}
}
- //buf_pool_mutex_exit(buf_pool);
mutex_exit(&buf_pool->zip_free_mutex);
if (status) {
@@ -1771,6 +1854,1755 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset =
INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
};
+/* Fields of the dynamic table INNODB_BUFFER_POOL_STATS. */
+static ST_FIELD_INFO i_s_innodb_buffer_stats_fields_info[] =
+{
+#define IDX_BUF_STATS_POOL_ID 0
+ {STRUCT_FLD(field_name, "POOL_ID"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_POOL_SIZE 1
+ {STRUCT_FLD(field_name, "POOL_SIZE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_FREE_BUFFERS 2
+ {STRUCT_FLD(field_name, "FREE_BUFFERS"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_LRU_LEN 3
+ {STRUCT_FLD(field_name, "DATABASE_PAGES"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_OLD_LRU_LEN 4
+ {STRUCT_FLD(field_name, "OLD_DATABASE_PAGES"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_FLUSH_LIST_LEN 5
+ {STRUCT_FLD(field_name, "MODIFIED_DATABASE_PAGES"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PENDING_ZIP 6
+ {STRUCT_FLD(field_name, "PENDING_DECOMPRESS"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PENDING_READ 7
+ {STRUCT_FLD(field_name, "PENDING_READS"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_FLUSH_LRU 8
+ {STRUCT_FLD(field_name, "PENDING_FLUSH_LRU"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_FLUSH_LIST 9
+ {STRUCT_FLD(field_name, "PENDING_FLUSH_LIST"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_YOUNG 10
+ {STRUCT_FLD(field_name, "PAGES_MADE_YOUNG"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_NOT_YOUNG 11
+ {STRUCT_FLD(field_name, "PAGES_NOT_MADE_YOUNG"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_YOUNG_RATE 12
+ {STRUCT_FLD(field_name, "PAGES_MADE_YOUNG_RATE"),
+ STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE 13
+ {STRUCT_FLD(field_name, "PAGES_MADE_NOT_YOUNG_RATE"),
+ STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_READ 14
+ {STRUCT_FLD(field_name, "NUMBER_PAGES_READ"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_CREATED 15
+ {STRUCT_FLD(field_name, "NUMBER_PAGES_CREATED"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_WRITTEN 16
+ {STRUCT_FLD(field_name, "NUMBER_PAGES_WRITTEN"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_READ_RATE 17
+ {STRUCT_FLD(field_name, "PAGES_READ_RATE"),
+ STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_CREATE_RATE 18
+ {STRUCT_FLD(field_name, "PAGES_CREATE_RATE"),
+ STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_WRITTEN_RATE 19
+ {STRUCT_FLD(field_name, "PAGES_WRITTEN_RATE"),
+ STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_GET 20
+ {STRUCT_FLD(field_name, "NUMBER_PAGES_GET"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_HIT_RATE 21
+ {STRUCT_FLD(field_name, "HIT_RATE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_MADE_YOUNG_PCT 22
+ {STRUCT_FLD(field_name, "YOUNG_MAKE_PER_THOUSAND_GETS"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_NOT_MADE_YOUNG_PCT 23
+ {STRUCT_FLD(field_name, "NOT_YOUNG_MAKE_PER_THOUSAND_GETS"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_READ_AHREAD 24
+ {STRUCT_FLD(field_name, "NUMBER_PAGES_READ_AHEAD"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_READ_AHEAD_EVICTED 25
+ {STRUCT_FLD(field_name, "NUMBER_READ_AHEAD_EVICTED"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_READ_AHEAD_RATE 26
+ {STRUCT_FLD(field_name, "READ_AHEAD_RATE"),
+ STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_READ_AHEAD_EVICT_RATE 27
+ {STRUCT_FLD(field_name, "READ_AHEAD_EVICTED_RATE"),
+ STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_LRU_IO_SUM 28
+ {STRUCT_FLD(field_name, "LRU_IO_TOTAL"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_LRU_IO_CUR 29
+ {STRUCT_FLD(field_name, "LRU_IO_CURRENT"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_UNZIP_SUM 30
+ {STRUCT_FLD(field_name, "UNCOMPRESS_TOTAL"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_UNZIP_CUR 31
+ {STRUCT_FLD(field_name, "UNCOMPRESS_CURRENT"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ END_OF_ST_FIELD_INFO
+};
+
+/*******************************************************************//**
+Fill Information Schema table INNODB_BUFFER_POOL_STATS for a particular
+buffer pool
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_stats_fill(
+/*==================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ const buf_pool_info_t* info) /*!< in: buffer pool
+ information */
+{
+ TABLE* table;
+ Field** fields;
+
+ DBUG_ENTER("i_s_innodb_stats_fill");
+
+ table = tables->table;
+
+ fields = table->field;
+
+ OK(fields[IDX_BUF_STATS_POOL_ID]->store(info->pool_unique_id));
+
+ OK(fields[IDX_BUF_STATS_POOL_SIZE]->store(info->pool_size));
+
+ OK(fields[IDX_BUF_STATS_LRU_LEN]->store(info->lru_len));
+
+ OK(fields[IDX_BUF_STATS_OLD_LRU_LEN]->store(info->old_lru_len));
+
+ OK(fields[IDX_BUF_STATS_FREE_BUFFERS]->store(info->free_list_len));
+
+ OK(fields[IDX_BUF_STATS_FLUSH_LIST_LEN]->store(
+ info->flush_list_len));
+
+ OK(fields[IDX_BUF_STATS_PENDING_ZIP]->store(info->n_pend_unzip));
+
+ OK(fields[IDX_BUF_STATS_PENDING_READ]->store(info->n_pend_reads));
+
+ OK(fields[IDX_BUF_STATS_FLUSH_LRU]->store(info->n_pending_flush_lru));
+
+ OK(fields[IDX_BUF_STATS_FLUSH_LIST]->store(info->n_pending_flush_list));
+
+ OK(fields[IDX_BUF_STATS_PAGE_YOUNG]->store(info->n_pages_made_young));
+
+ OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG]->store(
+ info->n_pages_not_made_young));
+
+ OK(fields[IDX_BUF_STATS_PAGE_YOUNG_RATE]->store(
+ info->page_made_young_rate));
+
+ OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE]->store(
+ info->page_not_made_young_rate));
+
+ OK(fields[IDX_BUF_STATS_PAGE_READ]->store(info->n_pages_read));
+
+ OK(fields[IDX_BUF_STATS_PAGE_CREATED]->store(info->n_pages_created));
+
+ OK(fields[IDX_BUF_STATS_PAGE_WRITTEN]->store(info->n_pages_written));
+
+ OK(fields[IDX_BUF_STATS_GET]->store(info->n_page_gets));
+
+ OK(fields[IDX_BUF_STATS_PAGE_READ_RATE]->store(info->pages_read_rate));
+
+ OK(fields[IDX_BUF_STATS_PAGE_CREATE_RATE]->store(info->pages_created_rate));
+
+ OK(fields[IDX_BUF_STATS_PAGE_WRITTEN_RATE]->store(info->pages_written_rate));
+
+ if (info->n_page_get_delta) {
+ OK(fields[IDX_BUF_STATS_HIT_RATE]->store(
+ 1000 - (1000 * info->page_read_delta
+ / info->n_page_get_delta)));
+
+ OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(
+ 1000 * info->young_making_delta
+ / info->n_page_get_delta));
+
+ OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(
+ 1000 * info->not_young_making_delta
+ / info->n_page_get_delta));
+ } else {
+ OK(fields[IDX_BUF_STATS_HIT_RATE]->store(0));
+ OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(0));
+ OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(0));
+ }
+
+ OK(fields[IDX_BUF_STATS_READ_AHREAD]->store(info->n_ra_pages_read));
+
+ OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICTED]->store(
+ info->n_ra_pages_evicted));
+
+ OK(fields[IDX_BUF_STATS_READ_AHEAD_RATE]->store(
+ info->pages_readahead_rate));
+
+ OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICT_RATE]->store(
+ info->pages_evicted_rate));
+
+ OK(fields[IDX_BUF_STATS_LRU_IO_SUM]->store(info->io_sum));
+
+ OK(fields[IDX_BUF_STATS_LRU_IO_CUR]->store(info->io_cur));
+
+ OK(fields[IDX_BUF_STATS_UNZIP_SUM]->store(info->unzip_sum));
+
+ OK(fields[IDX_BUF_STATS_UNZIP_CUR]->store( info->unzip_cur));
+
+ DBUG_RETURN(schema_table_store_record(thd, table));
+}
+
+/*******************************************************************//**
+This is the function that loops through each buffer pool and fetch buffer
+pool stats to information schema table: I_S_INNODB_BUFFER_POOL_STATS
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_buffer_stats_fill_table(
+/*===============================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ Item* ) /*!< in: condition (ignored) */
+{
+ int status = 0;
+ buf_pool_info_t* pool_info;
+
+ DBUG_ENTER("i_s_innodb_buffer_fill_general");
+
+ /* Only allow the PROCESS privilege holder to access the stats */
+ if (check_global_access(thd, PROCESS_ACL)) {
+ DBUG_RETURN(0);
+ }
+
+ pool_info = (buf_pool_info_t*) mem_zalloc(
+ srv_buf_pool_instances * sizeof *pool_info);
+
+ /* Walk through each buffer pool */
+ for (ulint i = 0; i < srv_buf_pool_instances; i++) {
+ buf_pool_t* buf_pool;
+
+ buf_pool = buf_pool_from_array(i);
+
+ /* Fetch individual buffer pool info */
+ buf_stats_get_pool_info(buf_pool, i, pool_info);
+
+ status = i_s_innodb_stats_fill(thd, tables, &pool_info[i]);
+
+ /* If something goes wrong, break and return */
+ if (status) {
+ break;
+ }
+ }
+
+ mem_free(pool_info);
+
+ DBUG_RETURN(status);
+}
+
+/*******************************************************************//**
+Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS.
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_buffer_pool_stats_init(
+/*==============================*/
+ void* p) /*!< in/out: table schema object */
+{
+ ST_SCHEMA_TABLE* schema;
+
+ DBUG_ENTER("i_s_innodb_buffer_pool_stats_init");
+
+ schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
+
+ schema->fields_info = i_s_innodb_buffer_stats_fields_info;
+ schema->fill_table = i_s_innodb_buffer_stats_fill_table;
+
+ DBUG_RETURN(0);
+}
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_stats =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_STATS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB Buffer Pool Statistics Information "),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_pool_stats_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
+};
+
+/* Fields of the dynamic table INNODB_BUFFER_POOL_PAGE. */
+static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] =
+{
+#define IDX_BUFFER_POOL_ID 0
+ {STRUCT_FLD(field_name, "POOL_ID"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_BLOCK_ID 1
+ {STRUCT_FLD(field_name, "BLOCK_ID"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_SPACE 2
+ {STRUCT_FLD(field_name, "SPACE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_NUM 3
+ {STRUCT_FLD(field_name, "PAGE_NUMBER"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_TYPE 4
+ {STRUCT_FLD(field_name, "PAGE_TYPE"),
+ STRUCT_FLD(field_length, 64),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_FLUSH_TYPE 5
+ {STRUCT_FLD(field_name, "FLUSH_TYPE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_FIX_COUNT 6
+ {STRUCT_FLD(field_name, "FIX_COUNT"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_HASHED 7
+ {STRUCT_FLD(field_name, "IS_HASHED"),
+ STRUCT_FLD(field_length, 3),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_NEWEST_MOD 8
+ {STRUCT_FLD(field_name, "NEWEST_MODIFICATION"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_OLDEST_MOD 9
+ {STRUCT_FLD(field_name, "OLDEST_MODIFICATION"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_ACCESS_TIME 10
+ {STRUCT_FLD(field_name, "ACCESS_TIME"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_TABLE_NAME 11
+ {STRUCT_FLD(field_name, "TABLE_NAME"),
+ STRUCT_FLD(field_length, 1024),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_INDEX_NAME 12
+ {STRUCT_FLD(field_name, "INDEX_NAME"),
+ STRUCT_FLD(field_length, 1024),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_NUM_RECS 13
+ {STRUCT_FLD(field_name, "NUMBER_RECORDS"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_DATA_SIZE 14
+ {STRUCT_FLD(field_name, "DATA_SIZE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_ZIP_SIZE 15
+ {STRUCT_FLD(field_name, "COMPRESSED_SIZE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_STATE 16
+ {STRUCT_FLD(field_name, "PAGE_STATE"),
+ STRUCT_FLD(field_length, 64),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_IO_FIX 17
+ {STRUCT_FLD(field_name, "IO_FIX"),
+ STRUCT_FLD(field_length, 64),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_IS_OLD 18
+ {STRUCT_FLD(field_name, "IS_OLD"),
+ STRUCT_FLD(field_length, 3),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_FREE_CLOCK 19
+ {STRUCT_FLD(field_name, "FREE_PAGE_CLOCK"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ END_OF_ST_FIELD_INFO
+};
+
+/*******************************************************************//**
+Fill Information Schema table INNODB_BUFFER_PAGE with information
+cached in the buf_page_info_t array
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_buffer_page_fill(
+/*========================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ const buf_page_info_t* info_array, /*!< in: array cached page
+ info */
+ ulint num_page, /*!< in: number of page info
+ cached */
+ mem_heap_t* heap) /*!< in: temp heap memory */
+{
+ TABLE* table;
+ Field** fields;
+
+ DBUG_ENTER("i_s_innodb_buffer_page_fill");
+
+ table = tables->table;
+
+ fields = table->field;
+
+ /* Iterate through the cached array and fill the I_S table rows */
+ for (ulint i = 0; i < num_page; i++) {
+ const buf_page_info_t* page_info;
+ const char* table_name;
+ const char* index_name;
+ const char* state_str;
+ enum buf_page_state state;
+
+ page_info = info_array + i;
+
+ table_name = NULL;
+ index_name = NULL;
+ state_str = NULL;
+
+ OK(fields[IDX_BUFFER_POOL_ID]->store(page_info->pool_id));
+
+ OK(fields[IDX_BUFFER_BLOCK_ID]->store(page_info->block_id));
+
+ OK(fields[IDX_BUFFER_PAGE_SPACE]->store(page_info->space_id));
+
+ OK(fields[IDX_BUFFER_PAGE_NUM]->store(page_info->page_num));
+
+ OK(field_store_string(
+ fields[IDX_BUFFER_PAGE_TYPE],
+ i_s_page_type[page_info->page_type].type_str));
+
+ OK(fields[IDX_BUFFER_PAGE_FLUSH_TYPE]->store(
+ page_info->flush_type));
+
+ OK(fields[IDX_BUFFER_PAGE_FIX_COUNT]->store(
+ page_info->fix_count));
+
+ if (page_info->hashed) {
+ OK(field_store_string(
+ fields[IDX_BUFFER_PAGE_HASHED], "YES"));
+ } else {
+ OK(field_store_string(
+ fields[IDX_BUFFER_PAGE_HASHED], "NO"));
+ }
+
+ OK(fields[IDX_BUFFER_PAGE_NEWEST_MOD]->store(
+ (longlong) page_info->newest_mod, true));
+
+ OK(fields[IDX_BUFFER_PAGE_OLDEST_MOD]->store(
+ (longlong) page_info->oldest_mod, true));
+
+ OK(fields[IDX_BUFFER_PAGE_ACCESS_TIME]->store(
+ page_info->access_time));
+
+ /* If this is an index page, fetch the index name
+ and table name */
+ if (page_info->page_type == I_S_PAGE_TYPE_INDEX) {
+ const dict_index_t* index;
+
+ mutex_enter(&dict_sys->mutex);
+ index = dict_index_get_if_in_cache_low(
+ page_info->index_id);
+
+ /* Copy the index/table name under mutex. We
+ do not want to hold the InnoDB mutex while
+ filling the IS table */
+ if (index) {
+ const char* name_ptr = index->name;
+
+ if (name_ptr[0] == TEMP_INDEX_PREFIX) {
+ name_ptr++;
+ }
+
+ index_name = mem_heap_strdup(heap, name_ptr);
+
+ table_name = mem_heap_strdup(heap,
+ index->table_name);
+
+ }
+
+ mutex_exit(&dict_sys->mutex);
+ }
+
+ OK(field_store_string(
+ fields[IDX_BUFFER_PAGE_TABLE_NAME], table_name));
+
+ OK(field_store_string(
+ fields[IDX_BUFFER_PAGE_INDEX_NAME], index_name));
+
+ OK(fields[IDX_BUFFER_PAGE_NUM_RECS]->store(
+ page_info->num_recs));
+
+ OK(fields[IDX_BUFFER_PAGE_DATA_SIZE]->store(
+ page_info->data_size));
+
+ OK(fields[IDX_BUFFER_PAGE_ZIP_SIZE]->store(
+ page_info->zip_ssize
+ ? (PAGE_ZIP_MIN_SIZE >> 1) << page_info->zip_ssize
+ : 0));
+
+#if BUF_PAGE_STATE_BITS > 3
+# error "BUF_PAGE_STATE_BITS > 3, please ensure that all 1<<BUF_PAGE_STATE_BITS values are checked for"
+#endif
+ state = static_cast<enum buf_page_state>(page_info->page_state);
+
+ switch (state) {
+ /* First three states are for compression pages and
+ are not states we would get as we scan pages through
+ buffer blocks */
+ case BUF_BLOCK_ZIP_FREE:
+ case BUF_BLOCK_ZIP_PAGE:
+ case BUF_BLOCK_ZIP_DIRTY:
+ state_str = NULL;
+ break;
+ case BUF_BLOCK_NOT_USED:
+ state_str = "NOT_USED";
+ break;
+ case BUF_BLOCK_READY_FOR_USE:
+ state_str = "READY_FOR_USE";
+ break;
+ case BUF_BLOCK_FILE_PAGE:
+ state_str = "FILE_PAGE";
+ break;
+ case BUF_BLOCK_MEMORY:
+ state_str = "MEMORY";
+ break;
+ case BUF_BLOCK_REMOVE_HASH:
+ state_str = "REMOVE_HASH";
+ break;
+ };
+
+ OK(field_store_string(fields[IDX_BUFFER_PAGE_STATE],
+ state_str));
+
+ switch (page_info->io_fix) {
+ case BUF_IO_NONE:
+ OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
+ "IO_NONE"));
+ break;
+ case BUF_IO_READ:
+ OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
+ "IO_READ"));
+ break;
+ case BUF_IO_WRITE:
+ OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
+ "IO_WRITE"));
+ break;
+ case BUF_IO_PIN:
+ OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
+ "IO_PIN"));
+ break;
+ }
+
+ OK(field_store_string(fields[IDX_BUFFER_PAGE_IS_OLD],
+ (page_info->is_old) ? "YES" : "NO"));
+
+ OK(fields[IDX_BUFFER_PAGE_FREE_CLOCK]->store(
+ page_info->freed_page_clock));
+
+ if (schema_table_store_record(thd, table)) {
+ DBUG_RETURN(1);
+ }
+ }
+
+ DBUG_RETURN(0);
+}
+
+/*******************************************************************//**
+Set appropriate page type to a buf_page_info_t structure */
+static
+void
+i_s_innodb_set_page_type(
+/*=====================*/
+ buf_page_info_t*page_info, /*!< in/out: structure to fill with
+ scanned info */
+ ulint page_type, /*!< in: page type */
+ const byte* frame) /*!< in: buffer frame */
+{
+ if (page_type == FIL_PAGE_INDEX) {
+ const page_t* page = (const page_t*) frame;
+
+ /* FIL_PAGE_INDEX is a bit special, its value
+ is defined as 17855, so we cannot use FIL_PAGE_INDEX
+ to index into i_s_page_type[] array, its array index
+ in the i_s_page_type[] array is I_S_PAGE_TYPE_INDEX
+ (1) */
+ page_info->page_type = I_S_PAGE_TYPE_INDEX;
+
+ page_info->index_id = btr_page_get_index_id(page);
+
+ page_info->data_size = (ulint)(page_header_get_field(
+ page, PAGE_HEAP_TOP) - (page_is_comp(page)
+ ? PAGE_NEW_SUPREMUM_END
+ : PAGE_OLD_SUPREMUM_END)
+ - page_header_get_field(page, PAGE_GARBAGE));
+
+ page_info->num_recs = page_get_n_recs(page);
+ } else if (page_type >= I_S_PAGE_TYPE_UNKNOWN) {
+ /* Encountered an unknown page type */
+ page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
+ } else {
+ /* Make sure we get the right index into the
+ i_s_page_type[] array */
+ ut_a(page_type == i_s_page_type[page_type].type_value);
+
+ page_info->page_type = page_type;
+ }
+
+ if (page_info->page_type == FIL_PAGE_TYPE_ZBLOB
+ || page_info->page_type == FIL_PAGE_TYPE_ZBLOB2) {
+ page_info->page_num = mach_read_from_4(
+ frame + FIL_PAGE_OFFSET);
+ page_info->space_id = mach_read_from_4(
+ frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
+ }
+}
+/*******************************************************************//**
+Scans pages in the buffer cache, and collect their general information
+into the buf_page_info_t array which is zero-filled. So any fields
+that are not initialized in the function will default to 0 */
+static
+void
+i_s_innodb_buffer_page_get_info(
+/*============================*/
+ const buf_page_t*bpage, /*!< in: buffer pool page to scan */
+ ulint pool_id, /*!< in: buffer pool id */
+ ulint pos, /*!< in: buffer block position in
+ buffer pool or in the LRU list */
+ buf_page_info_t*page_info) /*!< in: zero filled info structure;
+ out: structure filled with scanned
+ info */
+{
+ ut_ad(pool_id < MAX_BUFFER_POOLS);
+
+ page_info->pool_id = pool_id;
+
+ page_info->block_id = pos;
+
+ page_info->page_state = buf_page_get_state(bpage);
+
+ /* Only fetch information for buffers that map to a tablespace,
+ that is, buffer page with state BUF_BLOCK_ZIP_PAGE,
+ BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_FILE_PAGE */
+ if (buf_page_in_file(bpage)) {
+ const byte* frame;
+ ulint page_type;
+
+ page_info->space_id = buf_page_get_space(bpage);
+
+ page_info->page_num = buf_page_get_page_no(bpage);
+
+ page_info->flush_type = bpage->flush_type;
+
+ page_info->fix_count = bpage->buf_fix_count;
+
+ page_info->newest_mod = bpage->newest_modification;
+
+ page_info->oldest_mod = bpage->oldest_modification;
+
+ page_info->access_time = bpage->access_time;
+
+ page_info->zip_ssize = bpage->zip.ssize;
+
+ page_info->io_fix = bpage->io_fix;
+
+ page_info->is_old = bpage->old;
+
+ page_info->freed_page_clock = bpage->freed_page_clock;
+
+ if (page_info->page_state == BUF_BLOCK_FILE_PAGE) {
+ const buf_block_t*block;
+
+ block = reinterpret_cast<const buf_block_t*>(bpage);
+ frame = block->frame;
+ page_info->hashed = (block->index != NULL);
+ } else {
+ ut_ad(page_info->zip_ssize);
+ frame = bpage->zip.data;
+ }
+
+ page_type = fil_page_get_type(frame);
+
+ i_s_innodb_set_page_type(page_info, page_type, frame);
+ } else {
+ page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
+ }
+}
+
+/*******************************************************************//**
+This is the function that goes through each block of the buffer pool
+and fetch information to information schema tables: INNODB_BUFFER_PAGE.
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_fill_buffer_pool(
+/*========================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ buf_pool_t* buf_pool, /*!< in: buffer pool to scan */
+ const ulint pool_id) /*!< in: buffer pool id */
+{
+ int status = 0;
+ mem_heap_t* heap;
+
+ DBUG_ENTER("i_s_innodb_fill_buffer_pool");
+
+ heap = mem_heap_create(10000);
+
+ /* Go through each chunk of buffer pool. Currently, we only
+ have one single chunk for each buffer pool */
+ for (ulint n = 0; n < buf_pool->n_chunks; n++) {
+ const buf_block_t* block;
+ ulint n_blocks;
+ buf_page_info_t* info_buffer;
+ ulint num_page;
+ ulint mem_size;
+ ulint chunk_size;
+ ulint num_to_process = 0;
+ ulint block_id = 0;
+ mutex_t* block_mutex;
+
+ /* Get buffer block of the nth chunk */
+ block = buf_get_nth_chunk_block(buf_pool, n, &chunk_size);
+ num_page = 0;
+
+ while (chunk_size > 0) {
+ /* we cache maximum MAX_BUF_INFO_CACHED number of
+ buffer page info */
+ num_to_process = ut_min(chunk_size,
+ MAX_BUF_INFO_CACHED);
+
+ mem_size = num_to_process * sizeof(buf_page_info_t);
+
+ /* For each chunk, we'll pre-allocate information
+ structures to cache the page information read from
+ the buffer pool. Doing so before obtain any mutex */
+ info_buffer = (buf_page_info_t*) mem_heap_zalloc(
+ heap, mem_size);
+
+ /* GO through each block in the chunk */
+ for (n_blocks = num_to_process; n_blocks--; block++) {
+ block_mutex = buf_page_get_mutex_enter(&block->page);
+ i_s_innodb_buffer_page_get_info(
+ &block->page, pool_id, block_id,
+ info_buffer + num_page);
+ mutex_exit(block_mutex);
+ block_id++;
+ num_page++;
+ }
+
+
+ /* Fill in information schema table with information
+ just collected from the buffer chunk scan */
+ status = i_s_innodb_buffer_page_fill(
+ thd, tables, info_buffer,
+ num_page, heap);
+
+ /* If something goes wrong, break and return */
+ if (status) {
+ break;
+ }
+
+ mem_heap_empty(heap);
+ chunk_size -= num_to_process;
+ num_page = 0;
+ }
+ }
+
+ mem_heap_free(heap);
+
+ DBUG_RETURN(status);
+}
+
+/*******************************************************************//**
+Fill page information for pages in InnoDB buffer pool to the
+dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_buffer_page_fill_table(
+/*==============================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ Item* ) /*!< in: condition (ignored) */
+{
+ int status = 0;
+
+ DBUG_ENTER("i_s_innodb_buffer_page_fill_table");
+
+ /* deny access to user without PROCESS privilege */
+ if (check_global_access(thd, PROCESS_ACL)) {
+ DBUG_RETURN(0);
+ }
+
+ /* Walk through each buffer pool */
+ for (ulint i = 0; i < srv_buf_pool_instances; i++) {
+ buf_pool_t* buf_pool;
+
+ buf_pool = buf_pool_from_array(i);
+
+ /* Fetch information from pages in this buffer pool,
+ and fill the corresponding I_S table */
+ status = i_s_innodb_fill_buffer_pool(thd, tables, buf_pool, i);
+
+ /* If something wrong, break and return */
+ if (status) {
+ break;
+ }
+ }
+
+ DBUG_RETURN(status);
+}
+
+/*******************************************************************//**
+Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE.
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_buffer_page_init(
+/*========================*/
+ void* p) /*!< in/out: table schema object */
+{
+ ST_SCHEMA_TABLE* schema;
+
+ DBUG_ENTER("i_s_innodb_buffer_page_init");
+
+ schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
+
+ schema->fields_info = i_s_innodb_buffer_page_fields_info;
+ schema->fill_table = i_s_innodb_buffer_page_fill_table;
+
+ DBUG_RETURN(0);
+}
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_page =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_PAGE"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB Buffer Page Information"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_page_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
+};
+
+static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] =
+{
+#define IDX_BUF_LRU_POOL_ID 0
+ {STRUCT_FLD(field_name, "POOL_ID"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_POS 1
+ {STRUCT_FLD(field_name, "LRU_POSITION"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_SPACE 2
+ {STRUCT_FLD(field_name, "SPACE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_NUM 3
+ {STRUCT_FLD(field_name, "PAGE_NUMBER"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_TYPE 4
+ {STRUCT_FLD(field_name, "PAGE_TYPE"),
+ STRUCT_FLD(field_length, 64),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_FLUSH_TYPE 5
+ {STRUCT_FLD(field_name, "FLUSH_TYPE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_FIX_COUNT 6
+ {STRUCT_FLD(field_name, "FIX_COUNT"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_HASHED 7
+ {STRUCT_FLD(field_name, "IS_HASHED"),
+ STRUCT_FLD(field_length, 3),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_NEWEST_MOD 8
+ {STRUCT_FLD(field_name, "NEWEST_MODIFICATION"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_OLDEST_MOD 9
+ {STRUCT_FLD(field_name, "OLDEST_MODIFICATION"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_ACCESS_TIME 10
+ {STRUCT_FLD(field_name, "ACCESS_TIME"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_TABLE_NAME 11
+ {STRUCT_FLD(field_name, "TABLE_NAME"),
+ STRUCT_FLD(field_length, 1024),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_INDEX_NAME 12
+ {STRUCT_FLD(field_name, "INDEX_NAME"),
+ STRUCT_FLD(field_length, 1024),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_NUM_RECS 13
+ {STRUCT_FLD(field_name, "NUMBER_RECORDS"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_DATA_SIZE 14
+ {STRUCT_FLD(field_name, "DATA_SIZE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_ZIP_SIZE 15
+ {STRUCT_FLD(field_name, "COMPRESSED_SIZE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_STATE 16
+ {STRUCT_FLD(field_name, "COMPRESSED"),
+ STRUCT_FLD(field_length, 3),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_IO_FIX 17
+ {STRUCT_FLD(field_name, "IO_FIX"),
+ STRUCT_FLD(field_length, 64),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_IS_OLD 18
+ {STRUCT_FLD(field_name, "IS_OLD"),
+ STRUCT_FLD(field_length, 3),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_FREE_CLOCK 19
+ {STRUCT_FLD(field_name, "FREE_PAGE_CLOCK"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ END_OF_ST_FIELD_INFO
+};
+
+/*******************************************************************//**
+Fill Information Schema table INNODB_BUFFER_PAGE_LRU with information
+cached in the buf_page_info_t array
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_buf_page_lru_fill(
+/*=========================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ const buf_page_info_t* info_array, /*!< in: array cached page
+ info */
+ ulint num_page) /*!< in: number of page info
+ cached */
+{
+ TABLE* table;
+ Field** fields;
+ mem_heap_t* heap;
+
+ DBUG_ENTER("i_s_innodb_buf_page_lru_fill");
+
+ table = tables->table;
+
+ fields = table->field;
+
+ heap = mem_heap_create(1000);
+
+ /* Iterate through the cached array and fill the I_S table rows */
+ for (ulint i = 0; i < num_page; i++) {
+ const buf_page_info_t* page_info;
+ const char* table_name;
+ const char* index_name;
+ const char* state_str;
+ enum buf_page_state state;
+
+ table_name = NULL;
+ index_name = NULL;
+ state_str = NULL;
+
+ page_info = info_array + i;
+
+ OK(fields[IDX_BUF_LRU_POOL_ID]->store(page_info->pool_id));
+
+ OK(fields[IDX_BUF_LRU_POS]->store(page_info->block_id));
+
+ OK(fields[IDX_BUF_LRU_PAGE_SPACE]->store(page_info->space_id));
+
+ OK(fields[IDX_BUF_LRU_PAGE_NUM]->store(page_info->page_num));
+
+ OK(field_store_string(
+ fields[IDX_BUF_LRU_PAGE_TYPE],
+ i_s_page_type[page_info->page_type].type_str));
+
+ OK(fields[IDX_BUF_LRU_PAGE_FLUSH_TYPE]->store(
+ page_info->flush_type));
+
+ OK(fields[IDX_BUF_LRU_PAGE_FIX_COUNT]->store(
+ page_info->fix_count));
+
+ if (page_info->hashed) {
+ OK(field_store_string(
+ fields[IDX_BUF_LRU_PAGE_HASHED], "YES"));
+ } else {
+ OK(field_store_string(
+ fields[IDX_BUF_LRU_PAGE_HASHED], "NO"));
+ }
+
+ OK(fields[IDX_BUF_LRU_PAGE_NEWEST_MOD]->store(
+ page_info->newest_mod, true));
+
+ OK(fields[IDX_BUF_LRU_PAGE_OLDEST_MOD]->store(
+ page_info->oldest_mod, true));
+
+ OK(fields[IDX_BUF_LRU_PAGE_ACCESS_TIME]->store(
+ page_info->access_time));
+
+ /* If this is an index page, fetch the index name
+ and table name */
+ if (page_info->page_type == I_S_PAGE_TYPE_INDEX) {
+ const dict_index_t* index;
+
+ mutex_enter(&dict_sys->mutex);
+ index = dict_index_get_if_in_cache_low(
+ page_info->index_id);
+
+ /* Copy the index/table name under mutex. We
+ do not want to hold the InnoDB mutex while
+ filling the IS table */
+ if (index) {
+ const char* name_ptr = index->name;
+
+ if (name_ptr[0] == TEMP_INDEX_PREFIX) {
+ name_ptr++;
+ }
+
+ index_name = mem_heap_strdup(heap, name_ptr);
+
+ table_name = mem_heap_strdup(heap,
+ index->table_name);
+ }
+
+ mutex_exit(&dict_sys->mutex);
+ }
+
+ OK(field_store_string(
+ fields[IDX_BUF_LRU_PAGE_TABLE_NAME], table_name));
+
+ OK(field_store_string(
+ fields[IDX_BUF_LRU_PAGE_INDEX_NAME], index_name));
+ OK(fields[IDX_BUF_LRU_PAGE_NUM_RECS]->store(
+ page_info->num_recs));
+
+ OK(fields[IDX_BUF_LRU_PAGE_DATA_SIZE]->store(
+ page_info->data_size));
+
+ OK(fields[IDX_BUF_LRU_PAGE_ZIP_SIZE]->store(
+ page_info->zip_ssize ?
+ 512 << page_info->zip_ssize : 0));
+
+ state = static_cast<enum buf_page_state>(page_info->page_state);
+
+ switch (state) {
+ /* Compressed page */
+ case BUF_BLOCK_ZIP_PAGE:
+ case BUF_BLOCK_ZIP_DIRTY:
+ state_str = "YES";
+ break;
+ /* Uncompressed page */
+ case BUF_BLOCK_FILE_PAGE:
+ state_str = "NO";
+ break;
+ /* We should not see following states */
+ case BUF_BLOCK_ZIP_FREE:
+ case BUF_BLOCK_READY_FOR_USE:
+ case BUF_BLOCK_NOT_USED:
+ case BUF_BLOCK_MEMORY:
+ case BUF_BLOCK_REMOVE_HASH:
+ state_str = NULL;
+ break;
+ };
+
+ OK(field_store_string(fields[IDX_BUF_LRU_PAGE_STATE],
+ state_str));
+
+ switch (page_info->io_fix) {
+ case BUF_IO_NONE:
+ OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
+ "IO_NONE"));
+ break;
+ case BUF_IO_READ:
+ OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
+ "IO_READ"));
+ break;
+ case BUF_IO_WRITE:
+ OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
+ "IO_WRITE"));
+ break;
+ }
+
+ OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IS_OLD],
+ (page_info->is_old) ? "YES" : "NO"));
+
+ OK(fields[IDX_BUF_LRU_PAGE_FREE_CLOCK]->store(
+ page_info->freed_page_clock));
+
+ if (schema_table_store_record(thd, table)) {
+ mem_heap_free(heap);
+ DBUG_RETURN(1);
+ }
+
+ mem_heap_empty(heap);
+ }
+
+ mem_heap_free(heap);
+
+ DBUG_RETURN(0);
+}
+
+/*******************************************************************//**
+This is the function that goes through buffer pool's LRU list
+and fetch information to INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU.
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_fill_buffer_lru(
+/*=======================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ buf_pool_t* buf_pool, /*!< in: buffer pool to scan */
+ const ulint pool_id) /*!< in: buffer pool id */
+{
+ int status = 0;
+ buf_page_info_t* info_buffer;
+ ulint lru_pos = 0;
+ const buf_page_t* bpage;
+ ulint lru_len;
+ mutex_t* block_mutex;
+
+ DBUG_ENTER("i_s_innodb_fill_buffer_lru");
+
+ RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
+
+ /* Obtain buf_pool mutex before allocate info_buffer, since
+ UT_LIST_GET_LEN(buf_pool->LRU) could change */
+ mutex_enter(&buf_pool->LRU_list_mutex);
+
+ lru_len = UT_LIST_GET_LEN(buf_pool->LRU);
+
+ /* Print error message if malloc fail */
+ info_buffer = (buf_page_info_t*) my_malloc(
+ lru_len * sizeof *info_buffer, MYF(MY_WME));
+
+ if (!info_buffer) {
+ status = 1;
+ goto exit;
+ }
+
+ memset(info_buffer, 0, lru_len * sizeof *info_buffer);
+
+ /* Walk through Pool's LRU list and print the buffer page
+ information */
+ bpage = UT_LIST_GET_LAST(buf_pool->LRU);
+
+ while (bpage != NULL) {
+ block_mutex = buf_page_get_mutex_enter(bpage);
+ /* Use the same function that collect buffer info for
+ INNODB_BUFFER_PAGE to get buffer page info */
+ i_s_innodb_buffer_page_get_info(bpage, pool_id, lru_pos,
+ (info_buffer + lru_pos));
+
+ bpage = UT_LIST_GET_PREV(LRU, bpage);
+ mutex_exit(block_mutex);
+
+ lru_pos++;
+ }
+
+ ut_ad(lru_pos == lru_len);
+ ut_ad(lru_pos == UT_LIST_GET_LEN(buf_pool->LRU));
+
+exit:
+ mutex_exit(&buf_pool->LRU_list_mutex);
+
+ if (info_buffer) {
+ status = i_s_innodb_buf_page_lru_fill(
+ thd, tables, info_buffer, lru_len);
+
+ my_free(info_buffer);
+ }
+
+ DBUG_RETURN(status);
+}
+
+/*******************************************************************//**
+Fill page information for pages in InnoDB buffer pool to the
+dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_buf_page_lru_fill_table(
+/*===============================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ Item* ) /*!< in: condition (ignored) */
+{
+ int status = 0;
+
+ DBUG_ENTER("i_s_innodb_buf_page_lru_fill_table");
+
+ /* deny access to any users that do not hold PROCESS_ACL */
+ if (check_global_access(thd, PROCESS_ACL)) {
+ DBUG_RETURN(0);
+ }
+
+ /* Walk through each buffer pool */
+ for (ulint i = 0; i < srv_buf_pool_instances; i++) {
+ buf_pool_t* buf_pool;
+
+ buf_pool = buf_pool_from_array(i);
+
+ /* Fetch information from pages in this buffer pool's LRU list,
+ and fill the corresponding I_S table */
+ status = i_s_innodb_fill_buffer_lru(thd, tables, buf_pool, i);
+
+ /* If something wrong, break and return */
+ if (status) {
+ break;
+ }
+ }
+
+ DBUG_RETURN(status);
+}
+
+/*******************************************************************//**
+Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU.
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_buffer_page_lru_init(
+/*============================*/
+ void* p) /*!< in/out: table schema object */
+{
+ ST_SCHEMA_TABLE* schema;
+
+ DBUG_ENTER("i_s_innodb_buffer_page_lru_init");
+
+ schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
+
+ schema->fields_info = i_s_innodb_buf_page_lru_fields_info;
+ schema->fill_table = i_s_innodb_buf_page_lru_fill_table;
+
+ DBUG_RETURN(0);
+}
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_page_lru =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_PAGE_LRU"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB Buffer Page in LRU"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_page_lru_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
+};
+
/*******************************************************************//**
Unbind a dynamic INFORMATION_SCHEMA table.
@return 0 on success */
diff --git a/storage/xtradb/handler/i_s.h b/storage/xtradb/handler/i_s.h
index a8964356747..620309bebfe 100644
--- a/storage/xtradb/handler/i_s.h
+++ b/storage/xtradb/handler/i_s.h
@@ -52,5 +52,8 @@ extern struct st_maria_plugin i_s_innodb_buffer_pool_pages;
extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_index;
extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_blob;
extern struct st_maria_plugin i_s_innodb_changed_pages;
+extern struct st_maria_plugin i_s_innodb_buffer_page;
+extern struct st_maria_plugin i_s_innodb_buffer_page_lru;
+extern struct st_maria_plugin i_s_innodb_buffer_stats;
#endif /* i_s_h */
diff --git a/storage/xtradb/ibuf/ibuf0ibuf.c b/storage/xtradb/ibuf/ibuf0ibuf.c
index 562f207268a..78cb6e20176 100644
--- a/storage/xtradb/ibuf/ibuf0ibuf.c
+++ b/storage/xtradb/ibuf/ibuf0ibuf.c
@@ -3650,11 +3650,18 @@ bitmap_fail:
root = ibuf_tree_root_get(&mtr);
- err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG
- | BTR_NO_UNDO_LOG_FLAG,
- cursor,
- ibuf_entry, &ins_rec,
- &dummy_big_rec, 0, thr, &mtr);
+ err = btr_cur_optimistic_insert(
+ BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG,
+ cursor, ibuf_entry, &ins_rec,
+ &dummy_big_rec, 0, thr, &mtr);
+
+ if (err == DB_FAIL) {
+ err = btr_cur_pessimistic_insert(
+ BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG,
+ cursor, ibuf_entry, &ins_rec,
+ &dummy_big_rec, 0, thr, &mtr);
+ }
+
mutex_exit(&ibuf_pessimistic_insert_mutex);
ibuf_size_update(root, &mtr);
mutex_exit(&ibuf_mutex);
diff --git a/storage/xtradb/include/buf0buf.h b/storage/xtradb/include/buf0buf.h
index 1a4990be69f..d48c7f0212f 100644
--- a/storage/xtradb/include/buf0buf.h
+++ b/storage/xtradb/include/buf0buf.h
@@ -68,7 +68,10 @@ Created 11/5/1995 Heikki Tuuri
position of the block. */
/* @} */
-#define MAX_BUFFER_POOLS 64 /*!< The maximum number of buffer
+#define MAX_BUFFER_POOLS_BITS 6 /*!< Number of bits to representing
+ a buffer pool ID */
+#define MAX_BUFFER_POOLS (1 << MAX_BUFFER_POOLS_BITS)
+ /*!< The maximum number of buffer
pools that can be defined */
#define BUF_POOL_WATCH_SIZE 1 /*!< Maximum number of concurrent
@@ -233,6 +236,7 @@ ulint
buf_pool_init(
/*=========*/
ulint size, /*!< in: Size of the total pool in bytes */
+ ibool populate, /*!< in: Force virtual page preallocation */
ulint n_instances); /*!< in: Number of instances */
/********************************************************************//**
Frees the buffer pool at shutdown. This must not be invoked before
@@ -778,6 +782,18 @@ void
buf_print_io(
/*=========*/
FILE* file); /*!< in: file where to print */
+/*******************************************************************//**
+Collect buffer pool stats information for a buffer pool. Also
+record aggregated stats if there are more than one buffer pool
+in the server */
+UNIV_INTERN
+void
+buf_stats_get_pool_info(
+/*====================*/
+ buf_pool_t* buf_pool, /*!< in: buffer pool */
+ ulint pool_id, /*!< in: buffer pool ID */
+ buf_pool_info_t* all_pool_info); /*!< in/out: buffer pool info
+ to fill */
/*********************************************************************//**
Returns the ratio in percents of modified pages in the buffer pool /
database pages in the buffer pool.
@@ -1364,12 +1380,25 @@ void
buf_get_total_stat(
/*===============*/
buf_pool_stat_t*tot_stat); /*!< out: buffer pool stats */
+/*********************************************************************//**
+Get the nth chunk's buffer block in the specified buffer pool.
+@return the nth chunk's buffer block. */
+UNIV_INLINE
+buf_block_t*
+buf_get_nth_chunk_block(
+/*====================*/
+ const buf_pool_t* buf_pool, /*!< in: buffer pool instance */
+ ulint n, /*!< in: nth chunk in the buffer pool */
+ ulint* chunk_size); /*!< in: chunk size */
#endif /* !UNIV_HOTBACKUP */
/** The common buffer control block structure
for compressed and uncompressed frames */
+/** Number of bits used for buffer page states. */
+#define BUF_PAGE_STATE_BITS 3
+
struct buf_page_struct{
/** @name General fields
None of these bit-fields must be modified without holding
@@ -1384,7 +1413,8 @@ struct buf_page_struct{
unsigned offset:32; /*!< page number; also protected
by buf_pool->mutex. */
- unsigned state:3; /*!< state of the control block; also
+ unsigned state:BUF_PAGE_STATE_BITS;
+ /*!< state of the control block; also
protected by buf_pool->mutex.
State transitions from
BUF_BLOCK_READY_FOR_USE to
diff --git a/storage/xtradb/include/buf0buf.ic b/storage/xtradb/include/buf0buf.ic
index 6595e86a8fe..221f86d9d62 100644
--- a/storage/xtradb/include/buf0buf.ic
+++ b/storage/xtradb/include/buf0buf.ic
@@ -36,6 +36,8 @@ Created 11/5/1995 Heikki Tuuri
#include "buf0lru.h"
#include "buf0rea.h"
#include "srv0srv.h"
+#include "buf0types.h"
+
/*********************************************************************//**
Gets the current size of buffer buf_pool in bytes.
@return size in bytes */
@@ -1354,4 +1356,21 @@ buf_pool_page_hash_x_unlock_all(void)
rw_lock_x_unlock(&buf_pool->page_hash_latch);
}
}
+/*********************************************************************//**
+Get the nth chunk's buffer block in the specified buffer pool.
+@return the nth chunk's buffer block. */
+UNIV_INLINE
+buf_block_t*
+buf_get_nth_chunk_block(
+/*====================*/
+ const buf_pool_t* buf_pool, /*!< in: buffer pool instance */
+ ulint n, /*!< in: nth chunk in the buffer pool */
+ ulint* chunk_size) /*!< in: chunk size */
+{
+ const buf_chunk_t* chunk;
+
+ chunk = buf_pool->chunks + n;
+ *chunk_size = chunk->size;
+ return(chunk->blocks);
+}
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h
index 19bf5960ae4..7da62e68e56 100644
--- a/storage/xtradb/include/fil0fil.h
+++ b/storage/xtradb/include/fil0fil.h
@@ -144,6 +144,8 @@ extern fil_addr_t fil_addr_null;
#define FIL_PAGE_TYPE_BLOB 10 /*!< Uncompressed BLOB page */
#define FIL_PAGE_TYPE_ZBLOB 11 /*!< First compressed BLOB page */
#define FIL_PAGE_TYPE_ZBLOB2 12 /*!< Subsequent compressed BLOB page */
+#define FIL_PAGE_TYPE_LAST FIL_PAGE_TYPE_ZBLOB2
+ /*!< Last page type */
/* @} */
/** Space types @{ */
diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h
index 3eb96a1aade..075b4ff2617 100644
--- a/storage/xtradb/include/ha_prototypes.h
+++ b/storage/xtradb/include/ha_prototypes.h
@@ -111,7 +111,7 @@ UNIV_INTERN
ibool
thd_is_replication_slave_thread(
/*============================*/
- void* thd); /*!< in: thread handle (THD*) */
+ const void* thd); /*!< in: thread handle (THD*) */
/******************************************************************//**
Returns true if the transaction this thread is processing has edited
diff --git a/storage/xtradb/include/log0log.h b/storage/xtradb/include/log0log.h
index 96c4b81695a..9a149bcfa76 100644
--- a/storage/xtradb/include/log0log.h
+++ b/storage/xtradb/include/log0log.h
@@ -41,6 +41,9 @@ Created 12/9/1995 Heikki Tuuri
#include "sync0rw.h"
#endif /* !UNIV_HOTBACKUP */
+/* Type used for all log sequence number storage and arithmetics */
+typedef ib_uint64_t lsn_t;
+
/** Redo log buffer */
typedef struct log_struct log_t;
/** Redo log group */
diff --git a/storage/xtradb/include/os0proc.h b/storage/xtradb/include/os0proc.h
index fd46bd7db87..a78b1c2a250 100644
--- a/storage/xtradb/include/os0proc.h
+++ b/storage/xtradb/include/os0proc.h
@@ -58,7 +58,8 @@ UNIV_INTERN
void*
os_mem_alloc_large(
/*===============*/
- ulint* n); /*!< in/out: number of bytes */
+ ulint* n, /*!< in/out: number of bytes */
+ ibool populate); /*!< in: virtual page preallocation */
/****************************************************************//**
Frees large pages memory. */
UNIV_INTERN
diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h
index e07a84b0789..b99585ede77 100644
--- a/storage/xtradb/include/srv0srv.h
+++ b/storage/xtradb/include/srv0srv.h
@@ -186,6 +186,7 @@ extern my_bool srv_use_sys_malloc;
extern ibool srv_use_sys_malloc;
#endif /* UNIV_HOTBACKUP */
extern ulint srv_buf_pool_size; /*!< requested size in bytes */
+extern my_bool srv_buf_pool_populate; /*!< virtual page preallocation */
extern ulint srv_buf_pool_instances; /*!< requested number of buffer pool instances */
extern ulint srv_buf_pool_old_size; /*!< previously requested size */
extern ulint srv_buf_pool_curr_size; /*!< current size in bytes */
diff --git a/storage/xtradb/include/trx0sys.h b/storage/xtradb/include/trx0sys.h
index 259a675cbf4..7ae3ba74478 100644
--- a/storage/xtradb/include/trx0sys.h
+++ b/storage/xtradb/include/trx0sys.h
@@ -356,6 +356,14 @@ trx_sys_read_wsrep_checkpoint(
XID* xid); /*!< out: WSREP XID */
#endif /* WITH_WSREP */
/*****************************************************************//**
+Prints to stderr the MySQL master log offset info in the trx system header
+COMMIT set of fields if the magic number shows it valid and stores it
+in global variables. */
+UNIV_INTERN
+void
+trx_sys_print_committed_mysql_master_log_pos(void);
+/*==============================================*/
+/*****************************************************************//**
Prints to stderr the MySQL master log offset info in the trx system header if
the magic number shows it valid. */
UNIV_INTERN
@@ -548,10 +556,16 @@ We must remember this limit in order to keep file compatibility. */
//# error "UNIV_PAGE_SIZE < 4096"
//#endif
/** The offset of the MySQL replication info in the trx system header;
-this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
+this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below. These are
+written at prepare time and are the main copy. */
#define TRX_SYS_MYSQL_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 2000)
#define TRX_SYS_MYSQL_RELAY_LOG_INFO (UNIV_PAGE_SIZE - 1500)
+/** The copy of the above which is made at transaction COMMIT time. If binlog
+crash recovery rollbacks a PREPAREd transaction, they are copied back. */
+#define TRX_SYS_COMMIT_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 3000)
+#define TRX_SYS_COMMIT_RELAY_LOG_INFO (UNIV_PAGE_SIZE - 2500)
+
/** The offset of the MySQL binlog offset info in the trx system header */
#define TRX_SYS_MYSQL_LOG_INFO (UNIV_PAGE_SIZE - 1000)
#define TRX_SYS_MYSQL_LOG_MAGIC_N_FLD 0 /*!< magic number which is
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index 9aee2a0c7f9..5d2cd2d0313 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -54,7 +54,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_BUGFIX 8
#ifndef PERCONA_INNODB_VERSION
-#define PERCONA_INNODB_VERSION 29.0
+#define PERCONA_INNODB_VERSION 29.1
#endif
/* The following is the InnoDB version as shown in
diff --git a/storage/xtradb/os/os0file.c b/storage/xtradb/os/os0file.c
index b42c6300ef5..af50cfa1a24 100644
--- a/storage/xtradb/os/os0file.c
+++ b/storage/xtradb/os/os0file.c
@@ -1887,7 +1887,7 @@ os_file_rename_func(
#ifdef __WIN__
BOOL ret;
- ret = MoveFile((LPCTSTR)oldpath, (LPCTSTR)newpath);
+ ret = MoveFileEx((LPCTSTR)oldpath, (LPCTSTR)newpath, MOVEFILE_REPLACE_EXISTING);
if (ret) {
return(TRUE);
diff --git a/storage/xtradb/os/os0proc.c b/storage/xtradb/os/os0proc.c
index 68321e1aaf9..c9ee707e923 100644
--- a/storage/xtradb/os/os0proc.c
+++ b/storage/xtradb/os/os0proc.c
@@ -32,6 +32,12 @@ Created 9/30/1995 Heikki Tuuri
#include "ut0mem.h"
#include "ut0byte.h"
+/* Linux release version */
+#if defined(UNIV_LINUX) && defined(_GNU_SOURCE)
+#include <string.h> /* strverscmp() */
+#include <sys/utsname.h> /* uname() */
+#endif
+
/* FreeBSD for example has only MAP_ANON, Linux has MAP_ANONYMOUS and
MAP_ANON but MAP_ANON is marked as deprecated */
#if defined(MAP_ANONYMOUS)
@@ -40,6 +46,13 @@ MAP_ANON but MAP_ANON is marked as deprecated */
#define OS_MAP_ANON MAP_ANON
#endif
+/* Linux's MAP_POPULATE */
+#if defined(MAP_POPULATE)
+#define OS_MAP_POPULATE MAP_POPULATE
+#else
+#define OS_MAP_POPULATE 0
+#endif
+
UNIV_INTERN ibool os_use_large_pages;
/* Large page size. This may be a boot-time option on some platforms */
UNIV_INTERN ulint os_large_page_size;
@@ -63,13 +76,32 @@ os_proc_get_number(void)
}
/****************************************************************//**
+Retrieve and compare operating system release.
+@return TRUE if the OS release is equal to, or later than release. */
+UNIV_INTERN
+ibool
+os_compare_release(
+/*===============*/
+ const char* release /*!< in: OS release */
+ __attribute__((unused)))
+{
+#if defined(UNIV_LINUX) && defined(_GNU_SOURCE)
+ struct utsname name;
+ return uname(&name) == 0 && strverscmp(name.release, release) >= 0;
+#else
+ return 0;
+#endif
+}
+
+/****************************************************************//**
Allocates large pages memory.
@return allocated memory */
UNIV_INTERN
void*
os_mem_alloc_large(
/*===============*/
- ulint* n) /*!< in/out: number of bytes */
+ ulint* n, /*!< in/out: number of bytes */
+ ibool populate) /*!< in: virtual page preallocation */
{
void* ptr;
ulint size;
@@ -155,12 +187,13 @@ skip:
ut_ad(ut_is_2pow(size));
size = *n = ut_2pow_round(*n + (size - 1), size);
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | OS_MAP_ANON, -1, 0);
+ MAP_PRIVATE | OS_MAP_ANON |
+ (populate ? OS_MAP_POPULATE : 0), -1, 0);
if (UNIV_UNLIKELY(ptr == (void*) -1)) {
fprintf(stderr, "InnoDB: mmap(%lu bytes) failed;"
" errno %lu\n",
(ulong) size, (ulong) errno);
- ptr = NULL;
+ return(NULL);
} else {
os_fast_mutex_lock(&ut_list_mutex);
ut_total_allocated_memory += size;
@@ -168,6 +201,25 @@ skip:
UNIV_MEM_ALLOC(ptr, size);
}
#endif
+
+#if OS_MAP_ANON && OS_MAP_POPULATE
+ /* MAP_POPULATE is only supported for private mappings
+ since Linux 2.6.23. */
+ populate = populate && !os_compare_release("2.6.23");
+
+ if (populate) {
+ fprintf(stderr, "InnoDB: Warning: mmap(MAP_POPULATE) "
+ "is not supported for private mappings. "
+ "Forcing preallocation by faulting in pages.\n");
+ }
+#endif
+
+ /* Initialize the entire buffer to force the allocation
+ of physical memory page frames. */
+ if (populate) {
+ memset(ptr, '\0', size);
+ }
+
return(ptr);
}
diff --git a/storage/xtradb/page/page0page.c b/storage/xtradb/page/page0page.c
index 4a389bbe5b8..e29fa2eb1e5 100644
--- a/storage/xtradb/page/page0page.c
+++ b/storage/xtradb/page/page0page.c
@@ -781,12 +781,18 @@ page_copy_rec_list_start(
if (UNIV_LIKELY_NULL(new_page_zip)) {
mtr_set_log_mode(mtr, log_mode);
+ DBUG_EXECUTE_IF("page_copy_rec_list_start_compress_fail",
+ goto zip_reorganize;);
+
if (UNIV_UNLIKELY
(!page_zip_compress(new_page_zip, new_page, index, mtr))) {
+ ulint ret_pos;
+#ifndef DBUG_OFF
+zip_reorganize:
+#endif /* DBUG_OFF */
/* Before trying to reorganize the page,
store the number of preceding records on the page. */
- ulint ret_pos
- = page_rec_get_n_recs_before(ret);
+ ret_pos = page_rec_get_n_recs_before(ret);
/* Before copying, "ret" was the predecessor
of the predefined supremum record. If it was
the predefined infimum record, then it would
@@ -807,15 +813,10 @@ page_copy_rec_list_start(
btr_blob_dbg_add(new_page, index,
"copy_start_reorg_fail");
return(NULL);
- } else {
- /* The page was reorganized:
- Seek to ret_pos. */
- ret = new_page + PAGE_NEW_INFIMUM;
-
- do {
- ret = rec_get_next_ptr(ret, TRUE);
- } while (--ret_pos);
}
+
+ /* The page was reorganized: Seek to ret_pos. */
+ ret = page_rec_get_nth(new_page, ret_pos);
}
}
diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c
index a6a349c05bb..c648722870c 100644
--- a/storage/xtradb/row/row0ins.c
+++ b/storage/xtradb/row/row0ins.c
@@ -2228,9 +2228,16 @@ row_ins_index_entry_low(
goto function_exit;
}
- err = btr_cur_pessimistic_insert(
+
+ err = btr_cur_optimistic_insert(
0, &cursor, entry, &insert_rec, &big_rec,
n_ext, thr, &mtr);
+
+ if (err == DB_FAIL) {
+ err = btr_cur_pessimistic_insert(
+ 0, &cursor, entry, &insert_rec,
+ &big_rec, n_ext, thr, &mtr);
+ }
}
}
diff --git a/storage/xtradb/row/row0merge.c b/storage/xtradb/row/row0merge.c
index c7d6304d6a7..0fd13f5339c 100644
--- a/storage/xtradb/row/row0merge.c
+++ b/storage/xtradb/row/row0merge.c
@@ -1254,11 +1254,25 @@ row_merge_read_clustered_index(
goto err_exit;
}
+ /* Store the cursor position on the last user
+ record on the page. */
+ btr_pcur_move_to_prev_on_page(&pcur);
+ /* Leaf pages must never be empty, unless
+ this is the only page in the index tree. */
+ ut_ad(btr_pcur_is_on_user_rec(&pcur)
+ || buf_block_get_page_no(
+ btr_pcur_get_block(&pcur))
+ == clust_index->page);
+
btr_pcur_store_position(&pcur, &mtr);
mtr_commit(&mtr);
mtr_start(&mtr);
+ /* Restore position on the record, or its
+ predecessor if the record was purged
+ meanwhile. */
btr_pcur_restore_position(BTR_SEARCH_LEAF,
&pcur, &mtr);
+ /* Move to the successor of the original record. */
has_next = btr_pcur_move_to_next_user_rec(&pcur, &mtr);
}
@@ -2720,7 +2734,7 @@ row_merge_build_indexes(
merge_files = mem_alloc(n_indexes * sizeof *merge_files);
block_size = 3 * merge_sort_block_size;
- block_mem = os_mem_alloc_large(&block_size);
+ block_mem = os_mem_alloc_large(&block_size, FALSE);
for (i = 0; i < UT_ARR_SIZE(block); i++) {
block[i] = (row_merge_block_t ) ((byte *) block_mem +
diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c
index 91ee6197d56..afc3c7759d9 100644
--- a/storage/xtradb/srv/srv0srv.c
+++ b/storage/xtradb/srv/srv0srv.c
@@ -240,6 +240,8 @@ UNIV_INTERN const byte* srv_latin1_ordering;
UNIV_INTERN my_bool srv_use_sys_malloc = TRUE;
/* requested size in kilobytes */
UNIV_INTERN ulint srv_buf_pool_size = ULINT_MAX;
+/* force virtual page preallocation (prefault) */
+UNIV_INTERN my_bool srv_buf_pool_populate = FALSE;
/* requested number of buffer pool instances */
UNIV_INTERN ulint srv_buf_pool_instances = 1;
/* previously requested size */
diff --git a/storage/xtradb/srv/srv0start.c b/storage/xtradb/srv/srv0start.c
index 7c98f74909e..65a775b56da 100644
--- a/storage/xtradb/srv/srv0start.c
+++ b/storage/xtradb/srv/srv0start.c
@@ -1543,7 +1543,8 @@ innobase_start_or_create_for_mysql(void)
((double) srv_buf_pool_size) / (1024 * 1024));
}
- err = buf_pool_init(srv_buf_pool_size, srv_buf_pool_instances);
+ err = buf_pool_init(srv_buf_pool_size, (ibool) srv_buf_pool_populate,
+ srv_buf_pool_instances);
ut_print_timestamp(stderr);
fprintf(stderr,
diff --git a/storage/xtradb/trx/trx0sys.c b/storage/xtradb/trx/trx0sys.c
index a557587d528..59b7da4083d 100644
--- a/storage/xtradb/trx/trx0sys.c
+++ b/storage/xtradb/trx/trx0sys.c
@@ -1046,8 +1046,31 @@ trx_sys_read_wsrep_checkpoint(XID* xid)
#endif /* WITH_WSREP */
/*****************************************************************//**
-Prints to stderr the MySQL master log offset info in the trx system header if
-the magic number shows it valid. */
+Reads the log coordinates at the given offset in the trx sys header. */
+static
+void
+trx_sys_read_log_pos(
+/*=================*/
+ const trx_sysf_t* sys_header, /*!< in: the trx sys header */
+ uint header_offset, /*!< in: coord offset in the
+ header */
+ char* log_fn, /*!< out: the log file name */
+ ib_int64_t* log_pos) /*!< out: the log poistion */
+{
+ ut_memcpy(log_fn, sys_header + header_offset + TRX_SYS_MYSQL_LOG_NAME,
+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+
+ *log_pos =
+ (((ib_int64_t)mach_read_from_4(sys_header + header_offset
+ + TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
+ + mach_read_from_4(sys_header + header_offset
+ + TRX_SYS_MYSQL_LOG_OFFSET_LOW);
+}
+
+/*****************************************************************//**
+Prints to stderr the MySQL master log offset info in the trx system header
+PREPARE set of fields if the magic number shows it valid and stores it
+in global variables. */
UNIV_INTERN
void
trx_sys_print_mysql_master_log_pos(void)
@@ -1069,60 +1092,79 @@ trx_sys_print_mysql_master_log_pos(void)
return;
}
+ /* Copy the master log position info to global variables we can
+ use in ha_innobase.cc to initialize glob_mi to right values */
+ trx_sys_read_log_pos(sys_header, TRX_SYS_MYSQL_MASTER_LOG_INFO,
+ trx_sys_mysql_master_log_name,
+ &trx_sys_mysql_master_log_pos);
+
+ trx_sys_read_log_pos(sys_header, TRX_SYS_MYSQL_RELAY_LOG_INFO,
+ trx_sys_mysql_relay_log_name,
+ &trx_sys_mysql_relay_log_pos);
+
+ mtr_commit(&mtr);
+
fprintf(stderr,
"InnoDB: In a MySQL replication slave the last"
" master binlog file\n"
- "InnoDB: position %lu %lu, file name %s\n",
- (ulong) mach_read_from_4(sys_header
- + TRX_SYS_MYSQL_MASTER_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
- (ulong) mach_read_from_4(sys_header
- + TRX_SYS_MYSQL_MASTER_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
- sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
- + TRX_SYS_MYSQL_LOG_NAME);
+ "InnoDB: position %llu, file name %s\n",
+ trx_sys_mysql_master_log_pos,
+ trx_sys_mysql_master_log_name);
fprintf(stderr,
"InnoDB: and relay log file\n"
- "InnoDB: position %lu %lu, file name %s\n",
- (ulong) mach_read_from_4(sys_header
- + TRX_SYS_MYSQL_RELAY_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
- (ulong) mach_read_from_4(sys_header
- + TRX_SYS_MYSQL_RELAY_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
- sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
- + TRX_SYS_MYSQL_LOG_NAME);
+ "InnoDB: position %llu, file name %s\n",
+ trx_sys_mysql_relay_log_pos,
+ trx_sys_mysql_relay_log_name);
+}
- /* Copy the master log position info to global variables we can
- use in ha_innobase.cc to initialize glob_mi to right values */
+/*****************************************************************//**
+Prints to stderr the MySQL master log offset info in the trx system header
+COMMIT set of fields if the magic number shows it valid and stores it
+in global variables. */
+UNIV_INTERN
+void
+trx_sys_print_committed_mysql_master_log_pos(void)
+/*==============================================*/
+{
+ trx_sysf_t* sys_header;
+ mtr_t mtr;
- ut_memcpy(trx_sys_mysql_master_log_name,
- sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
- + TRX_SYS_MYSQL_LOG_NAME,
- TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+ mtr_start(&mtr);
- trx_sys_mysql_master_log_pos
- = (((ib_int64_t) mach_read_from_4(
- sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
- + ((ib_int64_t) mach_read_from_4(
- sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_LOW));
-
- ut_memcpy(trx_sys_mysql_relay_log_name,
- sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
- + TRX_SYS_MYSQL_LOG_NAME,
- TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+ sys_header = trx_sysf_get(&mtr);
+
+ if (mach_read_from_4(sys_header + TRX_SYS_COMMIT_MASTER_LOG_INFO
+ + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
+ != TRX_SYS_MYSQL_LOG_MAGIC_N) {
+
+ mtr_commit(&mtr);
+
+ return;
+ }
+
+ /* Copy the master log position info to global variables we can
+ use in ha_innobase.cc to initialize glob_mi to right values */
+ trx_sys_read_log_pos(sys_header, TRX_SYS_COMMIT_MASTER_LOG_INFO,
+ trx_sys_mysql_master_log_name,
+ &trx_sys_mysql_master_log_pos);
+
+ trx_sys_read_log_pos(sys_header, TRX_SYS_COMMIT_RELAY_LOG_INFO,
+ trx_sys_mysql_relay_log_name,
+ &trx_sys_mysql_relay_log_pos);
- trx_sys_mysql_relay_log_pos
- = (((ib_int64_t) mach_read_from_4(
- sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
- + ((ib_int64_t) mach_read_from_4(
- sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_LOW));
mtr_commit(&mtr);
+
+ fprintf(stderr,
+ "InnoDB: In a MySQL replication slave the last"
+ " master binlog file\n"
+ "InnoDB: position %llu, file name %s\n",
+ trx_sys_mysql_master_log_pos, trx_sys_mysql_master_log_name);
+
+ fprintf(stderr,
+ "InnoDB: and relay log file\n"
+ "InnoDB: position %llu, file name %s\n",
+ trx_sys_mysql_relay_log_pos, trx_sys_mysql_relay_log_name);
}
/****************************************************************//**
diff --git a/storage/xtradb/trx/trx0trx.c b/storage/xtradb/trx/trx0trx.c
index a6b5fab8589..521fc96d35c 100644
--- a/storage/xtradb/trx/trx0trx.c
+++ b/storage/xtradb/trx/trx0trx.c
@@ -951,13 +951,13 @@ trx_write_serialisation_history(
sys_header,
trx->mysql_relay_log_file_name,
trx->mysql_relay_log_pos,
- TRX_SYS_MYSQL_RELAY_LOG_INFO, &mtr);
+ TRX_SYS_COMMIT_RELAY_LOG_INFO, &mtr);
trx_sys_update_mysql_binlog_offset(
sys_header,
trx->mysql_master_log_file_name,
trx->mysql_master_log_pos,
- TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr);
+ TRX_SYS_COMMIT_MASTER_LOG_INFO, &mtr);
trx->mysql_master_log_file_name = "";
}
@@ -2069,6 +2069,23 @@ trx_prepare_off_kernel(
mutex_exit(&(rseg->mutex));
+ if (trx->mysql_master_log_file_name[0] != '\0') {
+ /* This database server is a MySQL replication slave */
+ trx_sysf_t* sys_header = trx_sysf_get(&mtr);
+
+ trx_sys_update_mysql_binlog_offset(
+ sys_header,
+ trx->mysql_relay_log_file_name,
+ trx->mysql_relay_log_pos,
+ TRX_SYS_MYSQL_RELAY_LOG_INFO, &mtr);
+ trx_sys_update_mysql_binlog_offset(
+ sys_header,
+ trx->mysql_master_log_file_name,
+ trx->mysql_master_log_pos,
+ TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr);
+ trx->mysql_master_log_file_name = "";
+ }
+
/*--------------*/
mtr_commit(&mtr); /* This mtr commit makes the
transaction prepared in the file-based
diff --git a/strings/decimal.c b/strings/decimal.c
index 51c4457d934..f318a234d3f 100644
--- a/strings/decimal.c
+++ b/strings/decimal.c
@@ -1170,7 +1170,7 @@ int decimal2longlong(const decimal_t *from, longlong *to)
And for -1234567890.1234 it would be
- 7E F2 04 37 2D FB 2D
+ 7E F2 04 C7 2D FB 2D
*/
int decimal2bin(const decimal_t *from, uchar *to, int precision, int frac)
{
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index 95fc61f2b72..91e7da6ff32 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -18554,6 +18554,22 @@ static void test_progress_reporting()
mysql_close(conn);
}
+/**
+ MDEV-3885 - connection suicide via mysql_kill() causes assertion in server
+*/
+
+static void test_mdev3885()
+{
+ int rc;
+ MYSQL *conn;
+
+ myheader("test_mdev3885");
+ conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
+ rc= mysql_kill(conn, mysql_thread_id(conn));
+ DIE_UNLESS(rc);
+ mysql_close(conn);
+}
+
/**
Bug#57058 SERVER_QUERY_WAS_SLOW not wired up.
@@ -19056,6 +19072,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug58036", test_bug58036 },
{ "test_bug57058", test_bug57058 },
{ "test_bug56976", test_bug56976 },
+ { "test_mdev3855", test_mdev3885 },
{ "test_bug11766854", test_bug11766854 },
{ "test_bug12337762", test_bug12337762 },
{ "test_progress_reporting", test_progress_reporting },