summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2012-12-16 16:49:19 -0800
committerIgor Babaev <igor@askmonty.org>2012-12-16 16:49:19 -0800
commit7760efad74140680b1eefaf2172b0fa26f7b1146 (patch)
tree57742baa180206a1cd3ea35d38c58108accd22a9
parent40bbf697aad7d923fc1bd995bc5f547e45461cbe (diff)
parentb8b875cb796743240bed71857eae73d37f03c28f (diff)
downloadmariadb-git-7760efad74140680b1eefaf2172b0fa26f7b1146.tar.gz
Merge mariadb-5.5 -> 10.0-base.
-rw-r--r--CMakeLists.txt4
-rw-r--r--client/mysql.cc29
-rw-r--r--client/mysql_upgrade.c7
-rw-r--r--client/mysqladmin.cc12
-rw-r--r--client/mysqlbinlog.cc20
-rw-r--r--client/mysqlcheck.c15
-rw-r--r--client/mysqldump.c4
-rw-r--r--client/mysqlimport.c5
-rw-r--r--client/mysqlshow.c8
-rw-r--r--client/mysqlslap.c4
-rw-r--r--client/mysqltest.cc5
-rw-r--r--client/sql_string.h.dontuse11
-rw-r--r--cmake/cpack_rpm.cmake7
-rw-r--r--cmake/mysql_version.cmake2
-rw-r--r--cmake/plugin.cmake3
-rw-r--r--cmake/ssl.cmake2
-rw-r--r--debian/mariadb-client-5.5.files1
-rwxr-xr-xdebian/patches/41_scripts__mysql_install_db.sh__no_test.dpatch4
-rw-r--r--extra/perror.c5
-rw-r--r--extra/yassl/README11
-rw-r--r--extra/yassl/include/lock.hpp9
-rw-r--r--extra/yassl/include/openssl/ssl.h2
-rw-r--r--extra/yassl/include/yassl_error.hpp2
-rw-r--r--extra/yassl/src/cert_wrapper.cpp3
-rw-r--r--extra/yassl/src/lock.cpp4
-rw-r--r--extra/yassl/src/ssl.cpp5
-rw-r--r--extra/yassl/src/yassl_error.cpp7
-rw-r--r--extra/yassl/taocrypt/include/aes.hpp1
-rw-r--r--extra/yassl/taocrypt/include/misc.hpp8
-rw-r--r--extra/yassl/taocrypt/include/pwdbased.hpp4
-rw-r--r--extra/yassl/taocrypt/src/asn.cpp4
-rw-r--r--extra/yassl/taocrypt/src/coding.cpp21
-rw-r--r--extra/yassl/taocrypt/src/crypto.cpp37
-rw-r--r--extra/yassl/taocrypt/taocrypt.dsw17
-rw-r--r--extra/yassl/taocrypt/test/memory.cpp2
-rw-r--r--extra/yassl/taocrypt/test/test.dsp (renamed from extra/yassl/taocrypt/test.dsp)14
-rw-r--r--extra/yassl/yassl.dsw5
-rw-r--r--include/my_base.h3
-rw-r--r--include/mysql.h12
-rw-r--r--include/mysql.h.pp1
-rw-r--r--include/mysql_com.h3
-rw-r--r--include/thread_pool_priv.h6
-rw-r--r--include/violite.h6
-rw-r--r--include/welcome_copyright_notice.h10
-rw-r--r--libmysqld/lib_sql.cc2
-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/derived_view.result6
-rw-r--r--mysql-test/r/func_str.result13
-rw-r--r--mysql-test/r/group_by.result11
-rw-r--r--mysql-test/r/information_schema.result6
-rw-r--r--mysql-test/r/information_schema_all_engines.result8
-rw-r--r--mysql-test/r/innodb_ext_key.result48
-rw-r--r--mysql-test/r/join_cache.result48
-rw-r--r--mysql-test/r/limit_rows_examined.result4
-rw-r--r--mysql-test/r/log_state.result12
-rw-r--r--mysql-test/r/mysqld--help,win.rdiff27
-rw-r--r--mysql-test/r/mysqld--help.result5
-rw-r--r--mysql-test/r/openssl_1.result8
-rw-r--r--mysql-test/r/order_by.result76
-rw-r--r--mysql-test/r/order_fill_sortbuf.result1
-rw-r--r--mysql-test/r/partition.result6
-rw-r--r--mysql-test/r/ps_1general.result11
-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/select.result48
-rw-r--r--mysql-test/r/select_jcl6.result56
-rw-r--r--mysql-test/r/select_pkeycache.result48
-rw-r--r--mysql-test/r/subselect.result152
-rw-r--r--mysql-test/r/subselect2.result116
-rw-r--r--mysql-test/r/subselect3.result2
-rw-r--r--mysql-test/r/subselect3_jcl6.result2
-rw-r--r--mysql-test/r/subselect4.result10
-rw-r--r--mysql-test/r/subselect_no_mat.result151
-rw-r--r--mysql-test/r/subselect_no_opts.result152
-rw-r--r--mysql-test/r/subselect_no_scache.result152
-rw-r--r--mysql-test/r/subselect_no_semijoin.result152
-rw-r--r--mysql-test/r/user_var.result32
-rw-r--r--mysql-test/r/variables.result4
-rw-r--r--mysql-test/r/view.result124
-rw-r--r--mysql-test/suite/federated/federated_archive.test4
-rw-r--r--mysql-test/suite/federated/federated_bug_13118.test4
-rw-r--r--mysql-test/suite/federated/federated_bug_25714.test4
-rw-r--r--mysql-test/suite/federated/federated_bug_32426.test4
-rw-r--r--mysql-test/suite/federated/federated_bug_35333.test4
-rw-r--r--mysql-test/suite/federated/federated_bug_585688.test4
-rw-r--r--mysql-test/suite/federated/federated_debug.test4
-rw-r--r--mysql-test/suite/federated/federated_innodb.test4
-rw-r--r--mysql-test/suite/federated/federated_partition.test4
-rw-r--r--mysql-test/suite/federated/federated_server.test4
-rw-r--r--mysql-test/suite/federated/federated_transactions.test4
-rw-r--r--mysql-test/suite/federated/federatedx.test4
-rw-r--r--mysql-test/suite/federated/include/federated.inc (renamed from mysql-test/suite/federated/federated.inc)0
-rw-r--r--mysql-test/suite/federated/include/federated_cleanup.inc (renamed from mysql-test/suite/federated/federated_cleanup.inc)0
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result4
-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/r/innodb_information_schema_buffer.result130
-rw-r--r--mysql-test/suite/innodb/t/innodb_bug14007649.test5
-rw-r--r--mysql-test/suite/innodb/t/innodb_information_schema_buffer.test76
-rw-r--r--mysql-test/suite/perfschema/disabled.def1
-rw-r--r--mysql-test/suite/plugins/r/audit_null.result29
-rw-r--r--mysql-test/suite/plugins/r/pam.result2
-rw-r--r--mysql-test/suite/plugins/t/audit_null.test30
-rw-r--r--mysql-test/suite/plugins/t/pam.test2
-rw-r--r--mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result2
-rw-r--r--mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test11
-rw-r--r--mysql-test/suite/sys_vars/r/debug_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result56
-rw-r--r--mysql-test/suite/sys_vars/r/ignore_db_dirs_basic.result49
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_buffer_pool_populate_basic.result1
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_changed_pages_limit_basic.result0
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_persistent_stats_root_page_basic.result24
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_track_changed_pages_basic.result21
-rw-r--r--mysql-test/suite/sys_vars/r/log_basic.result6
-rw-r--r--mysql-test/suite/sys_vars/r/log_slow_queries_basic.result18
-rw-r--r--mysql-test/suite/sys_vars/r/multi_range_count_basic.result54
-rw-r--r--mysql-test/suite/sys_vars/r/rpl_recovery_rank_basic.result28
-rw-r--r--mysql-test/suite/sys_vars/r/sql_big_selects_func.result2
-rw-r--r--mysql-test/suite/sys_vars/r/sql_max_join_size_basic.result10
-rw-r--r--mysql-test/suite/sys_vars/r/sql_max_join_size_func.result14
-rw-r--r--mysql-test/suite/sys_vars/t/default_master_connection_basic.test1
-rw-r--r--mysql-test/suite/sys_vars/t/ignore_db_dirs_basic-master.opt11
-rw-r--r--mysql-test/suite/sys_vars/t/ignore_db_dirs_basic.test38
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_buffer_pool_populate_basic.test1
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_changed_pages_limit_basic.test0
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_persistent_stats_root_page_basic.test26
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_track_changed_pages_basic.test21
-rw-r--r--mysql-test/suite/sys_vars/t/max_relay_log_size_basic.test2
-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/func_str.test11
-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.test60
-rw-r--r--mysql-test/t/join_cache.test49
-rw-r--r--mysql-test/t/mysqlshow.test16
-rw-r--r--mysql-test/t/openssl_1.test12
-rw-r--r--mysql-test/t/order_by.test65
-rw-r--r--mysql-test/t/order_fill_sortbuf-master.opt1
-rw-r--r--mysql-test/t/order_fill_sortbuf.test2
-rw-r--r--mysql-test/t/partition.test8
-rw-r--r--mysql-test/t/ps_1general.test10
-rwxr-xr-xmysql-test/t/range_vs_index_merge.test58
-rw-r--r--mysql-test/t/select.test2
-rw-r--r--mysql-test/t/subselect.test115
-rw-r--r--mysql-test/t/subselect2.test113
-rw-r--r--mysql-test/t/user_var.test28
-rw-r--r--mysql-test/t/view.test121
-rw-r--r--mysys/mf_iocache.c7
-rw-r--r--mysys/mf_pack.c15
-rw-r--r--mysys/my_context.c23
-rw-r--r--mysys/my_getopt.c5
-rw-r--r--mysys/stacktrace.c1
-rw-r--r--plugin/audit_null/audit_null.c2
-rw-r--r--plugin/auth_pam/mapper/pam_user_map.c93
-rw-r--r--plugin/auth_pam/testing/pam_mariadb_mtr.c20
-rw-r--r--plugin/feedback/CMakeLists.txt12
-rw-r--r--plugin/feedback/url_http.cc36
-rw-r--r--scripts/mysql_config.sh11
-rw-r--r--scripts/mysql_install_db.sh49
-rwxr-xr-xscripts/mysql_secure_installation.pl.in10
-rw-r--r--scripts/mysql_secure_installation.sh18
-rw-r--r--scripts/mysqlhotcopy.sh88
-rwxr-xr-xscripts/mytop.sh1
-rwxr-xr-xsql-bench/test-table-elimination.sh9
-rw-r--r--sql-common/mysql_async.c22
-rw-r--r--sql/create_options.cc7
-rw-r--r--sql/filesort.cc4
-rw-r--r--sql/gen_lex_hash.cc25
-rw-r--r--sql/ha_partition.cc155
-rw-r--r--sql/ha_partition.h12
-rw-r--r--sql/handler.cc35
-rw-r--r--sql/item.cc6
-rw-r--r--sql/item_func.h9
-rw-r--r--sql/item_strfunc.cc51
-rw-r--r--sql/item_subselect.cc27
-rw-r--r--sql/item_subselect.h5
-rw-r--r--sql/item_sum.cc6
-rw-r--r--sql/log.cc62
-rw-r--r--sql/log.h2
-rw-r--r--sql/mdl.cc120
-rw-r--r--sql/mdl.h6
-rw-r--r--sql/mysqld.cc73
-rw-r--r--sql/mysqld.h10
-rw-r--r--sql/opt_range.cc47
-rw-r--r--sql/scheduler.cc24
-rw-r--r--sql/scheduler.h2
-rw-r--r--sql/set_var.cc36
-rw-r--r--sql/set_var.h4
-rw-r--r--sql/share/charsets/Index.xml2
-rw-r--r--sql/share/errmsg-utf8.txt4
-rw-r--r--sql/sp_head.cc3
-rw-r--r--sql/spatial.cc7
-rw-r--r--sql/spatial.h8
-rw-r--r--sql/sql_acl.cc20
-rw-r--r--sql/sql_audit.h18
-rw-r--r--sql/sql_base.cc40
-rw-r--r--sql/sql_base.h3
-rw-r--r--sql/sql_class.cc70
-rw-r--r--sql/sql_delete.cc4
-rw-r--r--sql/sql_insert.cc3
-rw-r--r--sql/sql_join_cache.cc29
-rw-r--r--sql/sql_list.h4
-rw-r--r--sql/sql_parse.cc4
-rw-r--r--sql/sql_plugin.cc5
-rw-r--r--sql/sql_prepare.cc22
-rw-r--r--sql/sql_priv.h2
-rw-r--r--sql/sql_select.cc304
-rw-r--r--sql/sql_select.h21
-rw-r--r--sql/sql_show.cc283
-rw-r--r--sql/sql_show.h8
-rw-r--r--sql/sql_string.h11
-rw-r--r--sql/sql_table.cc2
-rw-r--r--sql/sql_update.cc8
-rw-r--r--sql/sys_vars.cc26
-rw-r--r--sql/sys_vars.h88
-rw-r--r--sql/table.cc38
-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/archive/ha_archive.cc6
-rw-r--r--storage/federated/ha_federated.cc2
-rw-r--r--storage/heap/CMakeLists.txt10
-rw-r--r--storage/heap/hp_rkey.c2
-rw-r--r--storage/innobase/btr/btr0btr.c47
-rw-r--r--storage/innobase/btr/btr0cur.c39
-rw-r--r--storage/innobase/btr/btr0pcur.c67
-rw-r--r--storage/innobase/buf/buf0buf.c11
-rw-r--r--storage/innobase/handler/ha_innodb.cc5
-rw-r--r--storage/innobase/handler/i_s.cc1853
-rw-r--r--storage/innobase/handler/i_s.h3
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.c17
-rw-r--r--storage/innobase/include/buf0buf.h33
-rw-r--r--storage/innobase/include/buf0buf.ic26
-rw-r--r--storage/innobase/include/fil0fil.h2
-rw-r--r--storage/innobase/include/log0log.h3
-rw-r--r--storage/innobase/page/page0cur.c1
-rw-r--r--storage/innobase/page/page0page.c31
-rw-r--r--storage/innobase/row/row0ins.c9
-rw-r--r--storage/innobase/row/row0merge.c14
-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_ft_nlq_search.c1
-rw-r--r--storage/maria/ma_rrnd.c4
-rw-r--r--storage/maria/ma_test2.c65
-rw-r--r--storage/myisam/ha_myisam.cc3
-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/CMakeLists.txt31
-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/btr/btr0sea.c9
-rw-r--r--storage/xtradb/buf/buf0buf.c35
-rw-r--r--storage/xtradb/buf/buf0lru.c114
-rw-r--r--storage/xtradb/buf/buf0rea.c4
-rw-r--r--storage/xtradb/handler/ha_innodb.cc398
-rw-r--r--storage/xtradb/handler/i_s.cc3402
-rw-r--r--storage/xtradb/handler/i_s.h74
-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/buf0lru.h11
-rw-r--r--storage/xtradb/include/fil0fil.h2
-rw-r--r--storage/xtradb/include/ha_prototypes.h2
-rw-r--r--storage/xtradb/include/log0log.h8
-rw-r--r--storage/xtradb/include/log0online.h111
-rw-r--r--storage/xtradb/include/log0recv.h37
-rw-r--r--storage/xtradb/include/os0file.h9
-rw-r--r--storage/xtradb/include/os0proc.h3
-rw-r--r--storage/xtradb/include/os0sync.h28
-rw-r--r--storage/xtradb/include/srv0srv.h24
-rw-r--r--storage/xtradb/include/trx0sys.h16
-rw-r--r--storage/xtradb/include/univ.i2
-rw-r--r--storage/xtradb/include/ut0rbt.h22
-rw-r--r--storage/xtradb/log/log0log.c126
-rw-r--r--storage/xtradb/log/log0online.c1085
-rw-r--r--storage/xtradb/log/log0recv.c8
-rw-r--r--storage/xtradb/os/os0file.c22
-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.c54
-rw-r--r--storage/xtradb/srv/srv0start.c22
-rw-r--r--storage/xtradb/trx/trx0sys.c132
-rw-r--r--storage/xtradb/trx/trx0trx.c21
-rw-r--r--storage/xtradb/ut/ut0rbt.c29
-rw-r--r--strings/decimal.c2
-rw-r--r--support-files/mysql.spec.sh28
-rw-r--r--support-files/rpm/server-postin.sh53
-rw-r--r--tests/mysql_client_fw.c65
-rw-r--r--tests/mysql_client_test.c26
-rw-r--r--vio/viosslfactories.c94
303 files changed, 12767 insertions, 2053 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5133d024ef1..84a2a1d625b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -320,6 +320,10 @@ IF(NOT WITHOUT_SERVER)
ADD_SUBDIRECTORY(mysql-test)
ADD_SUBDIRECTORY(mysql-test/lib/My/SafeProcess)
ADD_SUBDIRECTORY(sql-bench)
+
+ IF(EXISTS ${CMAKE_SOURCE_DIR}/internal/CMakeLists.txt)
+ ADD_SUBDIRECTORY(internal)
+ ENDIF()
ENDIF()
IF(UNIX)
diff --git a/client/mysql.cc b/client/mysql.cc
index 5aab3e1098f..67878b36227 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1,6 +1,6 @@
-/* Copyright (C) 2000-2009 MySQL AB
- Copyright 2000, 2010-2011, Oracle and/or its affiliates.
- Copyright 2000-2010 Monty Program Ab
+/*
+ Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2009, 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
@@ -15,10 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#define COPYRIGHT_NOTICE "\
-This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
-and you are welcome to modify and redistribute it under the GPL v2 license\n"
-
/* mysql command tool
* Commands compatible with mSQL by David J. Hughes
*
@@ -111,6 +107,7 @@ extern "C" {
#endif
#include "completion_hash.h"
+#include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
#define PROMPT_CHAR '\\'
#define DEFAULT_DELIMITER ";"
@@ -1193,7 +1190,7 @@ int main(int argc,char *argv[])
mysql_thread_id(&mysql), server_version_string(&mysql));
put_info((char*) glob_buffer.ptr(),INFO_INFO);
- put_info(COPYRIGHT_NOTICE, INFO_INFO);
+ put_info(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"), INFO_INFO);
#ifdef HAVE_READLINE
initialize_readline((char*) my_progname);
@@ -1624,7 +1621,7 @@ static void usage(int version)
if (version)
return;
- printf("%s", COPYRIGHT_NOTICE);
+ puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
printf("Usage: %s [OPTIONS] [database]\n", my_progname);
my_print_help(my_long_options);
print_defaults("my", load_default_groups);
@@ -2808,7 +2805,7 @@ static int com_server_help(String *buffer __attribute__((unused)),
char *line __attribute__((unused)), char *help_arg)
{
MYSQL_ROW cur;
- const char *server_cmd= buffer->ptr();
+ const char *server_cmd;
char cmd_buf[100 + 1];
MYSQL_RES *result;
int error;
@@ -2823,9 +2820,12 @@ static int com_server_help(String *buffer __attribute__((unused)),
*++end_arg= '\0';
}
(void) strxnmov(cmd_buf, sizeof(cmd_buf), "help '", help_arg, "'", NullS);
- server_cmd= cmd_buf;
}
-
+ else
+ (void) strxnmov(cmd_buf, sizeof(cmd_buf), "help ", help_arg, NullS);
+
+ server_cmd= cmd_buf;
+
if (!status.batch)
{
old_buffer= *buffer;
@@ -2893,6 +2893,11 @@ static int com_server_help(String *buffer __attribute__((unused)),
else
{
put_info("\nNothing found", INFO_INFO);
+ if (strncasecmp(server_cmd, "help 'contents'", 15) == 0)
+ {
+ put_info("\nPlease check if 'help tables' are loaded.\n", INFO_INFO);
+ goto err;
+ }
put_info("Please try to run 'help contents' for a list of all accessible topics\n", INFO_INFO);
}
}
diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index d7f311fcb69..71bc936cfe6 100644
--- a/client/mysql_upgrade.c
+++ b/client/mysql_upgrade.c
@@ -1,7 +1,6 @@
/*
- Copyright (C) 2000 MySQL AB
- Copyright (c) 2006, 2011, Oracle and/or its affiliates.
- Copyright (C) 2010-2011 Monty Program Ab
+ Copyright (c) 2006, 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
@@ -252,7 +251,7 @@ get_one_option(int optid, const struct my_option *opt,
case '?':
printf("%s Ver %s Distrib %s, for %s (%s)\n",
my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
- puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2010"));
+ puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
puts("MariaDB utility for upgrading databases to new MariaDB versions.\n");
my_print_help(my_long_options);
die(0);
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index 52474596dfe..61045518a17 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -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
@@ -22,6 +23,7 @@
#include <sys/stat.h>
#include <mysql.h>
#include <sql_common.h>
+#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
#define ADMIN_VERSION "9.1"
#define MAX_MYSQL_VAR 512
@@ -704,9 +706,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
case ADMIN_VER:
new_line=1;
print_version();
- puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc,\n"
- "2009 Monty Program Ab");
- puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
+ puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
printf("Server version\t\t%s\n", mysql_get_server_info(mysql));
printf("Protocol version\t%d\n", mysql_get_proto_info(mysql));
printf("Connection\t\t%s\n",mysql_get_host_info(mysql));
@@ -1219,9 +1219,7 @@ static void print_version(void)
static void usage(void)
{
print_version();
- puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc,\n"
- "2009 Monty Program Ab");
- puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
+ puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
puts("Administration program for the mysqld daemon.");
printf("Usage: %s [OPTIONS] command command....\n", my_progname);
my_print_help(my_long_options);
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index f604b8bc84f..8f6baea4b9f 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -38,6 +38,9 @@
#include "sql_priv.h"
#include "log_event.h"
#include "sql_common.h"
+#include "my_dir.h"
+#include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
+
#include "sql_string.h" // needed for Rpl_filter
#include "sql_list.h" // needed for Rpl_filter
@@ -1501,10 +1504,7 @@ static void print_version()
static void usage()
{
print_version();
- puts("By Monty and Sasha, for your professional use\n\
-This software comes with NO WARRANTY: This is free software,\n\
-and you are welcome to modify and redistribute it under the GPL license.\n");
-
+ puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
printf("\
Dumps a MySQL binary log in a format usable for viewing or for piping to\n\
the mysql command line client.\n\n");
@@ -2087,6 +2087,7 @@ static Exit_status check_header(IO_CACHE* file,
uchar header[BIN_LOG_HEADER_SIZE];
uchar buf[PROBE_HEADER_LEN];
my_off_t tmp_pos, pos;
+ MY_STAT my_file_stat;
delete glob_description_event;
if (!(glob_description_event= new Format_description_log_event(3)))
@@ -2096,7 +2097,16 @@ static Exit_status check_header(IO_CACHE* file,
}
pos= my_b_tell(file);
- my_b_seek(file, (my_off_t)0);
+
+ /* fstat the file to check if the file is a regular file. */
+ if (my_fstat(file->file, &my_file_stat, MYF(0)) == -1)
+ {
+ error("Unable to stat the file.");
+ return ERROR_STOP;
+ }
+ if ((my_file_stat.st_mode & S_IFMT) == S_IFREG)
+ my_b_seek(file, (my_off_t)0);
+
if (my_b_read(file, header, sizeof(header)))
{
error("Failed reading header; probably an empty file.");
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index 39ceb423968..4218f2da62c 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -1,6 +1,6 @@
-/* Copyright (C) 2000 MySQL AB & Jani Tolonen
- Copyright (c) 2001, 2011, Oracle and/or its affiliates.
- Copyright (C) 2010-2011 Monty Program Ab
+/*
+ Copyright (c) 2001, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2011, 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
@@ -25,6 +25,7 @@
#include <mysql_version.h>
#include <mysqld_error.h>
#include <sslopt-vars.h>
+#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
/* Exit codes */
@@ -229,13 +230,7 @@ static void usage(void)
{
DBUG_ENTER("usage");
print_version();
- puts("By Jani Tolonen, 2001-04-20, MySQL Development Team.\n");
- puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,");
- puts("and you are welcome to modify and redistribute it under the GPL license.\n");
- printf("Usage: %s [OPTIONS] database [tables]\n", my_progname);
- printf("OR %s [OPTIONS] --databases DB1 [DB2 DB3...]\n",
- my_progname);
- printf("OR %s [OPTIONS] --all-databases\n\n", my_progname);
+ puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
puts("This program can be used to CHECK (-c, -m, -C), REPAIR (-r), ANALYZE (-a),");
puts("or OPTIMIZE (-o) tables. Some of the options (like -e or -q) can be");
puts("used at the same time. Not all options are supported by all storage engines.");
diff --git a/client/mysqldump.c b/client/mysqldump.c
index e3572efa9ba..49b992e6c4d 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -1,5 +1,6 @@
/*
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
@@ -616,8 +617,7 @@ static void short_usage_sub(void)
static void usage(void)
{
print_version();
- puts("By Igor Romanenko, Monty, Jani & Sinisa and others.");
- puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license.\n");
+ puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
puts("Dumping structure and contents of MySQL databases and tables.");
short_usage_sub();
print_defaults("my",load_default_groups);
diff --git a/client/mysqlimport.c b/client/mysqlimport.c
index e4e34f786d7..77d0cd0a7d3 100644
--- a/client/mysqlimport.c
+++ b/client/mysqlimport.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
@@ -208,7 +208,8 @@ static void usage(void)
puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.");
puts("Copyright 2008-2011 Oracle and Monty Program Ab.");
print_version();
- printf("\n\
+ puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
+ printf("\
Loads tables from text files in various formats. The base name of the\n\
text file must be the name of the table that should be used.\n\
If one uses sockets to connect to the MySQL server, the server will open and\n\
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index d0db2020998..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
@@ -27,6 +28,7 @@
#include <signal.h>
#include <stdarg.h>
#include <sslopt-vars.h>
+#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
static char * host=0, *opt_password=0, *user=0;
static my_bool opt_show_keys= 0, opt_compress= 0, opt_count=0, opt_status= 0;
@@ -266,9 +268,7 @@ static void print_version(void)
static void usage(void)
{
print_version();
- puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.");
- puts("Copyright 2008-2011 Oracle and Monty Program Ab.");
- puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license.\n");
+ puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
puts("Shows the structure of a MySQL database (databases, tables, and columns).\n");
printf("Usage: %s [OPTIONS] [database [table [column]]]\n",my_progname);
puts("\n\
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
index e3da44e2fc5..8e70a2609c3 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2005, 2011, Oracle and/or its affiliates.
+ Copyright (c) 2005, 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
@@ -722,7 +722,7 @@ static void print_version(void)
static void usage(void)
{
print_version();
- puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2005, 2010"));
+ puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2005"));
puts("Run a query multiple times against the server.\n");
printf("Usage: %s [OPTIONS]\n",my_progname);
print_defaults("my",load_default_groups);
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index e309a62c28c..d61a48fe964 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -54,6 +54,8 @@
#include <signal.h>
#include <my_stacktrace.h>
+#include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
+
#ifdef __WIN__
#include <crtdbg.h>
#define SIGNAL_FMT "exception 0x%x"
@@ -6985,8 +6987,7 @@ void print_version(void)
void usage()
{
print_version();
- printf("MySQL AB, by Sasha, Matt, Monty & Jani and others\n");
- printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
+ puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
printf("Runs a test against the mysql server and compares output with a results file.\n\n");
printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname);
my_print_help(my_long_options);
diff --git a/client/sql_string.h.dontuse b/client/sql_string.h.dontuse
index fc302110513..67155ebcee7 100644
--- a/client/sql_string.h.dontuse
+++ b/client/sql_string.h.dontuse
@@ -1,8 +1,7 @@
#ifndef SQL_STRING_INCLUDED
#define SQL_STRING_INCLUDED
-/*
- Copyright (c) 2000, 2010, Oracle and/or its affiliates
+/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -194,8 +193,12 @@ public:
}
bool real_alloc(uint32 arg_length); // Empties old string
bool realloc(uint32 arg_length);
- inline void shrink(uint32 arg_length) // Shrink buffer
+
+ // Shrink the buffer, but only if it is allocated on the heap.
+ inline void shrink(uint32 arg_length)
{
+ if (!is_alloced())
+ return;
if (arg_length < Alloced_length)
{
char *new_ptr;
@@ -211,7 +214,7 @@ public:
}
}
}
- bool is_alloced() { return alloced; }
+ bool is_alloced() const { return alloced; }
inline String& operator = (const String &s)
{
if (&s != this)
diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake
index e915e732612..f5017d6c984 100644
--- a/cmake/cpack_rpm.cmake
+++ b/cmake/cpack_rpm.cmake
@@ -64,8 +64,10 @@ SET(CPACK_RPM_SPEC_MORE_DEFINE "${CPACK_RPM_SPEC_MORE_DEFINE}
SET(CPACK_RPM_PACKAGE_REQUIRES "MariaDB-common")
-SET(CPACK_RPM_server_USER_FILELIST "%ignore /etc" "%ignore /etc/init.d")
+SET(CPACK_RPM_server_USER_FILELIST "%ignore /etc" "%ignore /etc/init.d" "%config(noreplace) /etc/my.cnf.d/*")
SET(CPACK_RPM_common_USER_FILELIST "%config(noreplace) /etc/my.cnf")
+SET(CPACK_RPM_shared_USER_FILELIST "%config(noreplace) /etc/my.cnf.d/*")
+SET(CPACK_RPM_client_USER_FILELIST "%config(noreplace) /etc/my.cnf.d/*")
SET(CPACK_RPM_client_PACKAGE_OBSOLETES "mysql-client MySQL-client MySQL-OurDelta-client")
SET(CPACK_RPM_client_PACKAGE_PROVIDES "MariaDB-client MySQL-client mysql-client")
@@ -84,9 +86,10 @@ SET(CPACK_RPM_server_PACKAGE_PROVIDES "MariaDB MariaDB-server MySQL-server confi
SET(CPACK_RPM_server_PRE_INSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/server-prein.sh)
SET(CPACK_RPM_server_PRE_UNINSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/server-preun.sh)
SET(CPACK_RPM_server_POST_INSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/server-postin.sh)
+SET(CPACK_RPM_server_POST_UNINSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/server-postun.sh)
SET(CPACK_RPM_shared_PACKAGE_OBSOLETES "mysql-shared MySQL-shared-standard MySQL-shared-pro MySQL-shared-pro-cert MySQL-shared-pro-gpl MySQL-shared-pro-gpl-cert MySQL-shared MySQL-OurDelta-shared")
-SET(CPACK_RPM_shared_PACKAGE_PROVIDES "MariaDB-shared MySQL-shared mysql-shared libmysqlclient.so.${SHARED_LIB_MAJOR_VERSION} libmysqlclient.so.${SHARED_LIB_MAJOR_VERSION}(libmysqlclient_${SHARED_LIB_MAJOR_VERSION}) libmysqlclient_r.so.${SHARED_LIB_MAJOR_VERSION} libmysqlclient_r.so.${SHARED_LIB_MAJOR_VERSION}(libmysqlclient_${SHARED_LIB_MAJOR_VERSION})")
+SET(CPACK_RPM_shared_PACKAGE_PROVIDES "MariaDB-shared MySQL-shared mysql-shared libmysqlclient.so.18 libmysqlclient.so.18(libmysqlclient_16) libmysqlclient.so.18(libmysqlclient_18) libmysqlclient_r.so.18 libmysqlclient_r.so.18(libmysqlclient_18)")
SET(CPACK_RPM_shared_POST_INSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/shared-post.sh)
SET(CPACK_RPM_shared_POST_UNINSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/shared-post.sh)
diff --git a/cmake/mysql_version.cmake b/cmake/mysql_version.cmake
index 387be7156a0..ce6ff994eda 100644
--- a/cmake/mysql_version.cmake
+++ b/cmake/mysql_version.cmake
@@ -67,7 +67,7 @@ IF(NOT "${MAJOR_VERSION}" MATCHES "[0-9]+" OR
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/cmake/plugin.cmake b/cmake/plugin.cmake
index 1e7f83ec227..524f368c6d7 100644
--- a/cmake/plugin.cmake
+++ b/cmake/plugin.cmake
@@ -133,7 +133,6 @@ MACRO(MYSQL_ADD_PLUGIN)
ENDIF()
ADD_LIBRARY(${target} STATIC ${SOURCES})
- SET_TARGET_PROPERTIES(${target} PROPERTIES COMPILE_DEFINITONS "MYSQL_SERVER")
DTRACE_INSTRUMENT(${target})
ADD_DEPENDENCIES(${target} GenError ${ARG_DEPENDENCIES})
RESTRICT_SYMBOL_EXPORTS(${target})
@@ -146,7 +145,7 @@ MACRO(MYSQL_ADD_PLUGIN)
DTRACE_INSTRUMENT(${target}_embedded)
IF(ARG_RECOMPILE_FOR_EMBEDDED)
SET_TARGET_PROPERTIES(${target}_embedded
- PROPERTIES COMPILE_DEFINITIONS "MYSQL_SERVER;EMBEDDED_LIBRARY")
+ PROPERTIES COMPILE_DEFINITIONS "EMBEDDED_LIBRARY")
ENDIF()
ADD_DEPENDENCIES(${target}_embedded GenError)
ENDIF()
diff --git a/cmake/ssl.cmake b/cmake/ssl.cmake
index b5b94310d29..cabff530b47 100644
--- a/cmake/ssl.cmake
+++ b/cmake/ssl.cmake
@@ -25,7 +25,7 @@ MACRO (MYSQL_USE_BUNDLED_SSL)
SET(SSL_LIBRARIES yassl taocrypt)
SET(SSL_INCLUDE_DIRS ${INC_DIRS})
SET(SSL_INTERNAL_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extra/yassl/taocrypt/mySTL)
- SET(SSL_DEFINES "-DHAVE_YASSL -DYASSL_PURE_C -DYASSL_PREFIX -DHAVE_OPENSSL -DYASSL_THREAD_SAFE")
+ SET(SSL_DEFINES "-DHAVE_YASSL -DYASSL_PURE_C -DYASSL_PREFIX -DHAVE_OPENSSL -DMULTI_THREADED")
CHANGE_SSL_SETTINGS("bundled")
#Remove -fno-implicit-templates
#(yassl sources cannot be compiled with it)
diff --git a/debian/mariadb-client-5.5.files b/debian/mariadb-client-5.5.files
index 335f736d680..9cb949ea53e 100644
--- a/debian/mariadb-client-5.5.files
+++ b/debian/mariadb-client-5.5.files
@@ -11,7 +11,6 @@ usr/bin/mysqlimport
usr/bin/mysqlreport
usr/bin/mysqlshow
usr/bin/mysqlslap
-usr/bin/mytop
usr/bin/mysql_waitpid
usr/share/lintian/overrides/mariadb-client-5.5
usr/share/man/man1/innotop.1
diff --git a/debian/patches/41_scripts__mysql_install_db.sh__no_test.dpatch b/debian/patches/41_scripts__mysql_install_db.sh__no_test.dpatch
index e79ac71cc7b..d4e67b321b0 100755
--- a/debian/patches/41_scripts__mysql_install_db.sh__no_test.dpatch
+++ b/debian/patches/41_scripts__mysql_install_db.sh__no_test.dpatch
@@ -13,8 +13,8 @@
fi
# Create database directories
--for dir in $ldata $ldata/mysql $ldata/test
-+for dir in $ldata $ldata/mysql
+-for dir in "$ldata" "$ldata/mysql" "$ldata/test"
++for dir in "$ldata" "$ldata/mysql"
do
if test ! -d $dir
then
diff --git a/extra/perror.c b/extra/perror.c
index a3104b6ddf0..8aa6aa35b08 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
@@ -28,6 +28,7 @@
#include "../storage/ndb/src/kernel/error/ndbd_exit_codes.c"
#include "../storage/ndb/include/mgmapi/mgmapi_error.h"
#endif
+#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
static my_bool verbose, print_all_codes;
@@ -113,7 +114,7 @@ static void print_version(void)
static void usage(void)
{
print_version();
- puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
+ puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
printf("Print a description for a system error code or a MySQL error code.\n");
printf("If you want to get the error for a negative error code, you should use\n-- before the first error code to tell perror that there was no more options.\n\n");
printf("Usage: %s [OPTIONS] [ERRORCODE [ERRORCODE...]]\n",my_progname);
diff --git a/extra/yassl/README b/extra/yassl/README
index 7720a9453dd..24bdf32f989 100644
--- a/extra/yassl/README
+++ b/extra/yassl/README
@@ -12,7 +12,16 @@ before calling SSL_new();
*** end Note ***
-yaSSL Release notes, version 2.1.2 (9/2/2011)
+yaSSL Release notes, version 2.2.2 (7/5/2012)
+
+ This release of yaSSL contains bug fixes and more security checks around
+ malicious certificates.
+
+See normal build instructions below under 1.0.6.
+See libcurl build instructions below under 1.3.0 and note in 1.5.8.
+
+
+*****************yaSSL Release notes, version 2.1.2 (9/2/2011)
This release of yaSSL contains bug fixes, better non-blocking support with
SSL_write, and OpenSSL RSA public key format support.
diff --git a/extra/yassl/include/lock.hpp b/extra/yassl/include/lock.hpp
index ae875001633..487bedfcc70 100644
--- a/extra/yassl/include/lock.hpp
+++ b/extra/yassl/include/lock.hpp
@@ -27,7 +27,7 @@
Visual Studio Source Annotations header (sourceannotations.h) fails
to compile if outside of the global namespace.
*/
-#ifdef YASSL_THREAD_SAFE
+#ifdef MULTI_THREADED
#ifdef _WIN32
#include <windows.h>
#endif
@@ -36,8 +36,9 @@
namespace yaSSL {
-#ifdef YASSL_THREAD_SAFE
+#ifdef MULTI_THREADED
#ifdef _WIN32
+ #include <windows.h>
class Mutex {
CRITICAL_SECTION cs_;
@@ -77,7 +78,7 @@ namespace yaSSL {
};
#endif // _WIN32
-#else // YASSL_THREAD_SAFE (WE'RE SINGLE)
+#else // MULTI_THREADED (WE'RE SINGLE)
class Mutex {
public:
@@ -87,7 +88,7 @@ namespace yaSSL {
};
};
-#endif // YASSL_THREAD_SAFE
+#endif // MULTI_THREADED
diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h
index 0d99888da88..2fcba67cfdd 100644
--- a/extra/yassl/include/openssl/ssl.h
+++ b/extra/yassl/include/openssl/ssl.h
@@ -35,7 +35,7 @@
#include "rsa.h"
-#define YASSL_VERSION "2.2.0"
+#define YASSL_VERSION "2.2.2"
#if defined(__cplusplus)
diff --git a/extra/yassl/include/yassl_error.hpp b/extra/yassl/include/yassl_error.hpp
index 87bb4c55e96..8efc7f72e87 100644
--- a/extra/yassl/include/yassl_error.hpp
+++ b/extra/yassl/include/yassl_error.hpp
@@ -65,7 +65,7 @@ enum YasslError {
enum Library { yaSSL_Lib = 0, CryptoLib, SocketLib };
enum { MAX_ERROR_SZ = 80 };
-void SetErrorString(unsigned long, char*);
+void SetErrorString(YasslError, char*);
/* remove for now, if go back to exceptions use this wrapper
// Base class for all yaSSL exceptions
diff --git a/extra/yassl/src/cert_wrapper.cpp b/extra/yassl/src/cert_wrapper.cpp
index 7e73464001a..917cfa1a8fb 100644
--- a/extra/yassl/src/cert_wrapper.cpp
+++ b/extra/yassl/src/cert_wrapper.cpp
@@ -250,8 +250,7 @@ int CertManager::Validate()
TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length());
TaoCrypt::CertDecoder cert(source, true, &signers_, verifyNone_);
- int err = cert.GetError().What();
- if ( err )
+ if (int err = cert.GetError().What())
return err;
const TaoCrypt::PublicKey& key = cert.GetPublicKey();
diff --git a/extra/yassl/src/lock.cpp b/extra/yassl/src/lock.cpp
index 9eb41408ff7..d603440757f 100644
--- a/extra/yassl/src/lock.cpp
+++ b/extra/yassl/src/lock.cpp
@@ -26,7 +26,7 @@
namespace yaSSL {
-#ifdef YASSL_THREAD_SAFE
+#ifdef MULTI_THREADED
#ifdef _WIN32
Mutex::Mutex()
@@ -79,7 +79,7 @@ namespace yaSSL {
#endif // _WIN32
-#endif // YASSL_THREAD_SAFE
+#endif // MULTI_THREADED
diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp
index 8401798534b..6c839bc2f79 100644
--- a/extra/yassl/src/ssl.cpp
+++ b/extra/yassl/src/ssl.cpp
@@ -27,7 +27,6 @@
-
/* see man pages for function descriptions */
#include "runtime.hpp"
@@ -747,7 +746,7 @@ void SSL_CTX_set_verify(SSL_CTX* ctx, int mode, VerifyCallback vc)
int SSL_CTX_load_verify_locations(SSL_CTX* ctx, const char* file,
const char* path)
{
- int ret = SSL_SUCCESS;
+ int ret = SSL_FAILURE;
const int HALF_PATH = 128;
if (file) ret = read_file(ctx, file, SSL_FILETYPE_PEM, CA);
@@ -1014,7 +1013,7 @@ char* ERR_error_string(unsigned long errNumber, char* buffer)
static char* msg = (char*)"Please supply a buffer for error string";
if (buffer) {
- SetErrorString(errNumber, buffer);
+ SetErrorString(YasslError(errNumber), buffer);
return buffer;
}
diff --git a/extra/yassl/src/yassl_error.cpp b/extra/yassl/src/yassl_error.cpp
index e55c10c68c0..f48fbdc925e 100644
--- a/extra/yassl/src/yassl_error.cpp
+++ b/extra/yassl/src/yassl_error.cpp
@@ -31,11 +31,6 @@
#pragma warning(disable: 4996)
#endif
-#ifdef _MSC_VER
- // 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy
- #pragma warning(disable: 4996)
-#endif
-
namespace yaSSL {
@@ -60,7 +55,7 @@ Library Error::get_lib() const
*/
-void SetErrorString(unsigned long error, char* buffer)
+void SetErrorString(YasslError error, char* buffer)
{
using namespace TaoCrypt;
const int max = MAX_ERROR_SZ; // shorthand
diff --git a/extra/yassl/taocrypt/include/aes.hpp b/extra/yassl/taocrypt/include/aes.hpp
index dc19c98a83a..e2041fc9350 100644
--- a/extra/yassl/taocrypt/include/aes.hpp
+++ b/extra/yassl/taocrypt/include/aes.hpp
@@ -92,7 +92,6 @@ typedef BlockCipher<ENCRYPTION, AES, CBC> AES_CBC_Encryption;
typedef BlockCipher<DECRYPTION, AES, CBC> AES_CBC_Decryption;
-
} // naemspace
#endif // TAO_CRYPT_AES_HPP
diff --git a/extra/yassl/taocrypt/include/misc.hpp b/extra/yassl/taocrypt/include/misc.hpp
index b6925f916f8..c58713855dd 100644
--- a/extra/yassl/taocrypt/include/misc.hpp
+++ b/extra/yassl/taocrypt/include/misc.hpp
@@ -136,9 +136,13 @@ void CleanUp();
// Turn on ia32 ASM for Big Integer
// CodeWarrior defines _MSC_VER
+//
+// Do not use assembler with GCC, as the implementation for it is broken;
+// it does not use proper GCC asm contraints and makes assumptions about
+// frame pointers and so on, which breaks depending on GCC version and
+// optimization level.
#if !defined(TAOCRYPT_DISABLE_X86ASM) && ((defined(_MSC_VER) && \
- !defined(__MWERKS__) && defined(_M_IX86)) || \
- (defined(__GNUC__) && defined(__i386__)))
+ !defined(__MWERKS__) && defined(_M_IX86)))
#define TAOCRYPT_X86ASM_AVAILABLE
#endif
diff --git a/extra/yassl/taocrypt/include/pwdbased.hpp b/extra/yassl/taocrypt/include/pwdbased.hpp
index f40a336e2c3..d050fd8988b 100644
--- a/extra/yassl/taocrypt/include/pwdbased.hpp
+++ b/extra/yassl/taocrypt/include/pwdbased.hpp
@@ -48,9 +48,11 @@ word32 PBKDF2_HMAC<T>::DeriveKey(byte* derived, word32 dLen, const byte* pwd,
word32 pLen, const byte* salt, word32 sLen,
word32 iterations) const
{
- if (dLen > MaxDerivedKeyLength())
+ if (dLen > MaxDerivedKeyLength())
return 0;
+ if (iterations < 0)
+ return 0;
ByteBlock buffer(T::DIGEST_SIZE);
HMAC<T> hmac;
diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp
index 5ec4cac1c44..ad054809879 100644
--- a/extra/yassl/taocrypt/src/asn.cpp
+++ b/extra/yassl/taocrypt/src/asn.cpp
@@ -154,6 +154,8 @@ word32 GetLength(Source& source)
else
length = b;
+ if (source.IsLeft(length) == false) return 0;
+
return length;
}
@@ -832,7 +834,7 @@ void CertDecoder::GetName(NameType nt)
if (email) {
if (!(ptr = AddTag(ptr, buf_end, "/emailAddress=", 14, length))) {
source_.SetError(CONTENT_E);
- return;
+ return;
}
}
diff --git a/extra/yassl/taocrypt/src/coding.cpp b/extra/yassl/taocrypt/src/coding.cpp
index 97c62ea12a7..0512ea9c889 100644
--- a/extra/yassl/taocrypt/src/coding.cpp
+++ b/extra/yassl/taocrypt/src/coding.cpp
@@ -103,6 +103,16 @@ void HexDecoder::Decode()
byte b = coded_.next() - 0x30; // 0 starts at 0x30
byte b2 = coded_.next() - 0x30;
+ // sanity checks
+ if (b >= sizeof(hexDecode)/sizeof(hexDecode[0])) {
+ coded_.SetError(PEM_E);
+ return;
+ }
+ if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0])) {
+ coded_.SetError(PEM_E);
+ return;
+ }
+
b = hexDecode[b];
b2 = hexDecode[b2];
@@ -178,6 +188,7 @@ void Base64Decoder::Decode()
{
word32 bytes = coded_.size();
word32 plainSz = bytes - ((bytes + (pemLineSz - 1)) / pemLineSz);
+ const byte maxIdx = (byte)sizeof(base64Decode) + 0x2B - 1;
plainSz = ((plainSz * 3) / 4) + 3;
decoded_.New(plainSz);
@@ -200,6 +211,16 @@ void Base64Decoder::Decode()
if (e4 == pad)
pad4 = true;
+ if (e1 < 0x2B || e2 < 0x2B || e3 < 0x2B || e4 < 0x2B) {
+ coded_.SetError(PEM_E);
+ return;
+ }
+
+ if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) {
+ coded_.SetError(PEM_E);
+ return;
+ }
+
e1 = base64Decode[e1 - 0x2B];
e2 = base64Decode[e2 - 0x2B];
e3 = (e3 == pad) ? 0 : base64Decode[e3 - 0x2B];
diff --git a/extra/yassl/taocrypt/src/crypto.cpp b/extra/yassl/taocrypt/src/crypto.cpp
deleted file mode 100644
index 90d406bf0c2..00000000000
--- a/extra/yassl/taocrypt/src/crypto.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- Copyright (C) 2000-2007 MySQL 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
- the Free Software Foundation; version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- MA 02110-1301 USA.
-*/
-
-/* put features that other apps expect from OpenSSL type crypto */
-
-
-
-extern "C" {
-
- // for libcurl configure test, these are the signatures they use
- // locking handled internally by library
- char CRYPTO_lock() { return 0;}
- char CRYPTO_add_lock() { return 0;}
-
-
- // for openvpn, test are the signatures they use
- char EVP_CIPHER_CTX_init() { return 0; }
- char CRYPTO_mem_ctrl() { return 0; }
-} // extern "C"
-
-
-
diff --git a/extra/yassl/taocrypt/taocrypt.dsw b/extra/yassl/taocrypt/taocrypt.dsw
index d10d7534c3d..43115069160 100644
--- a/extra/yassl/taocrypt/taocrypt.dsw
+++ b/extra/yassl/taocrypt/taocrypt.dsw
@@ -3,6 +3,21 @@ Microsoft Developer Studio Workspace File, Format Version 6.00
###############################################################################
+Project: "benchmark"=.\benchmark\benchmark.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name taocrypt
+ End Project Dependency
+}}}
+
+###############################################################################
+
Project: "taocrypt"=.\taocrypt.dsp - Package Owner=<4>
Package=<5>
@@ -15,7 +30,7 @@ Package=<4>
###############################################################################
-Project: "test"=.\test.dsp - Package Owner=<4>
+Project: "test"=.\test\test.dsp - Package Owner=<4>
Package=<5>
{{{
diff --git a/extra/yassl/taocrypt/test/memory.cpp b/extra/yassl/taocrypt/test/memory.cpp
index ec398a64c45..a9b21f94902 100644
--- a/extra/yassl/taocrypt/test/memory.cpp
+++ b/extra/yassl/taocrypt/test/memory.cpp
@@ -31,7 +31,7 @@
To use MemoryTracker merely add this file to your project
No need to instantiate anything
-If your app is multi threaded define YASSL_THREAD_SAFE
+If your app is multi threaded define MULTI_THREADED
*********************************************************************/
diff --git a/extra/yassl/taocrypt/test.dsp b/extra/yassl/taocrypt/test/test.dsp
index 1084f8e06e3..93b369de3d9 100644
--- a/extra/yassl/taocrypt/test.dsp
+++ b/extra/yassl/taocrypt/test/test.dsp
@@ -37,12 +37,12 @@ RSC=rc.exe
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "test\Release"
-# PROP Intermediate_Dir "test\Release"
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /O2 /I "include" /I "mySTL" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /I "../include" /I "../mySTL" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -61,12 +61,12 @@ LINK32=link.exe
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "test\Debug"
-# PROP Intermediate_Dir "test\Debug"
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "include" /I "mySTL" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../include" /I "../mySTL" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
@@ -87,7 +87,7 @@ LINK32=link.exe
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
-SOURCE=.\test\test.cpp
+SOURCE=.\test.cpp
# End Source File
# End Group
# Begin Group "Header Files"
diff --git a/extra/yassl/yassl.dsw b/extra/yassl/yassl.dsw
index 288c88dfd5b..8da089fc1fa 100644
--- a/extra/yassl/yassl.dsw
+++ b/extra/yassl/yassl.dsw
@@ -90,7 +90,7 @@ Package=<4>
###############################################################################
-Project: "test"=.\taocrypt\test.dsp - Package Owner=<4>
+Project: "test"=.\taocrypt\test\test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -114,9 +114,6 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
- Project_Dep_Name taocrypt
- End Project Dependency
- Begin Project Dependency
Project_Dep_Name yassl
End Project Dependency
}}}
diff --git a/include/my_base.h b/include/my_base.h
index bf05d49db7d..b711c8bef13 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -283,6 +283,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 d71d049f69d..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 */
@@ -848,6 +847,7 @@ int STDCALL mysql_close_start(MYSQL *sock);
int STDCALL mysql_close_cont(MYSQL *sock, int status);
my_socket STDCALL mysql_get_socket(const MYSQL *mysql);
unsigned int STDCALL mysql_get_timeout_value(const MYSQL *mysql);
+unsigned int STDCALL mysql_get_timeout_value_ms(const MYSQL *mysql);
/* status return codes */
#define MYSQL_NO_DATA 100
diff --git a/include/mysql.h.pp b/include/mysql.h.pp
index ce577146581..48ce79046ff 100644
--- a/include/mysql.h.pp
+++ b/include/mysql.h.pp
@@ -729,3 +729,4 @@ int mysql_close_start(MYSQL *sock);
int mysql_close_cont(MYSQL *sock, int status);
my_socket mysql_get_socket(const MYSQL *mysql);
unsigned int mysql_get_timeout_value(const MYSQL *mysql);
+unsigned int mysql_get_timeout_value_ms(const MYSQL *mysql);
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 7fdd2c8d646..46a55e42e50 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/thread_pool_priv.h b/include/thread_pool_priv.h
index 4060cf51733..78526894e21 100644
--- a/include/thread_pool_priv.h
+++ b/include/thread_pool_priv.h
@@ -36,6 +36,7 @@
#include <debug_sync.h>
#include <sql_profile.h>
#include <table.h>
+#include <sql_list.h>
/* Needed to get access to scheduler variables */
void* thd_get_scheduler_data(THD *thd);
@@ -56,9 +57,14 @@ void thd_unlock_data(THD *thd);
bool thd_is_transaction_active(THD *thd);
int thd_connection_has_data(THD *thd);
void thd_set_net_read_write(THD *thd, uint val);
+uint thd_get_net_read_write(THD *thd);
void thd_set_mysys_var(THD *thd, st_my_thread_var *mysys_var);
+ulong thd_get_net_wait_timeout(THD *thd);
my_socket thd_get_fd(THD *thd);
+THD *first_global_thread();
+THD *next_global_thread(THD *thd);
+
/* Print to the MySQL error log */
void sql_print_error(const char *format, ...);
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 739aeb4ede8..01139677b7d 100644
--- a/include/welcome_copyright_notice.h
+++ b/include/welcome_copyright_notice.h
@@ -1,4 +1,5 @@
-/* Copyright (c) 2010, 2011, 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
@@ -16,11 +17,14 @@
#ifndef _welcome_copyright_notice_h_
#define _welcome_copyright_notice_h_
+#define COPYRIGHT_NOTICE_CURRENT_YEAR "2012"
+
/*
This define specifies copyright notice which is displayed by every MySQL
program on start, or on help screen.
*/
-#define ORACLE_WELCOME_COPYRIGHT_NOTICE(years) \
- "Copyright (c) " years ", Oracle, Monty Program Ab and others.\n"
+#define ORACLE_WELCOME_COPYRIGHT_NOTICE(first_year) \
+ "Copyright (c) " first_year ", " COPYRIGHT_NOTICE_CURRENT_YEAR \
+ ", Oracle, Monty Program Ab and others.\n"
#endif /* _welcome_copyright_notice_h_ */
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index b454fc0d2e0..955cc3c0dd1 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -1004,7 +1004,7 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
thd_cs->mbmaxlen);
}
client_field->type= server_field.type;
- client_field->flags= server_field.flags;
+ client_field->flags= (uint16) server_field.flags;
client_field->decimals= server_field.decimals;
client_field->db_length= strlen(client_field->db);
client_field->table_length= strlen(client_field->table);
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 c30cb7d1ff4..d957e33d41c 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/derived_view.result b/mysql-test/r/derived_view.result
index 5446406924f..ba01db4a66f 100644
--- a/mysql-test/r/derived_view.result
+++ b/mysql-test/r/derived_view.result
@@ -1687,6 +1687,7 @@ SELECT t.b, t.c, t1.a
FROM t1, (SELECT t2.b, t2.c FROM t3 RIGHT JOIN t2 ON t2.a = t3.b) AS t
WHERE t.b AND t.c = t1.a;
b c a
+8 c c
EXPLAIN EXTENDED
SELECT t.b, t.c, t1.a
FROM t1, (SELECT t2.b, t2.c FROM t3 RIGHT JOIN t2 ON t2.a = t3.b) AS t
@@ -1701,6 +1702,7 @@ SELECT t.b, t.c, t1.a
FROM t1, (SELECT t2.b, t2.c FROM t3 RIGHT JOIN t2 ON t2.a = t3.b) AS t
WHERE t.b <> 0 AND t.c = t1.a;
b c a
+8 c c
INSERT INTO t3 VALUES (100), (200);
EXPLAIN EXTENDED
SELECT t.b, t.c, t1.a
@@ -1716,7 +1718,7 @@ SELECT t.b, t.c, t1.a
FROM t1, (SELECT t2.b, t2.c FROM t3 RIGHT JOIN t2 ON t2.a = t3.b) AS t
WHERE t.b AND t.c = t1.a;
b c a
-NULL NULL c
+8 c c
EXPLAIN EXTENDED
SELECT t.b, t.c, t1.a
FROM t1, (SELECT t2.b, t2.c FROM t3 RIGHT JOIN t2 ON t2.a = t3.b) AS t
@@ -1731,7 +1733,7 @@ SELECT t.b, t.c, t1.a
FROM t1, (SELECT t2.b, t2.c FROM t3 RIGHT JOIN t2 ON t2.a = t3.b) AS t
WHERE t.b <> 0 AND t.c = t1.a;
b c a
-NULL NULL c
+8 c c
SET optimizer_switch=@save_optimizer_switch;
DROP TABLE t1,t2,t3;
#
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 205197bc7f6..80729545902 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -2867,3 +2867,16 @@ SET @@global.max_allowed_packet:= @tmp_max;
#
# End of 5.5 tests
#
+SELECT @tmp_max:= @@global.max_allowed_packet;
+@tmp_max:= @@global.max_allowed_packet
+1048576
+SET @@global.max_allowed_packet=1024*1024*1024;
+SELECT @@global.max_allowed_packet;
+@@global.max_allowed_packet
+1073741824
+SELECT CHAR_LENGTH(EXPORT_SET(1,1,1,REPEAT(1,100000000)));
+CHAR_LENGTH(EXPORT_SET(1,1,1,REPEAT(1,100000000)))
+NULL
+Warnings:
+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
+SET @@global.max_allowed_packet:= @tmp_max;
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 2c4f44888bb..ea4af4590e0 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/information_schema_all_engines.result b/mysql-test/r/information_schema_all_engines.result
index 7d47f0404bb..4dac9a3e53c 100644
--- a/mysql-test/r/information_schema_all_engines.result
+++ b/mysql-test/r/information_schema_all_engines.result
@@ -16,6 +16,7 @@ INDEX_STATISTICS
INNODB_BUFFER_POOL_PAGES
INNODB_BUFFER_POOL_PAGES_BLOB
INNODB_BUFFER_POOL_PAGES_INDEX
+INNODB_CHANGED_PAGES
INNODB_CMP
INNODB_CMPMEM
INNODB_CMPMEM_RESET
@@ -88,6 +89,7 @@ INDEX_STATISTICS TABLE_SCHEMA
INNODB_BUFFER_POOL_PAGES page_type
INNODB_BUFFER_POOL_PAGES_BLOB space_id
INNODB_BUFFER_POOL_PAGES_INDEX index_id
+INNODB_CHANGED_PAGES space_id
INNODB_CMP page_size
INNODB_CMPMEM page_size
INNODB_CMPMEM_RESET page_size
@@ -160,6 +162,7 @@ INDEX_STATISTICS TABLE_SCHEMA
INNODB_BUFFER_POOL_PAGES page_type
INNODB_BUFFER_POOL_PAGES_BLOB space_id
INNODB_BUFFER_POOL_PAGES_INDEX index_id
+INNODB_CHANGED_PAGES space_id
INNODB_CMP page_size
INNODB_CMPMEM page_size
INNODB_CMPMEM_RESET page_size
@@ -238,6 +241,7 @@ INDEX_STATISTICS information_schema.INDEX_STATISTICS 1
INNODB_BUFFER_POOL_PAGES information_schema.INNODB_BUFFER_POOL_PAGES 1
INNODB_BUFFER_POOL_PAGES_BLOB information_schema.INNODB_BUFFER_POOL_PAGES_BLOB 1
INNODB_BUFFER_POOL_PAGES_INDEX information_schema.INNODB_BUFFER_POOL_PAGES_INDEX 1
+INNODB_CHANGED_PAGES information_schema.INNODB_CHANGED_PAGES 1
INNODB_CMP information_schema.INNODB_CMP 1
INNODB_CMPMEM information_schema.INNODB_CMPMEM 1
INNODB_CMPMEM_RESET information_schema.INNODB_CMPMEM_RESET 1
@@ -299,6 +303,7 @@ Database: information_schema
| INNODB_BUFFER_POOL_PAGES |
| INNODB_BUFFER_POOL_PAGES_BLOB |
| INNODB_BUFFER_POOL_PAGES_INDEX |
+| INNODB_CHANGED_PAGES |
| INNODB_CMP |
| INNODB_CMPMEM |
| INNODB_CMPMEM_RESET |
@@ -361,6 +366,7 @@ Database: INFORMATION_SCHEMA
| INNODB_BUFFER_POOL_PAGES |
| INNODB_BUFFER_POOL_PAGES_BLOB |
| INNODB_BUFFER_POOL_PAGES_INDEX |
+| INNODB_CHANGED_PAGES |
| INNODB_CMP |
| INNODB_CMPMEM |
| INNODB_CMPMEM_RESET |
@@ -411,5 +417,5 @@ Wildcard: inf_rmation_schema
| information_schema |
SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') AND table_name<>'ndb_binlog_index' AND table_name<>'ndb_apply_status' GROUP BY TABLE_SCHEMA;
table_schema count(*)
-information_schema 57
+information_schema 58
mysql 23
diff --git a/mysql-test/r/innodb_ext_key.result b/mysql-test/r/innodb_ext_key.result
index d2fb29a023c..4e441245a39 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;
#
@@ -724,5 +744,33 @@ SELECT * FROM t1, t2 WHERE b=a;
a b
set optimizer_switch=@save_optimizer_switch;
DROP TABLE t1,t2;
+#
+# Bug mdev-3888: INSERT with UPDATE on duplicate keys
+# with extended_keys=on
+#
+CREATE TABLE t1 (
+c1 bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+c2 bigint(20) unsigned NOT NULL,
+c3 bigint(20) unsigned NOT NULL,
+c4 varchar(128) DEFAULT NULL,
+PRIMARY KEY (c1),
+UNIQUE KEY uq (c2,c3),
+KEY c3 (c3),
+KEY c4 (c4)
+) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
+set @save_optimizer_switch=@@optimizer_switch;
+set session optimizer_switch='extended_keys=off';
+INSERT INTO t1 (c2, c3, c4) VALUES (58291525, 2580, 'foobar')
+ON DUPLICATE KEY UPDATE c4 = VALUES(c4);
+INSERT INTO t1 (c2, c3, c4) VALUES (58291525, 2580, 'foobar')
+ON DUPLICATE KEY UPDATE c4 = VALUES(c4);
+DELETE FROM t1;
+set session optimizer_switch='extended_keys=on';
+INSERT INTO t1 (c2, c3, c4) VALUES (58291525, 2580, 'foobar')
+ON DUPLICATE KEY UPDATE c4 = VALUES(c4);
+INSERT INTO t1 (c2, c3, c4) VALUES (58291525, 2580, 'foobar')
+ON DUPLICATE KEY UPDATE c4 = VALUES(c4);
+set optimizer_switch=@save_optimizer_switch;
+DROP TABLE t1;
set optimizer_switch=@save_ext_key_optimizer_switch;
SET SESSION STORAGE_ENGINE=DEFAULT;
diff --git a/mysql-test/r/join_cache.result b/mysql-test/r/join_cache.result
index 6471a2f8bbd..bb455f2b39a 100644
--- a/mysql-test/r/join_cache.result
+++ b/mysql-test/r/join_cache.result
@@ -5589,4 +5589,52 @@ set join_buffer_size=default;
set join_cache_level=default;
set optimizer_switch=@tmp_optimizer_switch;
DROP TABLE t1,t2,t3;
+#
+# Bug #1058071: LEFT JOIN using blobs
+# (mdev-564) when join buffer size is small
+#
+CREATE TABLE t1 (
+col269 decimal(31,10) unsigned DEFAULT NULL,
+col280 multipoint DEFAULT NULL,
+col281 tinyint(1) DEFAULT NULL,
+col282 time NOT NULL,
+col284 datetime DEFAULT NULL,
+col286 date DEFAULT NULL,
+col287 datetime DEFAULT NULL,
+col288 decimal(30,29) DEFAULT NULL,
+col291 time DEFAULT NULL,
+col292 time DEFAULT NULL
+) ENGINE=Aria;
+INSERT INTO t1 VALUES
+(0.0,PointFromText('POINT(9 0)'),0,'11:24:05','2013-04-14 21:30:28',NULL,'2011-12-20 06:00:34',9.9,'13:04:39',NULL),
+(0.0,NULL,127,'05:43:12','2012-09-05 06:15:27','2027-01-01','2011-10-29 10:48:29',0.0,'06:24:05','11:33:37'),
+(0.0,NULL,127,'12:54:41','2013-01-12 11:32:58','2011-11-03','2013-01-03 02:00:34',00,'11:54:15','20:19:15'),
+(0.0,PointFromText('POINT(9 0)'),0,'19:48:07','2012-07-16 15:45:25','2012-03-25','2013-09-07 17:21:52',0.5,'17:36:54','21:24:19'),
+(0.0,PointFromText('POINT(9 0)'),0,'03:43:48','2012-09-28 00:00:00','2012-06-26','2011-11-16 05:01:09',00,'01:25:42','19:30:06'),
+(0.0,LineStringFromText('LINESTRING(0 0,9 9,0 0,9 0,0 0)'),127,'11:33:21','2012-03-31 10:29:22','2012-10-10','2012-04-21 19:21:06',NULL,'05:13:22','09:48:34'),
+(NULL,PointFromText('POINT(9 0)'),127,'00:00:00','0000-00-00','2012-04-04 21:26:12','2013-03-04',0.0,'12:54:30',NULL),
+(NULL,PointFromText('POINT(9 0)'),1,'00:00:00','2013-05-01 22:37:49','2013-06-26','2012-09-22 17:31:03',0.0,'08:09:57','11:15:36');
+Warnings:
+Note 1265 Data truncated for column 'col286' at row 7
+CREATE TABLE t2 (b int) ENGINE=Aria;
+INSERT INTO t2 VALUES (NULL);
+CREATE TABLE t3 (c int) ENGINE=Aria;
+INSERT INTO t3 VALUES (NULL);
+set @tmp_optimizer_switch=@@optimizer_switch;
+set optimizer_switch = 'outer_join_with_cache=on,join_cache_incremental=on';
+set join_buffer_size=128;
+EXPLAIN
+SELECT 1 AS c FROM t1 NATURAL LEFT JOIN t2 LEFT OUTER JOIN t3 ON 1
+GROUP BY elt(t1.col282,1,t1.col280);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using temporary; Using filesort
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (flat, BNL join)
+1 SIMPLE t3 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+SELECT 1 AS c FROM t1 NATURAL LEFT JOIN t2 LEFT OUTER JOIN t3 ON 1
+GROUP BY elt(t1.col282,1,t1.col280);
+c
+1
+set join_buffer_size=default;
+set optimizer_switch=@tmp_optimizer_switch;
+DROP table t1,t2,t3;
set @@optimizer_switch=@save_optimizer_switch;
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/log_state.result b/mysql-test/r/log_state.result
index 52f98494942..3ccd1451bc4 100644
--- a/mysql-test/r/log_state.result
+++ b/mysql-test/r/log_state.result
@@ -199,7 +199,7 @@ SELECT @@general_log, @@log;
1 1
SET GLOBAL log = 0;
Warnings:
-Warning 1287 The syntax '@@log' is deprecated and will be removed in MariaDB 10.1. Please use '@@general_log' instead
+Warning 1287 '@@log' is deprecated and will be removed in a future release. Please use '@@general_log' instead
SHOW VARIABLES LIKE 'general_log';
Variable_name Value
general_log OFF
@@ -230,7 +230,7 @@ SELECT @@slow_query_log, @@log_slow_queries;
0 0
SET GLOBAL log_slow_queries = 0;
Warnings:
-Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MariaDB 10.1. Please use '@@slow_query_log' instead
+Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead
SHOW VARIABLES LIKE 'slow_query_log';
Variable_name Value
slow_query_log OFF
@@ -283,16 +283,16 @@ SET GLOBAL slow_query_log_file = @old_slow_query_log_file;
deprecated:
SET GLOBAL log = 0;
Warnings:
-Warning 1287 The syntax '@@log' is deprecated and will be removed in MariaDB 10.1. Please use '@@general_log' instead
+Warning 1287 '@@log' is deprecated and will be removed in a future release. Please use '@@general_log' instead
SET GLOBAL log_slow_queries = 0;
Warnings:
-Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MariaDB 10.1. Please use '@@slow_query_log' instead
+Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead
SET GLOBAL log = DEFAULT;
Warnings:
-Warning 1287 The syntax '@@log' is deprecated and will be removed in MariaDB 10.1. Please use '@@general_log' instead
+Warning 1287 '@@log' is deprecated and will be removed in a future release. Please use '@@general_log' instead
SET GLOBAL log_slow_queries = DEFAULT;
Warnings:
-Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MariaDB 10.1. Please use '@@slow_query_log' instead
+Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead
not deprecated:
SELECT @@global.general_log_file INTO @my_glf;
SELECT @@global.slow_query_log_file INTO @my_sqlf;
diff --git a/mysql-test/r/mysqld--help,win.rdiff b/mysql-test/r/mysqld--help,win.rdiff
index 957292b265f..cd39445f3e6 100644
--- a/mysql-test/r/mysqld--help,win.rdiff
+++ b/mysql-test/r/mysqld--help,win.rdiff
@@ -1,6 +1,6 @@
---- r/mysqld--help.result 2012-01-13 16:50:49.000000000 +0100
-+++ r/mysqld--help-win.result 2012-01-19 14:12:00.000000000 +0100
-@@ -240,7 +240,6 @@
+--- mysql-test/r/mysqld--help.result 2012-09-08 22:22:06 +0000
++++ mysql-test/r/mysqld--help.result 2012-10-01 14:03:59 +0000
+@@ -244,7 +244,6 @@
The number of segments in a key cache
-L, --language=name Client error messages in given language. May be given as
a full path. Deprecated. Use --lc-messages-dir instead.
@@ -8,7 +8,7 @@
--lc-messages=name Set the language used for the error messages.
-L, --lc-messages-dir=name
Directory where error messages are
-@@ -436,6 +435,7 @@
+@@ -440,6 +439,7 @@
NULLS_UNEQUAL (default behavior for 4.1 and later),
NULLS_EQUAL (emulate 4.0 behavior), and NULLS_IGNORED
--myisam-use-mmap Use memory mapping for reading and writing MyISAM tables
@@ -16,7 +16,7 @@
--net-buffer-length=#
Buffer length for TCP/IP and socket communication
--net-read-timeout=#
-@@ -695,6 +695,9 @@
+@@ -707,6 +707,9 @@
files within specified directory
--server-id=# Uniquely identifies the server instance in the community
of replication partners
@@ -26,7 +26,7 @@
--show-slave-auth-info
Show user and password in SHOW SLAVE HOSTS on this
master.
-@@ -759,6 +762,10 @@
+@@ -774,6 +777,10 @@
Log slow queries to given log file. Defaults logging to
'hostname'-slow.log. Must be enabled to activate other
slow log options
@@ -37,7 +37,7 @@
--socket=name Socket file to use for connection
--sort-buffer-size=#
Each thread that needs to do a sort allocates a buffer of
-@@ -767,6 +774,7 @@
+@@ -782,6 +789,7 @@
for the complete list of valid sql modes
--stack-trace Print a symbolic stack trace on failure
(Defaults to on; use --skip-stack-trace to disable.)
@@ -45,7 +45,7 @@
--stored-program-cache=#
The soft upper limit for number of cached stored routines
for one connection.
-@@ -807,8 +815,8 @@
+@@ -822,8 +830,8 @@
size, MySQL will automatically convert it to an on-disk
MyISAM or Aria table
-t, --tmpdir=name Path for temporary files. Several paths may be specified,
@@ -56,15 +56,15 @@
--transaction-alloc-block-size=#
Allocation block size for transactions to be stored in
binary log
-@@ -908,7 +916,6 @@
+@@ -923,7 +931,6 @@ key-cache-age-threshold 300
+ key-cache-block-size 1024
key-cache-division-limit 100
key-cache-segments 0
- language MYSQL_SHAREDIR/
-large-pages FALSE
lc-messages en_US
lc-messages-dir MYSQL_SHAREDIR/
lc-time-names en_US
-@@ -971,6 +978,7 @@
+@@ -986,6 +993,7 @@ myisam-repair-threads 1
myisam-sort-buffer-size 8388608
myisam-stats-method nulls_unequal
myisam-use-mmap FALSE
@@ -72,7 +72,7 @@
net-buffer-length 16384
net-read-timeout 30
net-retry-count 10
-@@ -1035,6 +1043,8 @@
+@@ -1051,6 +1059,8 @@ safe-user-create FALSE
secure-auth FALSE
secure-file-priv (No default value)
server-id 0
@@ -81,7 +81,7 @@
show-slave-auth-info FALSE
skip-grant-tables TRUE
skip-name-resolve FALSE
-@@ -1050,6 +1060,7 @@
+@@ -1067,6 +1077,7 @@ slave-transaction-retries 10
slave-type-conversions
slow-launch-time 2
slow-query-log FALSE
@@ -89,3 +89,4 @@
sort-buffer-size 2097152
sql-mode
stack-trace TRUE
+
diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result
index 628d38a8523..da4aecc180e 100644
--- a/mysql-test/r/mysqld--help.result
+++ b/mysql-test/r/mysqld--help.result
@@ -204,6 +204,10 @@ The following options may be given as the first argument:
-?, --help Display this help and exit.
--ignore-builtin-innodb
Disable initialization of builtin InnoDB plugin
+ --ignore-db-dirs=name
+ Specifies a directory to add to the ignore list when
+ collecting database names from the datadir. Put a blank
+ argument to reset the list accumulated so far.
--init-connect=name Command(s) that are executed for each new connection
(unless the user has SUPER privilege)
--init-file=name Read SQL commands from this file at startup
@@ -908,6 +912,7 @@ general-log FALSE
group-concat-max-len 1024
help TRUE
ignore-builtin-innodb FALSE
+ignore-db-dirs
init-connect
init-file (No default value)
init-rpl-role MASTER
diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result
index 439930b8fe4..76b8e887d89 100644
--- a/mysql-test/r/openssl_1.result
+++ b/mysql-test/r/openssl_1.result
@@ -44,9 +44,9 @@ ERROR 42000: DELETE command denied to user 'ssl_user4'@'localhost' for table 't1
drop user ssl_user1@localhost, ssl_user2@localhost,
ssl_user3@localhost, ssl_user4@localhost, ssl_user5@localhost;
drop table t1;
-mysqltest: Could not open connection 'default': 2026 SSL connection error: ASN: bad other signature confirmation
-mysqltest: Could not open connection 'default': 2026 SSL connection error: ASN: bad other signature confirmation
-mysqltest: Could not open connection 'default': 2026 SSL connection error: ASN: bad other signature confirmation
+mysqltest: Could not open connection 'default': 2026 SSL connection error: xxxx
+mysqltest: Could not open connection 'default': 2026 SSL connection error: xxxx
+mysqltest: Could not open connection 'default': 2026 SSL connection error: xxxx
SSL error: Unable to get private key from ''
mysqltest: Could not open connection 'default': 2026 SSL connection error: Unable to get private key
SSL error: Unable to get certificate from ''
@@ -83,7 +83,7 @@ Ssl_cipher AES128-SHA
SHOW STATUS LIKE 'Ssl_cipher';
Variable_name Value
Ssl_cipher AES128-SHA
-mysqltest: Could not open connection 'default': 2026 SSL connection error: SSL_CTX_new failed
+mysqltest: Could not open connection 'default': 2026 SSL connection error: Failed to set ciphers to use
CREATE TABLE t1(a int);
INSERT INTO t1 VALUES (1), (2);
diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index 1ded1e90314..054dc9e4fc4 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -2830,3 +2830,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/order_fill_sortbuf.result b/mysql-test/r/order_fill_sortbuf.result
index 2226e842901..6a0bd9d966b 100644
--- a/mysql-test/r/order_fill_sortbuf.result
+++ b/mysql-test/r/order_fill_sortbuf.result
@@ -1,4 +1,5 @@
drop table if exists t1,t2;
+set @@sort_buffer_size=32804;
CREATE TABLE `t1` (
`id` int(11) NOT NULL default '0',
`id2` int(11) NOT NULL default '0',
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/ps_1general.result b/mysql-test/r/ps_1general.result
index 045a62a1d5a..3ca0cf8554f 100644
--- a/mysql-test/r/ps_1general.result
+++ b/mysql-test/r/ps_1general.result
@@ -777,3 +777,14 @@ execute stmt1 ;
prepare stmt1 from ' select * from t5 ' ;
execute stmt1 ;
drop table t1, t5, t9;
+#
+# testcase for bug#11765413 - Crash with dependent subquery and
+# prepared statement
+create table t1 (c1 int);
+insert into t1 values (1);
+prepare stmt1 from "select 1 from t1 where 1=(select 1 from t1 having c1)";
+execute stmt1;
+1
+1
+drop prepare stmt1;
+drop table t1;
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/select.result b/mysql-test/r/select.result
index 30d5ca00bc0..378b20829f3 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -4887,7 +4887,7 @@ CREATE TABLE t5 (f1 int) ;
INSERT INTO t5 VALUES (20),(5);
CREATE TABLE t6(f1 int);
INSERT INTO t6 VALUES (9),(7);
-SET SESSION join_buffer_size = 2048;
+SET SESSION join_buffer_size = 2176;
EXPLAIN
SELECT STRAIGHT_JOIN * FROM t2, (t1 LEFT JOIN (t3,t4) ON t1.f1 = t4.f1), t5, t6;
id select_type table type possible_keys key key_len ref rows Extra
@@ -4901,50 +4901,50 @@ SELECT STRAIGHT_JOIN * FROM t2, (t1 LEFT JOIN (t3,t4) ON t1.f1 = t4.f1), t5, t6;
f1 f1 f1 f1 f2 f1 f1
3 9 NULL NULL NULL 20 9
7 9 NULL NULL NULL 20 9
-3 9 NULL NULL NULL 20 7
-7 9 NULL NULL NULL 20 7
-3 9 NULL NULL NULL 5 9
-7 9 NULL NULL NULL 5 9
-3 9 NULL NULL NULL 5 7
-7 9 NULL NULL NULL 5 7
18 9 NULL NULL NULL 20 9
3 9 NULL NULL NULL 20 9
-18 9 NULL NULL NULL 20 7
-3 9 NULL NULL NULL 20 7
-18 9 NULL NULL NULL 5 9
-3 9 NULL NULL NULL 5 9
-18 9 NULL NULL NULL 5 7
-3 9 NULL NULL NULL 5 7
7 9 NULL NULL NULL 20 9
-18 9 NULL NULL NULL 20 9
+3 9 NULL NULL NULL 20 7
7 9 NULL NULL NULL 20 7
18 9 NULL NULL NULL 20 7
-7 9 NULL NULL NULL 5 9
-18 9 NULL NULL NULL 5 9
-7 9 NULL NULL NULL 5 7
-18 9 NULL NULL NULL 5 7
-3 9 NULL NULL NULL 20 9
-7 9 NULL NULL NULL 20 9
3 9 NULL NULL NULL 20 7
7 9 NULL NULL NULL 20 7
-3 9 NULL NULL NULL 5 9
-7 9 NULL NULL NULL 5 9
-3 9 NULL NULL NULL 5 7
-7 9 NULL NULL NULL 5 7
18 9 NULL NULL NULL 20 9
3 9 NULL NULL NULL 20 9
+3 9 NULL NULL NULL 5 9
+7 9 NULL NULL NULL 5 9
+18 9 NULL NULL NULL 5 9
18 9 NULL NULL NULL 20 7
3 9 NULL NULL NULL 20 7
+3 9 NULL NULL NULL 5 7
+7 9 NULL NULL NULL 5 7
+18 9 NULL NULL NULL 5 7
+3 9 NULL NULL NULL 5 9
+7 9 NULL NULL NULL 5 9
18 9 NULL NULL NULL 5 9
3 9 NULL NULL NULL 5 9
+7 9 NULL NULL NULL 20 9
+3 9 NULL NULL NULL 5 7
+7 9 NULL NULL NULL 5 7
18 9 NULL NULL NULL 5 7
3 9 NULL NULL NULL 5 7
+7 9 NULL NULL NULL 20 7
+18 9 NULL NULL NULL 20 9
+3 9 NULL NULL NULL 20 9
7 9 NULL NULL NULL 20 9
18 9 NULL NULL NULL 20 9
+7 9 NULL NULL NULL 5 9
+18 9 NULL NULL NULL 20 7
+3 9 NULL NULL NULL 20 7
7 9 NULL NULL NULL 20 7
18 9 NULL NULL NULL 20 7
+7 9 NULL NULL NULL 5 7
+18 9 NULL NULL NULL 5 9
+3 9 NULL NULL NULL 5 9
7 9 NULL NULL NULL 5 9
18 9 NULL NULL NULL 5 9
+18 9 NULL NULL NULL 5 7
+3 9 NULL NULL NULL 5 7
7 9 NULL NULL NULL 5 7
18 9 NULL NULL NULL 5 7
SET SESSION join_buffer_size = DEFAULT;
diff --git a/mysql-test/r/select_jcl6.result b/mysql-test/r/select_jcl6.result
index a9c74afdd9c..b5c6f89b87b 100644
--- a/mysql-test/r/select_jcl6.result
+++ b/mysql-test/r/select_jcl6.result
@@ -4898,7 +4898,7 @@ CREATE TABLE t5 (f1 int) ;
INSERT INTO t5 VALUES (20),(5);
CREATE TABLE t6(f1 int);
INSERT INTO t6 VALUES (9),(7);
-SET SESSION join_buffer_size = 2048;
+SET SESSION join_buffer_size = 2176;
EXPLAIN
SELECT STRAIGHT_JOIN * FROM t2, (t1 LEFT JOIN (t3,t4) ON t1.f1 = t4.f1), t5, t6;
id select_type table type possible_keys key key_len ref rows Extra
@@ -4913,48 +4913,48 @@ f1 f1 f1 f1 f2 f1 f1
3 9 NULL NULL NULL 20 9
7 9 NULL NULL NULL 20 9
18 9 NULL NULL NULL 20 9
-3 9 NULL NULL NULL 5 9
-7 9 NULL NULL NULL 5 9
-18 9 NULL NULL NULL 5 9
-3 9 NULL NULL NULL 20 7
-7 9 NULL NULL NULL 20 7
-18 9 NULL NULL NULL 20 7
-3 9 NULL NULL NULL 5 7
-7 9 NULL NULL NULL 5 7
-18 9 NULL NULL NULL 5 7
3 9 NULL NULL NULL 20 9
7 9 NULL NULL NULL 20 9
18 9 NULL NULL NULL 20 9
-3 9 NULL NULL NULL 5 9
-7 9 NULL NULL NULL 5 9
-18 9 NULL NULL NULL 5 9
-3 9 NULL NULL NULL 20 7
-7 9 NULL NULL NULL 20 7
-18 9 NULL NULL NULL 20 7
-3 9 NULL NULL NULL 5 7
-7 9 NULL NULL NULL 5 7
-18 9 NULL NULL NULL 5 7
3 9 NULL NULL NULL 20 9
7 9 NULL NULL NULL 20 9
18 9 NULL NULL NULL 20 9
-3 9 NULL NULL NULL 5 9
-7 9 NULL NULL NULL 5 9
-18 9 NULL NULL NULL 5 9
-3 9 NULL NULL NULL 20 7
-7 9 NULL NULL NULL 20 7
-18 9 NULL NULL NULL 20 7
-3 9 NULL NULL NULL 5 7
-7 9 NULL NULL NULL 5 7
-18 9 NULL NULL NULL 5 7
3 9 NULL NULL NULL 20 9
7 9 NULL NULL NULL 20 9
18 9 NULL NULL NULL 20 9
3 9 NULL NULL NULL 5 9
7 9 NULL NULL NULL 5 9
18 9 NULL NULL NULL 5 9
+3 9 NULL NULL NULL 5 9
+7 9 NULL NULL NULL 5 9
+18 9 NULL NULL NULL 5 9
+3 9 NULL NULL NULL 5 9
+7 9 NULL NULL NULL 5 9
+18 9 NULL NULL NULL 5 9
+3 9 NULL NULL NULL 5 9
+7 9 NULL NULL NULL 5 9
+18 9 NULL NULL NULL 5 9
3 9 NULL NULL NULL 20 7
7 9 NULL NULL NULL 20 7
18 9 NULL NULL NULL 20 7
+3 9 NULL NULL NULL 20 7
+7 9 NULL NULL NULL 20 7
+18 9 NULL NULL NULL 20 7
+3 9 NULL NULL NULL 20 7
+7 9 NULL NULL NULL 20 7
+18 9 NULL NULL NULL 20 7
+3 9 NULL NULL NULL 20 7
+7 9 NULL NULL NULL 20 7
+18 9 NULL NULL NULL 20 7
+3 9 NULL NULL NULL 5 7
+7 9 NULL NULL NULL 5 7
+18 9 NULL NULL NULL 5 7
+3 9 NULL NULL NULL 5 7
+7 9 NULL NULL NULL 5 7
+18 9 NULL NULL NULL 5 7
+3 9 NULL NULL NULL 5 7
+7 9 NULL NULL NULL 5 7
+18 9 NULL NULL NULL 5 7
3 9 NULL NULL NULL 5 7
7 9 NULL NULL NULL 5 7
18 9 NULL NULL NULL 5 7
diff --git a/mysql-test/r/select_pkeycache.result b/mysql-test/r/select_pkeycache.result
index 30d5ca00bc0..378b20829f3 100644
--- a/mysql-test/r/select_pkeycache.result
+++ b/mysql-test/r/select_pkeycache.result
@@ -4887,7 +4887,7 @@ CREATE TABLE t5 (f1 int) ;
INSERT INTO t5 VALUES (20),(5);
CREATE TABLE t6(f1 int);
INSERT INTO t6 VALUES (9),(7);
-SET SESSION join_buffer_size = 2048;
+SET SESSION join_buffer_size = 2176;
EXPLAIN
SELECT STRAIGHT_JOIN * FROM t2, (t1 LEFT JOIN (t3,t4) ON t1.f1 = t4.f1), t5, t6;
id select_type table type possible_keys key key_len ref rows Extra
@@ -4901,50 +4901,50 @@ SELECT STRAIGHT_JOIN * FROM t2, (t1 LEFT JOIN (t3,t4) ON t1.f1 = t4.f1), t5, t6;
f1 f1 f1 f1 f2 f1 f1
3 9 NULL NULL NULL 20 9
7 9 NULL NULL NULL 20 9
-3 9 NULL NULL NULL 20 7
-7 9 NULL NULL NULL 20 7
-3 9 NULL NULL NULL 5 9
-7 9 NULL NULL NULL 5 9
-3 9 NULL NULL NULL 5 7
-7 9 NULL NULL NULL 5 7
18 9 NULL NULL NULL 20 9
3 9 NULL NULL NULL 20 9
-18 9 NULL NULL NULL 20 7
-3 9 NULL NULL NULL 20 7
-18 9 NULL NULL NULL 5 9
-3 9 NULL NULL NULL 5 9
-18 9 NULL NULL NULL 5 7
-3 9 NULL NULL NULL 5 7
7 9 NULL NULL NULL 20 9
-18 9 NULL NULL NULL 20 9
+3 9 NULL NULL NULL 20 7
7 9 NULL NULL NULL 20 7
18 9 NULL NULL NULL 20 7
-7 9 NULL NULL NULL 5 9
-18 9 NULL NULL NULL 5 9
-7 9 NULL NULL NULL 5 7
-18 9 NULL NULL NULL 5 7
-3 9 NULL NULL NULL 20 9
-7 9 NULL NULL NULL 20 9
3 9 NULL NULL NULL 20 7
7 9 NULL NULL NULL 20 7
-3 9 NULL NULL NULL 5 9
-7 9 NULL NULL NULL 5 9
-3 9 NULL NULL NULL 5 7
-7 9 NULL NULL NULL 5 7
18 9 NULL NULL NULL 20 9
3 9 NULL NULL NULL 20 9
+3 9 NULL NULL NULL 5 9
+7 9 NULL NULL NULL 5 9
+18 9 NULL NULL NULL 5 9
18 9 NULL NULL NULL 20 7
3 9 NULL NULL NULL 20 7
+3 9 NULL NULL NULL 5 7
+7 9 NULL NULL NULL 5 7
+18 9 NULL NULL NULL 5 7
+3 9 NULL NULL NULL 5 9
+7 9 NULL NULL NULL 5 9
18 9 NULL NULL NULL 5 9
3 9 NULL NULL NULL 5 9
+7 9 NULL NULL NULL 20 9
+3 9 NULL NULL NULL 5 7
+7 9 NULL NULL NULL 5 7
18 9 NULL NULL NULL 5 7
3 9 NULL NULL NULL 5 7
+7 9 NULL NULL NULL 20 7
+18 9 NULL NULL NULL 20 9
+3 9 NULL NULL NULL 20 9
7 9 NULL NULL NULL 20 9
18 9 NULL NULL NULL 20 9
+7 9 NULL NULL NULL 5 9
+18 9 NULL NULL NULL 20 7
+3 9 NULL NULL NULL 20 7
7 9 NULL NULL NULL 20 7
18 9 NULL NULL NULL 20 7
+7 9 NULL NULL NULL 5 7
+18 9 NULL NULL NULL 5 9
+3 9 NULL NULL NULL 5 9
7 9 NULL NULL NULL 5 9
18 9 NULL NULL NULL 5 9
+18 9 NULL NULL NULL 5 7
+3 9 NULL NULL NULL 5 7
7 9 NULL NULL NULL 5 7
18 9 NULL NULL NULL 5 7
SET SESSION join_buffer_size = DEFAULT;
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index f775336299b..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
@@ -6638,6 +6748,23 @@ a ( 3, 3 ) NOT IN ( SELECT NULL, NULL )
set optimizer_switch=@mdev367_optimizer_switch;
DROP TABLE t1;
#
+# MDEV-521 single value subselect transformation problem
+#
+CREATE TABLE t1 (f1 char(2), PRIMARY KEY (f1)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES ('u1'),('u2');
+SELECT a.* FROM t1 a WHERE ( SELECT EXISTS ( SELECT 1 FROM t1 b WHERE b.f1 = a.f1 ) );
+f1
+u1
+u2
+FLUSH TABLES;
+SELECT a.* FROM t1 a WHERE ( SELECT EXISTS ( SELECT 1 FROM t1 b WHERE b.f1 = a.f1 ) );
+f1
+u1
+u2
+DROP TABLE t1;
+# return optimizer switch changed in the beginning of this test
+set optimizer_switch=@subselect_tmp;
+#
# lp:944706 Query with impossible or constant subquery in WHERE or HAVING is not
# precomputed and thus not part of optimization
#
@@ -6843,10 +6970,31 @@ 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;
#
+# MDEV-435: Expensive subqueries may be evaluated during optimization in merge_key_fields
+#
+CREATE TABLE t1 (a INT, KEY(a)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (8),(0);
+CREATE TABLE t2 (b INT, c VARCHAR(1)) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (4,'j'),(6,'v');
+CREATE TABLE t3 (d VARCHAR(1)) ENGINE=MyISAM;
+INSERT INTO t3 VALUES ('b'),('c');
+EXPLAIN
+SELECT * FROM t1
+WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 index a a 5 NULL 2 Using where; Using index
+2 SUBQUERY <subquery3> ALL distinct_key NULL NULL NULL 1
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
+3 MATERIALIZED t3 ALL NULL NULL NULL NULL 2
+SELECT * FROM t1
+WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10;
+a
+drop table t1, t2, t3;
+#
# MDEV-405: Server crashes in test_if_skip_sort_order on EXPLAIN with GROUP BY and HAVING in EXISTS subquery
#
CREATE TABLE t1 (a INT, KEY(a));
@@ -6856,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 ed00e4ef684..4fd303dfd44 100644
--- a/mysql-test/r/subselect2.result
+++ b/mysql-test/r/subselect2.result
@@ -179,4 +179,120 @@ pk a b
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));
+INSERT INTO t1 VALUES (9,0), (7,1), (1,9), (7,3), (2,1);
+CREATE TABLE t2 (a int, b int, INDEX idx(a));
+INSERT INTO t2 VALUES (2,1), (6,4), (7,6), (9,4);
+CREATE TABLE t3 (a int, b int);
+INSERT INTO t3 VALUES (1,0), (1,1), (1,3);
+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
+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/subselect4.result b/mysql-test/r/subselect4.result
index 7f290fb5b03..c35075d80a1 100644
--- a/mysql-test/r/subselect4.result
+++ b/mysql-test/r/subselect4.result
@@ -430,7 +430,7 @@ set @old_optimizer_switch = @@session.optimizer_switch,
SET SESSION OPTIMIZER_SWITCH = 'materialization=off,semijoin=off,loosescan=off,firstmatch=off,mrr=on';
SET SESSION engine_condition_pushdown = 1;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT `time_nokey` G1 FROM t1 WHERE ( `varchar_nokey` , `varchar_key` ) IN (
SELECT `varchar_nokey` , `varchar_nokey` ) AND `varchar_key` >= 'c' HAVING G1 ORDER
BY `pk` ;
@@ -438,7 +438,7 @@ G1
set @@session.optimizer_switch = @old_optimizer_switch,
@@session.engine_condition_pushdown = @old_engine_condition_pushdown;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
DROP TABLE t1;
#
# During work with BUG#45863 I had problems with a query that was
@@ -625,7 +625,7 @@ SELECT @old_icp:=@@engine_condition_pushdown;
#
SET SESSION engine_condition_pushdown = 'ON';
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT pk
FROM t2
@@ -640,7 +640,7 @@ pk
# Restore old value for Index condition pushdown
SET SESSION engine_condition_pushdown=@old_icp;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
DROP TABLE t1,t2;
#
# End of 5.3 tests.
@@ -1351,7 +1351,7 @@ ON SUBQUERY2_t3.f2)
GROUP BY t1.f4 ORDER BY t1.f1 LIMIT 10;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 system NULL NULL NULL NULL 1 Using temporary; Using filesort
-1 PRIMARY t1 index NULL f4 5 NULL 11 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 11 Using where
2 DEPENDENT SUBQUERY SUBQUERY2_t1 system NULL NULL NULL NULL 1
2 DEPENDENT SUBQUERY SUBQUERY2_t2 index NULL f4 5 NULL 11 Using index
2 DEPENDENT SUBQUERY SUBQUERY2_t3 ALL NULL NULL NULL NULL 11 Using where; Using join buffer (flat, BNL join)
diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result
index e72d25fdafa..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
@@ -6637,6 +6747,23 @@ a ( 3, 3 ) NOT IN ( SELECT NULL, NULL )
set optimizer_switch=@mdev367_optimizer_switch;
DROP TABLE t1;
#
+# MDEV-521 single value subselect transformation problem
+#
+CREATE TABLE t1 (f1 char(2), PRIMARY KEY (f1)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES ('u1'),('u2');
+SELECT a.* FROM t1 a WHERE ( SELECT EXISTS ( SELECT 1 FROM t1 b WHERE b.f1 = a.f1 ) );
+f1
+u1
+u2
+FLUSH TABLES;
+SELECT a.* FROM t1 a WHERE ( SELECT EXISTS ( SELECT 1 FROM t1 b WHERE b.f1 = a.f1 ) );
+f1
+u1
+u2
+DROP TABLE t1;
+# return optimizer switch changed in the beginning of this test
+set optimizer_switch=@subselect_tmp;
+#
# lp:944706 Query with impossible or constant subquery in WHERE or HAVING is not
# precomputed and thus not part of optimization
#
@@ -6841,10 +6968,30 @@ 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;
#
+# MDEV-435: Expensive subqueries may be evaluated during optimization in merge_key_fields
+#
+CREATE TABLE t1 (a INT, KEY(a)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (8),(0);
+CREATE TABLE t2 (b INT, c VARCHAR(1)) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (4,'j'),(6,'v');
+CREATE TABLE t3 (d VARCHAR(1)) ENGINE=MyISAM;
+INSERT INTO t3 VALUES ('b'),('c');
+EXPLAIN
+SELECT * FROM t1
+WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 index a a 5 NULL 2 Using where; Using index
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2
+SELECT * FROM t1
+WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10;
+a
+drop table t1, t2, t3;
+#
# MDEV-405: Server crashes in test_if_skip_sort_order on EXPLAIN with GROUP BY and HAVING in EXISTS subquery
#
CREATE TABLE t1 (a INT, KEY(a));
@@ -6854,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 9030265356b..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
@@ -6633,6 +6743,23 @@ a ( 3, 3 ) NOT IN ( SELECT NULL, NULL )
set optimizer_switch=@mdev367_optimizer_switch;
DROP TABLE t1;
#
+# MDEV-521 single value subselect transformation problem
+#
+CREATE TABLE t1 (f1 char(2), PRIMARY KEY (f1)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES ('u1'),('u2');
+SELECT a.* FROM t1 a WHERE ( SELECT EXISTS ( SELECT 1 FROM t1 b WHERE b.f1 = a.f1 ) );
+f1
+u1
+u2
+FLUSH TABLES;
+SELECT a.* FROM t1 a WHERE ( SELECT EXISTS ( SELECT 1 FROM t1 b WHERE b.f1 = a.f1 ) );
+f1
+u1
+u2
+DROP TABLE t1;
+# return optimizer switch changed in the beginning of this test
+set optimizer_switch=@subselect_tmp;
+#
# lp:944706 Query with impossible or constant subquery in WHERE or HAVING is not
# precomputed and thus not part of optimization
#
@@ -6838,10 +6965,31 @@ 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;
#
+# MDEV-435: Expensive subqueries may be evaluated during optimization in merge_key_fields
+#
+CREATE TABLE t1 (a INT, KEY(a)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (8),(0);
+CREATE TABLE t2 (b INT, c VARCHAR(1)) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (4,'j'),(6,'v');
+CREATE TABLE t3 (d VARCHAR(1)) ENGINE=MyISAM;
+INSERT INTO t3 VALUES ('b'),('c');
+EXPLAIN
+SELECT * FROM t1
+WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 index a a 5 NULL 2 Using where; Using index
+2 SUBQUERY <subquery3> ALL distinct_key NULL NULL NULL 1
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
+3 MATERIALIZED t3 ALL NULL NULL NULL NULL 2
+SELECT * FROM t1
+WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10;
+a
+drop table t1, t2, t3;
+#
# MDEV-405: Server crashes in test_if_skip_sort_order on EXPLAIN with GROUP BY and HAVING in EXISTS subquery
#
CREATE TABLE t1 (a INT, KEY(a));
@@ -6851,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 e68f5990c08..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
@@ -6644,6 +6754,23 @@ a ( 3, 3 ) NOT IN ( SELECT NULL, NULL )
set optimizer_switch=@mdev367_optimizer_switch;
DROP TABLE t1;
#
+# MDEV-521 single value subselect transformation problem
+#
+CREATE TABLE t1 (f1 char(2), PRIMARY KEY (f1)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES ('u1'),('u2');
+SELECT a.* FROM t1 a WHERE ( SELECT EXISTS ( SELECT 1 FROM t1 b WHERE b.f1 = a.f1 ) );
+f1
+u1
+u2
+FLUSH TABLES;
+SELECT a.* FROM t1 a WHERE ( SELECT EXISTS ( SELECT 1 FROM t1 b WHERE b.f1 = a.f1 ) );
+f1
+u1
+u2
+DROP TABLE t1;
+# return optimizer switch changed in the beginning of this test
+set optimizer_switch=@subselect_tmp;
+#
# lp:944706 Query with impossible or constant subquery in WHERE or HAVING is not
# precomputed and thus not part of optimization
#
@@ -6849,10 +6976,31 @@ 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;
#
+# MDEV-435: Expensive subqueries may be evaluated during optimization in merge_key_fields
+#
+CREATE TABLE t1 (a INT, KEY(a)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (8),(0);
+CREATE TABLE t2 (b INT, c VARCHAR(1)) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (4,'j'),(6,'v');
+CREATE TABLE t3 (d VARCHAR(1)) ENGINE=MyISAM;
+INSERT INTO t3 VALUES ('b'),('c');
+EXPLAIN
+SELECT * FROM t1
+WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 index a a 5 NULL 2 Using where; Using index
+2 SUBQUERY <subquery3> ALL distinct_key NULL NULL NULL 1
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
+3 MATERIALIZED t3 ALL NULL NULL NULL NULL 2
+SELECT * FROM t1
+WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10;
+a
+drop table t1, t2, t3;
+#
# MDEV-405: Server crashes in test_if_skip_sort_order on EXPLAIN with GROUP BY and HAVING in EXISTS subquery
#
CREATE TABLE t1 (a INT, KEY(a));
@@ -6862,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 f0ce541294a..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
@@ -6633,6 +6743,23 @@ a ( 3, 3 ) NOT IN ( SELECT NULL, NULL )
set optimizer_switch=@mdev367_optimizer_switch;
DROP TABLE t1;
#
+# MDEV-521 single value subselect transformation problem
+#
+CREATE TABLE t1 (f1 char(2), PRIMARY KEY (f1)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES ('u1'),('u2');
+SELECT a.* FROM t1 a WHERE ( SELECT EXISTS ( SELECT 1 FROM t1 b WHERE b.f1 = a.f1 ) );
+f1
+u1
+u2
+FLUSH TABLES;
+SELECT a.* FROM t1 a WHERE ( SELECT EXISTS ( SELECT 1 FROM t1 b WHERE b.f1 = a.f1 ) );
+f1
+u1
+u2
+DROP TABLE t1;
+# return optimizer switch changed in the beginning of this test
+set optimizer_switch=@subselect_tmp;
+#
# lp:944706 Query with impossible or constant subquery in WHERE or HAVING is not
# precomputed and thus not part of optimization
#
@@ -6838,10 +6965,31 @@ 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;
#
+# MDEV-435: Expensive subqueries may be evaluated during optimization in merge_key_fields
+#
+CREATE TABLE t1 (a INT, KEY(a)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (8),(0);
+CREATE TABLE t2 (b INT, c VARCHAR(1)) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (4,'j'),(6,'v');
+CREATE TABLE t3 (d VARCHAR(1)) ENGINE=MyISAM;
+INSERT INTO t3 VALUES ('b'),('c');
+EXPLAIN
+SELECT * FROM t1
+WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 index a a 5 NULL 2 Using where; Using index
+2 SUBQUERY <subquery3> ALL distinct_key NULL NULL NULL 1
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
+3 MATERIALIZED t3 ALL NULL NULL NULL NULL 2
+SELECT * FROM t1
+WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10;
+a
+drop table t1, t2, t3;
+#
# MDEV-405: Server crashes in test_if_skip_sort_order on EXPLAIN with GROUP BY and HAVING in EXISTS subquery
#
CREATE TABLE t1 (a INT, KEY(a));
@@ -6851,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/r/variables.result b/mysql-test/r/variables.result
index 4b1e525e1df..e055a333faf 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -538,7 +538,7 @@ Warning 1292 Truncated incorrect read_buffer_size value: '100'
set read_rnd_buffer_size=100;
set global rpl_recovery_rank=100;
Warnings:
-Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MariaDB 10.1.
+Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release.
set global server_id=100;
set global slow_launch_time=100;
set sort_buffer_size=100;
@@ -1060,7 +1060,7 @@ set global net_write_timeout =@my_net_write_timeout;
set global net_read_timeout =@my_net_read_timeout;
set global rpl_recovery_rank =@my_rpl_recovery_rank;
Warnings:
-Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MariaDB 10.1.
+Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release.
set global server_id =@my_server_id;
set global slow_launch_time =@my_slow_launch_time;
set global default_storage_engine =@my_storage_engine;
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index 5af20fd0c3c..8d2d1561456 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -4530,6 +4530,55 @@ WHERE t4.a >= v1.a);
a a
DROP VIEW v1;
DROP TABLE t1,t2,t3,t4;
+#
+# LP bug #823237: dependent subquery with LEFT JOIN
+# referencing view in WHERE
+# (duplicate of LP bug #823189)
+#
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 ( b int, d int, e int);
+INSERT INTO t2 VALUES (7,8,0);
+CREATE TABLE t3 ( c int);
+INSERT INTO t3 VALUES (0);
+CREATE TABLE t4 (a int, b int, c int);
+INSERT INTO t4 VALUES (93,1,0), (95,NULL,0);
+CREATE VIEW v4 AS SELECT * FROM t4;
+EXPLAIN EXTENDED
+SELECT * FROM t3 , t4
+WHERE t4.c <= (SELECT t2.e FROM t2 LEFT JOIN t1 ON ( t1.a = t2.d )
+WHERE t2.b > t4.b);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t3 system NULL NULL NULL NULL 1 100.00
+1 PRIMARY t4 ALL NULL NULL NULL NULL 2 100.00 Using where
+2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 1 100.00
+2 DEPENDENT SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
+Warnings:
+Note 1276 Field or reference 'test.t4.b' of SELECT #2 was resolved in SELECT #1
+Note 1003 select 0 AS `c`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t4`.`c` AS `c` from `test`.`t4` where (`test`.`t4`.`c` <= <expr_cache><`test`.`t4`.`b`>((select 0 from dual where (7 > `test`.`t4`.`b`))))
+SELECT * FROM t3 , t4
+WHERE t4.c <= (SELECT t2.e FROM t2 LEFT JOIN t1 ON ( t1.a = t2.d )
+WHERE t2.b > t4.b);
+c a b c
+0 93 1 0
+EXPLAIN EXTENDED
+SELECT * FROM t3, v4
+WHERE v4.c <= (SELECT t2.e FROM t2 LEFT JOIN t1 ON ( t1.a = t2.d )
+WHERE t2.b > v4.b);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t3 system NULL NULL NULL NULL 1 100.00
+1 PRIMARY t4 ALL NULL NULL NULL NULL 2 100.00 Using where
+2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 1 100.00
+2 DEPENDENT SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
+Warnings:
+Note 1276 Field or reference 'v4.b' of SELECT #2 was resolved in SELECT #1
+Note 1003 select 0 AS `c`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t4`.`c` AS `c` from `test`.`t4` where (`test`.`t4`.`c` <= <expr_cache><`test`.`t4`.`b`>((select 0 from dual where (7 > `test`.`t4`.`b`))))
+SELECT * FROM t3, v4
+WHERE v4.c <= (SELECT t2.e FROM t2 LEFT JOIN t1 ON ( t1.a = t2.d )
+WHERE t2.b > v4.b);
+c a b c
+0 93 1 0
+DROP VIEW v4;
+DROP TABLE t1,t2,t3,t4;
drop table if exists t_9801;
drop view if exists v_9801;
create table t_9801 (s1 int);
@@ -4730,7 +4779,82 @@ id id bbb iddqd val1
30631 NULL NULL NULL NULL
drop view v2;
drop table t1,t2;
+#
+# MDEV-589 (LP BUG#1007647) :
+# Assertion `vcol_table == 0 || vcol_table == table' failed in
+# fill_record(THD*, List<Item>&, List<Item>&, bool)
+#
+CREATE TABLE t1 (f1 INT, f2 INT);
+CREATE TABLE t2 (f1 INT, f2 INT);
+CREATE ALGORITHM=MERGE VIEW v1 AS SELECT a1.f1, a2.f2 FROM t1 AS a1, t1 AS a2;
+CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM v1;
+CREATE ALGORITHM=MERGE VIEW v3 AS SELECT a1.f1, a2.f2 FROM t1 AS a1, t2 AS a2;
+CREATE ALGORITHM=MERGE VIEW v4 AS SELECT * FROM v3;
+INSERT INTO v3 (f1, f2) VALUES (1, 2);
+ERROR HY000: Can not modify more than one base table through a join view 'test.v3'
+INSERT INTO v1 (f1, f2) VALUES (1, 2);
+ERROR HY000: Can not modify more than one base table through a join view 'test.v1'
+INSERT INTO v4 (f1, f2) VALUES (1, 2);
+ERROR HY000: Can not modify more than one base table through a join view 'test.v4'
+INSERT INTO v2 (f1, f2) VALUES (1, 2);
+ERROR HY000: Can not modify more than one base table through a join view 'test.v2'
+drop view v4,v3,v2,v1;
+drop table t1,t2;
+#
+# MDEV-3799 fix of above bugfix (MDEV-589)
+# Wrong result (NULLs instead of real values) with RIGHT JOIN
+# in a FROM subquery and derived_merge=on
+#
+CREATE TABLE t1 (f1 INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (4),(6);
+CREATE TABLE t2 (f2 INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (7),(8);
+SELECT * FROM (
+SELECT * FROM t1 RIGHT JOIN t2 ON f1 = f2
+) AS alias;
+f1 f2
+NULL 7
+NULL 8
+SELECT * FROM (
+SELECT * FROM t2 LEFT JOIN t1 ON f1 = f2
+) AS alias;
+f2 f1
+7 NULL
+8 NULL
+drop tables t1,t2;
# -----------------------------------------------------------------
# -- End of 5.3 tests.
# -----------------------------------------------------------------
+#
+# MDEV-3874: Server crashes in Item_field::print on a SELECT
+# from a MERGE view with materialization+semijoin, subquery, ORDER BY
+#
+SET @save_optimizer_switch_MDEV_3874=@@optimizer_switch;
+SET optimizer_switch = 'materialization=on,semijoin=on';
+CREATE TABLE t1 (a INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1),(7);
+CREATE TABLE t2 (b INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (4),(6);
+CREATE TABLE t3 (c INT) ENGINE=MyISAM;
+INSERT INTO t3 VALUES (1),(2);
+CREATE ALGORITHM=MERGE VIEW v1 AS SELECT
+( SELECT a FROM t1 WHERE ( 1, 1 ) IN (
+SELECT b, c FROM t2, t3 HAVING c > 2 ) ) AS field1,
+b + c AS field2
+FROM t2, t3 AS table1
+GROUP BY field1, field2 ORDER BY field1;
+Warnings:
+Warning 1354 View merge algorithm can't be used here for now (assumed undefined algorithm)
+SELECT * FROM v1;
+field1 field2
+NULL 5
+NULL 7
+NULL 6
+NULL 8
+drop view v1;
+drop table t1,t2,t3;
+SET optimizer_switch=@save_optimizer_switch_MDEV_3874;
+# -----------------------------------------------------------------
+# -- End of 5.5 tests.
+# -----------------------------------------------------------------
SET optimizer_switch=@save_optimizer_switch;
diff --git a/mysql-test/suite/federated/federated_archive.test b/mysql-test/suite/federated/federated_archive.test
index 1bde23889be..b35b82c6fa6 100644
--- a/mysql-test/suite/federated/federated_archive.test
+++ b/mysql-test/suite/federated/federated_archive.test
@@ -1,5 +1,5 @@
source include/have_archive.inc;
-source federated.inc;
+source suite/federated/include/federated.inc;
connection slave;
@@ -54,5 +54,5 @@ connection slave;
DROP TABLE federated.archive_table;
-source federated_cleanup.inc;
+source suite/federated/include/federated_cleanup.inc;
diff --git a/mysql-test/suite/federated/federated_bug_13118.test b/mysql-test/suite/federated/federated_bug_13118.test
index fad6be75dac..78115a7959f 100644
--- a/mysql-test/suite/federated/federated_bug_13118.test
+++ b/mysql-test/suite/federated/federated_bug_13118.test
@@ -1,4 +1,4 @@
-source federated.inc;
+source suite/federated/include/federated.inc;
connection slave;
--disable_warnings
@@ -37,5 +37,5 @@ connection slave;
DROP TABLE federated.bug_13118_table;
-source federated_cleanup.inc;
+source suite/federated/include/federated_cleanup.inc;
diff --git a/mysql-test/suite/federated/federated_bug_25714.test b/mysql-test/suite/federated/federated_bug_25714.test
index 633e469f595..bb5dcfe5d85 100644
--- a/mysql-test/suite/federated/federated_bug_25714.test
+++ b/mysql-test/suite/federated/federated_bug_25714.test
@@ -4,7 +4,7 @@ if (!$MYSQL_BUG25714)
skip Need bug25714 test program;
}
-source federated.inc;
+source suite/federated/include/federated.inc;
connection master;
# Disable concurrent inserts to avoid test failures when reading
@@ -59,4 +59,4 @@ SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT;
-source federated_cleanup.inc;
+source suite/federated/include/federated_cleanup.inc;
diff --git a/mysql-test/suite/federated/federated_bug_32426.test b/mysql-test/suite/federated/federated_bug_32426.test
index 254dfaa610a..2615adbc1bc 100644
--- a/mysql-test/suite/federated/federated_bug_32426.test
+++ b/mysql-test/suite/federated/federated_bug_32426.test
@@ -1,4 +1,4 @@
-source federated.inc;
+source include/federated.inc;
--echo #
--echo # Bug #32426: FEDERATED query returns corrupt results for ORDER BY
@@ -21,4 +21,4 @@ DROP TABLE federated.t1;
connection default;
-source federated_cleanup.inc;
+source include/federated_cleanup.inc;
diff --git a/mysql-test/suite/federated/federated_bug_35333.test b/mysql-test/suite/federated/federated_bug_35333.test
index 8bce63c34e5..6487e10e018 100644
--- a/mysql-test/suite/federated/federated_bug_35333.test
+++ b/mysql-test/suite/federated/federated_bug_35333.test
@@ -9,7 +9,7 @@
--echo # to complete while still indicating a problem. This fix applies to any non-fatal system
--echo # error that occurs during a query against I_S.TABLES.de
---source federated.inc
+--source suite/federated/include/federated.inc
--disable_warnings
# Federated database exists
@@ -74,4 +74,4 @@ DROP TABLE t1;
--echo # Cleanup
--echo #
---source federated_cleanup.inc
+--source suite/federated/include/federated_cleanup.inc
diff --git a/mysql-test/suite/federated/federated_bug_585688.test b/mysql-test/suite/federated/federated_bug_585688.test
index 6566125c419..02fec2c985c 100644
--- a/mysql-test/suite/federated/federated_bug_585688.test
+++ b/mysql-test/suite/federated/federated_bug_585688.test
@@ -1,4 +1,4 @@
-source federated.inc;
+source include/federated.inc;
--echo #
--echo # Bug #585688: maridb crashes in federatedx code
@@ -49,5 +49,5 @@ DROP TABLE federated.t1;
connection default;
-source federated_cleanup.inc;
+source include/federated_cleanup.inc;
diff --git a/mysql-test/suite/federated/federated_debug.test b/mysql-test/suite/federated/federated_debug.test
index 08bd13eefaf..a640987a127 100644
--- a/mysql-test/suite/federated/federated_debug.test
+++ b/mysql-test/suite/federated/federated_debug.test
@@ -1,6 +1,6 @@
--source include/have_debug.inc
--source include/long_test.inc
---source federated.inc
+--source include/federated.inc
--echo #
--echo # Bug#47525: MySQL crashed (Federated)
@@ -37,4 +37,4 @@ DROP TABLE t1;
connection default;
--echo # Federated cleanup
-source federated_cleanup.inc;
+source suite/federated/include/federated_cleanup.inc;
diff --git a/mysql-test/suite/federated/federated_innodb.test b/mysql-test/suite/federated/federated_innodb.test
index 278c5b18661..9212ba12b81 100644
--- a/mysql-test/suite/federated/federated_innodb.test
+++ b/mysql-test/suite/federated/federated_innodb.test
@@ -4,7 +4,7 @@
# See Bug #40645 Test main.federated_innodb does not always clean up after itself
source include/have_innodb.inc;
-source federated.inc;
+source suite/federated/include/federated.inc;
#
# Bug#25513 Federated transaction failures
@@ -36,4 +36,4 @@ connection slave;
drop table federated.t1;
-source federated_cleanup.inc;
+source suite/federated/include/federated_cleanup.inc;
diff --git a/mysql-test/suite/federated/federated_partition.test b/mysql-test/suite/federated/federated_partition.test
index 13f26ecd756..ef1e27ec505 100644
--- a/mysql-test/suite/federated/federated_partition.test
+++ b/mysql-test/suite/federated/federated_partition.test
@@ -4,7 +4,7 @@
source have_federatedx.inc;
source include/have_partition.inc;
source include/have_innodb.inc;
-source federated.inc;
+source include/federated.inc;
disable_warnings;
drop table if exists t1;
@@ -50,4 +50,4 @@ drop table federated.t1_2;
--echo End of 5.1 tests
-source federated_cleanup.inc;
+source include/federated_cleanup.inc;
diff --git a/mysql-test/suite/federated/federated_server.test b/mysql-test/suite/federated/federated_server.test
index 9f7f833a401..c47a1acf2a3 100644
--- a/mysql-test/suite/federated/federated_server.test
+++ b/mysql-test/suite/federated/federated_server.test
@@ -4,7 +4,7 @@
# Slow test, don't run during staging part
-- source include/not_staging.inc
-- source include/big_test.inc
--- source federated.inc
+-- source include/federated.inc
connection slave;
create database first_db;
@@ -343,4 +343,4 @@ drop table t1;
drop server if exists s;
-source federated_cleanup.inc;
+source suite/federated/include/federated_cleanup.inc;
diff --git a/mysql-test/suite/federated/federated_transactions.test b/mysql-test/suite/federated/federated_transactions.test
index 637df45a52a..480f9a6ba27 100644
--- a/mysql-test/suite/federated/federated_transactions.test
+++ b/mysql-test/suite/federated/federated_transactions.test
@@ -1,6 +1,6 @@
source have_federatedx.inc;
source include/have_innodb.inc;
-source federated.inc;
+source suite/federated/include/federated.inc;
connection slave;
DROP TABLE IF EXISTS federated.t1;
@@ -36,4 +36,4 @@ INSERT INTO federated.t1 (id, name) VALUES (6, 'fig');
SELECT * FROM federated.t1;
DELETE FROM federated.t1;
-source federated_cleanup.inc;
+source suite/federated/include/federated_cleanup.inc;
diff --git a/mysql-test/suite/federated/federatedx.test b/mysql-test/suite/federated/federatedx.test
index 2c307587b4f..15fdd47c4da 100644
--- a/mysql-test/suite/federated/federatedx.test
+++ b/mysql-test/suite/federated/federatedx.test
@@ -4,7 +4,7 @@
#
---source federated.inc
+--source include/federated.inc
--source have_federatedx.inc
connection default;
@@ -1999,4 +1999,4 @@ connection slave;
SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT;
connection default;
-source federated_cleanup.inc;
+source include/federated_cleanup.inc;
diff --git a/mysql-test/suite/federated/federated.inc b/mysql-test/suite/federated/include/federated.inc
index 17410846604..17410846604 100644
--- a/mysql-test/suite/federated/federated.inc
+++ b/mysql-test/suite/federated/include/federated.inc
diff --git a/mysql-test/suite/federated/federated_cleanup.inc b/mysql-test/suite/federated/include/federated_cleanup.inc
index 06fd7f6737a..06fd7f6737a 100644
--- a/mysql-test/suite/federated/federated_cleanup.inc
+++ b/mysql-test/suite/federated/include/federated_cleanup.inc
diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result
index d99e7f06295..508370bd7a8 100644
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result
@@ -59,7 +59,7 @@ def mysql func ret 2 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(1)
def mysql func type 4 NULL NO enum 9 27 NULL NULL NULL utf8 utf8_general_ci enum('function','aggregate')
def mysql general_log argument 6 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext
def mysql general_log command_type 5 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64)
-def mysql general_log event_time 1 CURRENT_TIMESTAMP NO timestamp NULL NULL NULL NULL 6 NULL NULL timestamp(6) on update CURRENT_TIMESTAMP
+def mysql general_log event_time 1 CURRENT_TIMESTAMP(6) NO timestamp NULL NULL NULL NULL 6 NULL NULL timestamp(6) on update CURRENT_TIMESTAMP
def mysql general_log server_id 4 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned
def mysql general_log thread_id 3 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11)
def mysql general_log user_host 2 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext
@@ -159,7 +159,7 @@ def mysql slow_log rows_examined 6 NULL NO int NULL NULL 10 0 NULL NULL NULL int
def mysql slow_log rows_sent 5 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11)
def mysql slow_log server_id 10 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned
def mysql slow_log sql_text 11 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext
-def mysql slow_log start_time 1 CURRENT_TIMESTAMP NO timestamp NULL NULL NULL NULL 6 NULL NULL timestamp(6) on update CURRENT_TIMESTAMP
+def mysql slow_log start_time 1 CURRENT_TIMESTAMP(6) NO timestamp NULL NULL NULL NULL 6 NULL NULL timestamp(6) on update CURRENT_TIMESTAMP
def mysql slow_log user_host 2 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext
def mysql tables_priv Column_priv 8 NO set 31 93 NULL NULL NULL utf8 utf8_general_ci set('Select','Insert','Update','References')
def mysql tables_priv Db 2 NO char 64 192 NULL NULL NULL utf8 utf8_bin char(64) PRI
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/r/innodb_information_schema_buffer.result b/mysql-test/suite/innodb/r/innodb_information_schema_buffer.result
new file mode 100644
index 00000000000..b4a350e77a3
--- /dev/null
+++ b/mysql-test/suite/innodb/r/innodb_information_schema_buffer.result
@@ -0,0 +1,130 @@
+SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS;
+SELECT count(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS;
+SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE;
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE;
+CREATE TABLE infoschema_buffer_test (col1 INT) ENGINE = INNODB;
+INSERT INTO infoschema_buffer_test VALUES(9);
+SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE
+FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
+WHERE TABLE_NAME like "%infoschema_buffer_test"
+ and PAGE_STATE="file_page" and PAGE_TYPE="index";
+TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE PAGE_STATE PAGE_TYPE
+test/infoschema_buffer_test GEN_CLUST_INDEX 1 29 FILE_PAGE INDEX
+INSERT INTO infoschema_buffer_test VALUES(19);
+SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE
+FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
+WHERE TABLE_NAME like "%infoschema_buffer_test"
+and PAGE_STATE="file_page" and PAGE_TYPE="index";
+TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE PAGE_STATE PAGE_TYPE
+test/infoschema_buffer_test GEN_CLUST_INDEX 2 58 FILE_PAGE INDEX
+CREATE INDEX idx ON infoschema_buffer_test(col1);
+SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE
+FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
+WHERE TABLE_NAME like "%infoschema_buffer_test"
+and PAGE_STATE="file_page" and INDEX_NAME = "idx" and PAGE_TYPE="index";
+TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE PAGE_STATE PAGE_TYPE
+test/infoschema_buffer_test idx 2 32 FILE_PAGE INDEX
+DROP TABLE infoschema_buffer_test;
+SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE
+FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
+WHERE TABLE_NAME like "%infoschema_buffer_test";
+TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE PAGE_STATE PAGE_TYPE
+CREATE TABLE infoschema_parent (id INT NOT NULL, PRIMARY KEY (id))
+ENGINE=INNODB;
+CREATE TABLE infoschema_child (id INT, parent_id INT, INDEX par_ind (parent_id),
+FOREIGN KEY (parent_id)
+REFERENCES infoschema_parent(id)
+ON DELETE CASCADE)
+ENGINE=INNODB;
+SELECT count(*)
+FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
+WHERE TABLE_NAME like "%infoschema_child" and PAGE_STATE="file_page"
+and PAGE_TYPE="index";
+count(*)
+2
+DROP TABLE infoschema_child;
+DROP TABLE infoschema_parent;
+show create table information_schema.innodb_buffer_page;
+Table Create Table
+INNODB_BUFFER_PAGE CREATE TEMPORARY TABLE `INNODB_BUFFER_PAGE` (
+ `POOL_ID` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `BLOCK_ID` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `SPACE` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `PAGE_NUMBER` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `PAGE_TYPE` varchar(64) DEFAULT NULL,
+ `FLUSH_TYPE` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `FIX_COUNT` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `IS_HASHED` varchar(3) DEFAULT NULL,
+ `NEWEST_MODIFICATION` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `OLDEST_MODIFICATION` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `ACCESS_TIME` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `TABLE_NAME` varchar(1024) DEFAULT NULL,
+ `INDEX_NAME` varchar(1024) DEFAULT NULL,
+ `NUMBER_RECORDS` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `DATA_SIZE` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `COMPRESSED_SIZE` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `PAGE_STATE` varchar(64) DEFAULT NULL,
+ `IO_FIX` varchar(64) DEFAULT NULL,
+ `IS_OLD` varchar(3) DEFAULT NULL,
+ `FREE_PAGE_CLOCK` bigint(21) unsigned NOT NULL DEFAULT '0'
+) ENGINE=MEMORY DEFAULT CHARSET=utf8
+show create table information_schema.innodb_buffer_page_lru;
+Table Create Table
+INNODB_BUFFER_PAGE_LRU CREATE TEMPORARY TABLE `INNODB_BUFFER_PAGE_LRU` (
+ `POOL_ID` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `LRU_POSITION` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `SPACE` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `PAGE_NUMBER` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `PAGE_TYPE` varchar(64) DEFAULT NULL,
+ `FLUSH_TYPE` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `FIX_COUNT` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `IS_HASHED` varchar(3) DEFAULT NULL,
+ `NEWEST_MODIFICATION` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `OLDEST_MODIFICATION` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `ACCESS_TIME` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `TABLE_NAME` varchar(1024) DEFAULT NULL,
+ `INDEX_NAME` varchar(1024) DEFAULT NULL,
+ `NUMBER_RECORDS` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `DATA_SIZE` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `COMPRESSED_SIZE` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `COMPRESSED` varchar(3) DEFAULT NULL,
+ `IO_FIX` varchar(64) DEFAULT NULL,
+ `IS_OLD` varchar(3) DEFAULT NULL,
+ `FREE_PAGE_CLOCK` bigint(21) unsigned NOT NULL DEFAULT '0'
+) ENGINE=MEMORY DEFAULT CHARSET=utf8
+show create table information_schema.innodb_buffer_pool_stats;
+Table Create Table
+INNODB_BUFFER_POOL_STATS CREATE TEMPORARY TABLE `INNODB_BUFFER_POOL_STATS` (
+ `POOL_ID` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `POOL_SIZE` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `FREE_BUFFERS` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `DATABASE_PAGES` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `OLD_DATABASE_PAGES` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `MODIFIED_DATABASE_PAGES` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `PENDING_DECOMPRESS` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `PENDING_READS` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `PENDING_FLUSH_LRU` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `PENDING_FLUSH_LIST` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `PAGES_MADE_YOUNG` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `PAGES_NOT_MADE_YOUNG` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `PAGES_MADE_YOUNG_RATE` double NOT NULL DEFAULT '0',
+ `PAGES_MADE_NOT_YOUNG_RATE` double NOT NULL DEFAULT '0',
+ `NUMBER_PAGES_READ` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `NUMBER_PAGES_CREATED` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `NUMBER_PAGES_WRITTEN` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `PAGES_READ_RATE` double NOT NULL DEFAULT '0',
+ `PAGES_CREATE_RATE` double NOT NULL DEFAULT '0',
+ `PAGES_WRITTEN_RATE` double NOT NULL DEFAULT '0',
+ `NUMBER_PAGES_GET` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `HIT_RATE` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `YOUNG_MAKE_PER_THOUSAND_GETS` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `NOT_YOUNG_MAKE_PER_THOUSAND_GETS` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `NUMBER_PAGES_READ_AHEAD` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `NUMBER_READ_AHEAD_EVICTED` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `READ_AHEAD_RATE` double NOT NULL DEFAULT '0',
+ `READ_AHEAD_EVICTED_RATE` double NOT NULL DEFAULT '0',
+ `LRU_IO_TOTAL` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `LRU_IO_CURRENT` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `UNCOMPRESS_TOTAL` bigint(21) unsigned NOT NULL DEFAULT '0',
+ `UNCOMPRESS_CURRENT` bigint(21) unsigned NOT NULL DEFAULT '0'
+) ENGINE=MEMORY DEFAULT CHARSET=utf8
diff --git a/mysql-test/suite/innodb/t/innodb_bug14007649.test b/mysql-test/suite/innodb/t/innodb_bug14007649.test
index da413e0ce59..9326e1c53ef 100644
--- a/mysql-test/suite/innodb/t/innodb_bug14007649.test
+++ b/mysql-test/suite/innodb/t/innodb_bug14007649.test
@@ -1,11 +1,6 @@
--source include/have_innodb.inc
--source include/have_debug.inc
-if (`select plugin_auth_version <= "1.0.17-13.01" from information_schema.plugins where plugin_name='innodb'`)
-{
- --skip Not fixed in XtraDB 1.0.17-13.01 or earlier
-}
-
create table t1 (
rowid int,
f1 int,
diff --git a/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test b/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test
new file mode 100644
index 00000000000..751a2bd6b5e
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test
@@ -0,0 +1,76 @@
+# Exercise the code path for INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS
+# and INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
+
+-- source include/have_innodb.inc
+
+-- disable_result_log
+SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS;
+
+# How many buffer pools we have
+SELECT count(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS;
+
+SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE;
+
+# This gives the over all buffer pool size
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE;
+
+-- enable_result_log
+
+# Create a table and check its page info behave correctly in the pool
+CREATE TABLE infoschema_buffer_test (col1 INT) ENGINE = INNODB;
+
+INSERT INTO infoschema_buffer_test VALUES(9);
+
+# We should be able to see this table in the buffer pool if we check
+# right away
+SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE
+FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
+WHERE TABLE_NAME like "%infoschema_buffer_test"
+ and PAGE_STATE="file_page" and PAGE_TYPE="index";
+
+# The NUMBER_RECORDS and DATA_SIZE should check with each insertion
+INSERT INTO infoschema_buffer_test VALUES(19);
+
+SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE
+FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
+WHERE TABLE_NAME like "%infoschema_buffer_test"
+and PAGE_STATE="file_page" and PAGE_TYPE="index";
+
+CREATE INDEX idx ON infoschema_buffer_test(col1);
+
+SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE
+FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
+WHERE TABLE_NAME like "%infoschema_buffer_test"
+and PAGE_STATE="file_page" and INDEX_NAME = "idx" and PAGE_TYPE="index";
+
+
+# Check the buffer after dropping the table
+DROP TABLE infoschema_buffer_test;
+
+SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE
+FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
+WHERE TABLE_NAME like "%infoschema_buffer_test";
+
+# Do one more test
+#--replace_regex /'*[0-9]*'/'NUM'/
+CREATE TABLE infoschema_parent (id INT NOT NULL, PRIMARY KEY (id))
+ENGINE=INNODB;
+
+CREATE TABLE infoschema_child (id INT, parent_id INT, INDEX par_ind (parent_id),
+ FOREIGN KEY (parent_id)
+ REFERENCES infoschema_parent(id)
+ ON DELETE CASCADE)
+ENGINE=INNODB;
+
+SELECT count(*)
+FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
+WHERE TABLE_NAME like "%infoschema_child" and PAGE_STATE="file_page"
+and PAGE_TYPE="index";
+
+DROP TABLE infoschema_child;
+DROP TABLE infoschema_parent;
+
+show create table information_schema.innodb_buffer_page;
+show create table information_schema.innodb_buffer_page_lru;
+show create table information_schema.innodb_buffer_pool_stats;
+
diff --git a/mysql-test/suite/perfschema/disabled.def b/mysql-test/suite/perfschema/disabled.def
index 8a843692d2a..888298bbb09 100644
--- a/mysql-test/suite/perfschema/disabled.def
+++ b/mysql-test/suite/perfschema/disabled.def
@@ -9,4 +9,3 @@
# Do not use any TAB characters for whitespace.
#
##############################################################################
-misc : bug#14113704 24/04/2012 Mayank issue reported causing failure.
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/r/pam.result b/mysql-test/suite/plugins/r/pam.result
index 432fb48eb5a..86303206b3b 100644
--- a/mysql-test/suite/plugins/r/pam.result
+++ b/mysql-test/suite/plugins/r/pam.result
@@ -4,7 +4,7 @@ create user pam_test;
grant proxy on pam_test to test_pam;
#
# athentication is successful, challenge/pin are ok
-# note that current_user() differts from user()
+# note that current_user() differs from user()
#
Challenge input first.
Enter: not very secret challenge
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/plugins/t/pam.test b/mysql-test/suite/plugins/t/pam.test
index 587a2380f94..68fa349a444 100644
--- a/mysql-test/suite/plugins/t/pam.test
+++ b/mysql-test/suite/plugins/t/pam.test
@@ -26,7 +26,7 @@ EOF
--echo #
--echo # athentication is successful, challenge/pin are ok
---echo # note that current_user() differts from user()
+--echo # note that current_user() differs from user()
--echo #
--exec $MYSQL_TEST -u test_pam --plugin-dir=$plugindir < $MYSQLTEST_VARDIR/tmp/pam_good.txt
diff --git a/mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result b/mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result
index cc693bff752..0cc1e4b5057 100644
--- a/mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result
+++ b/mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result
@@ -16,4 +16,6 @@ reset master;
stop slave;
reset slave;
drop table if exists t;
+reset master;
End of the tests
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test b/mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test
index 4825090d6cd..86ee64b5e73 100644
--- a/mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test
+++ b/mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test
@@ -65,12 +65,11 @@ reset master;
--connection slave
stop slave;
reset slave;
-# The table t may have been created on the slave from binlog. It does not exist
-# on the master.
-# "May", as it depends on whether the SQL thread had time do do the CREATE
-# TABLE before we stopped.
---disable_warnings
+# Table was created from binlog, it may not be created if SQL thread is running
+# slowly and IO thread reaches incident before SQL thread applies it.
drop table if exists t;
---enable_warnings
+reset master;
--echo End of the tests
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/sys_vars/r/debug_basic.result b/mysql-test/suite/sys_vars/r/debug_basic.result
index 7104775fa08..a97ad65b40f 100644
--- a/mysql-test/suite/sys_vars/r/debug_basic.result
+++ b/mysql-test/suite/sys_vars/r/debug_basic.result
@@ -1,6 +1,6 @@
set session debug="L";
Warnings:
-Warning 1287 The syntax '@@debug' is deprecated and will be removed in MariaDB 10.1. Please use '@@debug_dbug' instead
+Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
select @@global.debug="1";
@@global.debug="1"
0
diff --git a/mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result b/mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result
index 935e23f9c3c..55e6f747a19 100644
--- a/mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result
+++ b/mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result
@@ -13,26 +13,26 @@ index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_inters
'#--------------------FN_DYNVARS_028_01------------------------#'
SET @@session.engine_condition_pushdown = 0;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SET @@session.engine_condition_pushdown = DEFAULT;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@session.engine_condition_pushdown;
@@session.engine_condition_pushdown
0
SET @@global.engine_condition_pushdown = 0;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SET @@global.engine_condition_pushdown = DEFAULT;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@global.engine_condition_pushdown;
@@global.engine_condition_pushdown
1
'#---------------------FN_DYNVARS_028_02-------------------------#'
SET engine_condition_pushdown = 1;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@engine_condition_pushdown;
@@engine_condition_pushdown
1
@@ -44,38 +44,38 @@ SELECT global.engine_condition_pushdown;
ERROR 42S02: Unknown table 'global' in field list
SET session engine_condition_pushdown = 0;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@session.engine_condition_pushdown;
@@session.engine_condition_pushdown
0
SET global engine_condition_pushdown = 0;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@global.engine_condition_pushdown;
@@global.engine_condition_pushdown
0
'#--------------------FN_DYNVARS_028_03------------------------#'
SET @@session.engine_condition_pushdown = 0;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@session.engine_condition_pushdown;
@@session.engine_condition_pushdown
0
SET @@session.engine_condition_pushdown = 1;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@session.engine_condition_pushdown;
@@session.engine_condition_pushdown
1
SET @@global.engine_condition_pushdown = 0;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@global.engine_condition_pushdown;
@@global.engine_condition_pushdown
0
SET @@global.engine_condition_pushdown = 1;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@global.engine_condition_pushdown;
@@global.engine_condition_pushdown
1
@@ -115,16 +115,16 @@ ERROR 42000: Variable 'engine_condition_pushdown' can't be set to the value of '
'#-------------------FN_DYNVARS_028_05----------------------------#'
SET @@global.engine_condition_pushdown = 0;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SET @@session.engine_condition_pushdown = 1;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@global.engine_condition_pushdown AS res_is_0;
res_is_0
0
SET @@global.engine_condition_pushdown = 0;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@session.engine_condition_pushdown AS res_is_1;
res_is_1
1
@@ -159,50 +159,50 @@ ON
'#---------------------FN_DYNVARS_028_08-------------------------#'
SET @@session.engine_condition_pushdown = OFF;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@session.engine_condition_pushdown;
@@session.engine_condition_pushdown
0
SET @@session.engine_condition_pushdown = ON;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@session.engine_condition_pushdown;
@@session.engine_condition_pushdown
1
SET @@global.engine_condition_pushdown = OFF;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@global.engine_condition_pushdown;
@@global.engine_condition_pushdown
0
SET @@global.engine_condition_pushdown = ON;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@global.engine_condition_pushdown;
@@global.engine_condition_pushdown
1
'#---------------------FN_DYNVARS_028_09----------------------#'
SET @@session.engine_condition_pushdown = TRUE;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@session.engine_condition_pushdown;
@@session.engine_condition_pushdown
1
SET @@session.engine_condition_pushdown = FALSE;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@session.engine_condition_pushdown;
@@session.engine_condition_pushdown
0
SET @@global.engine_condition_pushdown = TRUE;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@global.engine_condition_pushdown;
@@global.engine_condition_pushdown
1
SET @@global.engine_condition_pushdown = FALSE;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@global.engine_condition_pushdown;
@@global.engine_condition_pushdown
0
@@ -215,7 +215,7 @@ select @@session.engine_condition_pushdown,
0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=off index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=off
set @@session.engine_condition_pushdown = TRUE;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
select @@session.engine_condition_pushdown,
@@global.engine_condition_pushdown,
@@session.optimizer_switch, @@global.optimizer_switch;
@@ -223,7 +223,7 @@ select @@session.engine_condition_pushdown,
1 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=off index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=off
set @@session.engine_condition_pushdown = FALSE;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
select @@session.engine_condition_pushdown,
@@global.engine_condition_pushdown,
@@session.optimizer_switch, @@global.optimizer_switch;
@@ -231,7 +231,7 @@ select @@session.engine_condition_pushdown,
0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=off index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=off
set @@global.engine_condition_pushdown = TRUE;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
select @@session.engine_condition_pushdown,
@@global.engine_condition_pushdown,
@@session.optimizer_switch, @@global.optimizer_switch;
@@ -239,7 +239,7 @@ select @@session.engine_condition_pushdown,
0 1 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=off index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=off
set @@global.engine_condition_pushdown = FALSE;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
select @@session.engine_condition_pushdown,
@@global.engine_condition_pushdown,
@@session.optimizer_switch, @@global.optimizer_switch;
@@ -271,13 +271,13 @@ select @@session.engine_condition_pushdown,
0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=off index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=off
SET @@session.engine_condition_pushdown = @session_start_value;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@session.engine_condition_pushdown;
@@session.engine_condition_pushdown
0
SET @@global.engine_condition_pushdown = @global_start_value;
Warnings:
-Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MariaDB 10.1. Please use '@@optimizer_switch' instead
+Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead
SELECT @@global.engine_condition_pushdown;
@@global.engine_condition_pushdown
0
diff --git a/mysql-test/suite/sys_vars/r/ignore_db_dirs_basic.result b/mysql-test/suite/sys_vars/r/ignore_db_dirs_basic.result
new file mode 100644
index 00000000000..55d61800a39
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/ignore_db_dirs_basic.result
@@ -0,0 +1,49 @@
+select @@ignore_db_dirs;
+@@ignore_db_dirs
+e,lost+found,.mysqlgui,ignored_db
+# Check that SHOW DATABASES ignores all directories from
+# @@ignore_db_dirs and all directories with names starting
+# with '.'
+SHOW DATABASES;
+Database
+information_schema
+#mysql50#.otherdir
+mtr
+mysql
+performance_schema
+test
+USE ignored_db;
+ERROR 42000: Incorrect database name 'ignored_db'
+SELECT * FROM ignored_db.t1;
+ERROR 42000: Incorrect database name 'ignored_db'
+CALL ignored_db.p1();
+ERROR 42000: Incorrect database name 'ignored_db'
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME='ignored_db';
+COUNT(*)
+1
+CREATE DATABASE ignored_db;
+ERROR 42000: Incorrect database name 'ignored_db'
+CREATE DATABASE `lost+found`;
+USE `lost+found`;
+CREATE TABLE t1(id INT);
+INSERT INTO t1 VALUES (1), (2);
+SELECT * FROM `lost+found`.t1;
+id
+1
+2
+SHOW DATABASES;
+Database
+information_schema
+#mysql50#.otherdir
+lost+found
+mtr
+mysql
+performance_schema
+test
+DROP DATABASE `lost+found`;
+SET @@global.ignore_db_dirs = 'aha';
+ERROR HY000: Variable 'ignore_db_dirs' is a read only variable
+SET @@local.ignore_db_dirs = 'aha';
+ERROR HY000: Variable 'ignore_db_dirs' is a read only variable
+SET @@ignore_db_dirs = 'aha';
+ERROR HY000: Variable 'ignore_db_dirs' is a read only variable
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/r/innodb_changed_pages_limit_basic.result b/mysql-test/suite/sys_vars/r/innodb_changed_pages_limit_basic.result
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/innodb_changed_pages_limit_basic.result
diff --git a/mysql-test/suite/sys_vars/r/innodb_persistent_stats_root_page_basic.result b/mysql-test/suite/sys_vars/r/innodb_persistent_stats_root_page_basic.result
new file mode 100644
index 00000000000..38347ef8c68
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/innodb_persistent_stats_root_page_basic.result
@@ -0,0 +1,24 @@
+SELECT @@global.innodb_persistent_stats_root_page;
+@@global.innodb_persistent_stats_root_page
+0
+SELECT COUNT(@@global.innodb_persistent_stats_root_page);
+COUNT(@@global.innodb_persistent_stats_root_page)
+1
+SET @@global.innodb_persistent_stats_root_page=100;
+ERROR HY000: Variable 'innodb_persistent_stats_root_page' is a read only variable
+SELECT @@global.innodb_persistent_stats_root_page = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='innodb_persistent_stats_root_page';
+@@global.innodb_persistent_stats_root_page = VARIABLE_VALUE
+1
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='innodb_persistent_stats_root_page';
+COUNT(*)
+1
+SELECT @@innodb_persistent_stats_root_page = @@global.innodb_persistent_stats_root_page;
+@@innodb_persistent_stats_root_page = @@global.innodb_persistent_stats_root_page
+1
+SELECT COUNT(@@local.innodb_persistent_stats_root_page);
+ERROR HY000: Variable 'innodb_persistent_stats_root_page' is a GLOBAL variable
+SELECT COUNT(@@session.innodb_persistent_stats_root_page);
+ERROR HY000: Variable 'innodb_persistent_stats_root_page' is a GLOBAL variable
diff --git a/mysql-test/suite/sys_vars/r/innodb_track_changed_pages_basic.result b/mysql-test/suite/sys_vars/r/innodb_track_changed_pages_basic.result
new file mode 100644
index 00000000000..60f62a661f1
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/innodb_track_changed_pages_basic.result
@@ -0,0 +1,21 @@
+SELECT COUNT(@@GLOBAL.innodb_track_changed_pages);
+COUNT(@@GLOBAL.innodb_track_changed_pages)
+1
+SET @@GLOBAL.innodb_track_changed_pages=1;
+ERROR HY000: Variable 'innodb_track_changed_pages' is a read only variable
+SELECT @@GLOBAL.innodb_track_changed_pages = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='innodb_track_changed_pages';
+@@GLOBAL.innodb_track_changed_pages = VARIABLE_VALUE
+1
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'OFF'
+SELECT @@innodb_track_changed_pages = @@GLOBAL.innodb_track_changed_pages;
+@@innodb_track_changed_pages = @@GLOBAL.innodb_track_changed_pages
+1
+SELECT COUNT(@@SESSION.innodb_track_changed_pages);
+ERROR HY000: Variable 'innodb_track_changed_pages' is a GLOBAL variable
+SELECT COUNT(@@LOCAL.innodb_track_changed_pages);
+ERROR HY000: Variable 'innodb_track_changed_pages' is a GLOBAL variable
+SELECT innodb_track_changed_pages = @@SESSION.innodb_track_changed_pages;
+ERROR 42S22: Unknown column 'innodb_track_changed_pages' in 'field list'
diff --git a/mysql-test/suite/sys_vars/r/log_basic.result b/mysql-test/suite/sys_vars/r/log_basic.result
index d55346aa392..381fa523133 100644
--- a/mysql-test/suite/sys_vars/r/log_basic.result
+++ b/mysql-test/suite/sys_vars/r/log_basic.result
@@ -8,10 +8,10 @@ INIT_VALUE
1
SET @@global.log = ON;
Warnings:
-Warning 1287 The syntax '@@log' is deprecated and will be removed in MariaDB 10.1. Please use '@@general_log' instead
+Warning 1287 '@@log' is deprecated and will be removed in a future release. Please use '@@general_log' instead
SET global log = 0;
Warnings:
-Warning 1287 The syntax '@@log' is deprecated and will be removed in MariaDB 10.1. Please use '@@general_log' instead
+Warning 1287 '@@log' is deprecated and will be removed in a future release. Please use '@@general_log' instead
'#--------------------FN_DYNVARS_062_02-------------------------#'
SELECT VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
@@ -20,4 +20,4 @@ VARIABLE_VALUE
OFF
SET @@global.log= @start_log;
Warnings:
-Warning 1287 The syntax '@@log' is deprecated and will be removed in MariaDB 10.1. Please use '@@general_log' instead
+Warning 1287 '@@log' is deprecated and will be removed in a future release. Please use '@@general_log' instead
diff --git a/mysql-test/suite/sys_vars/r/log_slow_queries_basic.result b/mysql-test/suite/sys_vars/r/log_slow_queries_basic.result
index 9dbe565d488..2c47106ecb3 100644
--- a/mysql-test/suite/sys_vars/r/log_slow_queries_basic.result
+++ b/mysql-test/suite/sys_vars/r/log_slow_queries_basic.result
@@ -5,20 +5,20 @@ SELECT @start_value;
'#---------------------FN_DYNVARS_004_01-------------------------#'
SET @@global.log_slow_queries = DEFAULT;
Warnings:
-Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MariaDB 10.1. Please use '@@slow_query_log' instead
+Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead
SELECT @@global.log_slow_queries = 0;
@@global.log_slow_queries = 0
1
'#--------------------FN_DYNVARS_004_02------------------------#'
SET @@global.log_slow_queries = ON;
Warnings:
-Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MariaDB 10.1. Please use '@@slow_query_log' instead
+Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead
SELECT @@global.log_slow_queries;
@@global.log_slow_queries
1
SET @@global.log_slow_queries = OFF;
Warnings:
-Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MariaDB 10.1. Please use '@@slow_query_log' instead
+Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead
SELECT @@global.log_slow_queries;
@@global.log_slow_queries
0
@@ -61,7 +61,7 @@ IF(@@global.log_slow_queries, "ON", "OFF") = VARIABLE_VALUE
'#---------------------FN_DYNVARS_004_06----------------------#'
SET @@global.log_slow_queries = 0;
Warnings:
-Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MariaDB 10.1. Please use '@@slow_query_log' instead
+Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead
SELECT @@global.log_slow_queries;
@@global.log_slow_queries
0
@@ -72,7 +72,7 @@ IF(@@global.log_slow_queries, "ON", "OFF") = VARIABLE_VALUE
1
SET @@global.log_slow_queries = 1;
Warnings:
-Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MariaDB 10.1. Please use '@@slow_query_log' instead
+Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead
SELECT @@global.log_slow_queries;
@@global.log_slow_queries
1
@@ -84,7 +84,7 @@ IF(@@global.log_slow_queries, "ON", "OFF") = VARIABLE_VALUE
'#---------------------FN_DYNVARS_004_07----------------------#'
SET @@global.log_slow_queries = TRUE;
Warnings:
-Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MariaDB 10.1. Please use '@@slow_query_log' instead
+Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead
SELECT @@global.log_slow_queries;
@@global.log_slow_queries
1
@@ -95,7 +95,7 @@ IF(@@global.log_slow_queries, "ON", "OFF") = VARIABLE_VALUE
1
SET @@global.log_slow_queries = FALSE;
Warnings:
-Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MariaDB 10.1. Please use '@@slow_query_log' instead
+Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead
SELECT @@global.log_slow_queries;
@@global.log_slow_queries
0
@@ -107,7 +107,7 @@ IF(@@global.log_slow_queries, "ON", "OFF") = VARIABLE_VALUE
'#---------------------FN_DYNVARS_004_08----------------------#'
SET @@global.log_slow_queries = ON;
Warnings:
-Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MariaDB 10.1. Please use '@@slow_query_log' instead
+Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead
SELECT @@log_slow_queries = @@global.log_slow_queries;
@@log_slow_queries = @@global.log_slow_queries
1
@@ -126,7 +126,7 @@ SELECT log_slow_queries = @@session.log_slow_queries;
ERROR 42S22: Unknown column 'log_slow_queries' in 'field list'
SET @@global.log_slow_queries = @start_value;
Warnings:
-Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MariaDB 10.1. Please use '@@slow_query_log' instead
+Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead
SELECT @@global.log_slow_queries;
@@global.log_slow_queries
1
diff --git a/mysql-test/suite/sys_vars/r/multi_range_count_basic.result b/mysql-test/suite/sys_vars/r/multi_range_count_basic.result
index c50e947b967..67ea0f7d03a 100644
--- a/mysql-test/suite/sys_vars/r/multi_range_count_basic.result
+++ b/mysql-test/suite/sys_vars/r/multi_range_count_basic.result
@@ -9,101 +9,101 @@ SELECT @start_session_value;
'#--------------------FN_DYNVARS_090_01-------------------------#'
SET @@global.multi_range_count = 100;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SET @@global.multi_range_count = DEFAULT;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@global.multi_range_count;
@@global.multi_range_count
256
SET @@session.multi_range_count = 200;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SET @@session.multi_range_count = DEFAULT;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@session.multi_range_count;
@@session.multi_range_count
256
'#--------------------FN_DYNVARS_090_02-------------------------#'
SET @@global.multi_range_count = DEFAULT;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@global.multi_range_count = 256;
@@global.multi_range_count = 256
1
SET @@session.multi_range_count = DEFAULT;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@session.multi_range_count = 256;
@@session.multi_range_count = 256
1
'#--------------------FN_DYNVARS_090_03-------------------------#'
SET @@global.multi_range_count = 1;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@global.multi_range_count;
@@global.multi_range_count
1
SET @@global.multi_range_count = 60020;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@global.multi_range_count;
@@global.multi_range_count
60020
SET @@global.multi_range_count = 65535;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@global.multi_range_count;
@@global.multi_range_count
65535
SET @@global.multi_range_count = 4294967295;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@global.multi_range_count;
@@global.multi_range_count
4294967295
SET @@global.multi_range_count = 4294967294;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@global.multi_range_count;
@@global.multi_range_count
4294967294
'#--------------------FN_DYNVARS_090_04-------------------------#'
SET @@session.multi_range_count = 1;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@session.multi_range_count;
@@session.multi_range_count
1
SET @@session.multi_range_count = 50050;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@session.multi_range_count;
@@session.multi_range_count
50050
SET @@session.multi_range_count = 65535;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@session.multi_range_count;
@@session.multi_range_count
65535
SET @@session.multi_range_count = 4294967295;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@session.multi_range_count;
@@session.multi_range_count
4294967295
SET @@session.multi_range_count = 4294967294;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@session.multi_range_count;
@@session.multi_range_count
4294967294
'#------------------FN_DYNVARS_090_05-----------------------#'
SET @@global.multi_range_count = 0;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
Warning 1292 Truncated incorrect multi_range_count value: '0'
SELECT @@global.multi_range_count;
@@global.multi_range_count
@@ -114,7 +114,7 @@ SELECT @@global.multi_range_count;
4294967295
SET @@global.multi_range_count = -1024;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
Warning 1292 Truncated incorrect multi_range_count value: '-1024'
SELECT @@global.multi_range_count;
@@global.multi_range_count
@@ -135,7 +135,7 @@ SELECT @@global.multi_range_count;
4294967295
SET @@session.multi_range_count = 0;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
Warning 1292 Truncated incorrect multi_range_count value: '0'
SELECT @@session.multi_range_count;
@@session.multi_range_count
@@ -146,7 +146,7 @@ SELECT @@session.multi_range_count;
4294967295
SET @@session.multi_range_count = -1;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
Warning 1292 Truncated incorrect multi_range_count value: '-1'
SELECT @@session.multi_range_count;
@@session.multi_range_count
@@ -178,13 +178,13 @@ WHERE VARIABLE_NAME='multi_range_count';
'#------------------FN_DYNVARS_090_08-----------------------#'
SET @@global.multi_range_count = TRUE;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@global.multi_range_count;
@@global.multi_range_count
1
SET @@global.multi_range_count = FALSE;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
Warning 1292 Truncated incorrect multi_range_count value: '0'
SELECT @@global.multi_range_count;
@@global.multi_range_count
@@ -192,14 +192,14 @@ SELECT @@global.multi_range_count;
'#---------------------FN_DYNVARS_090_09----------------------#'
SET @@global.multi_range_count = 10;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@multi_range_count = @@global.multi_range_count;
@@multi_range_count = @@global.multi_range_count
0
'#---------------------FN_DYNVARS_090_10----------------------#'
SET @@multi_range_count = 100;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@multi_range_count = @@local.multi_range_count;
@@multi_range_count = @@local.multi_range_count
1
@@ -209,7 +209,7 @@ SELECT @@local.multi_range_count = @@session.multi_range_count;
'#---------------------FN_DYNVARS_090_11----------------------#'
SET multi_range_count = 1;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@multi_range_count;
@@multi_range_count
1
@@ -221,13 +221,13 @@ SELECT multi_range_count = @@session.multi_range_count;
ERROR 42S22: Unknown column 'multi_range_count' in 'field list'
SET @@global.multi_range_count = @start_global_value;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@global.multi_range_count;
@@global.multi_range_count
256
SET @@session.multi_range_count = @start_session_value;
Warnings:
-Warning 1287 The syntax '@@multi_range_count' is deprecated and will be removed in MariaDB 10.1. Please use '@@mrr_buffer_size' instead
+Warning 1287 '@@multi_range_count' is deprecated and will be removed in a future release. Please use '@@mrr_buffer_size' instead
SELECT @@session.multi_range_count;
@@session.multi_range_count
256
diff --git a/mysql-test/suite/sys_vars/r/rpl_recovery_rank_basic.result b/mysql-test/suite/sys_vars/r/rpl_recovery_rank_basic.result
index 1962cf86db1..251f428b449 100644
--- a/mysql-test/suite/sys_vars/r/rpl_recovery_rank_basic.result
+++ b/mysql-test/suite/sys_vars/r/rpl_recovery_rank_basic.result
@@ -5,29 +5,29 @@ SELECT @start_global_value;
'#--------------------FN_DYNVARS_142_01-------------------------#'
SET @@global.rpl_recovery_rank = 500000;
Warnings:
-Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MariaDB 10.1.
+Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release.
SET @@global.rpl_recovery_rank = DEFAULT;
Warnings:
-Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MariaDB 10.1.
+Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release.
SELECT @@global.rpl_recovery_rank;
@@global.rpl_recovery_rank
0
'#--------------------FN_DYNVARS_142_02-------------------------#'
SET @@global.rpl_recovery_rank = 0;
Warnings:
-Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MariaDB 10.1.
+Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release.
SELECT @@global.rpl_recovery_rank;
@@global.rpl_recovery_rank
0
SET @@global.rpl_recovery_rank = 1024;
Warnings:
-Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MariaDB 10.1.
+Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release.
SELECT @@global.rpl_recovery_rank;
@@global.rpl_recovery_rank
1024
SET @@global.rpl_recovery_rank = 123456789;
Warnings:
-Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MariaDB 10.1.
+Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release.
SELECT @@global.rpl_recovery_rank;
@@global.rpl_recovery_rank
123456789
@@ -53,21 +53,21 @@ ERROR HY000: Variable 'rpl_recovery_rank' is a GLOBAL variable and should be set
'#------------------FN_DYNVARS_142_04-----------------------#'
SET @@global.rpl_recovery_rank = -1;
Warnings:
-Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MariaDB 10.1.
+Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release.
Warning 1292 Truncated incorrect rpl_recovery_rank value: '-1'
SELECT @@global.rpl_recovery_rank;
@@global.rpl_recovery_rank
0
SET @@global.rpl_recovery_rank = -2147483648;
Warnings:
-Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MariaDB 10.1.
+Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release.
Warning 1292 Truncated incorrect rpl_recovery_rank value: '-2147483648'
SELECT @@global.rpl_recovery_rank;
@@global.rpl_recovery_rank
0
SET @@global.rpl_recovery_rank = -2147483649;
Warnings:
-Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MariaDB 10.1.
+Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release.
Warning 1292 Truncated incorrect rpl_recovery_rank value: '-2147483649'
SELECT @@global.rpl_recovery_rank;
@@global.rpl_recovery_rank
@@ -81,7 +81,7 @@ ERROR 42000: Incorrect argument type to variable 'rpl_recovery_rank'
'#------------------FN_DYNVARS_142_05-----------------------#'
SET @@global.rpl_recovery_rank = 3000;
Warnings:
-Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MariaDB 10.1.
+Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release.
SELECT @@global.rpl_recovery_rank = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='rpl_recovery_rank';
@@ -96,20 +96,20 @@ count(VARIABLE_VALUE)
'#------------------FN_DYNVARS_142_07-----------------------#'
SET @@global.rpl_recovery_rank = TRUE;
Warnings:
-Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MariaDB 10.1.
+Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release.
SELECT @@global.rpl_recovery_rank;
@@global.rpl_recovery_rank
1
SET @@global.rpl_recovery_rank = FALSE;
Warnings:
-Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MariaDB 10.1.
+Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release.
SELECT @@global.rpl_recovery_rank;
@@global.rpl_recovery_rank
0
'#---------------------FN_DYNVARS_001_08----------------------#'
SET @@global.rpl_recovery_rank = 512;
Warnings:
-Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MariaDB 10.1.
+Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release.
SELECT @@rpl_recovery_rank = @@global.rpl_recovery_rank;
@@rpl_recovery_rank = @@global.rpl_recovery_rank
1
@@ -123,10 +123,10 @@ SELECT @@rpl_recovery_rank;
512
SET global rpl_recovery_rank = 64;
Warnings:
-Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MariaDB 10.1.
+Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release.
SET @@global.rpl_recovery_rank = @start_global_value;
Warnings:
-Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MariaDB 10.1.
+Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release.
SELECT @@global.rpl_recovery_rank;
@@global.rpl_recovery_rank
0
diff --git a/mysql-test/suite/sys_vars/r/sql_big_selects_func.result b/mysql-test/suite/sys_vars/r/sql_big_selects_func.result
index 9ee26c71fe6..f96e28379a3 100644
--- a/mysql-test/suite/sys_vars/r/sql_big_selects_func.result
+++ b/mysql-test/suite/sys_vars/r/sql_big_selects_func.result
@@ -5,7 +5,7 @@ SET @session_max_join_size = @@SESSION.max_join_size;
SET @global_max_join_size = @@GLOBAL.max_join_size;
SET SQL_MAX_JOIN_SIZE=9;
Warnings:
-Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MariaDB 10.1. Please use '@@max_join_size' instead
+Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. Please use '@@max_join_size' instead
CREATE TEMPORARY TABLE t1(a varchar(20) not null, b varchar(20));
CREATE TEMPORARY TABLE t2(a varchar(20) null, b varchar(20));
INSERT INTO t1 VALUES('aa','bb');
diff --git a/mysql-test/suite/sys_vars/r/sql_max_join_size_basic.result b/mysql-test/suite/sys_vars/r/sql_max_join_size_basic.result
index dc1efd1794e..ffd526aa5d9 100644
--- a/mysql-test/suite/sys_vars/r/sql_max_join_size_basic.result
+++ b/mysql-test/suite/sys_vars/r/sql_max_join_size_basic.result
@@ -22,10 +22,10 @@ VARIABLE_NAME VARIABLE_VALUE
SQL_MAX_JOIN_SIZE 18446744073709551615
set global sql_max_join_size=10;
Warnings:
-Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MariaDB 10.1. Please use '@@max_join_size' instead
+Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. Please use '@@max_join_size' instead
set session sql_max_join_size=20;
Warnings:
-Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MariaDB 10.1. Please use '@@max_join_size' instead
+Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. Please use '@@max_join_size' instead
select @@global.sql_max_join_size;
@@global.sql_max_join_size
10
@@ -55,20 +55,20 @@ select @@sql_big_selects;
0
set sql_max_join_size=cast(-1 as unsigned int);
Warnings:
-Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MariaDB 10.1. Please use '@@max_join_size' instead
+Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. Please use '@@max_join_size' instead
Note 1105 Cast to unsigned converted negative integer to it's positive complement
select @@sql_big_selects;
@@sql_big_selects
1
set sql_max_join_size=100;
Warnings:
-Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MariaDB 10.1. Please use '@@max_join_size' instead
+Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. Please use '@@max_join_size' instead
select @@sql_big_selects;
@@sql_big_selects
0
SET @@global.sql_max_join_size = @start_global_value;
Warnings:
-Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MariaDB 10.1. Please use '@@max_join_size' instead
+Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. Please use '@@max_join_size' instead
SELECT @@global.sql_max_join_size;
@@global.sql_max_join_size
18446744073709551615
diff --git a/mysql-test/suite/sys_vars/r/sql_max_join_size_func.result b/mysql-test/suite/sys_vars/r/sql_max_join_size_func.result
index ac6aaf087ab..9460adad1b7 100644
--- a/mysql-test/suite/sys_vars/r/sql_max_join_size_func.result
+++ b/mysql-test/suite/sys_vars/r/sql_max_join_size_func.result
@@ -17,7 +17,7 @@ INSERT INTO t2 VALUES('aa4','bb');
'#--------------------FN_DYNVARS_161_01-------------------------#'
SET SESSION sql_max_join_size=9;
Warnings:
-Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MariaDB 10.1. Please use '@@max_join_size' instead
+Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. Please use '@@max_join_size' instead
SELECT * FROM t1 INNER JOIN t2 ON t1.a = t2.a;
ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay
Expected error The SELECT would examine more than MAX_JOIN_SIZE rows.
@@ -33,7 +33,7 @@ aa4 bb aa4 bb
This should work
SET SESSION sql_max_join_size=DEFAULT;
Warnings:
-Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MariaDB 10.1. Please use '@@max_join_size' instead
+Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. Please use '@@max_join_size' instead
DELETE FROM t2 WHERE a = 'aa4';
SELECT * FROM t1 INNER JOIN t2 ON t1.a = t2.a;
a b a b
@@ -45,7 +45,7 @@ This should work
'#----------------------------FN_DYNVARS_136_05-------------------------#'
SET GLOBAL sql_max_join_size = 4;
Warnings:
-Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MariaDB 10.1. Please use '@@max_join_size' instead
+Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. Please use '@@max_join_size' instead
** Connecting con_int1 using root **
** Connection con_int1 **
SELECT @@SESSION.sql_max_join_size;
@@ -54,7 +54,7 @@ SELECT @@SESSION.sql_max_join_size;
4 Expected
SET SESSION sql_max_join_size = 2;
Warnings:
-Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MariaDB 10.1. Please use '@@max_join_size' instead
+Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. Please use '@@max_join_size' instead
** Connecting con_int2 using root **
** Connection con_int2 **
SELECT @@SESSION.sql_max_join_size;
@@ -63,7 +63,7 @@ SELECT @@SESSION.sql_max_join_size;
4 Expected
SET SESSION sql_max_join_size = 10;
Warnings:
-Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MariaDB 10.1. Please use '@@max_join_size' instead
+Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. Please use '@@max_join_size' instead
** Connection con_int2 **
SELECT @@SESSION.sql_max_join_size;
@@SESSION.sql_max_join_size
@@ -82,10 +82,10 @@ SELECT @@GLOBAL.sql_max_join_size;
Disconnecting Connections con_int1, con_int2
SET @@SESSION.sql_max_join_size = @session_max_join_size;
Warnings:
-Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MariaDB 10.1. Please use '@@max_join_size' instead
+Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. Please use '@@max_join_size' instead
SET @@GLOBAL.sql_max_join_size = @global_max_join_size ;
Warnings:
-Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MariaDB 10.1. Please use '@@max_join_size' instead
+Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. Please use '@@max_join_size' instead
SET @@SESSION.sql_big_selects = @session_sql_big_selects;
DROP TABLE t1;
DROP TABLE t2;
diff --git a/mysql-test/suite/sys_vars/t/default_master_connection_basic.test b/mysql-test/suite/sys_vars/t/default_master_connection_basic.test
index 3ec39eb82a4..ba73e5ed4dd 100644
--- a/mysql-test/suite/sys_vars/t/default_master_connection_basic.test
+++ b/mysql-test/suite/sys_vars/t/default_master_connection_basic.test
@@ -5,6 +5,7 @@
#
--source include/load_sysvars.inc
+--source include/not_embedded.inc
#############################################################
# Save initial value #
diff --git a/mysql-test/suite/sys_vars/t/ignore_db_dirs_basic-master.opt b/mysql-test/suite/sys_vars/t/ignore_db_dirs_basic-master.opt
new file mode 100644
index 00000000000..30ee4f67284
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/ignore_db_dirs_basic-master.opt
@@ -0,0 +1,11 @@
+--ignore-db-dir=a
+--ignore-db-dir=b
+--ignore-db-dir=c
+--ignore-db-dir=
+--ignore-db-dir=d
+--ignore-db-dir x
+--ignore-db-dir=
+--ignore-db-dir=e
+--ignore-db-dir=lost+found
+--ignore-db-dir=.mysqlgui
+--ignore-db-dir=ignored_db
diff --git a/mysql-test/suite/sys_vars/t/ignore_db_dirs_basic.test b/mysql-test/suite/sys_vars/t/ignore_db_dirs_basic.test
new file mode 100644
index 00000000000..9544fc540f9
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/ignore_db_dirs_basic.test
@@ -0,0 +1,38 @@
+select @@ignore_db_dirs;
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+mkdir $MYSQLD_DATADIR/.mysqlgui;
+mkdir $MYSQLD_DATADIR/.otherdir;
+mkdir $MYSQLD_DATADIR/lost+found;
+mkdir $MYSQLD_DATADIR/ignored_db;
+--echo # Check that SHOW DATABASES ignores all directories from
+--echo # @@ignore_db_dirs and all directories with names starting
+--echo # with '.'
+SHOW DATABASES;
+--error ER_WRONG_DB_NAME
+USE ignored_db;
+--error ER_WRONG_DB_NAME
+SELECT * FROM ignored_db.t1;
+--error ER_WRONG_DB_NAME
+CALL ignored_db.p1();
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME='ignored_db';
+--error ER_WRONG_DB_NAME
+CREATE DATABASE ignored_db;
+CREATE DATABASE `lost+found`;
+USE `lost+found`;
+CREATE TABLE t1(id INT);
+INSERT INTO t1 VALUES (1), (2);
+SELECT * FROM `lost+found`.t1;
+SHOW DATABASES;
+DROP DATABASE `lost+found`;
+rmdir $MYSQLD_DATADIR/.mysqlgui;
+rmdir $MYSQLD_DATADIR/.otherdir;
+rmdir $MYSQLD_DATADIR/lost+found;
+rmdir $MYSQLD_DATADIR/ignored_db;
+
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SET @@global.ignore_db_dirs = 'aha';
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SET @@local.ignore_db_dirs = 'aha';
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SET @@ignore_db_dirs = 'aha';
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/sys_vars/t/innodb_changed_pages_limit_basic.test b/mysql-test/suite/sys_vars/t/innodb_changed_pages_limit_basic.test
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/innodb_changed_pages_limit_basic.test
diff --git a/mysql-test/suite/sys_vars/t/innodb_persistent_stats_root_page_basic.test b/mysql-test/suite/sys_vars/t/innodb_persistent_stats_root_page_basic.test
new file mode 100644
index 00000000000..2e216e10521
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/innodb_persistent_stats_root_page_basic.test
@@ -0,0 +1,26 @@
+--source include/have_debug.inc
+--source include/have_xtradb.inc
+
+SELECT @@global.innodb_persistent_stats_root_page;
+SELECT COUNT(@@global.innodb_persistent_stats_root_page);
+
+# Read-only variable
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SET @@global.innodb_persistent_stats_root_page=100;
+
+# Check if INFORMATION_SCHEMA agrees with the var
+SELECT @@global.innodb_persistent_stats_root_page = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='innodb_persistent_stats_root_page';
+
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='innodb_persistent_stats_root_page';
+
+# Check if accessing the var without GLOBAL points to the same
+SELECT @@innodb_persistent_stats_root_page = @@global.innodb_persistent_stats_root_page;
+
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT COUNT(@@local.innodb_persistent_stats_root_page);
+
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT COUNT(@@session.innodb_persistent_stats_root_page);
diff --git a/mysql-test/suite/sys_vars/t/innodb_track_changed_pages_basic.test b/mysql-test/suite/sys_vars/t/innodb_track_changed_pages_basic.test
new file mode 100644
index 00000000000..09d92a6bc2d
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/innodb_track_changed_pages_basic.test
@@ -0,0 +1,21 @@
+# Tests for innodb_track_changed_pages variable
+
+--source include/have_xtradb.inc
+
+SELECT COUNT(@@GLOBAL.innodb_track_changed_pages);
+
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SET @@GLOBAL.innodb_track_changed_pages=1;
+
+SELECT @@GLOBAL.innodb_track_changed_pages = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='innodb_track_changed_pages';
+
+SELECT @@innodb_track_changed_pages = @@GLOBAL.innodb_track_changed_pages;
+
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT COUNT(@@SESSION.innodb_track_changed_pages);
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT COUNT(@@LOCAL.innodb_track_changed_pages);
+--error ER_BAD_FIELD_ERROR
+SELECT innodb_track_changed_pages = @@SESSION.innodb_track_changed_pages;
diff --git a/mysql-test/suite/sys_vars/t/max_relay_log_size_basic.test b/mysql-test/suite/sys_vars/t/max_relay_log_size_basic.test
index 2e8983f5f01..05d0fd1be82 100644
--- a/mysql-test/suite/sys_vars/t/max_relay_log_size_basic.test
+++ b/mysql-test/suite/sys_vars/t/max_relay_log_size_basic.test
@@ -24,7 +24,7 @@
###############################################################################
--source include/load_sysvars.inc
-
+--source include/not_embedded.inc
###################################################################
# START OF max_relay_log_size TESTS #
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/func_str.test b/mysql-test/t/func_str.test
index bdb206be07b..d8d8f4538e1 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -1506,3 +1506,14 @@ SET @@global.max_allowed_packet:= @tmp_max;
--echo #
--echo # End of 5.5 tests
--echo #
+
+#
+# Bug#11765562 58545:
+# EXPORT_SET() CAN BE USED TO MAKE ENTIRE SERVER COMPLETELY UNRESPONSIVE
+#
+SELECT @tmp_max:= @@global.max_allowed_packet;
+SET @@global.max_allowed_packet=1024*1024*1024;
+SELECT @@global.max_allowed_packet;
+SELECT CHAR_LENGTH(EXPORT_SET(1,1,1,REPEAT(1,100000000)));
+SET @@global.max_allowed_packet:= @tmp_max;
+
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index dd1f335cf77..6a2d0a1c030 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..3e82403ddb5 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;
@@ -407,5 +428,44 @@ set optimizer_switch=@save_optimizer_switch;
DROP TABLE t1,t2;
+
+--echo #
+--echo # Bug mdev-3888: INSERT with UPDATE on duplicate keys
+--echo # with extended_keys=on
+--echo #
+
+CREATE TABLE t1 (
+c1 bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+c2 bigint(20) unsigned NOT NULL,
+c3 bigint(20) unsigned NOT NULL,
+c4 varchar(128) DEFAULT NULL,
+PRIMARY KEY (c1),
+UNIQUE KEY uq (c2,c3),
+KEY c3 (c3),
+KEY c4 (c4)
+) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
+
+
+set @save_optimizer_switch=@@optimizer_switch;
+
+set session optimizer_switch='extended_keys=off';
+INSERT INTO t1 (c2, c3, c4) VALUES (58291525, 2580, 'foobar')
+ ON DUPLICATE KEY UPDATE c4 = VALUES(c4);
+INSERT INTO t1 (c2, c3, c4) VALUES (58291525, 2580, 'foobar')
+ ON DUPLICATE KEY UPDATE c4 = VALUES(c4);
+
+DELETE FROM t1;
+
+set session optimizer_switch='extended_keys=on';
+INSERT INTO t1 (c2, c3, c4) VALUES (58291525, 2580, 'foobar')
+ ON DUPLICATE KEY UPDATE c4 = VALUES(c4);
+INSERT INTO t1 (c2, c3, c4) VALUES (58291525, 2580, 'foobar')
+ ON DUPLICATE KEY UPDATE c4 = VALUES(c4);
+
+set optimizer_switch=@save_optimizer_switch;
+
+DROP TABLE t1;
+
set optimizer_switch=@save_ext_key_optimizer_switch;
SET SESSION STORAGE_ENGINE=DEFAULT;
+
diff --git a/mysql-test/t/join_cache.test b/mysql-test/t/join_cache.test
index 003ffc8ff19..9b04c264faf 100644
--- a/mysql-test/t/join_cache.test
+++ b/mysql-test/t/join_cache.test
@@ -3587,5 +3587,54 @@ set optimizer_switch=@tmp_optimizer_switch;
DROP TABLE t1,t2,t3;
+--echo #
+--echo # Bug #1058071: LEFT JOIN using blobs
+--echo # (mdev-564) when join buffer size is small
+--echo #
+
+CREATE TABLE t1 (
+ col269 decimal(31,10) unsigned DEFAULT NULL,
+ col280 multipoint DEFAULT NULL,
+ col281 tinyint(1) DEFAULT NULL,
+ col282 time NOT NULL,
+ col284 datetime DEFAULT NULL,
+ col286 date DEFAULT NULL,
+ col287 datetime DEFAULT NULL,
+ col288 decimal(30,29) DEFAULT NULL,
+ col291 time DEFAULT NULL,
+ col292 time DEFAULT NULL
+) ENGINE=Aria;
+
+INSERT INTO t1 VALUES
+(0.0,PointFromText('POINT(9 0)'),0,'11:24:05','2013-04-14 21:30:28',NULL,'2011-12-20 06:00:34',9.9,'13:04:39',NULL),
+(0.0,NULL,127,'05:43:12','2012-09-05 06:15:27','2027-01-01','2011-10-29 10:48:29',0.0,'06:24:05','11:33:37'),
+(0.0,NULL,127,'12:54:41','2013-01-12 11:32:58','2011-11-03','2013-01-03 02:00:34',00,'11:54:15','20:19:15'),
+(0.0,PointFromText('POINT(9 0)'),0,'19:48:07','2012-07-16 15:45:25','2012-03-25','2013-09-07 17:21:52',0.5,'17:36:54','21:24:19'),
+(0.0,PointFromText('POINT(9 0)'),0,'03:43:48','2012-09-28 00:00:00','2012-06-26','2011-11-16 05:01:09',00,'01:25:42','19:30:06'),
+(0.0,LineStringFromText('LINESTRING(0 0,9 9,0 0,9 0,0 0)'),127,'11:33:21','2012-03-31 10:29:22','2012-10-10','2012-04-21 19:21:06',NULL,'05:13:22','09:48:34'),
+(NULL,PointFromText('POINT(9 0)'),127,'00:00:00','0000-00-00','2012-04-04 21:26:12','2013-03-04',0.0,'12:54:30',NULL),
+(NULL,PointFromText('POINT(9 0)'),1,'00:00:00','2013-05-01 22:37:49','2013-06-26','2012-09-22 17:31:03',0.0,'08:09:57','11:15:36');
+
+CREATE TABLE t2 (b int) ENGINE=Aria;
+INSERT INTO t2 VALUES (NULL);
+CREATE TABLE t3 (c int) ENGINE=Aria;
+INSERT INTO t3 VALUES (NULL);
+
+set @tmp_optimizer_switch=@@optimizer_switch;
+set optimizer_switch = 'outer_join_with_cache=on,join_cache_incremental=on';
+set join_buffer_size=128;
+
+EXPLAIN
+SELECT 1 AS c FROM t1 NATURAL LEFT JOIN t2 LEFT OUTER JOIN t3 ON 1
+ GROUP BY elt(t1.col282,1,t1.col280);
+
+SELECT 1 AS c FROM t1 NATURAL LEFT JOIN t2 LEFT OUTER JOIN t3 ON 1
+ GROUP BY elt(t1.col282,1,t1.col280);
+
+set join_buffer_size=default;
+set optimizer_switch=@tmp_optimizer_switch;
+
+DROP table t1,t2,t3;
+
# this must be the last command in the file
set @@optimizer_switch=@save_optimizer_switch;
diff --git a/mysql-test/t/mysqlshow.test b/mysql-test/t/mysqlshow.test
index 105e03c841b..5dba7fa5b85 100644
--- a/mysql-test/t/mysqlshow.test
+++ b/mysql-test/t/mysqlshow.test
@@ -1,7 +1,5 @@
# Can't run test of external client with embedded server
-- source include/not_embedded.inc
-# Test lists tables in Information_schema, and InnoDB adds some
--- source include/have_innodb.inc
# Don't test when thread_pool active
--source include/not_threadpool.inc
@@ -30,4 +28,18 @@ select "---- -v -v -t ------" as "";
--exec $MYSQL_SHOW test -v -v -t
DROP TABLE t1, t2;
+
+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
+
+#
+# Bug #19147: mysqlshow INFORMATION_SCHEMA does not work
+#
+--exec $MYSQL_SHOW information_schema
+--exec $MYSQL_SHOW INFORMATION_SCHEMA
+--exec $MYSQL_SHOW inf_rmation_schema
+}
+
--echo End of 5.0 tests
diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test
index f9abb75b7e9..61e0dcc7197 100644
--- a/mysql-test/t/openssl_1.test
+++ b/mysql-test/t/openssl_1.test
@@ -74,25 +74,31 @@ drop table t1;
#
--exec echo "this query should not execute;" > $MYSQLTEST_VARDIR/tmp/test.sql
# Handle that openssl gives different error messages from YaSSL.
---replace_regex /error:00000001:lib\(0\):func\(0\):reason\(1\)/ASN: bad other signature confirmation/
+#--replace_regex /error:00000001:lib\(0\):func\(0\):reason\(1\)/ASN: bad other signature confirmation/
+--replace_regex /2026 SSL connection error.*/2026 SSL connection error: xxxx/
--error 1
--exec $MYSQL_TEST --ssl-ca=$MYSQL_TEST_DIR/std_data/untrusted-cacert.pem --max-connect-retries=1 < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1
+--echo
#
# Test that we can't open connection to server if we are using
# a blank ca
#
---replace_regex /error:00000001:lib\(0\):func\(0\):reason\(1\)/ASN: bad other signature confirmation/
+#--replace_regex /error:00000001:lib\(0\):func\(0\):reason\(1\)/ASN: bad other signature confirmation/
+--replace_regex /2026 SSL connection error.*/2026 SSL connection error: xxxx/
--error 1
--exec $MYSQL_TEST --ssl-ca= --max-connect-retries=1 < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1
+--echo
#
# Test that we can't open connection to server if we are using
# a nonexistent ca file
#
---replace_regex /error:00000001:lib\(0\):func\(0\):reason\(1\)/ASN: bad other signature confirmation/
+#--replace_regex /error:00000001:lib\(0\):func\(0\):reason\(1\)/ASN: bad other signature confirmation/
+--replace_regex /2026 SSL connection error.*/2026 SSL connection error: xxxx/
--error 1
--exec $MYSQL_TEST --ssl-ca=nonexisting_file.pem --max-connect-retries=1 < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1
+--echo
#
# Test that we can't open connection to server if we are using
diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test
index adb7e361a4f..d573c3b5b8a 100644
--- a/mysql-test/t/order_by.test
+++ b/mysql-test/t/order_by.test
@@ -1851,3 +1851,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/order_fill_sortbuf-master.opt b/mysql-test/t/order_fill_sortbuf-master.opt
deleted file mode 100644
index 7b6ade99226..00000000000
--- a/mysql-test/t/order_fill_sortbuf-master.opt
+++ /dev/null
@@ -1 +0,0 @@
---sort_buffer=32804
diff --git a/mysql-test/t/order_fill_sortbuf.test b/mysql-test/t/order_fill_sortbuf.test
index 7a8779b6e55..33c09e34b91 100644
--- a/mysql-test/t/order_fill_sortbuf.test
+++ b/mysql-test/t/order_fill_sortbuf.test
@@ -7,6 +7,8 @@
drop table if exists t1,t2;
--enable_warnings
+set @@sort_buffer_size=32804;
+
CREATE TABLE `t1` (
`id` int(11) NOT NULL default '0',
`id2` int(11) NOT NULL default '0',
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/ps_1general.test b/mysql-test/t/ps_1general.test
index b9e84d8d7df..812b1b5ff94 100644
--- a/mysql-test/t/ps_1general.test
+++ b/mysql-test/t/ps_1general.test
@@ -827,6 +827,16 @@ execute stmt1 ;
drop table t1, t5, t9;
+--echo #
+--echo # testcase for bug#11765413 - Crash with dependent subquery and
+--echo # prepared statement
+create table t1 (c1 int);
+insert into t1 values (1);
+prepare stmt1 from "select 1 from t1 where 1=(select 1 from t1 having c1)";
+execute stmt1;
+drop prepare stmt1;
+drop table t1;
+
##### RULES OF THUMB TO PRESERVE THE SYSTEMATICS OF THE PS TEST CASES #####
#
# 0. You don't have the time to
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/select.test b/mysql-test/t/select.test
index 618d6eb3ed4..44eaf7130a7 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -4174,7 +4174,7 @@ INSERT INTO t5 VALUES (20),(5);
CREATE TABLE t6(f1 int);
INSERT INTO t6 VALUES (9),(7);
-SET SESSION join_buffer_size = 2048;
+SET SESSION join_buffer_size = 2176;
EXPLAIN
SELECT STRAIGHT_JOIN * FROM t2, (t1 LEFT JOIN (t3,t4) ON t1.f1 = t4.f1), t5, t6;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 9f35ecc43f1..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 #
@@ -5597,6 +5673,22 @@ set optimizer_switch=@mdev367_optimizer_switch;
DROP TABLE t1;
--echo #
+--echo # MDEV-521 single value subselect transformation problem
+--echo #
+CREATE TABLE t1 (f1 char(2), PRIMARY KEY (f1)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES ('u1'),('u2');
+
+SELECT a.* FROM t1 a WHERE ( SELECT EXISTS ( SELECT 1 FROM t1 b WHERE b.f1 = a.f1 ) );
+FLUSH TABLES;
+SELECT a.* FROM t1 a WHERE ( SELECT EXISTS ( SELECT 1 FROM t1 b WHERE b.f1 = a.f1 ) );
+
+# Cleanup
+DROP TABLE t1;
+
+--echo # return optimizer switch changed in the beginning of this test
+set optimizer_switch=@subselect_tmp;
+
+--echo #
--echo # lp:944706 Query with impossible or constant subquery in WHERE or HAVING is not
--echo # precomputed and thus not part of optimization
--echo #
@@ -5757,6 +5849,29 @@ EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP B
DROP TABLE t1,t2;
--echo #
+--echo # MDEV-435: Expensive subqueries may be evaluated during optimization in merge_key_fields
+--echo #
+
+CREATE TABLE t1 (a INT, KEY(a)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (8),(0);
+
+CREATE TABLE t2 (b INT, c VARCHAR(1)) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (4,'j'),(6,'v');
+
+CREATE TABLE t3 (d VARCHAR(1)) ENGINE=MyISAM;
+INSERT INTO t3 VALUES ('b'),('c');
+
+EXPLAIN
+SELECT * FROM t1
+WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10;
+
+SELECT * FROM t1
+WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10;
+
+drop table t1, t2, t3;
+
+
+--echo #
--echo # MDEV-405: Server crashes in test_if_skip_sort_order on EXPLAIN with GROUP BY and HAVING in EXISTS subquery
--echo #
CREATE TABLE t1 (a INT, KEY(a));
diff --git a/mysql-test/t/subselect2.test b/mysql-test/t/subselect2.test
index 8d2939bdb53..68894ad18cb 100644
--- a/mysql-test/t/subselect2.test
+++ b/mysql-test/t/subselect2.test
@@ -203,5 +203,118 @@ SET optimizer_switch=@tmp_optimizer_switch;
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));
+INSERT INTO t1 VALUES (9,0), (7,1), (1,9), (7,3), (2,1);
+
+CREATE TABLE t2 (a int, b int, INDEX idx(a));
+INSERT INTO t2 VALUES (2,1), (6,4), (7,6), (9,4);
+
+CREATE TABLE t3 (a int, b int);
+INSERT INTO t3 VALUES (1,0), (1,1), (1,3);
+
+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);
+
+
+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/mysql-test/t/view.test b/mysql-test/t/view.test
index c4881f7df3f..d299718b54a 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -4381,6 +4381,46 @@ SELECT * FROM v1, t2
DROP VIEW v1;
DROP TABLE t1,t2,t3,t4;
+--echo #
+--echo # LP bug #823237: dependent subquery with LEFT JOIN
+--echo # referencing view in WHERE
+--echo # (duplicate of LP bug #823189)
+--echo #
+
+CREATE TABLE t1 (a int);
+
+CREATE TABLE t2 ( b int, d int, e int);
+INSERT INTO t2 VALUES (7,8,0);
+
+CREATE TABLE t3 ( c int);
+INSERT INTO t3 VALUES (0);
+
+CREATE TABLE t4 (a int, b int, c int);
+INSERT INTO t4 VALUES (93,1,0), (95,NULL,0);
+
+CREATE VIEW v4 AS SELECT * FROM t4;
+
+EXPLAIN EXTENDED
+SELECT * FROM t3 , t4
+ WHERE t4.c <= (SELECT t2.e FROM t2 LEFT JOIN t1 ON ( t1.a = t2.d )
+ WHERE t2.b > t4.b);
+SELECT * FROM t3 , t4
+ WHERE t4.c <= (SELECT t2.e FROM t2 LEFT JOIN t1 ON ( t1.a = t2.d )
+ WHERE t2.b > t4.b);
+
+
+EXPLAIN EXTENDED
+SELECT * FROM t3, v4
+ WHERE v4.c <= (SELECT t2.e FROM t2 LEFT JOIN t1 ON ( t1.a = t2.d )
+ WHERE t2.b > v4.b);
+
+SELECT * FROM t3, v4
+ WHERE v4.c <= (SELECT t2.e FROM t2 LEFT JOIN t1 ON ( t1.a = t2.d )
+ WHERE t2.b > v4.b);
+
+DROP VIEW v4;
+DROP TABLE t1,t2,t3,t4;
+
#
# Bug#9801 (Views: imperfect error message)
#
@@ -4661,8 +4701,89 @@ create algorithm=MERGE view v2 as select 2 as id, id is null as bbb, id as iddqd
select t1.*, v2.* from t1 left join v2 on t1.id = v2.id;
drop view v2;
drop table t1,t2;
+
+--echo #
+--echo # MDEV-589 (LP BUG#1007647) :
+--echo # Assertion `vcol_table == 0 || vcol_table == table' failed in
+--echo # fill_record(THD*, List<Item>&, List<Item>&, bool)
+--echo #
+CREATE TABLE t1 (f1 INT, f2 INT);
+CREATE TABLE t2 (f1 INT, f2 INT);
+CREATE ALGORITHM=MERGE VIEW v1 AS SELECT a1.f1, a2.f2 FROM t1 AS a1, t1 AS a2;
+CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM v1;
+CREATE ALGORITHM=MERGE VIEW v3 AS SELECT a1.f1, a2.f2 FROM t1 AS a1, t2 AS a2;
+CREATE ALGORITHM=MERGE VIEW v4 AS SELECT * FROM v3;
+--error ER_VIEW_MULTIUPDATE
+INSERT INTO v3 (f1, f2) VALUES (1, 2);
+--error ER_VIEW_MULTIUPDATE
+INSERT INTO v1 (f1, f2) VALUES (1, 2);
+--error ER_VIEW_MULTIUPDATE
+INSERT INTO v4 (f1, f2) VALUES (1, 2);
+--error ER_VIEW_MULTIUPDATE
+INSERT INTO v2 (f1, f2) VALUES (1, 2);
+drop view v4,v3,v2,v1;
+drop table t1,t2;
+
+--echo #
+--echo # MDEV-3799 fix of above bugfix (MDEV-589)
+--echo # Wrong result (NULLs instead of real values) with RIGHT JOIN
+--echo # in a FROM subquery and derived_merge=on
+--echo #
+
+CREATE TABLE t1 (f1 INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (4),(6);
+
+CREATE TABLE t2 (f2 INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (7),(8);
+
+SELECT * FROM (
+ SELECT * FROM t1 RIGHT JOIN t2 ON f1 = f2
+) AS alias;
+
+SELECT * FROM (
+ SELECT * FROM t2 LEFT JOIN t1 ON f1 = f2
+) AS alias;
+
+drop tables t1,t2;
+
+
--echo # -----------------------------------------------------------------
--echo # -- End of 5.3 tests.
--echo # -----------------------------------------------------------------
+--echo #
+--echo # MDEV-3874: Server crashes in Item_field::print on a SELECT
+--echo # from a MERGE view with materialization+semijoin, subquery, ORDER BY
+--echo #
+SET @save_optimizer_switch_MDEV_3874=@@optimizer_switch;
+
+SET optimizer_switch = 'materialization=on,semijoin=on';
+
+CREATE TABLE t1 (a INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1),(7);
+
+CREATE TABLE t2 (b INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (4),(6);
+
+CREATE TABLE t3 (c INT) ENGINE=MyISAM;
+INSERT INTO t3 VALUES (1),(2);
+
+
+CREATE ALGORITHM=MERGE VIEW v1 AS SELECT
+( SELECT a FROM t1 WHERE ( 1, 1 ) IN (
+SELECT b, c FROM t2, t3 HAVING c > 2 ) ) AS field1,
+b + c AS field2
+FROM t2, t3 AS table1
+GROUP BY field1, field2 ORDER BY field1;
+
+SELECT * FROM v1;
+
+drop view v1;
+drop table t1,t2,t3;
+SET optimizer_switch=@save_optimizer_switch_MDEV_3874;
+
+--echo # -----------------------------------------------------------------
+--echo # -- End of 5.5 tests.
+--echo # -----------------------------------------------------------------
+
SET optimizer_switch=@save_optimizer_switch;
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index f9e51e48189..02e5c5373ae 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -1527,8 +1527,13 @@ int _my_b_get(IO_CACHE *info)
int _my_b_write(register IO_CACHE *info, const uchar *Buffer, size_t Count)
{
size_t rest_length,length;
+ my_off_t pos_in_file= info->pos_in_file;
- if (info->pos_in_file+info->buffer_length > info->end_of_file)
+ DBUG_EXECUTE_IF("simulate_huge_load_data_file",
+ {
+ pos_in_file=(my_off_t)(5000000000ULL);
+ });
+ if (pos_in_file+info->buffer_length > info->end_of_file)
{
my_errno=errno=EFBIG;
return info->error = -1;
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/mysys/my_getopt.c b/mysys/my_getopt.c
index c1b0a129a30..7905ad90877 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -720,6 +720,11 @@ static int setval(const struct my_option *opts, void *value, char *argument,
}
*(ulong*)value= arg;
}
+ else if (type < 0)
+ {
+ res= EXIT_AMBIGUOUS_OPTION;
+ goto ret;
+ }
else
*(ulong*)value= type - 1;
}
diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c
index 846a90cc127..402520990b6 100644
--- a/mysys/stacktrace.c
+++ b/mysys/stacktrace.c
@@ -654,7 +654,6 @@ void my_print_stacktrace(uchar* unused1, ulong unused2)
&(package.sym));
have_source= SymGetLineFromAddr64(hProcess, addr, &line_offset, &line);
- my_safe_printf_stderr("%p ", (uintptr_t)addr);
if(have_module)
{
const char *base_image_name= my_basename(module.ImageName);
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/auth_pam/mapper/pam_user_map.c b/plugin/auth_pam/mapper/pam_user_map.c
new file mode 100644
index 00000000000..e73ab6de544
--- /dev/null
+++ b/plugin/auth_pam/mapper/pam_user_map.c
@@ -0,0 +1,93 @@
+/*
+ Pam module to change user names arbitrarily in the pam stack.
+
+ Compile as
+
+ gcc pam_user_map.c -shared -lpam -fPIC -o pam_user_map.so
+
+ Install as appropriate (for example, in /lib/security/).
+ Add to your /etc/pam.d/mysql (preferrably, at the end) this line:
+=========================================================
+auth required pam_user_map.so
+=========================================================
+
+ And create /etc/security/user_map.conf with the desired mapping
+ in the format: orig_user_name: mapped_user_name
+=========================================================
+#comments and emty lines are ignored
+john: jack
+bob: admin
+top: accounting
+=========================================================
+
+*/
+
+#include <stdio.h>
+#include <syslog.h>
+#include <security/pam_modules.h>
+
+#define FILENAME "/etc/security/user_map.conf"
+#define skip(what) while (*s && (what)) s++
+
+int pam_sm_authenticate(pam_handle_t *pamh, int flags,
+ int argc, const char *argv[])
+{
+ int pam_err, line= 0;
+ const char *username;
+ char buf[256];
+ FILE *f;
+
+ f= fopen(FILENAME, "r");
+ if (f == NULL)
+ {
+ pam_syslog(pamh, LOG_ERR, "Cannot open '%s'\n", FILENAME);
+ return PAM_SYSTEM_ERR;
+ }
+
+ pam_err = pam_get_item(pamh, PAM_USER, (const void**)&username);
+ if (pam_err != PAM_SUCCESS)
+ goto ret;
+
+ while (fgets(buf, sizeof(buf), f) != NULL)
+ {
+ char *s= buf, *from, *to, *end_from, *end_to;
+ line++;
+
+ skip(isspace(*s));
+ if (*s == '#' || *s == 0) continue;
+ from= s;
+ skip(isalnum(*s) || (*s == '_'));
+ end_from= s;
+ skip(isspace(*s));
+ if (end_from == from || *s++ != ':') goto syntax_error;
+ skip(isspace(*s));
+ to= s;
+ skip(isalnum(*s) || (*s == '_'));
+ end_to= s;
+ if (end_to == to) goto syntax_error;
+
+ *end_from= *end_to= 0;
+ if (strcmp(username, from) == 0)
+ {
+ pam_err= pam_set_item(pamh, PAM_USER, to);
+ goto ret;
+ }
+ }
+ pam_err= PAM_SUCCESS;
+ goto ret;
+
+syntax_error:
+ pam_syslog(pamh, LOG_ERR, "Syntax error at %s:%d", FILENAME, line);
+ pam_err= PAM_SYSTEM_ERR;
+ret:
+ fclose(f);
+ return pam_err;
+}
+
+int pam_sm_setcred(pam_handle_t *pamh, int flags,
+ int argc, const char *argv[])
+{
+
+ return PAM_SUCCESS;
+}
+
diff --git a/plugin/auth_pam/testing/pam_mariadb_mtr.c b/plugin/auth_pam/testing/pam_mariadb_mtr.c
index 8ad1e18e696..473ec246fe0 100644
--- a/plugin/auth_pam/testing/pam_mariadb_mtr.c
+++ b/plugin/auth_pam/testing/pam_mariadb_mtr.c
@@ -12,7 +12,7 @@
Create /etc/pam.d/mariadb_mtr with
=========================================================
auth required pam_mariadb_mtr.so pam_test
-account required pam_mariadb_mtr.so
+account required pam_permit.so
=========================================================
*/
@@ -23,9 +23,8 @@ account required pam_mariadb_mtr.so
#define N 3
-PAM_EXTERN int
-pam_sm_authenticate(pam_handle_t *pamh, int flags,
- int argc, const char *argv[])
+int pam_sm_authenticate(pam_handle_t *pamh, int flags,
+ int argc, const char *argv[])
{
struct pam_conv *conv;
struct pam_response *resp = 0;
@@ -71,17 +70,8 @@ ret:
return retval;
}
-PAM_EXTERN int
-pam_sm_setcred(pam_handle_t *pamh, int flags,
- int argc, const char *argv[])
-{
-
- return PAM_SUCCESS;
-}
-
-PAM_EXTERN int
-pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
- int argc, const char *argv[])
+int pam_sm_setcred(pam_handle_t *pamh, int flags,
+ int argc, const char *argv[])
{
return PAM_SUCCESS;
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_install_db.sh b/scripts/mysql_install_db.sh
index 0ed94d0ffa3..91780570194 100644
--- a/scripts/mysql_install_db.sh
+++ b/scripts/mysql_install_db.sh
@@ -257,7 +257,7 @@ fi
# Now we can get arguments from the groups [mysqld] and [mysql_install_db]
# in the my.cfg file, then re-run to merge with command line arguments.
-parse_arguments `$print_defaults $defaults mysqld mariadb mysql_install_db client-server`
+parse_arguments `"$print_defaults" $defaults mysqld mariadb mysql_install_db client-server`
parse_arguments PICK-ARGS-FROM-ARGV "$@"
# Configure paths to support files
@@ -307,7 +307,7 @@ fill_help_tables="$pkgdatadir/fill_help_tables.sql"
create_system_tables="$pkgdatadir/mysql_system_tables.sql"
fill_system_tables="$pkgdatadir/mysql_system_tables_data.sql"
-for f in $fill_help_tables $create_system_tables $fill_system_tables
+for f in "$fill_help_tables" "$create_system_tables" "$fill_system_tables"
do
if test ! -f "$f"
then
@@ -330,22 +330,25 @@ then
exit 1
fi
mysqld_opt="--lc-messages-dir=$langdir/.."
+else
+ mysqld_opt="--lc-messages=en_US"
fi
+
# Try to determine the hostname
hostname=`@HOSTNAME@`
# Check if hostname is valid
if test "$cross_bootstrap" -eq 0 -a "$in_rpm" -eq 0 -a "$force" -eq 0
then
- resolved=`$extra_bindir/resolveip $hostname 2>&1`
+ resolved=`"$extra_bindir/resolveip" $hostname 2>&1`
if test $? -ne 0
then
- resolved=`$extra_bindir/resolveip localhost 2>&1`
+ resolved=`"$extra_bindir/resolveip" localhost 2>&1`
if test $? -ne 0
then
echo "Neither host '$hostname' nor 'localhost' could be looked up with"
- echo "$extra_bindir/resolveip"
+ echo "'$extra_bindir/resolveip'"
echo "Please configure the 'hostname' command to return a correct"
echo "hostname."
echo "If you want to solve this at a later stage, restart this script"
@@ -368,21 +371,21 @@ then
fi
# Create database directories
-for dir in $ldata $ldata/mysql $ldata/test
+for dir in "$ldata" "$ldata/mysql" "$ldata/test"
do
- if test ! -d $dir
+ if test ! -d "$dir"
then
- if ! `mkdir -p $dir`
+ if ! `mkdir -p "$dir"`
then
echo "Fatal error Can't create database directory '$dir'"
link_to_help
exit 1
fi
- chmod 700 $dir
+ chmod 700 "$dir"
fi
if test -n "$user"
then
- chown $user $dir
+ chown $user "$dir"
if test $? -ne 0
then
echo "Cannot change ownership of the database directories to the '$user'"
@@ -409,15 +412,19 @@ fi
# Configure mysqld command line
mysqld_bootstrap="${MYSQLD_BOOTSTRAP-$mysqld}"
-mysqld_install_cmd_line="$mysqld_bootstrap $defaults $mysqld_opt --bootstrap \
- --basedir=$basedir --datadir=$ldata --log-warnings=0 --loose-skip-innodb \
+mysqld_install_cmd_line()
+{
+ "$mysqld_bootstrap" $defaults "$mysqld_opt" --bootstrap \
+ "--basedir=$basedir" "--datadir=$ldata" --log-warnings=0 --loose-skip-innodb \
--loose-skip-ndbcluster --loose-skip-pbxt $args --max_allowed_packet=8M \
--default-storage-engine=myisam \
- --net_buffer_length=16K"
+ --net_buffer_length=16K
+}
+
# Create the system and help tables by passing them to "mysqld --bootstrap"
s_echo "Installing MariaDB/MySQL system tables in '$ldata' ..."
-if { echo "use mysql;"; cat $create_system_tables $fill_system_tables; } | eval "$filter_cmd_line" | $mysqld_install_cmd_line > /dev/null
+if { echo "use mysql;"; cat "$create_system_tables" "$fill_system_tables"; } | eval "$filter_cmd_line" | mysqld_install_cmd_line > /dev/null
then
s_echo "OK"
else
@@ -452,7 +459,7 @@ else
fi
s_echo "Filling help tables..."
-if { echo "use mysql;"; cat $fill_help_tables; } | $mysqld_install_cmd_line > /dev/null
+if { echo "use mysql;"; cat "$fill_help_tables"; } | mysqld_install_cmd_line > /dev/null
then
s_echo "OK"
else
@@ -474,11 +481,11 @@ then
echo "PLEASE REMEMBER TO SET A PASSWORD FOR THE MariaDB root USER !"
echo "To do so, start the server, then issue the following commands:"
echo
- echo "$bindir/mysqladmin -u root password 'new-password'"
- echo "$bindir/mysqladmin -u root -h $hostname password 'new-password'"
+ echo "'$bindir/mysqladmin' -u root password 'new-password'"
+ echo "'$bindir/mysqladmin' -u root -h $hostname password 'new-password'"
echo
echo "Alternatively you can run:"
- echo "$bindir/mysql_secure_installation"
+ echo "'$bindir/mysql_secure_installation'"
echo
echo "which will also give you the option of removing the test"
echo "databases and anonymous user created by default. This is"
@@ -491,14 +498,14 @@ then
then
echo
echo "You can start the MariaDB daemon with:"
- echo "cd $basedir ; $bindir/mysqld_safe --datadir=$ldata"
+ echo "cd '$basedir' ; $bindir/mysqld_safe --datadir='$ldata'"
echo
echo "You can test the MariaDB daemon with mysql-test-run.pl"
- echo "cd $basedir/mysql-test ; perl mysql-test-run.pl"
+ echo "cd '$basedir/mysql-test' ; perl mysql-test-run.pl"
fi
echo
- echo "Please report any problems with the $scriptdir/mysqlbug script!"
+ echo "Please report any problems with the '$scriptdir/mysqlbug' script!"
echo
echo "The latest information about MariaDB is available at http://mariadb.org/."
echo "You can find additional information about the MySQL part at:"
diff --git a/scripts/mysql_secure_installation.pl.in b/scripts/mysql_secure_installation.pl.in
index ca39420952b..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, 2010, 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
@@ -28,7 +28,7 @@ my $mysql; # How to call the mysql client
my $rootpass = "";
-$SIG{QUIT} = $SIG{INT} = sub {
+$SIG{QUIT} = $SIG{INT} = $SIG{TERM} = $SIG{ABRT} = $SIG{HUP} = sub {
print "\nAborting!\n\n";
echo_on();
cleanup();
@@ -242,7 +242,11 @@ sub reload_privilege_tables {
}
sub cleanup {
- unlink($config,$command);
+ print "Cleaning up...\n";
+
+ foreach my $file ($config, $command) {
+ unlink $file or warn "Warning: Could not unlink $file: $!\n";
+ }
}
diff --git a/scripts/mysql_secure_installation.sh b/scripts/mysql_secure_installation.sh
index 772a9d8b1d8..9e9bce9fa87 100644
--- a/scripts/mysql_secure_installation.sh
+++ b/scripts/mysql_secure_installation.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-# Copyright (c) 2002, 2010, 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
@@ -18,7 +18,7 @@
config=".my.cnf.$$"
command=".mysql.$$"
-trap "interrupt" 2
+trap "interrupt" 1 2 3 6 15
rootpass=""
echo_n=
@@ -286,13 +286,16 @@ set_root_password() {
if [ $? -eq 0 ]; then
echo "Password updated successfully!"
echo "Reloading privilege tables.."
- reload_privilege_tables || exit 1
+ reload_privilege_tables
+ if [ $? -eq 1 ]; then
+ clean_and_exit
+ fi
echo
rootpass=$password1
make_config
else
echo "Password update failed!"
- exit 1
+ clean_and_exit
fi
return 0
@@ -304,7 +307,7 @@ remove_anonymous_users() {
echo " ... Success!"
else
echo " ... Failed!"
- exit 1
+ clean_and_exit
fi
return 0
@@ -364,6 +367,11 @@ cleanup() {
rm -f $config $command
}
+# Remove the files before exiting.
+clean_and_exit() {
+ cleanup
+ exit 1
+}
# The actual script starts here
diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh
index 48aefbd8c49..1ef743725e5 100644
--- a/scripts/mysqlhotcopy.sh
+++ b/scripts/mysqlhotcopy.sh
@@ -272,23 +272,28 @@ if ( defined $opt{regexp} ) {
}
}
-# --- get list of tables to hotcopy ---
+# --- get list of tables and views to hotcopy ---
my $hc_locks = "";
my $hc_tables = "";
+my $hc_base_tables = "";
+my $hc_views = "";
+my $num_base_tables = 0;
+my $num_views = 0;
my $num_tables = 0;
my $num_files = 0;
foreach my $rdb ( @db_desc ) {
my $db = $rdb->{src};
- my @dbh_tables = get_list_of_tables( $db );
+ my @dbh_base_tables = get_list_of_tables( $db );
+ my @dbh_views = get_list_of_views( $db );
## filter out certain system non-lockable tables.
## keep in sync with mysqldump.
if ($db =~ m/^mysql$/i)
{
- @dbh_tables = grep
- { !/^(apply_status|schema|general_log|slow_log)$/ } @dbh_tables
+ @dbh_base_tables = grep
+ { !/^(apply_status|schema|general_log|slow_log)$/ } @dbh_base_tables
}
## generate regex for tables/files
@@ -303,11 +308,20 @@ foreach my $rdb ( @db_desc ) {
## filter (out) tables specified in t_regex
print "Filtering tables with '$t_regex'\n" if $opt{debug};
- @dbh_tables = ( $negated
- ? grep { $_ !~ $t_regex } @dbh_tables
- : grep { $_ =~ $t_regex } @dbh_tables );
+ @dbh_base_tables = ( $negated
+ ? grep { $_ !~ $t_regex } @dbh_base_tables
+ : grep { $_ =~ $t_regex } @dbh_base_tables );
+
+ ## filter (out) views specified in t_regex
+ print "Filtering tables with '$t_regex'\n" if $opt{debug};
+ @dbh_views = ( $negated
+ ? grep { $_ !~ $t_regex } @dbh_views
+ : grep { $_ =~ $t_regex } @dbh_views );
}
+ ## Now concatenate the base table and view arrays.
+ my @dbh_tables = (@dbh_base_tables, @dbh_views);
+
## get list of files to copy
my $db_dir = "$datadir/$db";
opendir(DBDIR, $db_dir )
@@ -347,15 +361,25 @@ foreach my $rdb ( @db_desc ) {
$rdb->{files} = [ @db_files ];
$rdb->{index} = [ @index_files ];
- my @hc_tables = map { quote_names("$db.$_") } @dbh_tables;
+ my @hc_base_tables = map { quote_names("$db.$_") } @dbh_base_tables;
+ my @hc_views = map { quote_names("$db.$_") } @dbh_views;
+
+ my @hc_tables = (@hc_base_tables, @hc_views);
$rdb->{tables} = [ @hc_tables ];
$hc_locks .= ", " if ( length $hc_locks && @hc_tables );
$hc_locks .= join ", ", map { "$_ READ" } @hc_tables;
- $hc_tables .= ", " if ( length $hc_tables && @hc_tables );
- $hc_tables .= join ", ", @hc_tables;
- $num_tables += scalar @hc_tables;
+ $hc_base_tables .= ", " if ( length $hc_base_tables && @hc_base_tables );
+ $hc_base_tables .= join ", ", @hc_base_tables;
+ $hc_views .= ", " if ( length $hc_views && @hc_views );
+ $hc_views .= join " READ, ", @hc_views;
+
+ @hc_tables = (@hc_base_tables, @hc_views);
+
+ $num_base_tables += scalar @hc_base_tables;
+ $num_views += scalar @hc_views;
+ $num_tables += $num_base_tables + $num_views;
$num_files += scalar @{$rdb->{files}};
}
@@ -467,7 +491,10 @@ if ( $opt{dryrun} ) {
print "FLUSH TABLES /*!32323 $hc_tables */\n";
}
else {
- print "FLUSH TABLES $hc_tables WITH READ LOCK\n";
+ # Lock base tables and views separately.
+ print "FLUSH TABLES $hc_base_tables WITH READ LOCK\n"
+ if ( $hc_base_tables );
+ print "LOCK TABLES $hc_views READ\n" if ( $hc_views );
}
print "FLUSH LOGS\n" if ( $opt{flushlog} );
@@ -484,16 +511,24 @@ else {
# flush tables to make on-disk copy up to date
$start = time;
$dbh->do("FLUSH TABLES /*!32323 $hc_tables */");
+ printf "Flushed tables ($hc_tables) in %d seconds.\n", time-$start unless $opt{quiet};
}
else {
- $dbh->do("FLUSH TABLES $hc_tables WITH READ LOCK");
- printf "Locked $num_tables tables in %d seconds.\n", time-$start unless $opt{quiet};
- $hc_started = time; # count from time lock is granted
+ # Lock base tables and views separately, as 'FLUSH TABLES <tbl_name>
+ # ... WITH READ LOCK' (introduced in 5.5) would fail for views.
+ # Also, flush tables to make on-disk copy up to date
+ $dbh->do("FLUSH TABLES $hc_base_tables WITH READ LOCK")
+ if ( $hc_base_tables );
+ printf "Flushed $num_base_tables tables with read lock ($hc_base_tables) in %d seconds.\n",
+ time-$start unless $opt{quiet};
- # flush tables to make on-disk copy up to date
$start = time;
+ $dbh->do("LOCK TABLES $hc_views READ") if ( $hc_views );
+ printf "Locked $num_views views ($hc_views) in %d seconds.\n",
+ time-$start unless $opt{quiet};
+
+ $hc_started = time; # count from time lock is granted
}
- printf "Flushed tables ($hc_tables) in %d seconds.\n", time-$start unless $opt{quiet};
$dbh->do( "FLUSH LOGS" ) if ( $opt{flushlog} );
$dbh->do( "RESET MASTER" ) if ( $opt{resetmaster} );
$dbh->do( "RESET SLAVE" ) if ( $opt{resetslave} );
@@ -802,14 +837,29 @@ sub get_list_of_tables {
my $tables =
eval {
- $dbh->selectall_arrayref('SHOW TABLES FROM ' .
- $dbh->quote_identifier($db))
+ $dbh->selectall_arrayref('SHOW FULL TABLES FROM ' .
+ $dbh->quote_identifier($db) .
+ ' WHERE Table_type = \'BASE TABLE\'')
} || [];
warn "Unable to retrieve list of tables in $db: $@" if $@;
return (map { $_->[0] } @$tables);
}
+sub get_list_of_views {
+ my ( $db ) = @_;
+
+ my $views =
+ eval {
+ $dbh->selectall_arrayref('SHOW FULL TABLES FROM ' .
+ $dbh->quote_identifier($db) .
+ ' WHERE Table_type = \'VIEW\'')
+ } || [];
+ warn "Unable to retrieve list of views in $db: $@" if $@;
+
+ return (map { $_->[0] } @$views);
+}
+
sub quote_names {
my ( $name ) = @_;
# given a db.table name, add quotes
diff --git a/scripts/mytop.sh b/scripts/mytop.sh
index f0456498da7..480805e90b1 100755
--- a/scripts/mytop.sh
+++ b/scripts/mytop.sh
@@ -15,7 +15,6 @@ mytop - display MySQL server performance info like `top'
use 5.005;
use strict;
use DBI;
-use DBD::mysql;
use Getopt::Long;
use Socket;
use List::Util qw(min max);
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-common/mysql_async.c b/sql-common/mysql_async.c
index c130eab5061..c7e720076ea 100644
--- a/sql-common/mysql_async.c
+++ b/sql-common/mysql_async.c
@@ -247,6 +247,28 @@ mysql_get_timeout_value(const MYSQL *mysql)
/*
+ In 10.0, VIO timeouts are in milliseconds, so we support getting the
+ millisecond timeout value from async applications.
+
+ In 5.5, timeouts are always in seconds, but we support the 10.0 version
+ that provides milliseconds, so applications can work with either version
+ of the library easily.
+
+ When merging this to 10.0, this function must be removed and the 10.0
+ version used.
+*/
+unsigned int STDCALL
+mysql_get_timeout_value_ms(const MYSQL *mysql)
+{
+ unsigned int timeout= mysql->options.extension->async_context->timeout_value;
+ if (timeout <= UINT_MAX / 1000)
+ return timeout*1000;
+ else
+ return UINT_MAX;
+}
+
+
+/*
Now create non-blocking definitions for all the calls that may block.
Each call FOO gives rise to FOO_start() that prepares the MYSQL object for
diff --git a/sql/create_options.cc b/sql/create_options.cc
index e4881388688..5cedfa03a63 100644
--- a/sql/create_options.cc
+++ b/sql/create_options.cc
@@ -137,11 +137,8 @@ static bool set_one_value(ha_create_table_option *opt,
my_option optp=
{ opt->name, 1, 0, (uchar **)val, 0, 0, GET_ULL,
- REQUIRED_ARG,
- (longlong) opt->def_value,
- (longlong) opt->min_value,
- opt->max_value,
- 0, (long) opt->block_size, 0};
+ REQUIRED_ARG, (longlong)opt->def_value, (longlong)opt->min_value,
+ opt->max_value, 0, (long) opt->block_size, 0};
ulonglong orig_val= strtoull(value->str, NULL, 10);
my_bool unused;
diff --git a/sql/filesort.cc b/sql/filesort.cc
index c5046eefc62..97e33d3d5a2 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -1,5 +1,5 @@
-/*
- Copyright (c) 2000, 2011, Oracle and/or its affiliates.
+/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2009, 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/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc
index 7b50b26c6ca..c37f4f145cf 100644
--- a/sql/gen_lex_hash.cc
+++ b/sql/gen_lex_hash.cc
@@ -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
@@ -85,6 +85,7 @@ So, we can read full search-structure as 32-bit word
#include <stdio.h>
#include <string.h>
+#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
struct hash_lex_struct
{
@@ -376,25 +377,9 @@ int main(int argc,char **argv)
/* Broken up to indicate that it's not advice to you, gentle reader. */
printf("/*\n\n Do " "not " "edit " "this " "file " "directly!\n\n*/\n");
- printf("\
-/* Copyright (C) 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.\n\
- Copyright (C) 2008-2011 Oracle\n\
-\n\
- This program is free software; you can redistribute it and/or modify\n\
- it under the terms of the GNU General Public License as published by\n\
- the Free Software Foundation; version 2 of the License.\n\
-\n\
- This program is distributed in the hope that it will be useful,\n\
- but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
- GNU General Public License for more details.\n\
-\n\
- You should have received a copy of the GNU General Public License\n\
- along with this program; see the file COPYING. If not, write to the\n\
- Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston\n\
- MA 02110-1301 USA. */\n\
-\n\
-");
+ puts("/*");
+ puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
+ puts("*/");
/* Broken up to indicate that it's not advice to you, gentle reader. */
printf("/* Do " "not " "edit " "this " "file! This is generated by "
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 5f58247a79d..c139889a2f4 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -324,8 +324,7 @@ ha_partition::~ha_partition()
for (i= 0; i < m_tot_parts; i++)
delete m_file[i];
}
- my_free(m_ordered_rec_buffer);
- m_ordered_rec_buffer= NULL;
+ destroy_record_priority_queue();
my_free(m_part_ids_sorted_by_num_of_records);
clear_handler_file();
@@ -2826,7 +2825,6 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
{
char *name_buffer_ptr;
int error= HA_ERR_INITIALIZATION;
- uint alloc_len;
handler **file;
char name_buff[FN_REFLEN];
bool is_not_tmp_table= (table_share->tmp_table == NO_TMP_TABLE);
@@ -2844,32 +2842,6 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
m_start_key.length= 0;
m_rec0= table->record[0];
m_rec_length= table_share->stored_rec_length;
- alloc_len= m_tot_parts * (m_rec_length + PARTITION_BYTES_IN_POS);
- alloc_len+= table_share->max_key_length;
- if (!m_ordered_rec_buffer)
- {
- if (!(m_ordered_rec_buffer= (uchar*)my_malloc(alloc_len, MYF(MY_WME))))
- {
- DBUG_RETURN(error);
- }
- {
- /*
- We set-up one record per partition and each record has 2 bytes in
- front where the partition id is written. This is used by ordered
- index_read.
- We also set-up a reference to the first record for temporary use in
- setting up the scan.
- */
- char *ptr= (char*)m_ordered_rec_buffer;
- uint i= 0;
- do
- {
- int2store(ptr, i);
- ptr+= m_rec_length + PARTITION_BYTES_IN_POS;
- } while (++i < m_tot_parts);
- m_start_key.key= (const uchar*)ptr;
- }
- }
if (!m_part_ids_sorted_by_num_of_records)
{
if (!(m_part_ids_sorted_by_num_of_records=
@@ -2899,7 +2871,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
if (m_is_clone_of)
{
- uint i;
+ uint i, alloc_len;
DBUG_ASSERT(m_clone_mem_root);
/* Allocate an array of handler pointers for the partitions handlers. */
alloc_len= (m_tot_parts + 1) * sizeof(handler*);
@@ -2977,12 +2949,6 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
being opened once.
*/
clear_handler_file();
- /*
- Initialize priority queue, initialized to reading forward.
- */
- if ((error= init_queue(&m_queue, m_tot_parts, (uint) PARTITION_BYTES_IN_POS,
- 0, key_rec_cmp, (void*)this, 0, 0)))
- goto err_handler;
/*
Use table_share->ha_part_data to share auto_increment_value among
@@ -3107,7 +3073,7 @@ int ha_partition::close(void)
DBUG_ENTER("ha_partition::close");
DBUG_ASSERT(table->s == table_share);
- delete_queue(&m_queue);
+ destroy_record_priority_queue();
bitmap_free(&m_bulk_insert_started);
if (!m_is_clone_of)
bitmap_free(&(m_part_info->used_partitions));
@@ -4389,6 +4355,78 @@ int ha_partition::rnd_pos_by_record(uchar *record)
subset of the partitions are used, then only use those partitions.
*/
+
+/**
+ Setup the ordered record buffer and the priority queue.
+*/
+
+bool ha_partition::init_record_priority_queue()
+{
+ DBUG_ENTER("ha_partition::init_record_priority_queue");
+ DBUG_ASSERT(!m_ordered_rec_buffer);
+ /*
+ Initialize the ordered record buffer.
+ */
+ if (!m_ordered_rec_buffer)
+ {
+ uint alloc_len;
+ uint used_parts= bitmap_bits_set(&m_part_info->used_partitions);
+ /* Allocate record buffer for each used partition. */
+ alloc_len= used_parts * (m_rec_length + PARTITION_BYTES_IN_POS);
+ /* Allocate a key for temporary use when setting up the scan. */
+ alloc_len+= table_share->max_key_length;
+
+ if (!(m_ordered_rec_buffer= (uchar*)my_malloc(alloc_len, MYF(MY_WME))))
+ DBUG_RETURN(true);
+
+ /*
+ We set-up one record per partition and each record has 2 bytes in
+ front where the partition id is written. This is used by ordered
+ index_read.
+ We also set-up a reference to the first record for temporary use in
+ setting up the scan.
+ */
+ char *ptr= (char*) m_ordered_rec_buffer;
+ uint16 i= 0;
+ do
+ {
+ if (bitmap_is_set(&m_part_info->used_partitions, i))
+ {
+ int2store(ptr, i);
+ ptr+= m_rec_length + PARTITION_BYTES_IN_POS;
+ }
+ } while (++i < m_tot_parts);
+ m_start_key.key= (const uchar*)ptr;
+ /* Initialize priority queue, initialized to reading forward. */
+ if (init_queue(&m_queue, used_parts, (uint) PARTITION_BYTES_IN_POS,
+ 0, key_rec_cmp, (void*)m_curr_key_info, 0, 0))
+ {
+ my_free(m_ordered_rec_buffer);
+ m_ordered_rec_buffer= NULL;
+ DBUG_RETURN(true);
+ }
+ }
+ DBUG_RETURN(false);
+}
+
+
+/**
+ Destroy the ordered record buffer and the priority queue.
+*/
+
+void ha_partition::destroy_record_priority_queue()
+{
+ DBUG_ENTER("ha_partition::destroy_record_priority_queue");
+ if (m_ordered_rec_buffer)
+ {
+ delete_queue(&m_queue);
+ my_free(m_ordered_rec_buffer);
+ m_ordered_rec_buffer= NULL;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
/*
Initialize handler before start of index scan
@@ -4431,6 +4469,10 @@ int ha_partition::index_init(uint inx, bool sorted)
}
else
m_curr_key_info[1]= NULL;
+
+ if (init_record_priority_queue())
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+
/*
Some handlers only read fields as specified by the bitmap for the
read set. For partitioned handlers we always require that the
@@ -4505,11 +4547,11 @@ int ha_partition::index_end()
do
{
int tmp;
- /* TODO RONM: Change to index_end() when code is stable */
if (bitmap_is_set(&(m_part_info->used_partitions), (file - m_file)))
if ((tmp= (*file)->ha_index_end()))
error= tmp;
} while (*(++file));
+ destroy_record_priority_queue();
DBUG_RETURN(error);
}
@@ -4591,8 +4633,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)
{
@@ -5221,6 +5263,7 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
uint i;
uint j= queue_first_element(&m_queue);
bool found= FALSE;
+ uchar *part_rec_buf_ptr= m_ordered_rec_buffer;
DBUG_ENTER("ha_partition::handle_ordered_index_scan");
m_top_entry= NO_CURRENT_PART_ID;
@@ -5231,7 +5274,7 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
{
if (!(bitmap_is_set(&(m_part_info->used_partitions), i)))
continue;
- uchar *rec_buf_ptr= rec_buf(i);
+ uchar *rec_buf_ptr= part_rec_buf_ptr + PARTITION_BYTES_IN_POS;
int error;
handler *file= m_file[i];
@@ -5278,12 +5321,13 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
/*
Initialize queue without order first, simply insert
*/
- queue_element(&m_queue, j++)= (uchar*)queue_buf(i);
+ queue_element(&m_queue, j++)= part_rec_buf_ptr;
}
else if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
{
DBUG_RETURN(error);
}
+ part_rec_buf_ptr+= m_rec_length + PARTITION_BYTES_IN_POS;
}
if (found)
{
@@ -5346,18 +5390,19 @@ int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same)
{
int error;
uint part_id= m_top_entry;
+ uchar *rec_buf= queue_top(&m_queue) + PARTITION_BYTES_IN_POS;
handler *file= m_file[part_id];
DBUG_ENTER("ha_partition::handle_ordered_next");
if (m_index_scan_type == partition_read_range)
{
error= file->read_range_next();
- memcpy(rec_buf(part_id), table->record[0], m_rec_length);
+ memcpy(rec_buf, table->record[0], m_rec_length);
}
else if (!is_next_same)
- error= file->ha_index_next(rec_buf(part_id));
+ error= file->ha_index_next(rec_buf);
else
- error= file->ha_index_next_same(rec_buf(part_id), m_start_key.key,
+ error= file->ha_index_next_same(rec_buf, m_start_key.key,
m_start_key.length);
if (error)
{
@@ -5400,10 +5445,11 @@ int ha_partition::handle_ordered_prev(uchar *buf)
{
int error;
uint part_id= m_top_entry;
+ uchar *rec_buf= queue_top(&m_queue) + PARTITION_BYTES_IN_POS;
handler *file= m_file[part_id];
DBUG_ENTER("ha_partition::handle_ordered_prev");
- if ((error= file->ha_index_prev(rec_buf(part_id))))
+ if ((error= file->ha_index_prev(rec_buf)))
{
if (error == HA_ERR_END_OF_FILE)
{
@@ -7523,23 +7569,6 @@ int ha_partition::indexes_are_disabled(void)
struct st_mysql_storage_engine partition_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
-mysql_declare_plugin(partition)
-{
- MYSQL_STORAGE_ENGINE_PLUGIN,
- &partition_storage_engine,
- "partition",
- "Mikael Ronstrom, MySQL AB",
- "Partition Storage Engine Helper",
- PLUGIN_LICENSE_GPL,
- partition_initialize, /* Plugin Init */
- NULL, /* Plugin Deinit */
- 0x0100, /* 1.0 */
- NULL, /* status variables */
- NULL, /* system variables */
- NULL, /* config options */
- 0, /* flags */
-}
-mysql_declare_plugin_end;
maria_declare_plugin(partition)
{
MYSQL_STORAGE_ENGINE_PLUGIN,
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index 0f922394ec5..86d43e3750f 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -508,21 +508,13 @@ public:
virtual int read_range_next();
private:
+ bool init_record_priority_queue();
+ void destroy_record_priority_queue();
int common_index_read(uchar * buf, bool have_start_key);
int common_first_last(uchar * buf);
int partition_scan_set_up(uchar * buf, bool idx_read_flag);
int handle_unordered_next(uchar * buf, bool next_same);
int handle_unordered_scan_next_partition(uchar * buf);
- uchar *queue_buf(uint part_id)
- {
- return (m_ordered_rec_buffer +
- (part_id * (m_rec_length + PARTITION_BYTES_IN_POS)));
- }
- uchar *rec_buf(uint part_id)
- {
- return (queue_buf(part_id) +
- PARTITION_BYTES_IN_POS);
- }
int handle_ordered_index_scan(uchar * buf, bool reverse_order);
int handle_ordered_next(uchar * buf, bool next_same);
int handle_ordered_prev(uchar * buf);
diff --git a/sql/handler.cc b/sql/handler.cc
index e3a8c9352f5..6634bd6fb7a 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -2671,8 +2671,7 @@ int handler::update_auto_increment()
if (unlikely(nr == ULONGLONG_MAX))
DBUG_RETURN(HA_ERR_AUTOINC_ERANGE);
- DBUG_PRINT("info",("auto_increment: %llu nb_reserved_values: %llu",
- nr, nb_reserved_values));
+ DBUG_PRINT("info",("auto_increment: %llu",nr));
/* Store field without warning (Warning will be printed by insert) */
save_count_cuted_fields= thd->count_cuted_fields;
@@ -2690,6 +2689,8 @@ int handler::update_auto_increment()
}
if (append)
{
+ DBUG_PRINT("info",("nb_reserved_values: %llu",nb_reserved_values));
+
auto_inc_interval_for_cur_row.replace(nr, nb_reserved_values,
variables->auto_increment_increment);
auto_inc_intervals_count++;
@@ -4609,7 +4610,20 @@ int handler::read_range_first(const key_range *start_key,
DBUG_RETURN((result == HA_ERR_KEY_NOT_FOUND)
? HA_ERR_END_OF_FILE
: result);
- DBUG_RETURN (compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
+
+ if (compare_key(end_range) <= 0)
+ {
+ DBUG_RETURN(0);
+ }
+ else
+ {
+ /*
+ The last read row does not fall in the range. So request
+ storage engine to release row lock if possible.
+ */
+ unlock_row();
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ }
}
@@ -4641,7 +4655,20 @@ int handler::read_range_next()
result= ha_index_next(table->record[0]);
if (result)
DBUG_RETURN(result);
- DBUG_RETURN(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
+
+ if (compare_key(end_range) <= 0)
+ {
+ DBUG_RETURN(0);
+ }
+ else
+ {
+ /*
+ The last read row does not fall in the range. So request
+ storage engine to release row lock if possible.
+ */
+ unlock_row();
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ }
}
diff --git a/sql/item.cc b/sql/item.cc
index 4d80a153785..bc98a9a3184 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -6839,7 +6839,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
if (from_field != not_found_field)
{
Item_field* fld;
- if (!(fld= new Item_field(thd, last_checked_context, from_field)))
+ if (!(fld= new Item_field(from_field)))
goto error;
thd->change_item_tree(reference, fld);
mark_as_dependent(thd, last_checked_context->select_lex,
@@ -9609,7 +9609,7 @@ table_map Item_direct_view_ref::used_tables() const
{
return get_depended_from() ?
OUTER_REF_TABLE_BIT :
- ((view->merged || !view->table) ?
+ ((view->is_merged_derived() || view->merged || !view->table) ?
(*ref)->used_tables() :
view->table->map);
}
@@ -9618,7 +9618,7 @@ table_map Item_direct_view_ref::not_null_tables() const
{
return get_depended_from() ?
0 :
- ((view->merged || !view->table) ?
+ ((view->is_merged_derived() || view->merged || !view->table) ?
(*ref)->not_null_tables() :
view->table->map);
}
diff --git a/sql/item_func.h b/sql/item_func.h
index 07b246b3ccd..80fa0b5d634 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1572,6 +1572,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_strfunc.cc b/sql/item_strfunc.cc
index ebfca684ccb..cce99ec2991 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -3299,23 +3299,21 @@ err:
String* Item_func_export_set::val_str(String* str)
{
DBUG_ASSERT(fixed == 1);
- ulonglong the_set = (ulonglong) args[0]->val_int();
- String yes_buf, *yes;
- yes = args[1]->val_str(&yes_buf);
- String no_buf, *no;
- no = args[2]->val_str(&no_buf);
- String *sep = NULL, sep_buf ;
+ String yes_buf, no_buf, sep_buf;
+ const ulonglong the_set = (ulonglong) args[0]->val_int();
+ const String *yes= args[1]->val_str(&yes_buf);
+ const String *no= args[2]->val_str(&no_buf);
+ const String *sep= NULL;
uint num_set_values = 64;
- ulonglong mask = 0x1;
str->length(0);
str->set_charset(collation.collation);
/* Check if some argument is a NULL value */
if (args[0]->null_value || args[1]->null_value || args[2]->null_value)
{
- null_value=1;
- return 0;
+ null_value= true;
+ return NULL;
}
/*
Arg count can only be 3, 4 or 5 here. This is guaranteed from the
@@ -3328,37 +3326,56 @@ String* Item_func_export_set::val_str(String* str)
num_set_values=64;
if (args[4]->null_value)
{
- null_value=1;
- return 0;
+ null_value= true;
+ return NULL;
}
/* Fall through */
case 4:
if (!(sep = args[3]->val_str(&sep_buf))) // Only true if NULL
{
- null_value=1;
- return 0;
+ null_value= true;
+ return NULL;
}
break;
case 3:
{
/* errors is not checked - assume "," can always be converted */
uint errors;
- sep_buf.copy(STRING_WITH_LEN(","), &my_charset_bin, collation.collation, &errors);
+ sep_buf.copy(STRING_WITH_LEN(","), &my_charset_bin,
+ collation.collation, &errors);
sep = &sep_buf;
}
break;
default:
DBUG_ASSERT(0); // cannot happen
}
- null_value=0;
+ null_value= false;
+
+ const ulong max_allowed_packet= current_thd->variables.max_allowed_packet;
+ const uint num_separators= num_set_values > 0 ? num_set_values - 1 : 0;
+ const ulonglong max_total_length=
+ num_set_values * max(yes->length(), no->length()) +
+ num_separators * sep->length();
+
+ if (unlikely(max_total_length > max_allowed_packet))
+ {
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_ALLOWED_PACKET_OVERFLOWED,
+ ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
+ func_name(), max_allowed_packet);
+ null_value= true;
+ return NULL;
+ }
- for (uint i = 0; i < num_set_values; i++, mask = (mask << 1))
+ uint ix;
+ ulonglong mask;
+ for (ix= 0, mask=0x1; ix < num_set_values; ++ix, mask = (mask << 1))
{
if (the_set & mask)
str->append(*yes);
else
str->append(*no);
- if (i != num_set_values - 1)
+ if (ix != num_separators)
str->append(*sep);
}
return str;
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 83c7e3e1529..ab77bb0e59c 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);
}
@@ -1063,11 +1068,9 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
}
substitution= select_lex->item_list.head();
/*
- as far as we moved content to upper level, field which depend of
- 'upper' select is not really dependent => we remove this dependence
+ as far as we moved content to upper level we have to fix dependences & Co
*/
- substitution->walk(&Item::remove_dependence_processor, 0,
- (uchar *) select_lex->outer_select());
+ substitution->fix_after_pullout(select_lex->outer_select(), &substitution);
}
DBUG_RETURN(false);
}
@@ -2003,7 +2006,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN * join,
}
else
{
- Item *item= (Item*) select_lex->item_list.head();
+ Item *item= (Item*) select_lex->item_list.head()->real_item();
if (select_lex->table_list.elements)
{
@@ -3143,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 da9d576d1da..a96dfbbf461 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -317,7 +317,7 @@ public:
before_stmt_pos= MY_OFF_T_UNDEF;
}
- void set_binlog_cache_info(ulong param_max_binlog_cache_size,
+ void set_binlog_cache_info(my_off_t param_max_binlog_cache_size,
ulong *param_ptr_binlog_cache_use,
ulong *param_ptr_binlog_cache_disk_use)
{
@@ -394,7 +394,7 @@ private:
is configured. This corresponds to either
. max_binlog_cache_size or max_binlog_stmt_cache_size.
*/
- ulong saved_max_binlog_cache_size;
+ my_off_t saved_max_binlog_cache_size;
/*
Stores a pointer to the status variable that keeps track of the in-memory
@@ -432,8 +432,8 @@ private:
class binlog_cache_mngr {
public:
- binlog_cache_mngr(ulong param_max_binlog_stmt_cache_size,
- ulong param_max_binlog_cache_size,
+ binlog_cache_mngr(my_off_t param_max_binlog_stmt_cache_size,
+ my_off_t param_max_binlog_cache_size,
ulong *param_ptr_binlog_stmt_cache_use,
ulong *param_ptr_binlog_stmt_cache_disk_use,
ulong *param_ptr_binlog_cache_use,
@@ -1300,12 +1300,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();
@@ -1316,15 +1310,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;
}
@@ -5573,7 +5571,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;
@@ -7420,8 +7418,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;
@@ -7454,8 +7453,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)
@@ -7472,10 +7471,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);
@@ -7582,12 +7581,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);
}
@@ -7639,8 +7635,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 9facf309279..80fe34b5ff2 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -145,7 +145,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/mdl.cc b/sql/mdl.cc
index ca552a540b9..5e297051377 100644
--- a/sql/mdl.cc
+++ b/sql/mdl.cc
@@ -378,7 +378,8 @@ public:
bool has_pending_conflicting_lock(enum_mdl_type type);
- bool can_grant_lock(enum_mdl_type type, MDL_context *requstor_ctx) const;
+ bool can_grant_lock(enum_mdl_type type, MDL_context *requstor_ctx,
+ bool ignore_lock_priority) const;
inline static MDL_lock *create(const MDL_key *key);
@@ -392,14 +393,24 @@ public:
virtual bool needs_notification(const MDL_ticket *ticket) const = 0;
virtual void notify_conflicting_locks(MDL_context *ctx) = 0;
+ virtual bitmap_t hog_lock_types_bitmap() const = 0;
+
/** List of granted tickets for this lock. */
Ticket_list m_granted;
/** Tickets for contexts waiting to acquire a lock. */
Ticket_list m_waiting;
+
+ /**
+ Number of times high priority lock requests have been granted while
+ low priority lock requests were waiting.
+ */
+ ulong m_hog_lock_count;
+
public:
MDL_lock(const MDL_key *key_arg)
: key(key_arg),
+ m_hog_lock_count(0),
m_ref_usage(0),
m_ref_release(0),
m_is_destroyed(FALSE),
@@ -484,6 +495,15 @@ public:
}
virtual void notify_conflicting_locks(MDL_context *ctx);
+ /*
+ In scoped locks, only IX lock request would starve because of X/S. But that
+ is practically very rare case. So just return 0 from this function.
+ */
+ virtual bitmap_t hog_lock_types_bitmap() const
+ {
+ return 0;
+ }
+
private:
static const bitmap_t m_granted_incompatible[MDL_TYPE_END];
static const bitmap_t m_waiting_incompatible[MDL_TYPE_END];
@@ -536,6 +556,18 @@ public:
}
virtual void notify_conflicting_locks(MDL_context *ctx);
+ /*
+ To prevent starvation, these lock types that are only granted
+ max_write_lock_count times in a row while other lock types are
+ waiting.
+ */
+ virtual bitmap_t hog_lock_types_bitmap() const
+ {
+ return (MDL_BIT(MDL_SHARED_NO_WRITE) |
+ MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
+ MDL_BIT(MDL_EXCLUSIVE));
+ }
+
private:
static const bitmap_t m_granted_incompatible[MDL_TYPE_END];
static const bitmap_t m_waiting_incompatible[MDL_TYPE_END];
@@ -1268,6 +1300,41 @@ void MDL_lock::reschedule_waiters()
{
MDL_lock::Ticket_iterator it(m_waiting);
MDL_ticket *ticket;
+ bool skip_high_priority= false;
+ bitmap_t hog_lock_types= hog_lock_types_bitmap();
+
+ if (m_hog_lock_count >= max_write_lock_count)
+ {
+ /*
+ If number of successively granted high-prio, strong locks has exceeded
+ max_write_lock_count give a way to low-prio, weak locks to avoid their
+ starvation.
+ */
+
+ if ((m_waiting.bitmap() & ~hog_lock_types) != 0)
+ {
+ /*
+ Even though normally when m_hog_lock_count is non-0 there is
+ some pending low-prio lock, we still can encounter situation
+ when m_hog_lock_count is non-0 and there are no pending low-prio
+ locks. This, for example, can happen when a ticket for pending
+ low-prio lock was removed from waiters list due to timeout,
+ and reschedule_waiters() is called after that to update the
+ waiters queue. m_hog_lock_count will be reset to 0 at the
+ end of this call in such case.
+
+ Note that it is not an issue if we fail to wake up any pending
+ waiters for weak locks in the loop below. This would mean that
+ all of them are either killed, timed out or chosen as a victim
+ by deadlock resolver, but have not managed to remove ticket
+ from the waiters list yet. After tickets will be removed from
+ the waiters queue there will be another call to
+ reschedule_waiters() with pending bitmap updated to reflect new
+ state of waiters queue.
+ */
+ skip_high_priority= true;
+ }
+ }
/*
Find the first (and hence the oldest) waiting request which
@@ -1289,7 +1356,16 @@ void MDL_lock::reschedule_waiters()
*/
while ((ticket= it++))
{
- if (can_grant_lock(ticket->get_type(), ticket->get_ctx()))
+ /*
+ Skip high-prio, strong locks if earlier we have decided to give way to
+ low-prio, weaker locks.
+ */
+ if (skip_high_priority &&
+ ((MDL_BIT(ticket->get_type()) & hog_lock_types) != 0))
+ continue;
+
+ if (can_grant_lock(ticket->get_type(), ticket->get_ctx(),
+ skip_high_priority))
{
if (! ticket->get_ctx()->m_wait.set_status(MDL_wait::GRANTED))
{
@@ -1303,6 +1379,13 @@ void MDL_lock::reschedule_waiters()
*/
m_waiting.remove_ticket(ticket);
m_granted.add_ticket(ticket);
+
+ /*
+ Increase counter of successively granted high-priority strong locks,
+ if we have granted one.
+ */
+ if ((MDL_BIT(ticket->get_type()) & hog_lock_types) != 0)
+ m_hog_lock_count++;
}
/*
If we could not update the wait slot of the waiter,
@@ -1314,6 +1397,24 @@ void MDL_lock::reschedule_waiters()
*/
}
}
+
+ if ((m_waiting.bitmap() & ~hog_lock_types) == 0)
+ {
+ /*
+ Reset number of successively granted high-prio, strong locks
+ if there are no pending low-prio, weak locks.
+ This ensures:
+ - That m_hog_lock_count is correctly reset after strong lock
+ is released and weak locks are granted (or there are no
+ other lock requests).
+ - That situation when SNW lock is granted along with some SR
+ locks, but SW locks are still blocked are handled correctly.
+ - That m_hog_lock_count is zero in most cases when there are no pending
+ weak locks (see comment at the start of this method for example of
+ exception). This allows to save on checks at the start of this method.
+ */
+ m_hog_lock_count= 0;
+ }
}
@@ -1468,8 +1569,9 @@ MDL_object_lock::m_waiting_incompatible[MDL_TYPE_END] =
Check if request for the metadata lock can be satisfied given its
current state.
- @param type_arg The requested lock type.
- @param requestor_ctx The MDL context of the requestor.
+ @param type_arg The requested lock type.
+ @param requestor_ctx The MDL context of the requestor.
+ @param ignore_lock_priority Ignore lock priority.
@retval TRUE Lock request can be satisfied
@retval FALSE There is some conflicting lock.
@@ -1481,19 +1583,21 @@ MDL_object_lock::m_waiting_incompatible[MDL_TYPE_END] =
bool
MDL_lock::can_grant_lock(enum_mdl_type type_arg,
- MDL_context *requestor_ctx) const
+ MDL_context *requestor_ctx,
+ bool ignore_lock_priority) const
{
bool can_grant= FALSE;
bitmap_t waiting_incompat_map= incompatible_waiting_types_bitmap()[type_arg];
bitmap_t granted_incompat_map= incompatible_granted_types_bitmap()[type_arg];
+
/*
New lock request can be satisfied iff:
- There are no incompatible types of satisfied requests
in other contexts
- There are no waiting requests which have higher priority
- than this request.
+ than this request when priority was not ignored.
*/
- if (! (m_waiting.bitmap() & waiting_incompat_map))
+ if (ignore_lock_priority || !(m_waiting.bitmap() & waiting_incompat_map))
{
if (! (m_granted.bitmap() & granted_incompat_map))
can_grant= TRUE;
@@ -1789,7 +1893,7 @@ MDL_context::try_acquire_lock_impl(MDL_request *mdl_request,
ticket->m_lock= lock;
- if (lock->can_grant_lock(mdl_request->type, this))
+ if (lock->can_grant_lock(mdl_request->type, this, false))
{
lock->m_granted.add_ticket(ticket);
diff --git a/sql/mdl.h b/sql/mdl.h
index d50de7d14c3..af7d75c1297 100644
--- a/sql/mdl.h
+++ b/sql/mdl.h
@@ -860,4 +860,10 @@ extern mysql_mutex_t LOCK_open;
extern ulong mdl_locks_cache_size;
static const ulong MDL_LOCKS_CACHE_SIZE_DEFAULT = 1024;
+/*
+ Metadata locking subsystem tries not to grant more than
+ max_write_lock_count high-prio, strong locks successively,
+ to avoid starving out weak, low-prio locks.
+*/
+extern "C" ulong max_write_lock_count;
#endif
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index a3874bb49a6..e7197e4d65f 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -274,6 +274,8 @@ extern "C" sig_handler handle_fatal_signal(int sig);
/* Constants */
+#include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
+
const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
static const char *tc_heuristic_recover_names[]=
@@ -620,6 +622,21 @@ I_List<THD> threads;
Rpl_filter* rpl_filter;
Rpl_filter* binlog_filter;
+THD *first_global_thread()
+{
+ if (threads.is_empty())
+ return NULL;
+ return threads.head();
+}
+
+THD *next_global_thread(THD *thd)
+{
+ if (threads.is_last(thd))
+ return NULL;
+ struct ilink *next= thd->next;
+ return static_cast<THD*>(next);
+}
+
struct system_variables global_system_variables;
struct system_variables max_system_variables;
struct system_status_var global_status_var;
@@ -1790,6 +1807,7 @@ void clean_up(bool print_message)
my_tz_free();
my_dboptions_cache_free();
+ ignore_db_dirs_free();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
servers_free(1);
acl_free(1);
@@ -3436,6 +3454,9 @@ static int init_common_variables()
mysql_init_variables())
return 1;
+ if (ignore_db_dirs_init())
+ return 1;
+
#ifdef HAVE_TZNAME
struct tm tm_tmp;
localtime_r(&server_start_time,&tm_tmp);
@@ -3864,6 +3885,12 @@ You should consider changing lower_case_table_names to 1 or 2",
files_charset_info :
&my_charset_bin);
+ if (ignore_db_dirs_process_additions())
+ {
+ sql_print_error("An error occurred while storing ignore_db_dirs to a hash.");
+ return 1;
+ }
+
return 0;
}
@@ -6312,7 +6339,7 @@ struct my_option my_long_options[]=
#ifdef HAVE_MMAP
{"log-tc-size", 0, "Size of transaction coordinator log.",
&opt_tc_log_size, &opt_tc_log_size, 0, GET_ULONG,
- REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, (longlong) ULONG_MAX, 0,
+ REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, (ulonglong) ULONG_MAX, 0,
TC_LOG_PAGE_SIZE, 0},
#endif
{"master-info-file", 0,
@@ -6939,6 +6966,7 @@ SHOW_VAR status_vars[]= {
{"Aborted_clients", (char*) &aborted_threads, SHOW_LONG},
{"Aborted_connects", (char*) &aborted_connects, SHOW_LONG},
{"Access_denied_errors", (char*) offsetof(STATUS_VAR, access_denied_errors), SHOW_LONG_STATUS},
+ {"Binlog_bytes_written", (char*) offsetof(STATUS_VAR, binlog_bytes_written), SHOW_LONGLONG_STATUS},
{"Binlog_cache_disk_use", (char*) &binlog_cache_disk_use, SHOW_LONG},
{"Binlog_cache_use", (char*) &binlog_cache_use, SHOW_LONG},
{"Binlog_stmt_cache_disk_use",(char*) &binlog_stmt_cache_disk_use, SHOW_LONG},
@@ -6946,7 +6974,6 @@ SHOW_VAR status_vars[]= {
{"Busy_time", (char*) offsetof(STATUS_VAR, busy_time), SHOW_DOUBLE_STATUS},
{"Bytes_received", (char*) offsetof(STATUS_VAR, bytes_received), SHOW_LONGLONG_STATUS},
{"Bytes_sent", (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS},
- {"Binlog_bytes_written", (char*) offsetof(STATUS_VAR, binlog_bytes_written), SHOW_LONGLONG_STATUS},
{"Com", (char*) com_status_vars, SHOW_ARRAY},
{"Compression", (char*) &show_net_compression, SHOW_SIMPLE_FUNC},
{"Connections", (char*) &thread_id, SHOW_LONG_NOFLUSH},
@@ -6972,14 +6999,11 @@ SHOW_VAR status_vars[]= {
{"Handler_commit", (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS},
{"Handler_delete", (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS},
{"Handler_discover", (char*) offsetof(STATUS_VAR, ha_discover_count), SHOW_LONG_STATUS},
-
{"Handler_icp_attempts", (char*) offsetof(STATUS_VAR, ha_icp_attempts), SHOW_LONG_STATUS},
{"Handler_icp_match", (char*) offsetof(STATUS_VAR, ha_icp_match), SHOW_LONG_STATUS},
-
{"Handler_mrr_init", (char*) offsetof(STATUS_VAR, ha_mrr_init_count), SHOW_LONG_STATUS},
{"Handler_mrr_key_refills", (char*) offsetof(STATUS_VAR, ha_mrr_key_refills_count), SHOW_LONG_STATUS},
{"Handler_mrr_rowid_refills", (char*) offsetof(STATUS_VAR, ha_mrr_rowid_refills_count), SHOW_LONG_STATUS},
-
{"Handler_prepare", (char*) offsetof(STATUS_VAR, ha_prepare_count), SHOW_LONG_STATUS},
{"Handler_read_first", (char*) offsetof(STATUS_VAR, ha_read_first_count), SHOW_LONG_STATUS},
{"Handler_read_key", (char*) offsetof(STATUS_VAR, ha_read_key_count), SHOW_LONG_STATUS},
@@ -7005,8 +7029,8 @@ SHOW_VAR status_vars[]= {
{"Open_table_definitions", (char*) &show_table_definitions, SHOW_SIMPLE_FUNC},
{"Open_tables", (char*) &show_open_tables, SHOW_SIMPLE_FUNC},
{"Opened_files", (char*) &my_file_total_opened, SHOW_LONG_NOFLUSH},
- {"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS},
{"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares), SHOW_LONG_STATUS},
+ {"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS},
{"Opened_views", (char*) offsetof(STATUS_VAR, opened_views), SHOW_LONG_STATUS},
{"Prepared_stmt_count", (char*) &show_prepared_stmt_count, SHOW_SIMPLE_FUNC},
{"Rows_sent", (char*) offsetof(STATUS_VAR, rows_sent), SHOW_LONGLONG_STATUS},
@@ -7169,14 +7193,8 @@ static void usage(void)
if (!default_collation_name)
default_collation_name= (char*) default_charset_info->name;
print_version();
- puts("\
-Copyright (C) 2000-2008 MySQL AB, by Monty and others.\n\
-Copyright (C) 2000, 2011 Oracle.\n\
-Copyright (C) 2009-2011 Monty Program Ab.\n\
-This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
-and you are welcome to modify and redistribute it under the GPL license\n\n\
-Starts the MariaDB database server.\n");
-
+ puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
+ puts("Starts the MariaDB database server.\n");
printf("Usage: %s [OPTIONS]\n", my_progname);
if (!opt_verbose)
puts("\nFor more help options (several pages), use mysqld --verbose --help.");
@@ -7739,6 +7757,22 @@ mysqld_get_one_option(int optid,
case OPT_MAX_LONG_DATA_SIZE:
max_long_data_size_used= true;
break;
+
+
+ case OPT_IGNORE_DB_DIRECTORY:
+ if (*argument == 0)
+ ignore_db_dirs_reset();
+ else
+ {
+ if (push_ignored_db_dir(argument))
+ {
+ sql_print_error("Can't start server: "
+ "cannot process --ignore-db-dir=%.*s",
+ FN_REFLEN, argument);
+ return 1;
+ }
+ }
+ break;
}
return 0;
}
@@ -8032,10 +8066,13 @@ static int get_options(int *argc_ptr, char ***argv_ptr)
*/
max_relay_log_size_var= intern_find_sys_var("max_relay_log_size", 0);
max_binlog_size_var= intern_find_sys_var("max_binlog_size", 0);
- max_relay_log_size_var->option.min_value=
- max_binlog_size_var->option.min_value;
- max_relay_log_size_var->option.def_value=
- max_binlog_size_var->option.def_value;
+ if (max_binlog_size_var && max_relay_log_size_var)
+ {
+ max_relay_log_size_var->option.min_value=
+ max_binlog_size_var->option.min_value;
+ max_relay_log_size_var->option.def_value=
+ max_binlog_size_var->option.def_value;
+ }
}
return 0;
}
diff --git a/sql/mysqld.h b/sql/mysqld.h
index d346defad8e..8ec7e1ac751 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -372,19 +372,23 @@ enum options_mysqld
OPT_BINLOG_FORMAT,
OPT_BINLOG_IGNORE_DB,
OPT_BIN_LOG,
- OPT_LOG_BASENAME,
OPT_BOOTSTRAP,
OPT_CONSOLE,
OPT_DEBUG_SYNC_TIMEOUT,
OPT_DELAY_KEY_WRITE_ALL,
OPT_DEPRECATED_OPTION,
+ OPT_ENGINE_CONDITION_PUSHDOWN,
+ OPT_IGNORE_DB_DIRECTORY,
OPT_ISAM_LOG,
OPT_KEY_BUFFER_SIZE,
OPT_KEY_CACHE_AGE_THRESHOLD,
OPT_KEY_CACHE_BLOCK_SIZE,
OPT_KEY_CACHE_DIVISION_LIMIT,
OPT_KEY_CACHE_PARTITIONS,
+ OPT_LOG_BASENAME,
+ OPT_LOG_ERROR,
OPT_LOWER_CASE_TABLE_NAMES,
+ OPT_MAX_LONG_DATA_SIZE,
OPT_ONE_THREAD,
OPT_POOL_OF_THREADS,
OPT_REPLICATE_DO_DB,
@@ -410,9 +414,7 @@ enum options_mysqld
OPT_SSL_KEY,
OPT_UPDATE_LOG,
OPT_WANT_CORE,
- OPT_ENGINE_CONDITION_PUSHDOWN,
- OPT_LOG_ERROR,
- OPT_MAX_LONG_DATA_SIZE
+ OPT_which_is_always_the_last
};
#endif
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index dba72d76bb4..b98edeb15db 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -3853,27 +3853,28 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
ppar->cur_subpart_fields+= ppar->is_subpart_keypart[key_tree_part];
*(ppar->arg_stack_end++)= key_tree;
+ if (ignore_part_fields)
+ {
+ /*
+ We come here when a condition on the first partitioning
+ fields led to evaluating the partitioning condition
+ (due to finding a condition of the type a < const or
+ b > const). Thus we must ignore the rest of the
+ partitioning fields but we still want to analyse the
+ subpartitioning fields.
+ */
+ if (key_tree->next_key_part)
+ res= find_used_partitions(ppar, key_tree->next_key_part);
+ else
+ res= -1;
+ goto pop_and_go_right;
+ }
+
if (key_tree->type == SEL_ARG::KEY_RANGE)
{
if (ppar->part_info->get_part_iter_for_interval &&
key_tree->part <= ppar->last_part_partno)
{
- if (ignore_part_fields)
- {
- /*
- We come here when a condition on the first partitioning
- fields led to evaluating the partitioning condition
- (due to finding a condition of the type a < const or
- b > const). Thus we must ignore the rest of the
- partitioning fields but we still want to analyse the
- subpartitioning fields.
- */
- if (key_tree->next_key_part)
- res= find_used_partitions(ppar, key_tree->next_key_part);
- else
- res= -1;
- goto pop_and_go_right;
- }
/* Collect left and right bound, their lengths and flags */
uchar *min_key= ppar->cur_min_key;
uchar *max_key= ppar->cur_max_key;
@@ -4114,6 +4115,13 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
res= -1;
goto pop_and_go_right;
}
+ /*
+ No meaning in continuing with rest of partitioning key parts.
+ Will try to continue with subpartitioning key parts.
+ */
+ ppar->ignore_part_fields= true;
+ did_set_ignore_part_fields= true;
+ goto process_next_key_part;
}
}
@@ -10936,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/set_var.cc b/sql/set_var.cc
index 43aa10fbebd..2d3e0b7fec4 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -134,9 +134,9 @@ void sys_var_end()
put your additional checks here
@param on_update_func a function to be called at the end of sys_var::update,
any post-update activity should happen here
- @param deprecated_version if not 0 - when this variable will go away
- @param substitute if not 0 - what one should use instead when this
- deprecated variable
+ @param substitute If non-NULL, this variable is deprecated and the
+ string describes what one should use instead. If an empty string,
+ the variable is deprecated but no replacement is offered.
*/
sys_var::sys_var(sys_var_chain *chain, const char *name_arg,
const char *comment, int flags_arg, ptrdiff_t off,
@@ -145,11 +145,12 @@ sys_var::sys_var(sys_var_chain *chain, const char *name_arg,
PolyLock *lock, enum binlog_status_enum binlog_status_arg,
on_check_function on_check_func,
on_update_function on_update_func,
- uint deprecated_version, const char *substitute) :
+ const char *substitute) :
next(0),
binlog_status(binlog_status_arg),
flags(flags_arg), show_val_type(show_val_type_arg),
guard(lock), offset(off), on_check(on_check_func), on_update(on_update_func),
+ deprecation_substitute(substitute),
is_os_charset(FALSE)
{
/*
@@ -175,12 +176,6 @@ sys_var::sys_var(sys_var_chain *chain, const char *name_arg,
option.value= (uchar **)global_var_ptr();
option.def_value= def_val;
- deprecated.version= deprecated_version;
- deprecated.substitute= substitute;
- DBUG_ASSERT((deprecated_version != 0) || (substitute == 0));
- DBUG_ASSERT(deprecated_version % 100 == 0);
- DBUG_ASSERT(!deprecated_version || MYSQL_VERSION_ID < deprecated_version);
-
if (chain->last)
chain->last->next= this;
else
@@ -275,21 +270,24 @@ bool sys_var::set_default(THD *thd, enum_var_type type)
void sys_var::do_deprecated_warning(THD *thd)
{
- if (deprecated.version)
+ if (deprecation_substitute != NULL)
{
- char buf1[NAME_CHAR_LEN + 3], buf2[10];
+ char buf1[NAME_CHAR_LEN + 3];
strxnmov(buf1, sizeof(buf1)-1, "@@", name.str, 0);
- my_snprintf(buf2, sizeof(buf2), "%d.%d", deprecated.version/100/100,
- deprecated.version/100%100);
- uint errmsg= deprecated.substitute
- ? ER_WARN_DEPRECATED_SYNTAX_WITH_VER
- : ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT;
+
+ /*
+ if deprecation_substitute is an empty string,
+ there is no replacement for the syntax
+ */
+ uint errmsg= deprecation_substitute[0] == '\0'
+ ? ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT
+ : ER_WARN_DEPRECATED_SYNTAX;
if (thd)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DEPRECATED_SYNTAX, ER(errmsg),
- buf1, buf2, deprecated.substitute);
+ buf1, deprecation_substitute);
else
- sql_print_warning(ER_DEFAULT(errmsg), buf1, buf2, deprecated.substitute);
+ sql_print_warning(ER_DEFAULT(errmsg), buf1, deprecation_substitute);
}
}
diff --git a/sql/set_var.h b/sql/set_var.h
index fea947aa1da..d6dad2132ce 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -80,7 +80,7 @@ protected:
ptrdiff_t offset; ///< offset to the value from global_system_variables
on_check_function on_check;
on_update_function on_update;
- struct { uint version; const char *substitute; } deprecated;
+ const char *const deprecation_substitute;
bool is_os_charset; ///< true if the value is in character_set_filesystem
public:
@@ -89,7 +89,7 @@ public:
enum get_opt_arg_type getopt_arg_type, SHOW_TYPE show_val_type_arg,
longlong def_val, PolyLock *lock, enum binlog_status_enum binlog_status_arg,
on_check_function on_check_func, on_update_function on_update_func,
- uint deprecated_version, const char *substitute);
+ const char *substitute);
virtual ~sys_var() {}
diff --git a/sql/share/charsets/Index.xml b/sql/share/charsets/Index.xml
index 80b844e2f19..f32d8bf6127 100644
--- a/sql/share/charsets/Index.xml
+++ b/sql/share/charsets/Index.xml
@@ -3,7 +3,7 @@
<charsets max-id="99">
<copyright>
- Copyright (C) 2003 MySQL AB
+ Copyright (c) 2003, 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/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 6fedddc6b04..a6ebebeae39 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -6342,8 +6342,8 @@ ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT
ER_PATH_LENGTH
eng "The path specified for %.64s is too long."
ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT
- eng "The syntax '%s' is deprecated and will be removed in MariaDB %s."
- ger "Die Syntax '%s' ist veraltet und wird in MariaDB %s entfernt."
+ eng "'%s' is deprecated and will be removed in a future release."
+ ger "'%s' ist veraltet und wird in einer zukünftigen Version entfernt werden."
ER_WRONG_NATIVE_TABLE_STRUCTURE
eng "Native table '%-.64s'.'%-.64s' has the wrong structure"
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 0c8f1d8916a..a24da193c00 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -3112,8 +3112,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/spatial.cc b/sql/spatial.cc
index e82eec26fdb..de0b563eaf4 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -601,7 +601,8 @@ uint Gis_line_string::init_from_wkb(const char *wkb, uint len,
Gis_point p;
if (len < 4 ||
- (n_points= wkb_get_uint(wkb, bo))<1)
+ (n_points= wkb_get_uint(wkb, bo)) < 1 ||
+ n_points > max_n_points)
return 0;
proper_length= 4 + n_points * POINT_DATA_SIZE;
@@ -1334,9 +1335,9 @@ uint Gis_multi_point::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo,
Gis_point p;
const char *wkb_end;
- if (len < 4)
+ if (len < 4 ||
+ (n_points= wkb_get_uint(wkb, bo)) > max_n_points)
return 0;
- n_points= wkb_get_uint(wkb, bo);
proper_size= 4 + n_points * (WKB_HEADER_SIZE + POINT_DATA_SIZE);
if (len < proper_size || res->reserve(proper_size))
diff --git a/sql/spatial.h b/sql/spatial.h
index 07675d59040..1277e7bc01c 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -391,6 +391,10 @@ public:
class Gis_line_string: public Geometry
{
+ // Maximum number of points in LineString that can fit into String
+ static const uint32 max_n_points=
+ (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) /
+ POINT_DATA_SIZE;
public:
Gis_line_string() {} /* Remove gcc warning */
virtual ~Gis_line_string() {} /* Remove gcc warning */
@@ -451,6 +455,10 @@ public:
class Gis_multi_point: public Geometry
{
+ // Maximum number of points in MultiPoint that can fit into String
+ static const uint32 max_n_points=
+ (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) /
+ (WKB_HEADER_SIZE + POINT_DATA_SIZE);
public:
Gis_multi_point() {} /* Remove gcc warning */
virtual ~Gis_multi_point() {} /* Remove gcc warning */
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 139d761a78e..f07781629ea 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)))
{
@@ -4886,11 +4892,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 4baa6612c46..e503e0fc2aa 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -5009,8 +5009,6 @@ restart:
*/
if (thd->locked_tables_mode <= LTM_LOCK_TABLES)
{
- bool need_prelocking= FALSE;
- TABLE_LIST **save_query_tables_last= thd->lex->query_tables_last;
/*
Process elements of the prelocking set which are present there
since parsing stage or were added to it by invocations of
@@ -5023,10 +5021,19 @@ restart:
for (Sroutine_hash_entry *rt= *sroutine_to_open; rt;
sroutine_to_open= &rt->next, rt= rt->next)
{
+ bool need_prelocking= false;
+ TABLE_LIST **save_query_tables_last= thd->lex->query_tables_last;
+
error= open_and_process_routine(thd, thd->lex, rt, prelocking_strategy,
has_prelocking_list, &ot_ctx,
&need_prelocking);
+ if (need_prelocking && ! thd->lex->requires_prelocking())
+ thd->lex->mark_as_requiring_prelocking(save_query_tables_last);
+
+ if (need_prelocking && ! *start)
+ *start= thd->lex->query_tables;
+
if (error)
{
if (ot_ctx.can_recover_from_failed_open())
@@ -5047,12 +5054,6 @@ restart:
goto err;
}
}
-
- if (need_prelocking && ! thd->lex->requires_prelocking())
- thd->lex->mark_as_requiring_prelocking(save_query_tables_last);
-
- if (need_prelocking && ! *start)
- *start= thd->lex->query_tables;
}
}
@@ -5326,6 +5327,12 @@ static bool check_lock_and_start_stmt(THD *thd,
DBUG_ENTER("check_lock_and_start_stmt");
/*
+ Prelocking placeholder is not set for TABLE_LIST that
+ are directly used by TOP level statement.
+ */
+ DBUG_ASSERT(table_list->prelocking_placeholder == false);
+
+ /*
TL_WRITE_DEFAULT and TL_READ_DEFAULT are supposed to be parser only
types of locks so they should be converted to appropriate other types
to be passed to storage engine. The exact lock type passed to the
@@ -8873,7 +8880,9 @@ fill_record(THD * thd, TABLE *table_arg, 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;
@@ -8934,7 +8943,9 @@ fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, List<Item> &fields,
if (item_field && item_field->field && table && table->vfield)
{
DBUG_ASSERT(table == item_field->field->table);
- result= update_virtual_fields(thd, table, TRUE);
+ result= update_virtual_fields(thd, table,
+ table->triggers ? VCOL_UPDATE_ALL :
+ VCOL_UPDATE_FOR_WRITE);
}
}
}
@@ -9018,7 +9029,10 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values,
}
/* 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());
@@ -9069,7 +9083,9 @@ fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, Field **ptr,
{
DBUG_ASSERT(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 2d9cfa25131..af63aefa7f9 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_class.cc b/sql/sql_class.cc
index c2e8d17c355..70b43a9ac3e 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -275,6 +275,64 @@ bool Foreign_key::validate(List<Create_field> &table_fields)
/****************************************************************************
** Thread specific functions
****************************************************************************/
+#ifdef ONLY_FOR_MYSQL_CLOSED_SOURCE_SCHEDULED
+/**
+ Get reference to scheduler data object
+
+ @param thd THD object
+
+ @retval Scheduler data object on THD
+*/
+void *thd_get_scheduler_data(THD *thd)
+{
+ return thd->scheduler.data;
+}
+
+/**
+ Set reference to Scheduler data object for THD object
+
+ @param thd THD object
+ @param psi Scheduler data object to set on THD
+*/
+void thd_set_scheduler_data(THD *thd, void *data)
+{
+ thd->scheduler.data= data;
+}
+
+/**
+ Get reference to Performance Schema object for THD object
+
+ @param thd THD object
+
+ @retval Performance schema object for thread on THD
+*/
+PSI_thread *thd_get_psi(THD *thd)
+{
+ return thd->scheduler.m_psi;
+}
+
+/**
+ Get net_wait_timeout for THD object
+
+ @param thd THD object
+
+ @retval net_wait_timeout value for thread on THD
+*/
+ulong thd_get_net_wait_timeout(THD* thd)
+{
+ return thd->variables.net_wait_timeout;
+}
+
+/**
+ Set reference to Performance Schema object for THD object
+
+ @param thd THD object
+ @param psi Performance schema object for thread
+*/
+void thd_set_psi(THD *thd, PSI_thread *psi)
+{
+ thd->scheduler.m_psi= psi;
+}
/**
Set the state on connection to killed
@@ -407,6 +465,17 @@ void thd_set_net_read_write(THD *thd, uint val)
}
/**
+ Get reading/writing on socket from THD object
+ @param thd THD object
+
+ @retval net.reading_or_writing value for thread on THD.
+*/
+uint thd_get_net_read_write(THD *thd)
+{
+ return thd->net.reading_or_writing;
+}
+
+/**
Set reference to mysys variable in THD object
@param thd THD object
@@ -428,6 +497,7 @@ my_socket thd_get_fd(THD *thd)
{
return thd->net.vio->sd;
}
+#endif
/**
Get thread attributes for connection threads
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 5dff27b2f89..e536ca7a6b4 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -330,7 +330,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_insert.cc b/sql/sql_insert.cc
index 2b83b7afd5e..71ad80dee64 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1641,9 +1641,10 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
}
}
key_copy((uchar*) key,table->record[0],table->key_info+key_nr,0);
+ key_part_map keypart_map= (1 << table->key_info[key_nr].key_parts) - 1;
if ((error= (table->file->ha_index_read_idx_map(table->record[1],
key_nr, (uchar*) key,
- HA_WHOLE_KEY,
+ keypart_map,
HA_READ_KEY_EXACT))))
goto err;
}
diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc
index 4148842a826..1f375bf1a03 100644
--- a/sql/sql_join_cache.cc
+++ b/sql/sql_join_cache.cc
@@ -681,7 +681,23 @@ void JOIN_CACHE::set_constants()
uint len= length + fields*sizeof(uint)+blobs*sizeof(uchar *) +
(prev_cache ? prev_cache->get_size_of_rec_offset() : 0) +
sizeof(ulong);
- buff_size= max(join->thd->variables.join_buff_size, 2*len);
+ /*
+ The values of size_of_rec_ofs, size_of_rec_len, size_of_fld_ofs,
+ base_prefix_length, pack_length, pack_length_with_blob_ptrs
+ will be recalculated later in this function when we get the estimate
+ for the actual value of the join buffer size.
+ */
+ size_of_rec_ofs= size_of_rec_len= size_of_fld_ofs= 4;
+ base_prefix_length= (with_length ? size_of_rec_len : 0) +
+ (prev_cache ? prev_cache->get_size_of_rec_offset() : 0);
+ pack_length= (with_length ? size_of_rec_len : 0) +
+ (prev_cache ? prev_cache->get_size_of_rec_offset() : 0) +
+ length + fields*sizeof(uint);
+ pack_length_with_blob_ptrs= pack_length + blobs*sizeof(uchar *);
+ min_buff_size= 0;
+ min_records= 1;
+ buff_size= max(join->thd->variables.join_buff_size,
+ get_min_join_buffer_size());
size_of_rec_ofs= offset_size(buff_size);
size_of_rec_len= blobs ? size_of_rec_ofs : offset_size(len);
size_of_fld_ofs= size_of_rec_len;
@@ -754,19 +770,24 @@ ulong JOIN_CACHE::get_min_join_buffer_size()
if (!min_buff_size)
{
size_t len= 0;
+ size_t len_last= 0;
for (JOIN_TAB *tab= start_tab; tab != join_tab;
tab= next_linear_tab(join, tab, WITHOUT_BUSH_ROOTS))
{
len+= tab->get_max_used_fieldlength();
+ len_last=+ tab->get_used_fieldlength();
}
- len+= get_record_max_affix_length() + get_max_key_addon_space_per_record();
- size_t min_sz= len*min_records;
+ size_t len_addon= get_record_max_affix_length() +
+ get_max_key_addon_space_per_record();
+ len+= len_addon;
+ len_last+= len_addon;
+ size_t min_sz= len*(min_records-1) + len_last;
+ min_sz+= pack_length_with_blob_ptrs;
size_t add_sz= 0;
for (uint i=0; i < min_records; i++)
add_sz+= join_tab_scan->aux_buffer_incr(i+1);
avg_aux_buffer_incr= add_sz/min_records;
min_sz+= add_sz;
- min_sz+= pack_length_with_blob_ptrs;
set_if_bigger(min_sz, 1);
min_buff_size= min_sz;
}
diff --git a/sql/sql_list.h b/sql/sql_list.h
index e3a04c36071..2b2d9e59771 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -667,6 +667,9 @@ public:
inline void empty() { first= &last; last.prev= &first; }
base_ilist() { empty(); }
inline bool is_empty() { return first == &last; }
+ // Returns true if p is the last "real" object in the list,
+ // i.e. p->next points to the sentinel.
+ inline bool is_last(ilink *p) { return p->next == NULL || p->next == &last; }
inline void append(ilink *a)
{
first->prev= &a->next;
@@ -742,6 +745,7 @@ class I_List :private base_ilist
{
public:
I_List() :base_ilist() {}
+ inline bool is_last(T *p) { return base_ilist::is_last(p); }
inline void empty() { base_ilist::empty(); }
inline bool is_empty() { return base_ilist::is_empty(); }
inline void append(T* a) { base_ilist::append(a); }
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 73746b826d0..7bc4f8f1833 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -6878,8 +6878,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_plugin.cc b/sql/sql_plugin.cc
index f19b8ca26ef..e15f6339847 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -274,7 +274,7 @@ public:
(plugin_var_arg->flags & PLUGIN_VAR_THDLOCAL ? SESSION : GLOBAL) |
(plugin_var_arg->flags & PLUGIN_VAR_READONLY ? READONLY : 0),
0, -1, NO_ARG, pluginvar_show_type(plugin_var_arg), 0, 0,
- VARIABLE_NOT_IN_BINLOG, 0, 0, 0, 0),
+ VARIABLE_NOT_IN_BINLOG, NULL, NULL, NULL),
plugin_var(plugin_var_arg), orig_pluginvar_name(plugin_var_arg->name)
{ plugin_var->name= name_arg; }
sys_var_pluginvar *cast_pluginvar() { return this; }
@@ -2159,7 +2159,8 @@ static bool do_uninstall(THD *thd, TABLE *table, const LEX_STRING *name)
struct st_plugin_int *plugin;
mysql_mutex_assert_owner(&LOCK_plugin);
- if (!(plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
+ if (!(plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)) ||
+ plugin->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_DYING))
{
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PLUGIN", name->str);
return 1;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index d3e3195081d..96b7d825bd3 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -878,6 +878,14 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array,
param->set_param_func(param, &read_pos, (uint) (data_end - read_pos));
if (param->state == Item_param::NO_VALUE)
DBUG_RETURN(1);
+
+ if (param->limit_clause_param && param->item_type != Item::INT_ITEM)
+ {
+ param->set_int(param->val_int(), MY_INT64_NUM_DECIMAL_DIGITS);
+ param->item_type= Item::INT_ITEM;
+ if (!param->unsigned_flag && param->value.integer < 0)
+ DBUG_RETURN(1);
+ }
}
}
/*
@@ -2500,14 +2508,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_priv.h b/sql/sql_priv.h
index a1c0b2d8729..762a7769acf 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -365,6 +365,8 @@ inline int hexchar_to_int(char c)
#define IS_TABLESPACES_NODEGROUP_ID 7
#define IS_TABLESPACES_TABLESPACE_COMMENT 8
+bool db_name_is_in_ignore_db_dirs_list(const char *dbase);
+
#endif /* MYSQL_SERVER */
#endif /* MYSQL_CLIENT */
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 04fa90024e9..6495211dd9f 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -769,8 +769,6 @@ JOIN::prepare(Item ***rref_pointer_array,
if (having)
{
- Query_arena backup, *arena;
- arena= thd->activate_stmt_arena_if_needed(&backup);
nesting_map save_allow_sum_func= thd->lex->allow_sum_func;
thd->where="having clause";
thd->lex->allow_sum_func|= 1 << select_lex_arg->nest_level;
@@ -786,9 +784,6 @@ JOIN::prepare(Item ***rref_pointer_array,
(having->fix_fields(thd, &having) ||
having->check_cols(1)));
select_lex->having_fix_field= 0;
- select_lex->having= having;
- if (arena)
- thd->restore_active_arena(arena, &backup);
if (having_fix_rc || thd->is_error())
DBUG_RETURN(-1); /* purecov: inspected */
@@ -1301,11 +1296,9 @@ JOIN::optimize_inner()
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;
@@ -1743,12 +1736,19 @@ JOIN::optimize_inner()
DBUG_RETURN(1);
}
}
-
+ /*
+ Calculate a possible 'limit' of table rows for 'GROUP BY': 'need_tmp'
+ implies that there will be more postprocessing so the specified
+ 'limit' should not be enforced yet in the call to
+ 'test_if_skip_sort_order'.
+ */
+ const ha_rows limit = need_tmp ? HA_POS_ERROR : unit->select_limit_cnt;
+
if (!(select_options & SELECT_BIG_RESULT) &&
((group_list &&
(!simple_group ||
!test_if_skip_sort_order(&join_tab[const_tables], group_list,
- unit->select_limit_cnt, 0,
+ limit, 0,
&join_tab[const_tables].table->
keys_in_use_for_group_by))) ||
select_distinct) &&
@@ -2146,6 +2146,7 @@ JOIN::reinit()
ULL(0));
first_record= 0;
+ cleaned= false;
if (exec_tmp_table1)
{
@@ -4020,8 +4021,10 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
new_fields->null_rejecting);
}
else if (old->eq_func && new_fields->eq_func &&
- ((old->val->const_item() && old->val->is_null()) ||
- new_fields->val->is_null()))
+ ((old->val->const_item() && !old->val->is_expensive() &&
+ old->val->is_null()) ||
+ (!new_fields->val->is_expensive() &&
+ new_fields->val->is_null())))
{
/* field = expression OR field IS NULL */
old->level= and_level;
@@ -4035,7 +4038,8 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
Remember the NOT NULL value unless the value does not depend
on other tables.
*/
- if (!old->val->used_tables() && old->val->is_null())
+ if (!old->val->used_tables() && !old->val->is_expensive() &&
+ old->val->is_null())
old->val= new_fields->val;
}
else
@@ -5512,7 +5516,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;
@@ -8109,18 +8114,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)
{
@@ -8167,6 +8177,7 @@ get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables,
key_part->length,
((Item_field*) keyuse->val->real_item())->field,
keyuse->val->real_item()->full_name());
+
return new store_key_item(thd,
key_part->field,
key_buff + maybe_null,
@@ -9280,7 +9291,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;
@@ -10773,6 +10784,7 @@ void JOIN::cleanup(bool full)
{
tab->cleanup();
}
+ cleaned= true;
}
else
{
@@ -16654,6 +16666,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)
{
@@ -16772,6 +16795,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)
{
@@ -16804,12 +16837,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
@@ -18670,15 +18700,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.
@@ -19098,6 +19131,20 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
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());
@@ -19188,64 +19235,9 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
*(join->pre_sort_join_tab)= *tab;
- if (table->file->inited == handler::INDEX)
- {
- // Save index #, save index condition
- 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?
- err= table->file->ha_index_end();
- }
- else
- join->pre_sort_index= MAX_KEY;
-
- /*TODO: here, close the index scan, cancel index-only read. */
-#if 0
- /* MariaDB doesn't need the following: */
- if (select)
- {
- /*
- 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;
-
- // 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
- it will delete the quick object.
- */
- if (!keep_quick)
- {
- select->cleanup();
- /*
- The select object should now be ready for the next use. If it
- is re-used then there exists a backup copy of this join tab
- which has the pointer to it. The join tab will be restored in
- JOIN::reset(). So here we just delete the pointer to it.
- */
- tab->select= NULL;
- // If we deleted the quick select object we need to clear quick_keys
- table->quick_keys.clear_all();
- table->intersect_keys.clear_all();
- }
- // 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();
@@ -19267,34 +19259,13 @@ void JOIN::clean_pre_sort_join_tab()
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
@@ -20775,40 +20746,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)
{
@@ -20820,20 +20817,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);
}
@@ -22644,6 +22641,17 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
str->append(STRING_WITH_LEN("select "));
+ if (join && join->cleaned)
+ {
+ /*
+ JOIN already cleaned up so it is dangerous to print items
+ because temporary tables they pointed on could be freed.
+ */
+ str->append('#');
+ str->append(select_number);
+ return;
+ }
+
/* First add options */
if (options & SELECT_STRAIGHT_JOIN)
str->append(STRING_WITH_LEN("straight_join "));
@@ -23111,6 +23119,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
@@ -23135,7 +23144,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)
@@ -23242,7 +23252,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 */
@@ -23324,7 +23334,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 3b323908532..638de926d75 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -904,6 +904,15 @@ 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
either:
@@ -916,15 +925,6 @@ public:
JOIN_TAB *table_access_tabs;
uint top_table_access_tabs_count;
- /*
- 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();
-
-
JOIN_TAB **map2table; ///< mapping between table indexes and JOIN_TABs
JOIN_TAB *join_tab_save; ///< saved join_tab for subquery reexecution
@@ -1148,6 +1148,8 @@ public:
bool skip_sort_order;
bool need_tmp, hidden_group_fields;
+ /* TRUE if there was full cleunap of the JOIN */
+ bool cleaned;
DYNAMIC_ARRAY keyuse;
Item::cond_result cond_value, having_value;
List<Item> all_fields; ///< to store all fields that used in query
@@ -1282,6 +1284,7 @@ public:
optimized= 0;
have_query_plan= QEP_NOT_PRESENT_YET;
initialized= 0;
+ cleaned= 0;
cond_equal= 0;
having_equal= 0;
exec_const_cond= 0;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index dccf54b0199..a1c77760681 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -414,6 +414,281 @@ bool mysqld_show_privileges(THD *thd)
}
+/** Hash of LEX_STRINGs used to search for ignored db directories. */
+static HASH ignore_db_dirs_hash;
+
+/**
+ An array of LEX_STRING pointers to collect the options at
+ option parsing time.
+*/
+static DYNAMIC_ARRAY ignore_db_dirs_array;
+
+/**
+ A value for the read only system variable to show a list of
+ ignored directories.
+*/
+char *opt_ignore_db_dirs= NULL;
+
+/**
+ This flag is ON if:
+ - the list of ignored directories is not empty
+
+ - and some of the ignored directory names
+ need no tablename-to-filename conversion.
+ Otherwise, if the name of the directory contains
+ unconditional characters like '+' or '.', they
+ never can match the database directory name. So the
+ db_name_is_in_ignore_db_dirs_list() can just return at once.
+*/
+static bool skip_ignored_dir_check= TRUE;
+
+/**
+ Sets up the data structures for collection of directories at option
+ processing time.
+ We need to collect the directories in an array first, because
+ we need the character sets initialized before setting up the hash.
+
+ @return state
+ @retval TRUE failed
+ @retval FALSE success
+*/
+
+bool
+ignore_db_dirs_init()
+{
+ return my_init_dynamic_array(&ignore_db_dirs_array, sizeof(LEX_STRING *),
+ 0, 0);
+}
+
+
+/**
+ Retrieves the key (the string itself) from the LEX_STRING hash members.
+
+ Needed by hash_init().
+
+ @param data the data element from the hash
+ @param out len_ret Placeholder to return the length of the key
+ @param unused
+ @return a pointer to the key
+*/
+
+static uchar *
+db_dirs_hash_get_key(const uchar *data, size_t *len_ret,
+ my_bool __attribute__((unused)))
+{
+ LEX_STRING *e= (LEX_STRING *) data;
+
+ *len_ret= e->length;
+ return (uchar *) e->str;
+}
+
+
+/**
+ Wrap a directory name into a LEX_STRING and push it to the array.
+
+ Called at option processing time for each --ignore-db-dir option.
+
+ @param path the name of the directory to push
+ @return state
+ @retval TRUE failed
+ @retval FALSE success
+*/
+
+bool
+push_ignored_db_dir(char *path)
+{
+ LEX_STRING *new_elt;
+ char *new_elt_buffer;
+ size_t path_len= strlen(path);
+
+ if (!path_len || path_len >= FN_REFLEN)
+ return true;
+
+ // No need to normalize, it's only a directory name, not a path.
+ if (!my_multi_malloc(0,
+ &new_elt, sizeof(LEX_STRING),
+ &new_elt_buffer, path_len + 1,
+ NullS))
+ return true;
+ new_elt->str= new_elt_buffer;
+ memcpy(new_elt_buffer, path, path_len);
+ new_elt_buffer[path_len]= 0;
+ new_elt->length= path_len;
+ return insert_dynamic(&ignore_db_dirs_array, (uchar*) &new_elt);
+}
+
+
+/**
+ Clean up the directory ignore options accumulated so far.
+
+ Called at option processing time for each --ignore-db-dir option
+ with an empty argument.
+*/
+
+void
+ignore_db_dirs_reset()
+{
+ LEX_STRING **elt;
+ while (NULL!= (elt= (LEX_STRING **) pop_dynamic(&ignore_db_dirs_array)))
+ if (elt && *elt)
+ my_free(*elt);
+}
+
+
+/**
+ Free the directory ignore option variables.
+
+ Called at server shutdown.
+*/
+
+void
+ignore_db_dirs_free()
+{
+ if (opt_ignore_db_dirs)
+ {
+ my_free(opt_ignore_db_dirs);
+ opt_ignore_db_dirs= NULL;
+ }
+ ignore_db_dirs_reset();
+ delete_dynamic(&ignore_db_dirs_array);
+ my_hash_free(&ignore_db_dirs_hash);
+}
+
+
+/**
+ Initialize the ignore db directories hash and status variable from
+ the options collected in the array.
+
+ Called when option processing is over and the server's in-memory
+ structures are fully initialized.
+
+ @return state
+ @retval TRUE failed
+ @retval FALSE success
+*/
+
+static void dispose_db_dir(void *ptr)
+{
+ my_free(ptr);
+}
+
+
+bool
+ignore_db_dirs_process_additions()
+{
+ ulong i;
+ size_t len;
+ char *ptr;
+ LEX_STRING *dir;
+
+
+ skip_ignored_dir_check= TRUE;
+
+ if (my_hash_init(&ignore_db_dirs_hash,
+ lower_case_table_names ?
+ character_set_filesystem : &my_charset_bin,
+ 0, 0, 0, db_dirs_hash_get_key,
+ dispose_db_dir,
+ HASH_UNIQUE))
+ return true;
+
+ /* len starts from 1 because of the terminating zero. */
+ len= 1;
+ for (i= 0; i < ignore_db_dirs_array.elements; i++)
+ {
+ get_dynamic(&ignore_db_dirs_array, (uchar *) &dir, i);
+ len+= dir->length + 1; // +1 for the comma
+ if (skip_ignored_dir_check)
+ {
+ char buff[FN_REFLEN];
+ (void) tablename_to_filename(dir->str, buff, sizeof(buff));
+ skip_ignored_dir_check= strcmp(dir->str, buff) != 0;
+ }
+ }
+
+ /* No delimiter for the last directory. */
+ if (len > 1)
+ len--;
+
+ /* +1 the terminating zero */
+ ptr= opt_ignore_db_dirs= (char *) my_malloc(len + 1, MYF(0));
+ if (!ptr)
+ return true;
+
+ /* Make sure we have an empty string to start with. */
+ *ptr= 0;
+
+ for (i= 0; i < ignore_db_dirs_array.elements; i++)
+ {
+ get_dynamic(&ignore_db_dirs_array, (uchar *) &dir, i);
+ if (my_hash_insert(&ignore_db_dirs_hash, (uchar *) dir))
+ return true;
+ ptr= strnmov(ptr, dir->str, dir->length);
+ if (i + 1 < ignore_db_dirs_array.elements)
+ ptr= strmov(ptr, ",");
+
+ /*
+ Set the transferred array element to NULL to avoid double free
+ in case of error.
+ */
+ dir= NULL;
+ set_dynamic(&ignore_db_dirs_array, (uchar *) &dir, i);
+ }
+
+ /* make sure the string is terminated */
+ DBUG_ASSERT(ptr - opt_ignore_db_dirs <= (ptrdiff_t) len);
+ *ptr= 0;
+
+ /*
+ It's OK to empty the array here as the allocated elements are
+ referenced through the hash now.
+ */
+ reset_dynamic(&ignore_db_dirs_array);
+
+ return false;
+}
+
+
+/**
+ Check if a directory name is in the hash of ignored directories.
+
+ @return search result
+ @retval TRUE found
+ @retval FALSE not found
+*/
+
+static inline bool
+is_in_ignore_db_dirs_list(const char *directory)
+{
+ return ignore_db_dirs_hash.records &&
+ NULL != my_hash_search(&ignore_db_dirs_hash, (const uchar *) directory,
+ strlen(directory));
+}
+
+
+/**
+ Check if a database name is in the hash of ignored directories.
+
+ @return search result
+ @retval TRUE found
+ @retval FALSE not found
+*/
+
+bool
+db_name_is_in_ignore_db_dirs_list(const char *directory)
+{
+ char buff[FN_REFLEN];
+ uint buff_len;
+
+ if (skip_ignored_dir_check)
+ return 0;
+
+ buff_len= tablename_to_filename(directory, buff, sizeof(buff));
+
+ return my_hash_search(&ignore_db_dirs_hash, (uchar *) buff, buff_len)!=NULL;
+}
+
+
/*
find_files() - find files in a given directory.
@@ -499,6 +774,9 @@ find_files(THD *thd, List<LEX_STRING> *files, const char *db,
if (!MY_S_ISDIR(file->mystat->st_mode))
continue;
+ if (is_in_ignore_db_dirs_list(file->name))
+ continue;
+
file_name_len= filename_to_tablename(file->name, uname, sizeof(uname));
if (wild)
{
@@ -3810,8 +4088,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_show.h b/sql/sql_show.h
index 7541ed58e48..03d8af3aabd 100644
--- a/sql/sql_show.h
+++ b/sql/sql_show.h
@@ -158,4 +158,12 @@ public:
void call_in_target_thread();
};
+/* Handle the ignored database directories list for SHOW/I_S. */
+bool ignore_db_dirs_init();
+void ignore_db_dirs_free();
+void ignore_db_dirs_reset();
+bool ignore_db_dirs_process_additions();
+bool push_ignored_db_dir(char *path);
+extern char *opt_ignore_db_dirs;
+
#endif /* SQL_SHOW_H */
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 633170a5e20..2966fc2a920 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -2,8 +2,8 @@
#define SQL_STRING_INCLUDED
/*
- Copyright (c) 2000, 2011, Oracle and/or its affiliates.
- Copyright (c) 2008-2011 Monty Program Ab
+ Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2008, 2011, 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
@@ -279,8 +279,11 @@ public:
}
return realloc_with_extra(arg_length);
}
- inline void shrink(uint32 arg_length) // Shrink buffer
+ // Shrink the buffer, but only if it is allocated on the heap.
+ inline void shrink(uint32 arg_length)
{
+ if (!is_alloced())
+ return;
if (ALIGN_SIZE(arg_length+1) < Alloced_length)
{
char *new_ptr;
@@ -296,7 +299,7 @@ public:
}
}
}
- bool is_alloced() { return alloced; }
+ bool is_alloced() const { return alloced; }
inline String& operator = (const String &s)
{
if (&s != this)
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 214580f53ca..72bc3b6dc69 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -7481,7 +7481,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 (to->default_field && to->update_default_fields())
{
error= 1;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 4f3843c989f..518c2c70994 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -551,7 +551,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)
{
@@ -667,7 +669,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/sys_vars.cc b/sql/sys_vars.cc
index 5eb75687dff..9cf2a64a1b8 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -48,6 +48,7 @@
#include <myisam.h>
#include "log_slow.h"
#include "debug_sync.h" // DEBUG_SYNC
+#include "sql_show.h"
#include "log_event.h"
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
@@ -568,14 +569,14 @@ static Sys_var_ulong Sys_connect_timeout(
static Sys_var_charptr Sys_datadir(
"datadir", "Path to the database root directory",
READ_ONLY GLOBAL_VAR(mysql_real_data_home_ptr),
- CMD_LINE(REQUIRED_ARG, 'h'), IN_FS_CHARSET, DEFAULT(0));
+ CMD_LINE(REQUIRED_ARG, 'h'), IN_FS_CHARSET, DEFAULT(mysql_real_data_home));
#ifndef DBUG_OFF
static Sys_var_dbug Sys_dbug(
"debug", "Built-in DBUG debugger", sys_var::SESSION,
CMD_LINE(OPT_ARG, '#'), DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG,
ON_CHECK(check_has_super), ON_UPDATE(0),
- DEPRECATED(100100, "'@@debug_dbug'"));
+ DEPRECATED("'@@debug_dbug'"));
static Sys_var_dbug Sys_debug_dbug(
"debug_dbug", "Built-in DBUG debugger", sys_var::SESSION,
@@ -1235,7 +1236,7 @@ static Sys_var_harows Sys_sql_max_join_size(
SESSION_VAR(max_join_size), NO_CMD_LINE,
VALID_RANGE(1, HA_POS_ERROR), DEFAULT(HA_POS_ERROR), BLOCK_SIZE(1),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
- ON_UPDATE(fix_max_join_size), DEPRECATED(100100, "'@@max_join_size'"));
+ ON_UPDATE(fix_max_join_size), DEPRECATED("'@@max_join_size'"));
static Sys_var_ulong Sys_max_long_data_size(
"max_long_data_size",
@@ -1678,7 +1679,7 @@ static Sys_var_ulong Sys_rpl_recovery_rank(
GLOBAL_VAR(rpl_recovery_rank), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(0, ULONG_MAX), DEFAULT(0), BLOCK_SIZE(1),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0),
- DEPRECATED(100100, 0));
+ DEPRECATED(""));
static Sys_var_ulong Sys_range_alloc_block_size(
"range_alloc_block_size",
@@ -1692,7 +1693,7 @@ static Sys_var_ulong Sys_multi_range_count(
SESSION_VAR(multi_range_count), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(1, ULONG_MAX), DEFAULT(256), BLOCK_SIZE(1),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0),
- DEPRECATED(100100, "'@@mrr_buffer_size'"));
+ DEPRECATED("'@@mrr_buffer_size'"));
static bool fix_thd_mem_root(sys_var *self, THD *thd, enum_var_type type)
{
@@ -2427,7 +2428,7 @@ static Sys_var_mybool Sys_engine_condition_pushdown(
CMD_LINE(OPT_ARG, OPT_ENGINE_CONDITION_PUSHDOWN),
DEFAULT(TRUE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(NULL),
ON_UPDATE(fix_engine_condition_pushdown),
- DEPRECATED(100100, "'@@optimizer_switch'"));
+ DEPRECATED("'@@optimizer_switch'"));
static Sys_var_plugin Sys_default_storage_engine(
"default_storage_engine", "The default storage engine for new tables",
@@ -3109,7 +3110,7 @@ static Sys_var_mybool Sys_log(
"log", "Alias for --general-log. Deprecated",
GLOBAL_VAR(opt_log), NO_CMD_LINE,
DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
- ON_UPDATE(fix_log_state), DEPRECATED(100100, "'@@general_log'"));
+ ON_UPDATE(fix_log_state), DEPRECATED("'@@general_log'"));
static Sys_var_mybool Sys_slow_query_log(
"slow_query_log",
@@ -3126,7 +3127,7 @@ static Sys_var_mybool Sys_log_slow(
"Alias for --slow-query-log. Deprecated",
GLOBAL_VAR(opt_slow_log), NO_CMD_LINE,
DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
- ON_UPDATE(fix_log_state), DEPRECATED(100100, "'@@slow_query_log'"));
+ ON_UPDATE(fix_log_state), DEPRECATED("'@@slow_query_log'"));
static bool fix_log_state(sys_var *self, THD *thd, enum_var_type type)
{
@@ -3564,6 +3565,15 @@ static Sys_var_tz Sys_time_zone(
SESSION_VAR(time_zone), NO_CMD_LINE,
DEFAULT(&default_tz), NO_MUTEX_GUARD, IN_BINLOG);
+static Sys_var_charptr Sys_ignore_db_dirs(
+ "ignore_db_dirs",
+ "Specifies a directory to add to the ignore list when collecting "
+ "database names from the datadir. Put a blank argument to reset "
+ "the list accumulated so far.",
+ READ_ONLY GLOBAL_VAR(opt_ignore_db_dirs),
+ CMD_LINE(REQUIRED_ARG, OPT_IGNORE_DB_DIRECTORY),
+ IN_FS_CHARSET, DEFAULT(0));
+
static Sys_var_ulong Sys_sp_cache_size(
"stored_program_cache",
"The soft upper limit for number of cached stored routines for "
diff --git a/sql/sys_vars.h b/sql/sys_vars.h
index b438295c1b0..ceb0a223dff 100644
--- a/sql/sys_vars.h
+++ b/sql/sys_vars.h
@@ -59,7 +59,7 @@
@@foreign_key_checks <-> OPTION_NO_FOREIGN_KEY_CHECKS
*/
#define REVERSE(X) ~(X)
-#define DEPRECATED(X, Y) X, Y
+#define DEPRECATED(X) X
#define session_var(THD, TYPE) (*(TYPE*)session_var_ptr(THD))
#define global_var(TYPE) (*(TYPE*)global_var_ptr())
@@ -126,10 +126,10 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, SHOWT, def_val, lock, binlog_status_arg,
- on_check_func, on_update_func, deprecated_version, substitute)
+ on_check_func, on_update_func, substitute)
{
option.var_type= ARGT;
option.min_value= min_val;
@@ -238,11 +238,11 @@ public:
ulonglong def_val, PolyLock *lock,
enum binlog_status_enum binlog_status_arg,
on_check_function on_check_func, on_update_function on_update_func,
- uint deprecated_version, const char *substitute)
+ const char *substitute)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, show_val_type_arg, def_val, lock,
binlog_status_arg, on_check_func,
- on_update_func, deprecated_version, substitute)
+ on_update_func, substitute)
{
for (typelib.count= 0; values[typelib.count]; typelib.count++) /*no-op */;
typelib.name="";
@@ -305,11 +305,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
SHOW_CHAR, values, def_val, lock,
binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
option.var_type= GET_ENUM;
global_var(ulong)= def_val;
@@ -352,11 +352,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
SHOW_MY_BOOL, bool_values, def_val, lock,
binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
option.var_type= GET_BOOL;
global_var(my_bool)= def_val;
@@ -407,11 +407,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, SHOW_CHAR_PTR, (intptr)def_val,
lock, binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
is_os_charset= is_os_charset_arg == IN_FS_CHARSET;
/*
@@ -502,7 +502,7 @@ public:
: sys_var(&all_sys_vars, name_arg, comment,
sys_var::READONLY+sys_var::ONLY_SESSION, 0, -1,
NO_ARG, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG,
- NULL, NULL, 0, NULL)
+ NULL, NULL, NULL)
{
is_os_charset= is_os_charset_arg == IN_FS_CHARSET;
option.var_type= GET_STR;
@@ -561,7 +561,7 @@ public:
Sys_var_rpl_filter(const char *name, int getopt_id, const char *comment)
: sys_var(&all_sys_vars, name, comment, sys_var::GLOBAL, 0, -1,
NO_ARG, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG,
- NULL, NULL, 0, NULL), opt_id(getopt_id)
+ NULL, NULL, NULL), opt_id(getopt_id)
{
option.var_type= GET_STR;
}
@@ -615,10 +615,10 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_charptr(name_arg, comment, flag_args, off, sizeof(char*),
getopt, is_os_charset_arg, def_val, lock, binlog_status_arg,
- on_check_func, on_update_func, deprecated_version, substitute)
+ on_check_func, on_update_func, substitute)
{
global_var(LEX_STRING).length= strlen(def_val);
SYSVAR_ASSERT(size == sizeof(LEX_STRING));
@@ -653,7 +653,7 @@ public:
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, SHOW_CHAR, (intptr)def_val,
0, VARIABLE_NOT_IN_BINLOG, on_check_func, on_update_func,
- 0, 0),max_length(max_length_arg)
+ 0),max_length(max_length_arg)
{
option.var_type= GET_NO_ARG;
SYSVAR_ASSERT(scope() == ONLY_SESSION)
@@ -742,11 +742,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id,
getopt.arg_type, SHOW_CHAR, (intptr)def_val,
lock, binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{ option.var_type= GET_NO_ARG; }
bool do_check(THD *thd, set_var *var)
{
@@ -826,11 +826,11 @@ public:
enum binlog_status_enum binlog_status_arg,
on_check_function on_check_func,
keycache_update_function on_update_func,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_ulonglong(name_arg, comment, flag_args, off, size,
getopt, min_val, max_val, def_val,
block_size, lock, binlog_status_arg, on_check_func, 0,
- deprecated_version, substitute),
+ substitute),
keycache_update(on_update_func)
{
option.var_type|= GET_ASK_ADDR;
@@ -987,11 +987,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, SHOW_DOUBLE, (longlong) double2ulonglong(def_val),
lock, binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
option.var_type= GET_DOUBLE;
option.min_value= (longlong) double2ulonglong(min_val);
@@ -1051,11 +1051,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_int(name_arg, comment, SESSION, off, size, getopt,
min_val, max_val, def_val, block_size,
lock, binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{ }
uchar *session_value_ptr(THD *thd, LEX_STRING *base)
{
@@ -1092,11 +1092,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
SHOW_CHAR, values, def_val, lock,
binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
option.var_type= GET_FLAGSET;
global_var(ulonglong)= def_val;
@@ -1203,11 +1203,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
SHOW_CHAR, values, def_val, lock,
binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
option.var_type= GET_SET;
global_var(ulonglong)= def_val;
@@ -1309,11 +1309,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, SHOW_CHAR, (intptr)def_val,
lock, binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute),
+ substitute),
plugin_type(plugin_type_arg)
{
option.var_type= GET_STR;
@@ -1422,11 +1422,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id,
getopt.arg_type, SHOW_CHAR, (intptr)def_val,
lock, binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
SYSVAR_ASSERT(scope() == ONLY_SESSION);
option.var_type= GET_NO_ARG;
@@ -1515,11 +1515,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
SHOW_MY_BOOL, bool_values, def_val, lock,
binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
option.var_type= GET_BOOL;
reverse_semantics= my_count_bits(bitmask_arg) > 1;
@@ -1588,11 +1588,11 @@ public:
on_check_function on_check_func,
session_special_update_function update_func_arg,
session_special_read_function read_func_arg,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_ulonglong(name_arg, comment, flag_args, 0,
sizeof(ulonglong), getopt, min_val,
max_val, 0, block_size, lock, binlog_status_arg, on_check_func, 0,
- deprecated_version, substitute),
+ substitute),
read_func(read_func_arg), update_func(update_func_arg)
{
SYSVAR_ASSERT(scope() == ONLY_SESSION);
@@ -1638,11 +1638,11 @@ public:
on_check_function on_check_func,
session_special_update_function update_func_arg,
session_special_read_function read_func_arg,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_double(name_arg, comment, flag_args, 0,
sizeof(double), getopt, min_val,
max_val, 0, lock, binlog_status_arg, on_check_func, 0,
- deprecated_version, substitute),
+ substitute),
read_func(read_func_arg), update_func(update_func_arg)
{
SYSVAR_ASSERT(scope() == ONLY_SESSION);
@@ -1692,11 +1692,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, SHOW_CHAR, 0,
lock, binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
SYSVAR_ASSERT(scope() == GLOBAL);
SYSVAR_ASSERT(getopt.id == -1);
@@ -1760,11 +1760,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, SHOW_CHAR, (intptr)def_val,
lock, binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute),
+ substitute),
name_offset(name_off)
{
option.var_type= GET_STR;
@@ -1832,11 +1832,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, SHOW_CHAR, (intptr)def_val,
lock, binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
SYSVAR_ASSERT(getopt.id == -1);
SYSVAR_ASSERT(size == sizeof(Time_zone *));
diff --git a/sql/table.cc b/sql/table.cc
index 4b408704c63..bd9dcb4e261 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;
}
@@ -3462,6 +3463,9 @@ bool check_db_name(LEX_STRING *org_name)
if (lower_case_table_names && name != any_db)
my_casedn_str(files_charset_info, name);
+ if (db_name_is_in_ignore_db_dirs_list(name))
+ return 1;
+
return check_table_name(name, name_length, check_for_path_chars);
}
@@ -4982,7 +4986,16 @@ TABLE *TABLE_LIST::get_real_join_table()
tbl= (tbl->view != NULL ?
tbl->view->select_lex.get_table_list() :
tbl->derived->first_select()->get_table_list());
+
+ /* find left table in outer join on this level */
+ while(tbl->outer_join & JOIN_TYPE_RIGHT)
+ {
+ DBUG_ASSERT(tbl->next_local);
+ tbl= tbl->next_local;
+ }
+
}
+
return tbl->table;
}
@@ -6463,22 +6476,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;
@@ -6491,9 +6507,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 b5671b50083..a43f729ba5c 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -300,6 +300,12 @@ 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
+};
class Filesort_info
{
@@ -1871,6 +1877,7 @@ struct TABLE_LIST
/* TRUE <=> derived table should be filled right after optimization. */
bool fill_me;
/* TRUE <=> view/DT is merged. */
+ /* TODO: replace with derived_type */
bool merged;
bool merged_for_insert;
/* TRUE <=> don't prepare this derived table/view as it should be merged.*/
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/archive/ha_archive.cc b/storage/archive/ha_archive.cc
index 396d5a21be5..d40971e4adf 100644
--- a/storage/archive/ha_archive.cc
+++ b/storage/archive/ha_archive.cc
@@ -275,7 +275,7 @@ int archive_discover(handlerton *hton, THD* thd, const char *db,
build_table_filename(az_file, sizeof(az_file) - 1, db, name, ARZ, 0);
- if (!(mysql_file_stat(arch_key_file_data, az_file, &file_stat, MYF(0))))
+ if (!(mysql_file_stat(/* arch_key_file_data */ 0, az_file, &file_stat, MYF(0))))
goto err;
if (!(azopen(&frm_stream, az_file, O_RDONLY|O_BINARY)))
@@ -738,7 +738,7 @@ int ha_archive::create(const char *name, TABLE *table_arg,
There is a chance that the file was "discovered". In this case
just use whatever file is there.
*/
- if (!(mysql_file_stat(arch_key_file_data, name_buff, &file_stat, MYF(0))))
+ if (!(mysql_file_stat(/* arch_key_file_data */ 0, name_buff, &file_stat, MYF(0))))
{
my_errno= 0;
if (!(azopen(&create_stream, name_buff, O_CREAT|O_RDWR|O_BINARY)))
@@ -1628,7 +1628,7 @@ int ha_archive::info(uint flag)
{
MY_STAT file_stat; // Stat information for the data file
- (void) mysql_file_stat(arch_key_file_data, share->data_file_name, &file_stat, MYF(MY_WME));
+ (void) mysql_file_stat(/* arch_key_file_data */ 0, share->data_file_name, &file_stat, MYF(MY_WME));
if (flag & HA_STATUS_TIME)
stats.update_time= (ulong) file_stat.st_mtime;
diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc
index 18ba636c0e2..b543c9ffc90 100644
--- a/storage/federated/ha_federated.cc
+++ b/storage/federated/ha_federated.cc
@@ -1398,7 +1398,7 @@ bool ha_federated::create_where_from_key(String *to,
break;
}
DBUG_PRINT("info", ("federated HA_READ_AFTER_KEY %d", i));
- if (store_length >= length) /* end key */
+ if ((store_length >= length) || (i > 0)) /* for all parts of end key*/
{
if (emit_key_part_name(&tmp, key_part))
goto err;
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 b714219e304..a6fdff72f50 100644
--- a/storage/innobase/btr/btr0btr.c
+++ b/storage/innobase/btr/btr0btr.c
@@ -1844,6 +1844,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 */
@@ -2324,12 +2325,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);
+ }
}
/**************************************************************//**
@@ -3254,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
@@ -3489,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),
@@ -4002,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 (;;) {
@@ -4017,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/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
index 9c61e0cf763..ce43cba8525 100644
--- a/storage/innobase/btr/btr0cur.c
+++ b/storage/innobase/btr/btr0cur.c
@@ -1323,7 +1323,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;
+ }
}
}
@@ -1459,20 +1464,9 @@ btr_cur_pessimistic_insert(
ut_ad(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);
@@ -2076,8 +2070,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))
@@ -2433,7 +2431,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)
@@ -2462,7 +2465,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/innobase/btr/btr0pcur.c b/storage/innobase/btr/btr0pcur.c
index 7ac96c1a1b1..c989498408a 100644
--- a/storage/innobase/btr/btr0pcur.c
+++ b/storage/innobase/btr/btr0pcur.c
@@ -348,44 +348,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/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
index 32d376136e6..70841a168ab 100644
--- a/storage/innobase/buf/buf0buf.c
+++ b/storage/innobase/buf/buf0buf.c
@@ -294,14 +294,7 @@ 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. */
-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
@@ -4424,7 +4417,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/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index f8450cb89f0..42b0fe2b65f 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -11986,7 +11986,10 @@ i_s_innodb_lock_waits,
i_s_innodb_cmp,
i_s_innodb_cmp_reset,
i_s_innodb_cmpmem,
-i_s_innodb_cmpmem_reset
+i_s_innodb_cmpmem_reset,
+i_s_innodb_buffer_page,
+i_s_innodb_buffer_page_lru,
+i_s_innodb_buffer_stats
mysql_declare_plugin_end;
/** @brief Initialize the default value of innodb_commit_concurrency.
diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index abbb8b10ce7..59ea065c5c7 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -45,8 +45,93 @@ extern "C" {
#include "srv0start.h" /* for srv_was_started */
#include "trx0i_s.h"
#include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */
+#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:UNIV_PAGE_SIZE_SHIFT-2;
+ /*!< Number of records on Page */
+ unsigned data_size:UNIV_PAGE_SIZE_SHIFT;
+ /*!< 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); \
@@ -1792,6 +1877,1772 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset =
STRUCT_FLD(flags, 0UL),
};
+/* 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_mysql_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),
+
+ /* reserved for dependency checking */
+ /* void* */
+ STRUCT_FLD(__reserved1, NULL),
+
+ /* Plugin flags */
+ /* unsigned long */
+ STRUCT_FLD(flags, 0UL),
+};
+
+/* 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;
+
+ /* 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);
+
+ /* Obtain appropriate mutexes. Since this is diagnostic
+ buffer pool info printout, we are not required to
+ preserve the overall consistency, so we can
+ release mutex periodically */
+ buf_pool_mutex_enter(buf_pool);
+
+ /* GO through each block in the chunk */
+ for (n_blocks = num_to_process; n_blocks--; block++) {
+ i_s_innodb_buffer_page_get_info(
+ &block->page, pool_id, block_id,
+ info_buffer + num_page);
+ block_id++;
+ num_page++;
+ }
+
+ buf_pool_mutex_exit(buf_pool);
+
+ /* 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_mysql_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),
+
+ /* reserved for dependency checking */
+ /* void* */
+ STRUCT_FLD(__reserved1, NULL),
+
+ /* Plugin flags */
+ /* unsigned long */
+ STRUCT_FLD(flags, 0UL),
+};
+
+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;
+
+ DBUG_ENTER("i_s_innodb_fill_buffer_lru");
+
+ /* Obtain buf_pool mutex before allocate info_buffer, since
+ UT_LIST_GET_LEN(buf_pool->LRU) could change */
+ buf_pool_mutex_enter(buf_pool);
+
+ 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) {
+ /* 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);
+
+ lru_pos++;
+ }
+
+ ut_ad(lru_pos == lru_len);
+ ut_ad(lru_pos == UT_LIST_GET_LEN(buf_pool->LRU));
+
+exit:
+ buf_pool_mutex_exit(buf_pool);
+
+ 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_mysql_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),
+
+ /* reserved for dependency checking */
+ /* void* */
+ STRUCT_FLD(__reserved1, NULL),
+
+ /* Plugin flags */
+ /* unsigned long */
+ STRUCT_FLD(flags, 0UL),
+};
+
/*******************************************************************//**
Unbind a dynamic INFORMATION_SCHEMA table.
@return 0 on success */
@@ -1807,3 +3658,5 @@ i_s_common_deinit(
DBUG_RETURN(0);
}
+
+
diff --git a/storage/innobase/handler/i_s.h b/storage/innobase/handler/i_s.h
index dc0deef119b..6b95ce25b58 100644
--- a/storage/innobase/handler/i_s.h
+++ b/storage/innobase/handler/i_s.h
@@ -35,5 +35,8 @@ extern struct st_mysql_plugin i_s_innodb_cmp;
extern struct st_mysql_plugin i_s_innodb_cmp_reset;
extern struct st_mysql_plugin i_s_innodb_cmpmem;
extern struct st_mysql_plugin i_s_innodb_cmpmem_reset;
+extern struct st_mysql_plugin i_s_innodb_buffer_page;
+extern struct st_mysql_plugin i_s_innodb_buffer_page_lru;
+extern struct st_mysql_plugin i_s_innodb_buffer_stats;;
#endif /* i_s_h */
diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c
index e534e165c0c..c7887afef92 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.c
+++ b/storage/innobase/ibuf/ibuf0ibuf.c
@@ -3604,11 +3604,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/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index a39592943d8..fd8620eab3b 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/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
@@ -758,6 +761,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.
@@ -1325,12 +1340,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
@@ -1345,7 +1373,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/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic
index 0d9687e6b2a..84c0ab9d610 100644
--- a/storage/innobase/include/buf0buf.ic
+++ b/storage/innobase/include/buf0buf.ic
@@ -36,6 +36,15 @@ Created 11/5/1995 Heikki Tuuri
#include "buf0lru.h"
#include "buf0rea.h"
+/** A chunk of buffers. The buffer pool is allocated in chunks. */
+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 current size of buffer buf_pool in bytes.
@return size in bytes */
@@ -1276,4 +1285,21 @@ buf_pool_mutex_exit_all(void)
buf_pool_mutex_exit(buf_pool);
}
}
+/*********************************************************************//**
+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/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index 610bd4b0e5c..ed47ccff052 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -142,6 +142,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/innobase/include/log0log.h b/storage/innobase/include/log0log.h
index 0b8d7b6fa03..f280deeee77 100644
--- a/storage/innobase/include/log0log.h
+++ b/storage/innobase/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/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 5f0380cb55f..78135b0aff2 100644
--- a/storage/innobase/page/page0page.c
+++ b/storage/innobase/page/page0page.c
@@ -781,17 +781,23 @@ 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
- 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))) {
@@ -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);
}
}
@@ -1051,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;
@@ -1066,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);
}
@@ -1470,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/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c
index 60a66ea3945..18486514267 100644
--- a/storage/innobase/row/row0ins.c
+++ b/storage/innobase/row/row0ins.c
@@ -2168,9 +2168,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/innobase/row/row0merge.c b/storage/innobase/row/row0merge.c
index 750f9d72cf2..7c9fb8812e6 100644
--- a/storage/innobase/row/row0merge.c
+++ b/storage/innobase/row/row0merge.c
@@ -1235,11 +1235,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);
}
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 f8f3abc41a5..6fbdfd2ccf4 100644
--- a/storage/maria/ha_maria.cc
+++ b/storage/maria/ha_maria.cc
@@ -2478,9 +2478,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_ft_nlq_search.c b/storage/maria/ma_ft_nlq_search.c
index 5c1ab85ef8a..c8b87c4f42c 100644
--- a/storage/maria/ma_ft_nlq_search.c
+++ b/storage/maria/ma_ft_nlq_search.c
@@ -82,6 +82,7 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
#error
#endif
DBUG_ENTER("walk_and_match");
+ LINT_INIT(subkeys.i);
LINT_INIT_STRUCT(subkeys);
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/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
index 5f24a002014..e53a0cc584f 100644
--- a/storage/myisam/ha_myisam.cc
+++ b/storage/myisam/ha_myisam.cc
@@ -515,7 +515,8 @@ int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
t1_keysegs[j].language != t2_keysegs[j].language) ||
t1_keysegs_j__type != t2_keysegs[j].type ||
t1_keysegs[j].null_bit != t2_keysegs[j].null_bit ||
- t1_keysegs[j].length != t2_keysegs[j].length)
+ t1_keysegs[j].length != t2_keysegs[j].length ||
+ t1_keysegs[j].start != t2_keysegs[j].start)
{
DBUG_PRINT("error", ("Key segment %d (key %d) has different "
"definition", j, i));
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/CMakeLists.txt b/storage/xtradb/CMakeLists.txt
index 1d2b0b29dea..4c098049fd4 100644
--- a/storage/xtradb/CMakeLists.txt
+++ b/storage/xtradb/CMakeLists.txt
@@ -91,12 +91,41 @@ IF(NOT CMAKE_CROSSCOMPILING)
}"
HAVE_IB_GCC_ATOMIC_BUILTINS
)
+ CHECK_C_SOURCE_RUNS(
+ "
+ #include <stdint.h>
+ int main()
+ {
+ int64_t x, y, res;
+
+ x = 10;
+ y = 123;
+ res = __sync_bool_compare_and_swap(&x, x, y);
+ if (!res || x != y) {
+ return(1);
+ }
+
+ x = 10;
+ y = 123;
+ res = __sync_add_and_fetch(&x, y);
+ if (res != 123 + 10 || x != 123 + 10) {
+ return(1);
+ }
+
+ return(0);
+ }"
+ HAVE_IB_GCC_ATOMIC_BUILTINS_64
+ )
ENDIF()
IF(HAVE_IB_GCC_ATOMIC_BUILTINS)
ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_BUILTINS=1)
ENDIF()
+IF(HAVE_IB_GCC_ATOMIC_BUILTINS_64)
+ ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_BUILTINS_64=1)
+ENDIF()
+
# either define HAVE_IB_ATOMIC_PTHREAD_T_GCC or not
IF(NOT CMAKE_CROSSCOMPILING)
CHECK_C_SOURCE_RUNS(
@@ -240,7 +269,7 @@ SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
ibuf/ibuf0ibuf.c
pars/lexyy.c pars/pars0grm.c pars/pars0opt.c pars/pars0pars.c pars/pars0sym.c
lock/lock0lock.c lock/lock0iter.c
- log/log0log.c log/log0recv.c
+ log/log0log.c log/log0recv.c log/log0online.c
mach/mach0data.c
mem/mem0mem.c mem/mem0pool.c
mtr/mtr0log.c mtr/mtr0mtr.c
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/btr/btr0sea.c b/storage/xtradb/btr/btr0sea.c
index 855ab62c42f..7e9449a6474 100644
--- a/storage/xtradb/btr/btr0sea.c
+++ b/storage/xtradb/btr/btr0sea.c
@@ -183,6 +183,15 @@ btr_search_sys_create(
//rw_lock_create(btr_search_latch_key, &btr_search_latch,
// SYNC_SEARCH_SYS);
+ /* PS bug lp:1018264 - Multiple hash index partitions causes overly
+ large hash index: When multiple adaptive hash index partitions are
+ specified, _each_ partition was being created with hash_size which
+ should be 1/64 of the total size of all buffer pools which is
+ incorrect and can cause overly high memory usage. hash_size
+ should be representing the _total_ size of all partitions, not the
+ individual size of each partition. */
+ hash_size /= btr_search_index_num;
+
btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
/* btr_search_index_num should be <= 32. (bits of trx->has_search_latch) */
diff --git a/storage/xtradb/buf/buf0buf.c b/storage/xtradb/buf/buf0buf.c
index a2ff171e0c5..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);
@@ -2838,6 +2832,7 @@ wait_until_unfixed:
&& ibuf_debug) {
/* Try to evict the block from the buffer pool, to use the
insert buffer (change buffer) as much as possible. */
+ ulint page_no = buf_block_get_page_no(block);
if (buf_LRU_free_block(&block->page, TRUE, FALSE)) {
mutex_exit(block_mutex);
@@ -2864,6 +2859,18 @@ wait_until_unfixed:
"innodb_change_buffering_debug evict %u %u\n",
(unsigned) space, (unsigned) offset);
return(NULL);
+ } else if (UNIV_UNLIKELY(buf_block_get_state(block)
+ != BUF_BLOCK_FILE_PAGE
+ || (buf_block_get_page_no(block) != page_no)
+ || (buf_block_get_space(block) != space))) {
+
+ /* buf_LRU_free_block temporarily releases the
+ block mutex, and now block points to something
+ else. */
+ mutex_exit(block_mutex);
+ block = NULL;
+ goto loop2;
+
} else if (buf_flush_page_try(buf_pool, block)) {
fprintf(stderr,
"innodb_change_buffering_debug flush %u %u\n",
@@ -4960,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 16a91358080..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)
@@ -2531,6 +2531,14 @@ func_exit:
Dump the LRU page list to the specific file. */
#define LRU_DUMP_FILE "ib_lru_dump"
#define LRU_DUMP_TEMP_FILE "ib_lru_dump.tmp"
+#define LRU_OS_FILE_WRITE() \
+ os_file_write(LRU_DUMP_FILE, dump_file, buffer, \
+ (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL, \
+ (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)), \
+ buffer_size)
+#define LRU_DUMP_PAGE_COUNT 1 /* Specifies how many dump pages
+ should be filled for each hold
+ of the LRU_list_mutex. */
UNIV_INTERN
ibool
@@ -2541,23 +2549,30 @@ buf_LRU_file_dump(void)
ibool success;
byte* buffer_base = NULL;
byte* buffer = NULL;
+ const ulint buffer_size = LRU_DUMP_PAGE_COUNT * UNIV_PAGE_SIZE;
buf_page_t* bpage;
+ buf_page_t* first_bpage;
ulint buffers;
ulint offset;
- ibool ret = FALSE;
+ ulint pages_written;
ulint i;
+ ulint total_pages;
+
+ /* Sanity test to make sure page size is a multiple of
+ assumed dump record size */
+ ut_a(UNIV_PAGE_SIZE % 8 == 0);
for (i = 0; i < srv_n_data_files; i++) {
if (strstr(srv_data_file_names[i], LRU_DUMP_FILE) != NULL) {
fprintf(stderr,
" InnoDB: The name '%s' seems to be used for"
- " innodb_data_file_path. For safety, dumping of the LRU list"
- " is not being done.\n", LRU_DUMP_FILE);
+ " innodb_data_file_path. Dumping LRU list is"
+ " not done for safeness.\n", LRU_DUMP_FILE);
goto end;
}
}
- buffer_base = ut_malloc(2 * UNIV_PAGE_SIZE);
+ buffer_base = ut_malloc(UNIV_PAGE_SIZE + buffer_size);
buffer = ut_align(buffer_base, UNIV_PAGE_SIZE);
if (!buffer) {
fprintf(stderr,
@@ -2577,18 +2592,28 @@ buf_LRU_file_dump(void)
}
buffers = offset = 0;
-
for (i = 0; i < srv_buf_pool_instances; i++) {
buf_pool_t* buf_pool;
buf_pool = buf_pool_from_array(i);
mutex_enter(&buf_pool->LRU_list_mutex);
- bpage = UT_LIST_GET_LAST(buf_pool->LRU);
+ bpage = first_bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
+ total_pages = UT_LIST_GET_LEN(buf_pool->LRU);
- while (bpage != NULL) {
- if (offset == 0) {
- memset(buffer, 0, UNIV_PAGE_SIZE);
+ pages_written = 0;
+ while (bpage != NULL && (pages_written++ < total_pages)) {
+
+ buf_page_t* next_bpage = UT_LIST_GET_NEXT(LRU, bpage);
+
+ if (next_bpage == first_bpage) {
+ /* Do not release list mutex here, it will be
+ released just outside this while loop */
+ fprintf(stderr,
+ "InnoDB: detected cycle in LRU for"
+ " buffer pool %lu, skipping to next"
+ " buffer pool.\n", i);
+ break;
}
mach_write_to_4(buffer + offset * 4, bpage->space);
@@ -2596,52 +2621,71 @@ buf_LRU_file_dump(void)
mach_write_to_4(buffer + offset * 4, bpage->offset);
offset++;
- if (offset == UNIV_PAGE_SIZE/4) {
+ ut_a(offset <= buffer_size);
+ if (offset == buffer_size/4) {
+ mutex_t *next_block_mutex = NULL;
+
if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
- success = 0;
+ mutex_exit(&buf_pool->LRU_list_mutex);
+ success = FALSE;
fprintf(stderr,
" InnoDB: stopped dumping lru"
" pages because of server"
" shutdown.\n");
+ goto end;
}
- success = os_file_write(LRU_DUMP_FILE, dump_file, buffer,
- (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
- (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
- UNIV_PAGE_SIZE);
+
+ /* While writing file, release buffer pool
+ mutex but keep the next page fixed so we
+ don't worry about our list iterator becoming
+ invalid */
+ if (next_bpage) {
+ next_block_mutex = buf_page_get_mutex(
+ next_bpage);
+
+ mutex_enter(next_block_mutex);
+ next_bpage->buf_fix_count++;
+ mutex_exit(next_block_mutex);
+ }
+ mutex_exit(&buf_pool->LRU_list_mutex);
+
+ success = LRU_OS_FILE_WRITE();
+
+ /* Grab this here so that next_bpage can't
+ be purged when we drop the fix_count */
+ mutex_enter(&buf_pool->LRU_list_mutex);
+
+ if (next_bpage) {
+ mutex_enter(next_block_mutex);
+ next_bpage->buf_fix_count--;
+ mutex_exit(next_block_mutex);
+ }
+
if (!success) {
mutex_exit(&buf_pool->LRU_list_mutex);
fprintf(stderr,
- " InnoDB: cannot write page %lu of %s\n",
+ " InnoDB: cannot write page"
+ " %lu of %s\n",
buffers, LRU_DUMP_FILE);
goto end;
}
buffers++;
offset = 0;
- }
- bpage = UT_LIST_GET_PREV(LRU, bpage);
- }
+ bpage = next_bpage;
+ } else {
+ bpage = UT_LIST_GET_NEXT(LRU, bpage);
+ }
+ } /* while(bpage ...) */
mutex_exit(&buf_pool->LRU_list_mutex);
- }
-
- if (offset == 0) {
- memset(buffer, 0, UNIV_PAGE_SIZE);
- }
+ } /* for(srv_buf_pool_instances ...) */
mach_write_to_4(buffer + offset * 4, 0xFFFFFFFFUL);
offset++;
mach_write_to_4(buffer + offset * 4, 0xFFFFFFFFUL);
offset++;
- success = os_file_write(LRU_DUMP_FILE, dump_file, buffer,
- (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
- (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
- UNIV_PAGE_SIZE);
- if (!success) {
- goto end;
- }
-
- ret = TRUE;
+ success = LRU_OS_FILE_WRITE();
end:
if (dump_file != (os_file_t) -1) {
if (success) {
@@ -2656,7 +2700,7 @@ end:
if (buffer_base)
ut_free(buffer_base);
- return(ret);
+ return(success);
}
typedef struct {
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 a5873bc05d3..965863eb2d2 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -361,7 +361,8 @@ static PSI_thread_info all_innodb_threads[] = {
{&srv_error_monitor_thread_key, "srv_error_monitor_thread", 0},
{&srv_monitor_thread_key, "srv_monitor_thread", 0},
{&srv_master_thread_key, "srv_master_thread", 0},
- {&srv_purge_thread_key, "srv_purge_thread", 0}
+ {&srv_purge_thread_key, "srv_purge_thread", 0},
+ {&srv_log_tracking_thread_key, "srv_redo_log_follow_thread", 0}
};
# endif /* UNIV_PFS_THREAD */
@@ -371,7 +372,8 @@ performance schema instrumented if "UNIV_PFS_IO" is defined */
static PSI_file_info all_innodb_files[] = {
{&innodb_file_data_key, "innodb_data_file", 0},
{&innodb_file_log_key, "innodb_log_file", 0},
- {&innodb_file_temp_key, "innodb_temp_file", 0}
+ {&innodb_file_temp_key, "innodb_temp_file", 0},
+ {&innodb_file_bmp_key, "innodb_bmp_file", 0}
};
# endif /* UNIV_PFS_IO */
#endif /* HAVE_PSI_INTERFACE */
@@ -883,7 +885,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));
}
@@ -2474,6 +2476,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 */
@@ -2608,12 +2726,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) {
@@ -2622,13 +2741,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))) {
@@ -2639,16 +2759,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;
@@ -2657,13 +2779,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;
@@ -2671,10 +2799,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, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
- trx_sys_mysql_master_log_pos = (ib_int64_t) pos;
+ 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(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)
@@ -3009,75 +3142,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);
@@ -3184,6 +3251,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
@@ -3217,6 +3310,12 @@ innobase_commit_low(
#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);
}
}
@@ -3415,6 +3514,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);
@@ -11710,7 +11812,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 */
@@ -11803,6 +11925,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);
@@ -12782,9 +12920,9 @@ static MYSQL_SYSVAR_BOOL(use_sys_stats_table, innobase_use_sys_stats_table,
"So you should use ANALYZE TABLE command intentionally.",
NULL, NULL, FALSE);
-#ifdef UNIV_DEBUG_never
-static MYSQL_SYSVAR_ULONG(sys_stats_root_page, innobase_sys_stats_root_page,
- PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
+#ifdef UNIV_DEBUG
+static MYSQL_SYSVAR_ULONG(persistent_stats_root_page,
+ innobase_sys_stats_root_page, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Override the SYS_STATS root page id, 0 = no override (for testing only)",
NULL, NULL, 0, 0, ULONG_MAX, 0);
#endif
@@ -12821,6 +12959,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",
@@ -12987,6 +13131,18 @@ static MYSQL_SYSVAR_ENUM(stats_method, srv_innodb_stats_method,
"NULLS_UNEQUAL and NULLS_IGNORED",
NULL, NULL, SRV_STATS_NULLS_EQUAL, &innodb_stats_method_typelib);
+static MYSQL_SYSVAR_BOOL(track_changed_pages, srv_track_changed_pages,
+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
+ "Track the redo log for changed pages and output a changed page bitmap",
+ NULL, NULL, FALSE);
+
+static MYSQL_SYSVAR_ULONGLONG(changed_pages_limit, srv_changed_pages_limit,
+ PLUGIN_VAR_RQCMDARG,
+ "The maximum number of rows for "
+ "INFORMATION_SCHEMA.INNODB_CHANGED_PAGES table, "
+ "0 - unlimited",
+ NULL, NULL, 1000000, 0, ~0ULL, 0);
+
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
static MYSQL_SYSVAR_UINT(change_buffering_debug, ibuf_debug,
PLUGIN_VAR_RQCMDARG,
@@ -13151,7 +13307,7 @@ static MYSQL_SYSVAR_UINT(buffer_pool_restore_at_startup, srv_auto_lru_dump,
static MYSQL_SYSVAR_BOOL(blocking_buffer_pool_restore,
innobase_blocking_lru_restore,
- PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
+ PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
"Block XtraDB startup process until buffer pool is full restored from a "
"dump file (if present). Disabled by default.",
NULL, NULL, FALSE);
@@ -13188,6 +13344,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),
@@ -13238,8 +13395,8 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(stats_auto_update),
MYSQL_SYSVAR(stats_update_need_lock),
MYSQL_SYSVAR(use_sys_stats_table),
-#ifdef UNIV_DEBUG_never /* disable this flag. --innodb-sys-stats becomes ambiguous */
- MYSQL_SYSVAR(sys_stats_root_page),
+#ifdef UNIV_DEBUG
+ MYSQL_SYSVAR(persistent_stats_root_page),
#endif
MYSQL_SYSVAR(stats_sample_pages),
MYSQL_SYSVAR(adaptive_hash_index),
@@ -13271,6 +13428,8 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(use_sys_malloc),
MYSQL_SYSVAR(use_native_aio),
MYSQL_SYSVAR(change_buffering),
+ MYSQL_SYSVAR(track_changed_pages),
+ MYSQL_SYSVAR(changed_pages_limit),
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
MYSQL_SYSVAR(change_buffering_debug),
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
@@ -13308,32 +13467,35 @@ maria_declare_plugin(xtradb)
INNODB_VERSION_STR, /* string version */
MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
},
-i_s_innodb_rseg_maria,
-i_s_innodb_undo_logs_maria,
-i_s_innodb_trx_maria,
-i_s_innodb_locks_maria,
-i_s_innodb_lock_waits_maria,
-i_s_innodb_cmp_maria,
-i_s_innodb_cmp_reset_maria,
-i_s_innodb_cmpmem_maria,
-i_s_innodb_cmpmem_reset_maria,
-i_s_innodb_sys_tables_maria,
-i_s_innodb_sys_tablestats_maria,
-i_s_innodb_sys_indexes_maria,
-i_s_innodb_sys_columns_maria,
-i_s_innodb_sys_fields_maria,
-i_s_innodb_sys_foreign_maria,
-i_s_innodb_sys_foreign_cols_maria,
-i_s_innodb_sys_stats_maria,
-i_s_innodb_table_stats_maria,
-i_s_innodb_index_stats_maria,
-i_s_innodb_buffer_pool_pages_maria,
-i_s_innodb_buffer_pool_pages_index_maria,
-i_s_innodb_buffer_pool_pages_blob_maria,
-i_s_innodb_admin_command_maria
+i_s_innodb_rseg,
+i_s_innodb_undo_logs,
+i_s_innodb_trx,
+i_s_innodb_locks,
+i_s_innodb_lock_waits,
+i_s_innodb_cmp,
+i_s_innodb_cmp_reset,
+i_s_innodb_cmpmem,
+i_s_innodb_cmpmem_reset,
+i_s_innodb_sys_tables,
+i_s_innodb_sys_tablestats,
+i_s_innodb_sys_indexes,
+i_s_innodb_sys_columns,
+i_s_innodb_sys_fields,
+i_s_innodb_sys_foreign,
+i_s_innodb_sys_foreign_cols,
+i_s_innodb_sys_stats,
+i_s_innodb_table_stats,
+i_s_innodb_index_stats,
+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_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.
Once InnoDB is running, the innodb_commit_concurrency must not change
diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc
index 5d86ea98d27..29a80594344 100644
--- a/storage/xtradb/handler/i_s.cc
+++ b/storage/xtradb/handler/i_s.cc
@@ -22,6 +22,14 @@ InnoDB INFORMATION SCHEMA tables interface to MySQL.
Created July 18, 2007 Vasil Dimov
*******************************************************/
+#ifndef MYSQL_SERVER
+#define MYSQL_SERVER /* For Item_* classes */
+#include <item.h>
+/* Prevent influence of this definition to other headers */
+#undef MYSQL_SERVER
+#else
+#include <mysql_priv.h>
+#endif //MYSQL_SERVER
#include <ctype.h> /*toupper*/
#include <mysqld_error.h>
@@ -45,6 +53,7 @@ extern "C" {
#include "dict0mem.h"
#include "dict0types.h"
#include "ha_prototypes.h" /* for innobase_convert_name() */
+#include "srv0srv.h" /* for srv_track_changed_pages */
#include "srv0start.h" /* for srv_was_started */
#include "trx0i_s.h"
#include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */
@@ -54,8 +63,94 @@ extern "C" {
#include "dict0dict.h" /* for dict_sys */
#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); \
@@ -601,7 +696,52 @@ static struct st_mysql_information_schema i_s_info =
MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_trx =
+{
+ /* 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_TRX"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB transactions"),
+
+ /* 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, innodb_trx_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 INFORMATION_SCHEMA.innodb_locks */
static ST_FIELD_INFO innodb_locks_fields_info[] =
@@ -820,6 +960,52 @@ innodb_locks_init(
DBUG_RETURN(0);
}
+UNIV_INTERN struct st_maria_plugin i_s_innodb_locks =
+{
+ /* 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_LOCKS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB conflicting locks"),
+
+ /* 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, innodb_locks_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 INFORMATION_SCHEMA.innodb_lock_waits */
static ST_FIELD_INFO innodb_lock_waits_fields_info[] =
@@ -955,6 +1141,52 @@ innodb_lock_waits_init(
DBUG_RETURN(0);
}
+UNIV_INTERN struct st_maria_plugin i_s_innodb_lock_waits =
+{
+ /* 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_LOCK_WAITS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB which lock is blocking which"),
+
+ /* 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, innodb_lock_waits_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
+};
/*******************************************************************//**
Common function to fill any of the dynamic tables:
@@ -1240,7 +1472,100 @@ i_s_cmp_reset_init(
DBUG_RETURN(0);
}
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp =
+{
+ /* 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_CMP"),
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression"),
+
+ /* 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_cmp_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
+};
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_reset =
+{
+ /* 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_CMP_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression;"
+ " reset cumulated counts"),
+
+ /* 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_cmp_reset_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 information_schema.innodb_cmpmem. */
static ST_FIELD_INFO i_s_cmpmem_fields_info[] =
@@ -1330,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++) {
@@ -1361,7 +1685,6 @@ i_s_cmpmem_fill_low(
}
}
- //buf_pool_mutex_exit(buf_pool);
mutex_exit(&buf_pool->zip_free_mutex);
if (status) {
@@ -1436,8 +1759,1849 @@ i_s_cmpmem_reset_init(
DBUG_RETURN(0);
}
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem =
+{
+ /* 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_CMPMEM"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool"),
+
+ /* 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_cmpmem_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
+};
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset =
+{
+ /* 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_CMPMEM_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool;"
+ " reset cumulated counts"),
+
+ /* 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_cmpmem_reset_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_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.
@@ -1656,6 +3820,52 @@ innodb_sys_tables_init(
DBUG_RETURN(0);
}
+UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_tables =
+{
+ /* 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_SYS_TABLES"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Percona"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB SYS_TABLES"),
+
+ /* 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, innodb_sys_tables_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 INFORMATION_SCHEMA.SYS_TABLESTATS */
static ST_FIELD_INFO innodb_sys_tablestats_fields_info[] =
@@ -1907,6 +4117,52 @@ innodb_sys_tablestats_init(
DBUG_RETURN(0);
}
+UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_tablestats =
+{
+ /* 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_SYS_TABLESTATS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Percona"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB SYS_TABLESTATS"),
+
+ /* 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, innodb_sys_tablestats_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 INFORMATION_SCHEMA.SYS_INDEXES */
static ST_FIELD_INFO innodb_sysindex_fields_info[] =
@@ -2107,6 +4363,52 @@ innodb_sys_indexes_init(
DBUG_RETURN(0);
}
+UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_indexes =
+{
+ /* 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_SYS_INDEXES"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Percona"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB SYS_INDEXES"),
+
+ /* 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, innodb_sys_indexes_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 INFORMATION_SCHEMA.SYS_COLUMNS */
static ST_FIELD_INFO innodb_sys_columns_fields_info[] =
@@ -2297,6 +4599,52 @@ innodb_sys_columns_init(
DBUG_RETURN(0);
}
+UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_columns =
+{
+ /* 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_SYS_COLUMNS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Percona"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB SYS_COLUMNS"),
+
+ /* 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, innodb_sys_columns_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 INFORMATION_SCHEMA.innodb_sys_fields */
static ST_FIELD_INFO innodb_sys_fields_fields_info[] =
{
@@ -2458,6 +4806,52 @@ innodb_sys_fields_init(
DBUG_RETURN(0);
}
+UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_fields =
+{
+ /* 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_SYS_FIELDS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Percona"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB SYS_FIELDS"),
+
+ /* 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, innodb_sys_fields_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 INFORMATION_SCHEMA.innodb_sys_foreign */
static ST_FIELD_INFO innodb_sys_foreign_fields_info[] =
@@ -2633,6 +5027,52 @@ innodb_sys_foreign_init(
DBUG_RETURN(0);
}
+UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_foreign =
+{
+ /* 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_SYS_FOREIGN"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Percona"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB SYS_FOREIGN"),
+
+ /* 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, innodb_sys_foreign_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 INFORMATION_SCHEMA.innodb_sys_foreign_cols */
static ST_FIELD_INFO innodb_sys_foreign_cols_fields_info[] =
{
@@ -2801,6 +5241,52 @@ innodb_sys_foreign_cols_init(
DBUG_RETURN(0);
}
+UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_foreign_cols =
+{
+ /* 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_SYS_FOREIGN_COLS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Percona"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB SYS_FOREIGN_COLS"),
+
+ /* 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, innodb_sys_foreign_cols_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 INFORMATION_SCHEMA.innodb_sys_stats */
static ST_FIELD_INFO innodb_sys_stats_fields_info[] =
@@ -2970,6 +5456,52 @@ innodb_sys_stats_init(
DBUG_RETURN(0);
}
+UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_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_SYS_STATS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Percona"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "XtraDB SYS_STATS table"),
+
+ /* 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, innodb_sys_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
+};
/***********************************************************************
*/
@@ -3085,6 +5617,52 @@ i_s_innodb_rseg_init(
DBUG_RETURN(0);
}
+UNIV_INTERN struct st_maria_plugin i_s_innodb_rseg =
+{
+ /* 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_RSEG"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Percona"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB rollback segment 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_rseg_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, 0x0100 /* 1.0 */),
+
+ /* 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
+};
/***********************************************************************
*/
@@ -3402,7 +5980,37 @@ i_s_innodb_index_stats_init(
DBUG_RETURN(0);
}
+UNIV_INTERN struct st_maria_plugin i_s_innodb_table_stats =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "INNODB_TABLE_STATS"),
+ STRUCT_FLD(author, "Percona"),
+ STRUCT_FLD(descr, "InnoDB table statistics in memory"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_table_stats_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
+};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_index_stats =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "INNODB_INDEX_STATS"),
+ STRUCT_FLD(author, "Percona"),
+ STRUCT_FLD(descr, "InnoDB index statistics in memory"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_index_stats_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
+};
/***********************************************************************
*/
@@ -3556,6 +6164,21 @@ i_s_innodb_admin_command_init(
DBUG_RETURN(0);
}
+UNIV_INTERN struct st_maria_plugin i_s_innodb_admin_command =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "XTRADB_ADMIN_COMMAND"),
+ STRUCT_FLD(author, "Percona"),
+ STRUCT_FLD(descr, "XtraDB specific command acceptor"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_admin_command_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
+};
/***********************************************************************
*/
@@ -4106,337 +6729,146 @@ i_s_innodb_buffer_pool_pages_blob_init(
DBUG_RETURN(0);
}
-/* MariaDB structures of I_S plugins above */
-
-UNIV_INTERN struct st_maria_plugin i_s_innodb_trx_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_TRX",
- plugin_author,
- "InnoDB transactions",
- PLUGIN_LICENSE_GPL,
- innodb_trx_init,
- i_s_common_deinit,
- INNODB_VERSION_SHORT,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_locks_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_LOCKS",
- plugin_author,
- "InnoDB conflicting locks",
- PLUGIN_LICENSE_GPL,
- innodb_locks_init,
- i_s_common_deinit,
- INNODB_VERSION_SHORT,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_lock_waits_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_LOCK_WAITS",
- plugin_author,
- "InnoDB which lock is blocking which",
- PLUGIN_LICENSE_GPL,
- innodb_lock_waits_init,
- i_s_common_deinit,
- INNODB_VERSION_SHORT,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_CMP",
- plugin_author,
- "Statistics for the InnoDB compression",
- PLUGIN_LICENSE_GPL,
- i_s_cmp_init,
- i_s_common_deinit,
- INNODB_VERSION_SHORT,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_reset_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_CMP_RESET",
- plugin_author,
- "Statistics for the InnoDB compression; reset cumulated counts",
- PLUGIN_LICENSE_GPL,
- i_s_cmp_reset_init,
- i_s_common_deinit,
- INNODB_VERSION_SHORT,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_CMPMEM",
- plugin_author,
- "Statistics for the InnoDB compressed buffer pool",
- PLUGIN_LICENSE_GPL,
- i_s_cmpmem_init,
- i_s_common_deinit,
- INNODB_VERSION_SHORT,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_CMPMEM_RESET",
- plugin_author,
- "Statistics for the InnoDB compressed buffer pool; reset cumulated counts",
- PLUGIN_LICENSE_GPL,
- i_s_cmpmem_reset_init,
- i_s_common_deinit,
- INNODB_VERSION_SHORT,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_tables_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_SYS_TABLES",
- "Percona",
- "InnoDB SYS_TABLES",
- PLUGIN_LICENSE_GPL,
- innodb_sys_tables_init,
- i_s_common_deinit,
- INNODB_VERSION_SHORT,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_tablestats_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_SYS_TABLESTATS",
- "Percona",
- "InnoDB SYS_TABLESTATS",
- PLUGIN_LICENSE_GPL,
- innodb_sys_tablestats_init,
- i_s_common_deinit,
- INNODB_VERSION_SHORT,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_indexes_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_SYS_INDEXES",
- "Percona",
- "InnoDB SYS_INDEXES",
- PLUGIN_LICENSE_GPL,
- innodb_sys_indexes_init,
- i_s_common_deinit,
- INNODB_VERSION_SHORT,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_columns_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_SYS_COLUMNS",
- "Percona",
- "InnoDB SYS_COLUMNS",
- PLUGIN_LICENSE_GPL,
- innodb_sys_columns_init,
- i_s_common_deinit,
- INNODB_VERSION_SHORT,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_fields_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_SYS_FIELDS",
- "Percona",
- "InnoDB SYS_FIELDS",
- PLUGIN_LICENSE_GPL,
- innodb_sys_fields_init,
- i_s_common_deinit,
- INNODB_VERSION_SHORT,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_foreign_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_SYS_FOREIGN",
- "Percona",
- "InnoDB SYS_FOREIGN",
- PLUGIN_LICENSE_GPL,
- innodb_sys_foreign_init,
- i_s_common_deinit,
- INNODB_VERSION_SHORT,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_foreign_cols_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_SYS_FOREIGN_COLS",
- "Percona",
- "InnoDB SYS_FOREIGN_COLS",
- PLUGIN_LICENSE_GPL,
- innodb_sys_foreign_cols_init,
- i_s_common_deinit,
- INNODB_VERSION_SHORT,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_stats_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_SYS_STATS",
- "Percona",
- "XtraDB SYS_STATS table",
- PLUGIN_LICENSE_GPL,
- innodb_sys_stats_init,
- i_s_common_deinit,
- INNODB_VERSION_SHORT,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_rseg_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_RSEG",
- "Percona",
- "InnoDB rollback segment information",
- PLUGIN_LICENSE_GPL,
- i_s_innodb_rseg_init,
- i_s_common_deinit,
- 0x0100,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_table_stats_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_TABLE_STATS",
- "Percona",
- "InnoDB table statistics in memory",
- PLUGIN_LICENSE_GPL,
- i_s_innodb_table_stats_init,
- i_s_common_deinit,
- 0x0100,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_index_stats_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_INDEX_STATS",
- "Percona",
- "InnoDB index statistics in memory",
- PLUGIN_LICENSE_GPL,
- i_s_innodb_index_stats_init,
- i_s_common_deinit,
- 0x0100,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_admin_command_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "XTRADB_ADMIN_COMMAND",
- "Percona",
- "XtraDB specific command acceptor",
- PLUGIN_LICENSE_GPL,
- i_s_innodb_admin_command_init,
- i_s_common_deinit,
- 0x0100,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
-};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_BUFFER_POOL_PAGES",
- "Percona",
- "InnoDB buffer pool pages",
- PLUGIN_LICENSE_GPL,
- i_s_innodb_buffer_pool_pages_init,
- i_s_common_deinit,
- 0x0100,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages =
+{
+ /* 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_PAGES"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Percona"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB buffer pool pages"),
+
+ /* 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_pages_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, 0x0100 /* 1.0 */),
+
+ /* 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
};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_index_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_BUFFER_POOL_PAGES_INDEX",
- "Percona",
- "InnoDB buffer pool index pages",
- PLUGIN_LICENSE_GPL,
- i_s_innodb_buffer_pool_pages_index_init,
- i_s_common_deinit,
- 0x0100,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_index =
+{
+ /* 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_PAGES_INDEX"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Percona"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB buffer pool index pages"),
+
+ /* 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_pages_index_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, 0x0100 /* 1.0 */),
+
+ /* 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
};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_blob_maria =
-{
- MYSQL_INFORMATION_SCHEMA_PLUGIN,
- &i_s_info,
- "INNODB_BUFFER_POOL_PAGES_BLOB",
- "Percona",
- "InnoDB buffer pool blob pages",
- PLUGIN_LICENSE_GPL,
- i_s_innodb_buffer_pool_pages_blob_init,
- i_s_common_deinit,
- 0x0100,
- NULL,
- NULL,
- INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_blob =
+{
+ /* 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_PAGES_BLOB"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Percona"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB buffer pool blob pages"),
+
+ /* 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_pages_blob_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, 0x0100 /* 1.0 */),
+
+ /* 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
};
@@ -4632,7 +7064,7 @@ i_s_innodb_undo_logs_init(
DBUG_RETURN(0);
}
-UNIV_INTERN struct st_mysql_plugin i_s_innodb_undo_logs =
+UNIV_INTERN struct st_maria_plugin i_s_innodb_undo_logs =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
/* int */
@@ -4674,56 +7106,290 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_undo_logs =
/* struct st_mysql_sys_var** */
STRUCT_FLD(system_vars, NULL),
- /* reserved for dependency checking */
- /* void* */
- STRUCT_FLD(__reserved1, NULL),
+ INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
+};
+
+static ST_FIELD_INFO i_s_innodb_changed_pages_info[] =
+{
+ {STRUCT_FLD(field_name, "space_id"),
+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
- /* Plugin flags */
- /* unsigned long */
- STRUCT_FLD(flags, 0UL),
+ {STRUCT_FLD(field_name, "page_id"),
+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ {STRUCT_FLD(field_name, "start_lsn"),
+ 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)},
+
+ {STRUCT_FLD(field_name, "end_lsn"),
+ 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
};
-UNIV_INTERN struct st_maria_plugin i_s_innodb_undo_logs_maria =
+/***********************************************************************
+ This function parses condition and gets upper bounds for start and end LSN's
+ if condition corresponds to certain pattern.
+
+ We can't know right position to avoid scanning bitmap files from the beginning
+ to the lower bound. But we can stop scanning bitmap files if we reach upper bound.
+
+ It's expected the most used queries will be like the following:
+
+ SELECT * FROM INNODB_CHANGED_PAGES WHERE START_LSN > num1 AND start_lsn < num2;
+
+ That's why the pattern is:
+
+ pattern: comp | and_comp;
+ comp: lsn < int_num | lsn <= int_num | int_num > lsn | int_num >= lsn;
+ lsn: start_lsn | end_lsn;
+ and_comp: some_expression AND some_expression | some_expression AND and_comp;
+ some_expression: comp | any_other_expression;
+
+ Suppose the condition is start_lsn < 100, this means we have to read all
+ blocks with start_lsn < 100. Which is equivalent to reading all the blocks
+ with end_lsn <= 99, or just end_lsn < 100. That's why it's enough to find
+ maximum lsn value, doesn't matter if this is start or end lsn and compare
+ it with "start_lsn" field.
+
+ Example:
+
+ SELECT * FROM INNODB_CHANGED_PAGES
+ WHERE
+ start_lsn > 10 AND
+ end_lsn <= 1111 AND
+ 555 > end_lsn AND
+ page_id = 100;
+
+ max_lsn will be set to 555.
+*/
+static
+void
+limit_lsn_range_from_condition(
+/*===========================*/
+ TABLE* table, /*!<in: table */
+ COND* cond, /*!<in: condition */
+ ib_uint64_t* max_lsn) /*!<in/out: maximum LSN
+ (must be initialized with maximum
+ available value) */
{
- /* the plugin type (a MYSQL_XXX_PLUGIN value) */
- /* int */
- STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ if (cond->type() != Item::COND_ITEM &&
+ cond->type() != Item::FUNC_ITEM)
+ return;
+
+ switch (((Item_func*) cond)->functype())
+ {
+ case Item_func::COND_AND_FUNC:
+ {
+ List_iterator<Item> li(*((Item_cond*) cond)->
+ argument_list());
+ Item *item;
+ while ((item= li++))
+ limit_lsn_range_from_condition(table,
+ item,
+ max_lsn);
+ break;
+ }
+ case Item_func::LT_FUNC:
+ case Item_func::LE_FUNC:
+ case Item_func::GT_FUNC:
+ case Item_func::GE_FUNC:
+ {
+ Item *left;
+ Item *right;
+ Item_field *item_field;
+ ib_uint64_t tmp_result;
+
+ /*
+ a <= b equals to b >= a that's why we just exchange
+ "left" and "right" in the case of ">" or ">="
+ function
+ */
+ if (((Item_func*) cond)->functype() ==
+ Item_func::LT_FUNC ||
+ ((Item_func*) cond)->functype() ==
+ Item_func::LE_FUNC)
+ {
+ left = ((Item_func*) cond)->arguments()[0];
+ right = ((Item_func*) cond)->arguments()[1];
+ } else {
+ left = ((Item_func*) cond)->arguments()[1];
+ right = ((Item_func*) cond)->arguments()[0];
+ }
- /* pointer to type-specific plugin descriptor */
- /* void* */
- STRUCT_FLD(info, &i_s_info),
+ if (!left || !right)
+ return;
+ if (left->type() != Item::FIELD_ITEM)
+ return;
+ if (right->type() != Item::INT_ITEM)
+ return;
- /* plugin name */
- /* const char* */
- STRUCT_FLD(name, "INNODB_UNDO_LOGS"),
+ item_field = (Item_field*)left;
- /* plugin author (for SHOW PLUGINS) */
- /* const char* */
- STRUCT_FLD(author, "Percona"),
+ if (/* START_LSN */
+ table->field[2] != item_field->field &&
+ /* END_LSN */
+ table->field[3] != item_field->field)
+ {
+ return;
+ }
- /* general descriptive text (for SHOW PLUGINS) */
- /* const char* */
- STRUCT_FLD(descr, "InnoDB rollback undo segment information"),
+ /* Check if the current field belongs to our table */
+ if (table != item_field->field->table)
+ return;
- /* the plugin license (PLUGIN_LICENSE_XXX) */
- /* int */
- STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ tmp_result = right->val_int();
+ if (tmp_result < *max_lsn)
+ *max_lsn = tmp_result;
- /* the function to invoke when plugin is loaded */
- /* int (*)(void*); */
- STRUCT_FLD(init, i_s_innodb_undo_logs_init),
+ break;
+ }
+ default:;
+ }
- /* the function to invoke when plugin is unloaded */
- /* int (*)(void*); */ STRUCT_FLD(deinit, i_s_common_deinit),
+}
- /* plugin version (for SHOW PLUGINS) */
- STRUCT_FLD(version, 0x0100 /* 1.0 */),
+/***********************************************************************
+Fill the dynamic table information_schema.innodb_changed_pages.
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_changed_pages_fill(
+/*==========================*/
+ THD* thd, /*!<in: thread */
+ TABLE_LIST* tables, /*!<in/out: tables to fill */
+ COND* cond) /*!<in: condition */
+{
+ TABLE* table = (TABLE *) tables->table;
+ log_bitmap_iterator_t i;
+ ib_uint64_t output_rows_num = 0UL;
+ ib_uint64_t max_lsn = ~0ULL;
+
+ if (!srv_track_changed_pages)
+ return 0;
+
+ if (!log_online_bitmap_iterator_init(&i))
+ return 1;
+
+ if (cond)
+ limit_lsn_range_from_condition(table, cond, &max_lsn);
+
+ while(log_online_bitmap_iterator_next(&i) &&
+ (!srv_changed_pages_limit ||
+ output_rows_num < srv_changed_pages_limit) &&
+ /*
+ There is no need to compare both start LSN and end LSN fields
+ with maximum value. It's enough to compare only start LSN.
+ Example:
+
+ max_lsn = 100
+ \\\\\\\\\\\\\\\\\\\\\\\\\|\\\\\\\\ - Query 1
+ I------I I-------I I-------------I I----I
+ ////////////////// | - Query 2
+ 1 2 3 4
+
+ Query 1:
+ SELECT * FROM INNODB_CHANGED_PAGES WHERE start_lsn < 100
+ will select 1,2,3 bitmaps
+ Query 2:
+ SELECT * FROM INNODB_CHANGED_PAGES WHERE end_lsn < 100
+ will select 1,2 bitmaps
+
+ The condition start_lsn <= 100 will be false after reading
+ 1,2,3 bitmaps which suits for both cases.
+ */
+ LOG_BITMAP_ITERATOR_START_LSN(i) <= max_lsn)
+ {
+ if (!LOG_BITMAP_ITERATOR_PAGE_CHANGED(i))
+ continue;
- /* struct st_mysql_show_var* */
- STRUCT_FLD(status_vars, NULL),
+ /* SPACE_ID */
+ table->field[0]->store(
+ LOG_BITMAP_ITERATOR_SPACE_ID(i));
+ /* PAGE_ID */
+ table->field[1]->store(
+ LOG_BITMAP_ITERATOR_PAGE_NUM(i));
+ /* START_LSN */
+ table->field[2]->store(
+ LOG_BITMAP_ITERATOR_START_LSN(i));
+ /* END_LSN */
+ table->field[3]->store(
+ LOG_BITMAP_ITERATOR_END_LSN(i));
+
+ /*
+ I_S tables are in-memory tables. If bitmap file is big enough
+ a lot of memory can be used to store the table. But the size
+ of used memory can be diminished if we store only data which
+ corresponds to some conditions (in WHERE sql clause). Here
+ conditions are checked for the field values stored above.
+
+ Conditions are checked twice. The first is here (during table
+ generation) and the second during query execution. Maybe it
+ makes sense to use some flag in THD object to avoid double
+ checking.
+ */
+ if (cond && !cond->val_int())
+ continue;
- /* struct st_mysql_sys_var** */
- STRUCT_FLD(system_vars, NULL),
+ if (schema_table_store_record(thd, table))
+ {
+ log_online_bitmap_iterator_release(&i);
+ return 1;
+ }
+
+ ++output_rows_num;
+ }
+
+ log_online_bitmap_iterator_release(&i);
+ return 0;
+}
+
+static
+int
+i_s_innodb_changed_pages_init(
+/*==========================*/
+ void* p)
+{
+ DBUG_ENTER("i_s_innodb_changed_pages_init");
+ ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
+
+ schema->fields_info = i_s_innodb_changed_pages_info;
+ schema->fill_table = i_s_innodb_changed_pages_fill;
+ DBUG_RETURN(0);
+}
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_changed_pages =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "INNODB_CHANGED_PAGES"),
+ STRUCT_FLD(author, "Percona"),
+ STRUCT_FLD(descr, "InnoDB CHANGED_PAGES table"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_changed_pages_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
};
diff --git a/storage/xtradb/handler/i_s.h b/storage/xtradb/handler/i_s.h
index 329cc2f5f91..620309bebfe 100644
--- a/storage/xtradb/handler/i_s.h
+++ b/storage/xtradb/handler/i_s.h
@@ -28,52 +28,32 @@ Created July 18, 2007 Vasil Dimov
const char plugin_author[] = "Oracle Corporation";
-extern struct st_mysql_plugin i_s_innodb_trx;
-extern struct st_mysql_plugin i_s_innodb_locks;
-extern struct st_mysql_plugin i_s_innodb_lock_waits;
-extern struct st_mysql_plugin i_s_innodb_cmp;
-extern struct st_mysql_plugin i_s_innodb_cmp_reset;
-extern struct st_mysql_plugin i_s_innodb_cmpmem;
-extern struct st_mysql_plugin i_s_innodb_cmpmem_reset;
-extern struct st_mysql_plugin i_s_innodb_sys_tables;
-extern struct st_mysql_plugin i_s_innodb_sys_tablestats;
-extern struct st_mysql_plugin i_s_innodb_sys_indexes;
-extern struct st_mysql_plugin i_s_innodb_sys_columns;
-extern struct st_mysql_plugin i_s_innodb_sys_fields;
-extern struct st_mysql_plugin i_s_innodb_sys_foreign;
-extern struct st_mysql_plugin i_s_innodb_sys_foreign_cols;
-extern struct st_mysql_plugin i_s_innodb_rseg;
-extern struct st_mysql_plugin i_s_innodb_undo_logs;
-extern struct st_mysql_plugin i_s_innodb_sys_stats;
-extern struct st_mysql_plugin i_s_innodb_table_stats;
-extern struct st_mysql_plugin i_s_innodb_index_stats;
-extern struct st_mysql_plugin i_s_innodb_admin_command;
-extern struct st_mysql_plugin i_s_innodb_buffer_pool_pages;
-extern struct st_mysql_plugin i_s_innodb_buffer_pool_pages_index;
-extern struct st_mysql_plugin i_s_innodb_buffer_pool_pages_blob;
-
-extern struct st_maria_plugin i_s_innodb_trx_maria;
-extern struct st_maria_plugin i_s_innodb_locks_maria;
-extern struct st_maria_plugin i_s_innodb_lock_waits_maria;
-extern struct st_maria_plugin i_s_innodb_cmp_maria;
-extern struct st_maria_plugin i_s_innodb_cmp_reset_maria;
-extern struct st_maria_plugin i_s_innodb_cmpmem_maria;
-extern struct st_maria_plugin i_s_innodb_cmpmem_reset_maria;
-extern struct st_maria_plugin i_s_innodb_sys_tables_maria;
-extern struct st_maria_plugin i_s_innodb_sys_tablestats_maria;
-extern struct st_maria_plugin i_s_innodb_sys_indexes_maria;
-extern struct st_maria_plugin i_s_innodb_sys_columns_maria;
-extern struct st_maria_plugin i_s_innodb_sys_fields_maria;
-extern struct st_maria_plugin i_s_innodb_sys_foreign_maria;
-extern struct st_maria_plugin i_s_innodb_sys_foreign_cols_maria;
-extern struct st_maria_plugin i_s_innodb_sys_stats_maria;
-extern struct st_maria_plugin i_s_innodb_rseg_maria;
-extern struct st_maria_plugin i_s_innodb_undo_logs_maria;
-extern struct st_maria_plugin i_s_innodb_table_stats_maria;
-extern struct st_maria_plugin i_s_innodb_index_stats_maria;
-extern struct st_maria_plugin i_s_innodb_admin_command_maria;
-extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_maria;
-extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_index_maria;
-extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_blob_maria;
+extern struct st_maria_plugin i_s_innodb_trx;
+extern struct st_maria_plugin i_s_innodb_locks;
+extern struct st_maria_plugin i_s_innodb_lock_waits;
+extern struct st_maria_plugin i_s_innodb_cmp;
+extern struct st_maria_plugin i_s_innodb_cmp_reset;
+extern struct st_maria_plugin i_s_innodb_cmpmem;
+extern struct st_maria_plugin i_s_innodb_cmpmem_reset;
+extern struct st_maria_plugin i_s_innodb_sys_tables;
+extern struct st_maria_plugin i_s_innodb_sys_tablestats;
+extern struct st_maria_plugin i_s_innodb_sys_indexes;
+extern struct st_maria_plugin i_s_innodb_sys_columns;
+extern struct st_maria_plugin i_s_innodb_sys_fields;
+extern struct st_maria_plugin i_s_innodb_sys_foreign;
+extern struct st_maria_plugin i_s_innodb_sys_foreign_cols;
+extern struct st_maria_plugin i_s_innodb_rseg;
+extern struct st_maria_plugin i_s_innodb_undo_logs;
+extern struct st_maria_plugin i_s_innodb_sys_stats;
+extern struct st_maria_plugin i_s_innodb_table_stats;
+extern struct st_maria_plugin i_s_innodb_index_stats;
+extern struct st_maria_plugin i_s_innodb_admin_command;
+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/buf0lru.h b/storage/xtradb/include/buf0lru.h
index c3672a65ed7..efaa758f27a 100644
--- a/storage/xtradb/include/buf0lru.h
+++ b/storage/xtradb/include/buf0lru.h
@@ -94,13 +94,12 @@ buf_LRU_insert_zip_clean(
Try to free a block. If bpage is a descriptor of a compressed-only
page, the descriptor object will be freed as well.
-NOTE: If this function returns TRUE, it will temporarily
-release buf_pool->mutex. Furthermore, the page frame will no longer be
-accessible via bpage.
+NOTE: This will temporarily release buf_pool_mutex. Furthermore, the
+page frame will no longer be accessible via bpage.
-The caller must hold buf_pool->mutex and buf_page_get_mutex(bpage) and
-release these two mutexes after the call. No other
-buf_page_get_mutex() may be held when calling this function.
+The caller must hold buf_page_get_mutex(bpage) and release this mutex
+after the call. No other buf_page_get_mutex() may be held when
+calling this function.
@return TRUE if freed, FALSE otherwise. */
UNIV_INTERN
ibool
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 890bf33ac02..c2209c89029 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 8a6430fb105..4f017e01dfd 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 */
@@ -984,6 +987,11 @@ struct log_struct{
become signaled */
/* @} */
#endif /* UNIV_LOG_ARCHIVE */
+ ib_uint64_t tracked_lsn; /*!< log tracking has advanced to this
+ lsn. Field accessed atomically where
+ 64-bit atomic ops are supported,
+ protected by the log sys mutex
+ otherwise. */
};
/** Test if flush order mutex is owned. */
diff --git a/storage/xtradb/include/log0online.h b/storage/xtradb/include/log0online.h
new file mode 100644
index 00000000000..0e0ca169f6f
--- /dev/null
+++ b/storage/xtradb/include/log0online.h
@@ -0,0 +1,111 @@
+/*****************************************************************************
+
+Copyright (c) 2011-2012, Percona Inc. All Rights Reserved.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+*****************************************************************************/
+
+/**************************************************//**
+@file include/log0online.h
+Online database log parsing for changed page tracking
+*******************************************************/
+
+#ifndef log0online_h
+#define log0online_h
+
+#include "univ.i"
+#include "os0file.h"
+
+/*********************************************************************//**
+Initializes the online log following subsytem. */
+UNIV_INTERN
+void
+log_online_read_init();
+/*===================*/
+
+/*********************************************************************//**
+Shuts down the online log following subsystem. */
+UNIV_INTERN
+void
+log_online_read_shutdown();
+/*=======================*/
+
+/*********************************************************************//**
+Reads and parses the redo log up to last checkpoint LSN to build the changed
+page bitmap which is then written to disk. */
+UNIV_INTERN
+void
+log_online_follow_redo_log();
+/*=========================*/
+
+/** The iterator through all bits of changed pages bitmap blocks */
+struct log_bitmap_iterator_struct
+{
+ char in_name[FN_REFLEN]; /*!< the file name for bitmap
+ input */
+ os_file_t in; /*!< the bitmap input file */
+ ib_uint64_t in_offset; /*!< the next write position in the
+ bitmap output file */
+ ib_uint32_t bit_offset; /*!< bit offset inside of bitmap
+ block*/
+ ib_uint64_t start_lsn; /*!< Start lsn of the block */
+ ib_uint64_t end_lsn; /*!< End lsn of the block */
+ ib_uint32_t space_id; /*!< Block space id */
+ ib_uint32_t first_page_id; /*!< First block page id */
+ ibool changed; /*!< true if current page was changed */
+ byte* page; /*!< Bitmap block */
+};
+
+typedef struct log_bitmap_iterator_struct log_bitmap_iterator_t;
+
+#define LOG_BITMAP_ITERATOR_START_LSN(i) \
+ ((i).start_lsn)
+#define LOG_BITMAP_ITERATOR_END_LSN(i) \
+ ((i).end_lsn)
+#define LOG_BITMAP_ITERATOR_SPACE_ID(i) \
+ ((i).space_id)
+#define LOG_BITMAP_ITERATOR_PAGE_NUM(i) \
+ ((i).first_page_id + (i).bit_offset)
+#define LOG_BITMAP_ITERATOR_PAGE_CHANGED(i) \
+ ((i).changed)
+
+/*********************************************************************//**
+Initializes log bitmap iterator.
+@return TRUE if the iterator is initialized OK, FALSE otherwise. */
+UNIV_INTERN
+ibool
+log_online_bitmap_iterator_init(
+/*============================*/
+ log_bitmap_iterator_t *i); /*!<in/out: iterator */
+
+/*********************************************************************//**
+Releases log bitmap iterator. */
+UNIV_INTERN
+void
+log_online_bitmap_iterator_release(
+/*===============================*/
+ log_bitmap_iterator_t *i); /*!<in/out: iterator */
+
+/*********************************************************************//**
+Iterates through bits of saved bitmap blocks.
+Sequentially reads blocks from bitmap file(s) and interates through
+their bits. Ignores blocks with wrong checksum.
+@return TRUE if iteration is successful, FALSE if all bits are iterated. */
+UNIV_INTERN
+ibool
+log_online_bitmap_iterator_next(
+/*============================*/
+ log_bitmap_iterator_t *i); /*!<in/out: iterator */
+
+#endif
diff --git a/storage/xtradb/include/log0recv.h b/storage/xtradb/include/log0recv.h
index 15065267250..fdffd86e4c4 100644
--- a/storage/xtradb/include/log0recv.h
+++ b/storage/xtradb/include/log0recv.h
@@ -32,6 +32,28 @@ Created 9/20/1997 Heikki Tuuri
#include "hash0hash.h"
#include "log0log.h"
+/******************************************************//**
+Checks the 4-byte checksum to the trailer checksum field of a log
+block. We also accept a log block in the old format before
+InnoDB-3.23.52 where the checksum field contains the log block number.
+@return TRUE if ok, or if the log block may be in the format of InnoDB
+version predating 3.23.52 */
+UNIV_INTERN
+ibool
+log_block_checksum_is_ok_or_old_format(
+/*===================================*/
+ const byte* block); /*!< in: pointer to a log block */
+
+/*******************************************************//**
+Calculates the new value for lsn when more data is added to the log. */
+UNIV_INTERN
+ib_uint64_t
+recv_calc_lsn_on_data_add(
+/*======================*/
+ ib_uint64_t lsn, /*!< in: old lsn */
+ ib_uint64_t len); /*!< in: this many bytes of data is
+ added, log block headers not included */
+
#ifdef UNIV_HOTBACKUP
extern ibool recv_replay_file_ops;
@@ -182,6 +204,21 @@ UNIV_INTERN
void
recv_recovery_rollback_active(void);
/*===============================*/
+
+/*******************************************************************//**
+Tries to parse a single log record and returns its length.
+@return length of the record, or 0 if the record was not complete */
+UNIV_INTERN
+ulint
+recv_parse_log_rec(
+/*===============*/
+ byte* ptr, /*!< in: pointer to a buffer */
+ byte* end_ptr,/*!< in: pointer to the buffer end */
+ byte* type, /*!< out: type */
+ ulint* space, /*!< out: space id */
+ ulint* page_no,/*!< out: page number */
+ byte** body); /*!< out: log record body start */
+
/*******************************************************//**
Scans log from a buffer and stores new log data to the parsing buffer.
Parses and hashes the log records if new data found. Unless
diff --git a/storage/xtradb/include/os0file.h b/storage/xtradb/include/os0file.h
index 5b1f9339845..4c795d93141 100644
--- a/storage/xtradb/include/os0file.h
+++ b/storage/xtradb/include/os0file.h
@@ -197,6 +197,7 @@ extern ulint srv_log_block_size;
extern mysql_pfs_key_t innodb_file_data_key;
extern mysql_pfs_key_t innodb_file_log_key;
extern mysql_pfs_key_t innodb_file_temp_key;
+extern mysql_pfs_key_t innodb_file_bmp_key;
/* Following four macros are instumentations to register
various file I/O operations with performance schema.
@@ -867,6 +868,14 @@ os_file_set_eof(
/*============*/
FILE* file); /*!< in: file to be truncated */
/***********************************************************************//**
+Truncates a file at the specified position.
+@return TRUE if success */
+UNIV_INTERN
+ibool
+os_file_set_eof_at(
+ os_file_t file, /*!< in: handle to a file */
+ ib_uint64_t new_len);/*!< in: new file length */
+/***********************************************************************//**
NOTE! Use the corresponding macro os_file_flush(), not directly this function!
Flushes the write buffers of a given file to the disk.
@return TRUE if success */
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/os0sync.h b/storage/xtradb/include/os0sync.h
index 6a99c60226b..887a40c64ea 100644
--- a/storage/xtradb/include/os0sync.h
+++ b/storage/xtradb/include/os0sync.h
@@ -265,7 +265,11 @@ Atomic compare-and-swap and increment for InnoDB. */
#if defined(HAVE_IB_GCC_ATOMIC_BUILTINS)
-#define HAVE_ATOMIC_BUILTINS
+# define HAVE_ATOMIC_BUILTINS
+
+# ifdef HAVE_IB_GCC_ATOMIC_BUILTINS_64
+# define HAVE_ATOMIC_BUILTINS_64
+# endif
/**********************************************************//**
Returns true if swapped, ptr is pointer to target, old_val is value to
@@ -304,6 +308,9 @@ amount of increment. */
# define os_atomic_increment_ulint(ptr, amount) \
os_atomic_increment(ptr, amount)
+# define os_atomic_increment_uint64(ptr, amount) \
+ os_atomic_increment(ptr, amount)
+
/**********************************************************//**
Returns the old value of *ptr, atomically sets *ptr to new_val */
@@ -312,12 +319,13 @@ Returns the old value of *ptr, atomically sets *ptr to new_val */
#elif defined(HAVE_IB_SOLARIS_ATOMICS)
-#define HAVE_ATOMIC_BUILTINS
+# define HAVE_ATOMIC_BUILTINS
+# define HAVE_ATOMIC_BUILTINS_64
/* If not compiling with GCC or GCC doesn't support the atomic
intrinsics and running on Solaris >= 10 use Solaris atomics */
-#include <atomic.h>
+# include <atomic.h>
/**********************************************************//**
Returns true if swapped, ptr is pointer to target, old_val is value to
@@ -357,6 +365,9 @@ amount of increment. */
# define os_atomic_increment_ulint(ptr, amount) \
atomic_add_long_nv(ptr, amount)
+# define os_atomic_increment_uint64(ptr, amount) \
+ atomic_add_64_nv(ptr, amount)
+
/**********************************************************//**
Returns the old value of *ptr, atomically sets *ptr to new_val */
@@ -365,7 +376,11 @@ Returns the old value of *ptr, atomically sets *ptr to new_val */
#elif defined(HAVE_WINDOWS_ATOMICS)
-#define HAVE_ATOMIC_BUILTINS
+# define HAVE_ATOMIC_BUILTINS
+
+# ifndef _WIN32
+# define HAVE_ATOMIC_BUILTINS_64
+# endif
/* On Windows, use Windows atomics / interlocked */
# ifdef _WIN64
@@ -403,6 +418,11 @@ amount of increment. */
# define os_atomic_increment_ulint(ptr, amount) \
((ulint) (win_xchg_and_add(ptr, amount) + amount))
+# define os_atomic_increment_uint64(ptr, amount) \
+ ((ib_uint64_t) (InterlockedExchangeAdd64( \
+ (ib_int64_t*) ptr, \
+ (ib_int64_t) amount) + amount))
+
/**********************************************************//**
Returns the old value of *ptr, atomically sets *ptr to new_val.
InterlockedExchange() operates on LONG, and the LONG will be
diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h
index a40683e00f1..a95eb8a1d58 100644
--- a/storage/xtradb/include/srv0srv.h
+++ b/storage/xtradb/include/srv0srv.h
@@ -69,6 +69,14 @@ extern os_event_t srv_error_event;
/* This event is set at shutdown to wakeup threads from sleep */
extern os_event_t srv_shutdown_event;
+/* This event is set on checkpoint completion to wake the redo log parser
+thread */
+extern os_event_t srv_checkpoint_completed_event;
+
+/* This event is set on the online redo log following thread exit to signal
+that the (slow) shutdown may proceed */
+extern os_event_t srv_redo_log_thread_finished_event;
+
/* If the last data file is auto-extended, we add this many pages to it
at a time */
#define SRV_AUTO_EXTEND_INCREMENT \
@@ -136,6 +144,11 @@ extern char* srv_doublewrite_file;
extern ibool srv_recovery_stats;
+extern my_bool srv_track_changed_pages;
+
+extern
+ulonglong srv_changed_pages_limit;
+
extern ibool srv_auto_extend_last_data_file;
extern ulint srv_last_file_size_max;
extern char** srv_log_group_home_dirs;
@@ -169,6 +182,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 */
@@ -402,6 +416,7 @@ extern mysql_pfs_key_t srv_error_monitor_thread_key;
extern mysql_pfs_key_t srv_monitor_thread_key;
extern mysql_pfs_key_t srv_master_thread_key;
extern mysql_pfs_key_t srv_purge_thread_key;
+extern mysql_pfs_key_t srv_log_tracking_thread_key;
/* This macro register the current thread and its key with performance
schema */
@@ -697,6 +712,15 @@ srv_LRU_dump_restore_thread(
void* arg); /*!< in: a dummy parameter required by
os_thread_create */
/******************************************************************//**
+A thread which follows the redo log and outputs the changed page bitmap.
+@return a dummy value */
+UNIV_INTERN
+os_thread_ret_t
+srv_redo_log_follow_thread(
+/*=======================*/
+ void* arg); /*!< in: a dummy parameter required by
+ os_thread_create */
+/******************************************************************//**
Outputs to a file the output of the InnoDB Monitor.
@return FALSE if not all information printed
due to failure to obtain necessary mutex */
diff --git a/storage/xtradb/include/trx0sys.h b/storage/xtradb/include/trx0sys.h
index c933fb405e1..cba21ae97a9 100644
--- a/storage/xtradb/include/trx0sys.h
+++ b/storage/xtradb/include/trx0sys.h
@@ -342,6 +342,14 @@ void
trx_sys_print_mysql_binlog_offset(void);
/*===================================*/
/*****************************************************************//**
+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
@@ -534,10 +542,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 ce59a3f2741..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 28.1
+#define PERCONA_INNODB_VERSION 29.1
#endif
/* The following is the InnoDB version as shown in
diff --git a/storage/xtradb/include/ut0rbt.h b/storage/xtradb/include/ut0rbt.h
index e26b637ae13..cd9df1c1a3d 100644
--- a/storage/xtradb/include/ut0rbt.h
+++ b/storage/xtradb/include/ut0rbt.h
@@ -116,6 +116,10 @@ struct ib_rbt_bound_struct {
/* Compare a key with the node value (t is tree, k is key, n is node)*/
#define rbt_compare(t, k, n) (t->compare(k, n->value))
+/* Node size. FIXME: name might clash, but currently it does not, so for easier
+ maintenance do not rename it for now. */
+#define SIZEOF_NODE(t) ((sizeof(ib_rbt_node_t) + t->sizeof_value) - 1)
+
/**********************************************************************//**
Free an instance of a red black tree */
UNIV_INTERN
@@ -187,6 +191,17 @@ rbt_add_node(
ib_rbt_bound_t* parent, /*!< in: parent */
const void* value); /*!< in: this value is copied
to the node */
+/****************************************************************//**
+Add a new caller-provided node to tree at the specified position.
+The node must have its key fields initialized correctly.
+@return added node */
+UNIV_INTERN
+const ib_rbt_node_t*
+rbt_add_preallocated_node(
+/*======================*/
+ ib_rbt_t* tree, /*!< in: rb tree */
+ ib_rbt_bound_t* parent, /*!< in: parent */
+ ib_rbt_node_t* node); /*!< in: node */
/**********************************************************************//**
Return the left most data node in the tree
@return left most node */
@@ -273,6 +288,13 @@ void
rbt_clear(
/*======*/
ib_rbt_t* tree); /*!< in: rb tree */
+/****************************************************************//**
+Clear the tree without deleting and freeing its nodes. */
+UNIV_INTERN
+void
+rbt_reset(
+/*======*/
+ ib_rbt_t* tree); /*!< in: rb tree */
/**********************************************************************//**
Merge the node from dst into src. Return the number of nodes merged.
@return no. of recs merged */
diff --git a/storage/xtradb/log/log0log.c b/storage/xtradb/log/log0log.c
index 4f8133b3036..f2066b49662 100644
--- a/storage/xtradb/log/log0log.c
+++ b/storage/xtradb/log/log0log.c
@@ -216,6 +216,54 @@ log_buf_pool_get_oldest_modification(void)
return(lsn);
}
+/****************************************************************//**
+Safely reads the log_sys->tracked_lsn value. Uses atomic operations
+if available, otherwise this field is protected with the log system
+mutex. The writer counterpart function is log_set_tracked_lsn() in
+log0online.c.
+
+@return log_sys->tracked_lsn value. */
+UNIV_INLINE
+ib_uint64_t
+log_get_tracked_lsn()
+{
+#ifdef HAVE_ATOMIC_BUILTINS_64
+ return os_atomic_increment_uint64(&log_sys->tracked_lsn, 0);
+#else
+ ut_ad(mutex_own(&(log_sys->mutex)));
+ return log_sys->tracked_lsn;
+#endif
+}
+
+/****************************************************************//**
+Checks if the log groups have a big enough margin of free space in
+so that a new log entry can be written without overwriting log data
+that is not read by the changed page bitmap thread.
+@return TRUE if there is not enough free space. */
+static
+ibool
+log_check_tracking_margin(
+ ulint lsn_advance) /*!< in: an upper limit on how much log data we
+ plan to write. If zero, the margin will be
+ checked for the already-written log. */
+{
+ ib_uint64_t tracked_lsn;
+ ulint tracked_lsn_age;
+
+ if (!srv_track_changed_pages) {
+ return FALSE;
+ }
+
+ ut_ad(mutex_own(&(log_sys->mutex)));
+
+ tracked_lsn = log_get_tracked_lsn();
+ tracked_lsn_age = log_sys->lsn - tracked_lsn;
+
+ /* The overwrite would happen when log_sys->log_group_capacity is
+ exceeded, but we use max_checkpoint_age for an extra safety margin. */
+ return tracked_lsn_age + lsn_advance > log_sys->max_checkpoint_age;
+}
+
/************************************************************//**
Opens the log for log_write_low. The log must be closed with log_close and
released with log_release.
@@ -232,9 +280,7 @@ log_reserve_and_open(
ulint archived_lsn_age;
ulint dummy;
#endif /* UNIV_LOG_ARCHIVE */
-#ifdef UNIV_DEBUG
ulint count = 0;
-#endif /* UNIV_DEBUG */
ut_a(len < log->buf_size / 2);
loop:
@@ -262,6 +308,19 @@ loop:
goto loop;
}
+ if (log_check_tracking_margin(len_upper_limit) && (++count < 50)) {
+
+ /* This log write would violate the untracked LSN free space
+ margin. Limit this to 50 retries as there might be situations
+ where we have no choice but to proceed anyway, i.e. if the log
+ is about to be overflown, log tracking or not. */
+ mutex_exit(&(log->mutex));
+
+ os_thread_sleep(10000);
+
+ goto loop;
+ }
+
#ifdef UNIV_LOG_ARCHIVE
if (log->archiving_state != LOG_ARCH_OFF) {
@@ -400,6 +459,8 @@ log_close(void)
ulint first_rec_group;
ib_uint64_t oldest_lsn;
ib_uint64_t lsn;
+ ib_uint64_t tracked_lsn;
+ ulint tracked_lsn_age;
log_t* log = log_sys;
ib_uint64_t checkpoint_age;
@@ -426,6 +487,19 @@ log_close(void)
log->check_flush_or_checkpoint = TRUE;
}
+ if (srv_track_changed_pages) {
+
+ tracked_lsn = log_get_tracked_lsn();
+ tracked_lsn_age = lsn - tracked_lsn;
+
+ if (tracked_lsn_age >= log->log_group_capacity) {
+
+ fprintf(stderr, " InnoDB: Error: the age of the "
+ "oldest untracked record exceeds the log "
+ "group capacity!\n");
+ }
+ }
+
checkpoint_age = lsn - log->last_checkpoint_lsn;
if (checkpoint_age >= log->log_group_capacity) {
@@ -893,6 +967,8 @@ log_init(void)
log_sys->archiving_on = os_event_create(NULL);
#endif /* UNIV_LOG_ARCHIVE */
+ log_sys->tracked_lsn = 0;
+
/*----------------------------*/
log_block_init(log_sys->buf, log_sys->lsn);
@@ -1749,6 +1825,12 @@ log_io_complete_checkpoint(void)
}
mutex_exit(&(log_sys->mutex));
+
+ /* Wake the redo log watching thread to parse the log up to this
+ checkpoint. */
+ if (srv_track_changed_pages) {
+ os_event_set(srv_checkpoint_completed_event);
+ }
}
/*******************************************************************//**
@@ -3176,6 +3258,15 @@ loop:
log_checkpoint_margin();
+ mutex_enter(&(log_sys->mutex));
+ if (log_check_tracking_margin(0)) {
+
+ mutex_exit(&(log_sys->mutex));
+ os_thread_sleep(10000);
+ goto loop;
+ }
+ mutex_exit(&(log_sys->mutex));
+
#ifdef UNIV_LOG_ARCHIVE
log_archive_margin();
#endif /* UNIV_LOG_ARCHIVE */
@@ -3204,6 +3295,7 @@ logs_empty_and_mark_files_at_shutdown(void)
/*=======================================*/
{
ib_uint64_t lsn;
+ ib_uint64_t tracked_lsn;
ulint arch_log_no;
ibool server_busy;
ulint count = 0;
@@ -3395,6 +3487,12 @@ loop:
}
srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE;
+ /* Wake the log tracking thread which will then immediatelly
+ quit because of srv_shutdown_state value */
+ if (srv_track_changed_pages) {
+ os_event_set(srv_checkpoint_completed_event);
+ os_event_wait(srv_redo_log_thread_finished_event);
+ }
fil_close_all_files();
ut_a(srv_get_active_thread_type() == ULINT_UNDEFINED);
return;
@@ -3404,9 +3502,12 @@ loop:
mutex_enter(&log_sys->mutex);
+ tracked_lsn = log_get_tracked_lsn();
+
lsn = log_sys->lsn;
if (lsn != log_sys->last_checkpoint_lsn
+ || (srv_track_changed_pages && (tracked_lsn != log_sys->last_checkpoint_lsn))
#ifdef UNIV_LOG_ARCHIVE
|| (srv_log_archive_on
&& lsn != log_sys->archived_lsn + LOG_BLOCK_HDR_SIZE)
@@ -3464,6 +3565,11 @@ loop:
srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE;
+ /* Signal the log following thread to quit */
+ if (srv_track_changed_pages) {
+ os_event_set(srv_checkpoint_completed_event);
+ }
+
/* Make some checks that the server really is quiet */
ut_a(srv_get_active_thread_type() == ULINT_UNDEFINED);
@@ -3484,6 +3590,10 @@ loop:
fil_flush_file_spaces(FIL_TABLESPACE);
+ if (srv_track_changed_pages) {
+ os_event_wait(srv_redo_log_thread_finished_event);
+ }
+
fil_close_all_files();
/* Make some checks that the server really is quiet */
@@ -3610,6 +3720,18 @@ log_print(
((log_sys->n_log_ios - log_sys->n_log_ios_old)
/ time_elapsed));
+ if (srv_track_changed_pages) {
+
+ /* The maximum tracked LSN age is equal to the maximum
+ checkpoint age */
+ fprintf(file,
+ "Log tracking enabled\n"
+ "Log tracked up to %llu\n"
+ "Max tracked LSN age %lu\n",
+ log_get_tracked_lsn(),
+ log_sys->max_checkpoint_age);
+ }
+
log_sys->n_log_ios_old = log_sys->n_log_ios;
log_sys->last_printout_time = current_time;
diff --git a/storage/xtradb/log/log0online.c b/storage/xtradb/log/log0online.c
new file mode 100644
index 00000000000..1d478c467e6
--- /dev/null
+++ b/storage/xtradb/log/log0online.c
@@ -0,0 +1,1085 @@
+/*****************************************************************************
+
+Copyright (c) 2011-2012 Percona Inc. All Rights Reserved.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+*****************************************************************************/
+
+/**************************************************//**
+@file log/log0online.c
+Online database log parsing for changed page tracking
+
+*******************************************************/
+
+#include "log0online.h"
+
+#include "my_dbug.h"
+
+#include "log0recv.h"
+#include "mach0data.h"
+#include "mtr0log.h"
+#include "srv0srv.h"
+#include "srv0start.h"
+#include "trx0sys.h"
+#include "ut0rbt.h"
+
+enum { FOLLOW_SCAN_SIZE = 4 * (UNIV_PAGE_SIZE_MAX) };
+
+/** Log parsing and bitmap output data structure */
+struct log_bitmap_struct {
+ byte read_buf[FOLLOW_SCAN_SIZE];
+ /*!< log read buffer */
+ byte parse_buf[RECV_PARSING_BUF_SIZE];
+ /*!< log parse buffer */
+ byte* parse_buf_end; /*!< parse buffer position where the
+ next read log data should be copied to.
+ If the previous log records were fully
+ parsed, it points to the start,
+ otherwise points immediatelly past the
+ end of the incomplete log record. */
+ char* out_name; /*!< the file name for bitmap output */
+ os_file_t out; /*!< the bitmap output file */
+ ib_uint64_t out_offset; /*!< the next write position in the
+ bitmap output file */
+ ib_uint64_t start_lsn; /*!< the LSN of the next unparsed
+ record and the start of the next LSN
+ interval to be parsed. */
+ ib_uint64_t end_lsn; /*!< the end of the LSN interval to be
+ parsed, equal to the next checkpoint
+ LSN at the time of parse */
+ ib_uint64_t next_parse_lsn; /*!< the LSN of the next unparsed
+ record in the current parse */
+ ib_rbt_t* modified_pages; /*!< the current modified page set,
+ organized as the RB-tree with the keys
+ of (space, 4KB-block-start-page-id)
+ pairs */
+ ib_rbt_node_t* page_free_list; /*!< Singly-linked list of freed nodes
+ of modified_pages tree for later
+ reuse. Nodes are linked through
+ ib_rbt_node_t.left as this field has
+ both the correct type and the tree does
+ not mind its overwrite during
+ rbt_next() tree traversal. */
+};
+
+/* The log parsing and bitmap output struct instance */
+static struct log_bitmap_struct* log_bmp_sys;
+
+/* File name stem for modified page bitmaps */
+static const char* modified_page_stem = "ib_modified_log.";
+
+/* On server startup with empty database srv_start_lsn == 0, in
+which case the first LSN of actual log records will be this. */
+#define MIN_TRACKED_LSN ((LOG_START_LSN) + (LOG_BLOCK_HDR_SIZE))
+
+/* Tests if num bit of bitmap is set */
+#define IS_BIT_SET(bitmap, num) \
+ (*((bitmap) + ((num) >> 3)) & (1UL << ((num) & 7UL)))
+
+/** The bitmap file block size in bytes. All writes will be multiples of this.
+ */
+enum {
+ MODIFIED_PAGE_BLOCK_SIZE = 4096
+};
+
+
+/** Offsets in a file bitmap block */
+enum {
+ MODIFIED_PAGE_IS_LAST_BLOCK = 0,/* 1 if last block in the current
+ write, 0 otherwise. */
+ MODIFIED_PAGE_START_LSN = 4, /* The starting tracked LSN of this and
+ other blocks in the same write */
+ MODIFIED_PAGE_END_LSN = 12, /* The ending tracked LSN of this and
+ other blocks in the same write */
+ MODIFIED_PAGE_SPACE_ID = 20, /* The space ID of tracked pages in
+ this block */
+ MODIFIED_PAGE_1ST_PAGE_ID = 24, /* The page ID of the first tracked
+ page in this block */
+ MODIFIED_PAGE_BLOCK_UNUSED_1 = 28,/* Unused in order to align the start
+ of bitmap at 8 byte boundary */
+ MODIFIED_PAGE_BLOCK_BITMAP = 32,/* Start of the bitmap itself */
+ MODIFIED_PAGE_BLOCK_UNUSED_2 = MODIFIED_PAGE_BLOCK_SIZE - 8,
+ /* Unused in order to align the end of
+ bitmap at 8 byte boundary */
+ MODIFIED_PAGE_BLOCK_CHECKSUM = MODIFIED_PAGE_BLOCK_SIZE - 4
+ /* The checksum of the current block */
+};
+
+/** Length of the bitmap data in a block in bytes */
+enum { MODIFIED_PAGE_BLOCK_BITMAP_LEN
+ = MODIFIED_PAGE_BLOCK_UNUSED_2 - MODIFIED_PAGE_BLOCK_BITMAP };
+
+/** Length of the bitmap data in a block in page ids */
+enum { MODIFIED_PAGE_BLOCK_ID_COUNT = MODIFIED_PAGE_BLOCK_BITMAP_LEN * 8 };
+
+/****************************************************************//**
+Provide a comparisson function for the RB-tree tree (space,
+block_start_page) pairs. Actual implementation does not matter as
+long as the ordering is full.
+@return -1 if p1 < p2, 0 if p1 == p2, 1 if p1 > p2
+*/
+static
+int
+log_online_compare_bmp_keys(
+/*========================*/
+ const void* p1, /*!<in: 1st key to compare */
+ const void* p2) /*!<in: 2nd key to compare */
+{
+ const byte *k1 = (const byte *)p1;
+ const byte *k2 = (const byte *)p2;
+
+ ulint k1_space = mach_read_from_4(k1 + MODIFIED_PAGE_SPACE_ID);
+ ulint k2_space = mach_read_from_4(k2 + MODIFIED_PAGE_SPACE_ID);
+ if (k1_space == k2_space) {
+ ulint k1_start_page
+ = mach_read_from_4(k1 + MODIFIED_PAGE_1ST_PAGE_ID);
+ ulint k2_start_page
+ = mach_read_from_4(k2 + MODIFIED_PAGE_1ST_PAGE_ID);
+ return k1_start_page < k2_start_page
+ ? -1 : k1_start_page > k2_start_page ? 1 : 0;
+ }
+ return k1_space < k2_space ? -1 : 1;
+}
+
+/****************************************************************//**
+Set a bit for tracked page in the bitmap. Expand the bitmap tree as
+necessary. */
+static
+void
+log_online_set_page_bit(
+/*====================*/
+ ulint space, /*!<in: log record space id */
+ ulint page_no)/*!<in: log record page id */
+{
+ ulint block_start_page;
+ ulint block_pos;
+ uint bit_pos;
+ ib_rbt_bound_t tree_search_pos;
+ byte search_page[MODIFIED_PAGE_BLOCK_SIZE];
+ byte *page_ptr;
+
+ ut_a(space != ULINT_UNDEFINED);
+ ut_a(page_no != ULINT_UNDEFINED);
+
+ block_start_page = page_no / MODIFIED_PAGE_BLOCK_ID_COUNT
+ * MODIFIED_PAGE_BLOCK_ID_COUNT;
+ block_pos = block_start_page ? (page_no % block_start_page / 8)
+ : (page_no / 8);
+ bit_pos = page_no % 8;
+
+ mach_write_to_4(search_page + MODIFIED_PAGE_SPACE_ID, space);
+ mach_write_to_4(search_page + MODIFIED_PAGE_1ST_PAGE_ID,
+ block_start_page);
+
+ if (!rbt_search(log_bmp_sys->modified_pages, &tree_search_pos,
+ search_page)) {
+ page_ptr = rbt_value(byte, tree_search_pos.last);
+ }
+ else {
+ ib_rbt_node_t *new_node;
+
+ if (log_bmp_sys->page_free_list) {
+ new_node = log_bmp_sys->page_free_list;
+ log_bmp_sys->page_free_list = new_node->left;
+ }
+ else {
+ new_node = ut_malloc(SIZEOF_NODE(
+ log_bmp_sys->modified_pages));
+ }
+ memset(new_node, 0, SIZEOF_NODE(log_bmp_sys->modified_pages));
+
+ page_ptr = rbt_value(byte, new_node);
+ mach_write_to_4(page_ptr + MODIFIED_PAGE_SPACE_ID, space);
+ mach_write_to_4(page_ptr + MODIFIED_PAGE_1ST_PAGE_ID,
+ block_start_page);
+
+ rbt_add_preallocated_node(log_bmp_sys->modified_pages,
+ &tree_search_pos, new_node);
+ }
+ page_ptr[MODIFIED_PAGE_BLOCK_BITMAP + block_pos] |= (1U << bit_pos);
+}
+
+/****************************************************************//**
+Calculate a bitmap block checksum. Algorithm borrowed from
+log_block_calc_checksum.
+@return checksum */
+UNIV_INLINE
+ulint
+log_online_calc_checksum(
+/*=====================*/
+ const byte* block) /*!<in: bitmap block */
+{
+ ulint sum;
+ ulint sh;
+ ulint i;
+
+ sum = 1;
+ sh = 0;
+
+ for (i = 0; i < MODIFIED_PAGE_BLOCK_CHECKSUM; i++) {
+
+ ulint b = block[i];
+ sum &= 0x7FFFFFFFUL;
+ sum += b;
+ sum += b << sh;
+ sh++;
+ if (sh > 24) {
+ sh = 0;
+ }
+ }
+
+ return sum;
+}
+
+/****************************************************************//**
+Get the last tracked fully LSN from the bitmap file by reading
+backwards untile a correct end page is found. Detects incomplete
+writes and corrupted data. Sets the start output position for the
+written bitmap data.
+@return the last fully tracked LSN */
+static
+ib_uint64_t
+log_online_read_last_tracked_lsn()
+/*==============================*/
+{
+ byte page[MODIFIED_PAGE_BLOCK_SIZE];
+ ib_uint64_t read_offset = log_bmp_sys->out_offset;
+ /* Initialize these to nonequal values so that file size == 0 case with
+ zero loop repetitions is handled correctly */
+ ulint checksum = 0;
+ ulint actual_checksum = !checksum;
+ ibool is_last_page = FALSE;
+ ib_uint64_t result;
+
+ ut_ad(log_bmp_sys->out_offset % MODIFIED_PAGE_BLOCK_SIZE == 0);
+
+ while (checksum != actual_checksum && read_offset > 0 && !is_last_page)
+ {
+
+ ulint offset_low, offset_high;
+ ibool success;
+
+ read_offset -= MODIFIED_PAGE_BLOCK_SIZE;
+ offset_high = (ulint)(read_offset >> 32);
+ offset_low = (ulint)(read_offset & 0xFFFFFFFF);
+
+ success = os_file_read(log_bmp_sys->out, page, offset_low,
+ offset_high, MODIFIED_PAGE_BLOCK_SIZE);
+ if (!success) {
+
+ /* The following call prints an error message */
+ os_file_get_last_error(TRUE);
+ /* Here and below assume that bitmap file names do not
+ contain apostrophes, thus no need for
+ ut_print_filename(). */
+ fprintf(stderr, "InnoDB: Warning: failed reading "
+ "changed page bitmap file \'%s\'\n",
+ log_bmp_sys->out_name);
+ return MIN_TRACKED_LSN;
+ }
+
+ is_last_page
+ = mach_read_from_4(page + MODIFIED_PAGE_IS_LAST_BLOCK);
+ checksum = mach_read_from_4(page
+ + MODIFIED_PAGE_BLOCK_CHECKSUM);
+ actual_checksum = log_online_calc_checksum(page);
+ if (checksum != actual_checksum) {
+
+ fprintf(stderr, "InnoDB: Warning: corruption "
+ "detected in \'%s\' at offset %llu\n",
+ log_bmp_sys->out_name, read_offset);
+ }
+
+ };
+
+ if (UNIV_LIKELY(checksum == actual_checksum && is_last_page)) {
+
+ log_bmp_sys->out_offset = read_offset
+ + MODIFIED_PAGE_BLOCK_SIZE;
+ result = mach_read_from_8(page + MODIFIED_PAGE_END_LSN);
+ }
+ else {
+ log_bmp_sys->out_offset = read_offset;
+ result = 0;
+ }
+
+ /* Truncate the output file to discard the corrupted bitmap data, if
+ any */
+ if (!os_file_set_eof_at(log_bmp_sys->out,
+ log_bmp_sys->out_offset)) {
+ fprintf(stderr, "InnoDB: Warning: failed truncating "
+ "changed page bitmap file \'%s\' to %llu bytes\n",
+ log_bmp_sys->out_name, log_bmp_sys->out_offset);
+ result = 0;
+ }
+ return result;
+}
+
+/****************************************************************//**
+Safely write the log_sys->tracked_lsn value. Uses atomic operations
+if available, otherwise this field is protected with the log system
+mutex. The reader counterpart function is log_get_tracked_lsn() in
+log0log.c. */
+UNIV_INLINE
+void
+log_set_tracked_lsn(
+/*================*/
+ ib_uint64_t tracked_lsn) /*!<in: new value */
+{
+#ifdef HAVE_ATOMIC_BUILTINS_64
+ /* Single writer, no data race here */
+ ib_uint64_t old_value
+ = os_atomic_increment_uint64(&log_sys->tracked_lsn, 0);
+ (void) os_atomic_increment_uint64(&log_sys->tracked_lsn,
+ tracked_lsn - old_value);
+#else
+ mutex_enter(&log_sys->mutex);
+ log_sys->tracked_lsn = tracked_lsn;
+ mutex_exit(&log_sys->mutex);
+#endif
+}
+
+/****************************************************************//**
+Diagnose a gap in tracked LSN range on server startup due to crash or
+very fast shutdown and try to close it by tracking the data
+immediatelly, if possible. */
+static
+void
+log_online_track_missing_on_startup(
+/*================================*/
+ ib_uint64_t last_tracked_lsn, /*!<in: last tracked LSN read
+ from the bitmap file */
+ ib_uint64_t tracking_start_lsn) /*!<in: last checkpoint LSN of
+ the current server startup */
+{
+ ut_ad(last_tracked_lsn != tracking_start_lsn);
+
+ fprintf(stderr, "InnoDB: last tracked LSN in \'%s\' is %llu, but "
+ "last checkpoint LSN is %llu. This might be due to a server "
+ "crash or a very fast shutdown. ", log_bmp_sys->out_name,
+ last_tracked_lsn, tracking_start_lsn);
+
+ /* last_tracked_lsn might be < MIN_TRACKED_LSN in the case of empty
+ bitmap file, handle this too. */
+ last_tracked_lsn = ut_max(last_tracked_lsn, MIN_TRACKED_LSN);
+
+ /* See if we can fully recover the missing interval */
+ if (log_sys->lsn - last_tracked_lsn < log_sys->log_group_capacity) {
+
+ fprintf(stderr,
+ "Reading the log to advance the last tracked LSN.\n");
+
+ log_bmp_sys->start_lsn = last_tracked_lsn;
+ log_set_tracked_lsn(log_bmp_sys->start_lsn);
+ log_online_follow_redo_log();
+ ut_ad(log_bmp_sys->end_lsn >= tracking_start_lsn);
+
+ fprintf(stderr,
+ "InnoDB: continuing tracking changed pages from LSN "
+ "%llu\n", log_bmp_sys->end_lsn);
+ }
+ else {
+ fprintf(stderr,
+ "The age of last tracked LSN exceeds log capacity, "
+ "tracking-based incremental backups will work only "
+ "from the higher LSN!\n");
+
+ log_bmp_sys->end_lsn = log_bmp_sys->start_lsn
+ = tracking_start_lsn;
+ log_set_tracked_lsn(log_bmp_sys->start_lsn);
+
+ fprintf(stderr,
+ "InnoDB: starting tracking changed pages from LSN "
+ "%llu\n", log_bmp_sys->end_lsn);
+ }
+}
+
+/*********************************************************************//**
+Initialize the online log following subsytem. */
+UNIV_INTERN
+void
+log_online_read_init()
+/*==================*/
+{
+ char buf[FN_REFLEN];
+ ibool success;
+ ib_uint64_t tracking_start_lsn
+ = ut_max(log_sys->last_checkpoint_lsn, MIN_TRACKED_LSN);
+
+ /* Assert (could be compile-time assert) that bitmap data start and end
+ in a bitmap block is 8-byte aligned */
+ ut_a(MODIFIED_PAGE_BLOCK_BITMAP % 8 == 0);
+ ut_a(MODIFIED_PAGE_BLOCK_BITMAP_LEN % 8 == 0);
+
+ log_bmp_sys = ut_malloc(sizeof(*log_bmp_sys));
+
+ ut_snprintf(buf, FN_REFLEN, "%s%s%d", srv_data_home,
+ modified_page_stem, 1);
+ log_bmp_sys->out_name = ut_malloc(strlen(buf) + 1);
+ ut_strcpy(log_bmp_sys->out_name, buf);
+
+ log_bmp_sys->modified_pages = rbt_create(MODIFIED_PAGE_BLOCK_SIZE,
+ log_online_compare_bmp_keys);
+ log_bmp_sys->page_free_list = NULL;
+
+ log_bmp_sys->out
+ = os_file_create_simple_no_error_handling
+ (innodb_file_bmp_key, log_bmp_sys->out_name, OS_FILE_OPEN,
+ OS_FILE_READ_WRITE, &success);
+
+ if (!success) {
+
+ /* New file, tracking from scratch */
+ log_bmp_sys->out
+ = os_file_create_simple_no_error_handling
+ (innodb_file_bmp_key, log_bmp_sys->out_name,
+ OS_FILE_CREATE, OS_FILE_READ_WRITE, &success);
+ if (!success) {
+
+ /* The following call prints an error message */
+ os_file_get_last_error(TRUE);
+ fprintf(stderr,
+ "InnoDB: Error: Cannot create \'%s\'\n",
+ log_bmp_sys->out_name);
+ exit(1);
+ }
+
+ log_bmp_sys->out_offset = 0;
+ }
+ else {
+
+ /* Old file, read last tracked LSN and continue from there */
+ ulint size_low;
+ ulint size_high;
+ ib_uint64_t last_tracked_lsn;
+
+ success = os_file_get_size(log_bmp_sys->out, &size_low,
+ &size_high);
+ ut_a(success);
+
+ log_bmp_sys->out_offset
+ = ((ib_uint64_t)size_high << 32) | size_low;
+
+ if (log_bmp_sys->out_offset % MODIFIED_PAGE_BLOCK_SIZE != 0) {
+
+ fprintf(stderr,
+ "InnoDB: Warning: truncated block detected "
+ "in \'%s\' at offset %llu\n",
+ log_bmp_sys->out_name,
+ log_bmp_sys->out_offset);
+ log_bmp_sys->out_offset -=
+ log_bmp_sys->out_offset
+ % MODIFIED_PAGE_BLOCK_SIZE;
+ }
+
+ last_tracked_lsn = log_online_read_last_tracked_lsn();
+
+ if (last_tracked_lsn < tracking_start_lsn) {
+
+ log_online_track_missing_on_startup(last_tracked_lsn,
+ tracking_start_lsn);
+ return;
+ }
+
+ if (last_tracked_lsn > tracking_start_lsn) {
+
+ fprintf(stderr, "InnoDB: last tracked LSN in \'%s\' "
+ "is %llu, but last checkpoint LSN is %llu. "
+ "The tracking-based incremental backups will "
+ "work only from the latter LSN!\n",
+ log_bmp_sys->out_name, last_tracked_lsn,
+ tracking_start_lsn);
+ }
+
+ }
+
+ fprintf(stderr, "InnoDB: starting tracking changed pages from "
+ "LSN %llu\n", tracking_start_lsn);
+ log_bmp_sys->start_lsn = tracking_start_lsn;
+ log_set_tracked_lsn(tracking_start_lsn);
+}
+
+/*********************************************************************//**
+Shut down the online log following subsystem. */
+UNIV_INTERN
+void
+log_online_read_shutdown()
+/*======================*/
+{
+ ib_rbt_node_t *free_list_node = log_bmp_sys->page_free_list;
+
+ os_file_close(log_bmp_sys->out);
+
+ rbt_free(log_bmp_sys->modified_pages);
+
+ while (free_list_node) {
+ ib_rbt_node_t *next = free_list_node->left;
+ ut_free(free_list_node);
+ free_list_node = next;
+ }
+
+ ut_free(log_bmp_sys->out_name);
+ ut_free(log_bmp_sys);
+}
+
+/*********************************************************************//**
+For the given minilog record type determine if the record has (space; page)
+associated with it.
+@return TRUE if the record has (space; page) in it */
+static
+ibool
+log_online_rec_has_page(
+/*====================*/
+ byte type) /*!<in: the minilog record type */
+{
+ return type != MLOG_MULTI_REC_END && type != MLOG_DUMMY_RECORD;
+}
+
+/*********************************************************************//**
+Check if a page field for a given log record type actually contains a page
+id. It does not for file operations and MLOG_LSN.
+@return TRUE if page field contains actual page id, FALSE otherwise */
+static
+ibool
+log_online_rec_page_means_page(
+/*===========================*/
+ byte type) /*!<in: log record type */
+{
+ return log_online_rec_has_page(type)
+#ifdef UNIV_LOG_LSN_DEBUG
+ && type != MLOG_LSN
+#endif
+ && type != MLOG_FILE_CREATE
+ && type != MLOG_FILE_RENAME
+ && type != MLOG_FILE_DELETE
+ && type != MLOG_FILE_CREATE2;
+}
+
+/*********************************************************************//**
+Parse the log data in the parse buffer for the (space, page) pairs and add
+them to the modified page set as necessary. Removes the fully-parsed records
+from the buffer. If an incomplete record is found, moves it to the end of the
+buffer. */
+static
+void
+log_online_parse_redo_log()
+/*=======================*/
+{
+ byte *ptr = log_bmp_sys->parse_buf;
+ byte *end = log_bmp_sys->parse_buf_end;
+
+ ulint len = 0;
+
+ while (ptr != end
+ && log_bmp_sys->next_parse_lsn < log_bmp_sys->end_lsn) {
+
+ byte type;
+ ulint space;
+ ulint page_no;
+ byte* body;
+
+ /* recv_sys is not initialized, so on corrupt log we will
+ SIGSEGV. But the log of a live database should not be
+ corrupt. */
+ len = recv_parse_log_rec(ptr, end, &type, &space, &page_no,
+ &body);
+ if (len > 0) {
+
+ if (log_online_rec_page_means_page(type)
+ && (space != TRX_DOUBLEWRITE_SPACE)) {
+
+ ut_a(len >= 3);
+ log_online_set_page_bit(space, page_no);
+ }
+
+ ptr += len;
+ ut_ad(ptr <= end);
+ log_bmp_sys->next_parse_lsn
+ = recv_calc_lsn_on_data_add
+ (log_bmp_sys->next_parse_lsn, len);
+ }
+ else {
+
+ /* Incomplete log record. Shift it to the
+ beginning of the parse buffer and leave it to be
+ completed on the next read. */
+ ut_memmove(log_bmp_sys->parse_buf, ptr, end - ptr);
+ log_bmp_sys->parse_buf_end
+ = log_bmp_sys->parse_buf + (end - ptr);
+ ptr = end;
+ }
+ }
+
+ if (len > 0) {
+
+ log_bmp_sys->parse_buf_end = log_bmp_sys->parse_buf;
+ }
+}
+
+/*********************************************************************//**
+Check the log block checksum.
+@return TRUE if the log block checksum is OK, FALSE otherwise. */
+static
+ibool
+log_online_is_valid_log_seg(
+/*========================*/
+ const byte* log_block) /*!< in: read log data */
+{
+ ibool checksum_is_ok
+ = log_block_checksum_is_ok_or_old_format(log_block);
+
+ if (!checksum_is_ok) {
+
+ fprintf(stderr,
+ "InnoDB Error: log block checksum mismatch"
+ "expected %lu, calculated checksum %lu\n",
+ (ulong) log_block_get_checksum(log_block),
+ (ulong) log_block_calc_checksum(log_block));
+ }
+
+ return checksum_is_ok;
+}
+
+/*********************************************************************//**
+Copy new log data to the parse buffer while skipping log block header,
+trailer and already parsed data. */
+static
+void
+log_online_add_to_parse_buf(
+/*========================*/
+ const byte* log_block, /*!< in: read log data */
+ ulint data_len, /*!< in: length of read log data */
+ ulint skip_len) /*!< in: how much of log data to
+ skip */
+{
+ ulint start_offset = skip_len ? skip_len : LOG_BLOCK_HDR_SIZE;
+ ulint end_offset
+ = (data_len == OS_FILE_LOG_BLOCK_SIZE)
+ ? data_len - LOG_BLOCK_TRL_SIZE
+ : data_len;
+ ulint actual_data_len = (end_offset >= start_offset)
+ ? end_offset - start_offset : 0;
+
+ ut_memcpy(log_bmp_sys->parse_buf_end, log_block + start_offset,
+ actual_data_len);
+
+ log_bmp_sys->parse_buf_end += actual_data_len;
+
+ ut_a(log_bmp_sys->parse_buf_end - log_bmp_sys->parse_buf
+ <= RECV_PARSING_BUF_SIZE);
+}
+
+/*********************************************************************//**
+Parse the log block: first copies the read log data to the parse buffer while
+skipping log block header, trailer and already parsed data. Then it actually
+parses the log to add to the modified page bitmap. */
+static
+void
+log_online_parse_redo_log_block(
+/*============================*/
+ const byte* log_block, /*!< in: read log data */
+ ulint skip_already_parsed_len) /*!< in: how many bytes of
+ log data should be skipped as
+ they were parsed before */
+{
+ ulint block_data_len;
+
+ block_data_len = log_block_get_data_len(log_block);
+
+ ut_ad(block_data_len % OS_FILE_LOG_BLOCK_SIZE == 0
+ || block_data_len < OS_FILE_LOG_BLOCK_SIZE);
+
+ log_online_add_to_parse_buf(log_block, block_data_len,
+ skip_already_parsed_len);
+ log_online_parse_redo_log();
+}
+
+/*********************************************************************//**
+Read and parse one redo log chunk and updates the modified page bitmap. */
+static
+void
+log_online_follow_log_seg(
+/*======================*/
+ log_group_t* group, /*!< in: the log group to use */
+ ib_uint64_t block_start_lsn, /*!< in: the LSN to read from */
+ ib_uint64_t block_end_lsn) /*!< in: the LSN to read to */
+{
+ /* Pointer to the current OS_FILE_LOG_BLOCK-sized chunk of the read log
+ data to parse */
+ byte* log_block = log_bmp_sys->read_buf;
+ byte* log_block_end = log_bmp_sys->read_buf
+ + (block_end_lsn - block_start_lsn);
+
+ mutex_enter(&log_sys->mutex);
+ log_group_read_log_seg(LOG_RECOVER, log_bmp_sys->read_buf,
+ group, block_start_lsn, block_end_lsn);
+ mutex_exit(&log_sys->mutex);
+
+ while (log_block < log_block_end
+ && log_bmp_sys->next_parse_lsn < log_bmp_sys->end_lsn) {
+
+ /* How many bytes of log data should we skip in the current log
+ block. Skipping is necessary because we round down the next
+ parse LSN thus it is possible to read the already-processed log
+ data many times */
+ ulint skip_already_parsed_len = 0;
+
+ if (!log_online_is_valid_log_seg(log_block)) {
+ break;
+ }
+
+ if ((block_start_lsn <= log_bmp_sys->next_parse_lsn)
+ && (block_start_lsn + OS_FILE_LOG_BLOCK_SIZE
+ > log_bmp_sys->next_parse_lsn)) {
+
+ /* The next parse LSN is inside the current block, skip
+ data preceding it. */
+ skip_already_parsed_len
+ = log_bmp_sys->next_parse_lsn
+ - block_start_lsn;
+ }
+ else {
+
+ /* If the next parse LSN is not inside the current
+ block, then the only option is that we have processed
+ ahead already. */
+ ut_a(block_start_lsn > log_bmp_sys->next_parse_lsn);
+ }
+
+ /* TODO: merge the copying to the parse buf code with
+ skip_already_len calculations */
+ log_online_parse_redo_log_block(log_block,
+ skip_already_parsed_len);
+
+ log_block += OS_FILE_LOG_BLOCK_SIZE;
+ block_start_lsn += OS_FILE_LOG_BLOCK_SIZE;
+ }
+
+ return;
+}
+
+/*********************************************************************//**
+Read and parse the redo log in a given group in FOLLOW_SCAN_SIZE-sized
+chunks and updates the modified page bitmap. */
+static
+void
+log_online_follow_log_group(
+/*========================*/
+ log_group_t* group, /*!< in: the log group to use */
+ ib_uint64_t contiguous_lsn) /*!< in: the LSN of log block start
+ containing the log_parse_start_lsn */
+{
+ ib_uint64_t block_start_lsn = contiguous_lsn;
+ ib_uint64_t block_end_lsn;
+
+ log_bmp_sys->next_parse_lsn = log_bmp_sys->start_lsn;
+ log_bmp_sys->parse_buf_end = log_bmp_sys->parse_buf;
+
+ do {
+ block_end_lsn = block_start_lsn + FOLLOW_SCAN_SIZE;
+
+ log_online_follow_log_seg(group, block_start_lsn,
+ block_end_lsn);
+
+ /* Next parse LSN can become higher than the last read LSN
+ only in the case when the read LSN falls right on the block
+ boundary, in which case next parse lsn is bumped to the actual
+ data LSN on the next (not yet read) block. This assert is
+ slightly conservative. */
+ ut_a(log_bmp_sys->next_parse_lsn
+ <= block_end_lsn + LOG_BLOCK_HDR_SIZE
+ + LOG_BLOCK_TRL_SIZE);
+
+ block_start_lsn = block_end_lsn;
+ } while (block_end_lsn < log_bmp_sys->end_lsn);
+
+ /* Assert that the last read log record is a full one */
+ ut_a(log_bmp_sys->parse_buf_end == log_bmp_sys->parse_buf);
+}
+
+/*********************************************************************//**
+Write, flush one bitmap block to disk and advance the output position if
+successful. */
+static
+void
+log_online_write_bitmap_page(
+/*=========================*/
+ const byte *block) /*!< in: block to write */
+{
+ ibool success;
+
+ success = os_file_write(log_bmp_sys->out_name,log_bmp_sys->out,
+ block,
+ (ulint)(log_bmp_sys->out_offset & 0xFFFFFFFF),
+ (ulint)(log_bmp_sys->out_offset << 32),
+ MODIFIED_PAGE_BLOCK_SIZE);
+ if (UNIV_UNLIKELY(!success)) {
+
+ /* The following call prints an error message */
+ os_file_get_last_error(TRUE);
+ fprintf(stderr, "InnoDB: Error: failed writing changed page "
+ "bitmap file \'%s\'\n", log_bmp_sys->out_name);
+ return;
+ }
+
+ success = os_file_flush(log_bmp_sys->out, FALSE);
+ if (UNIV_UNLIKELY(!success)) {
+
+ /* The following call prints an error message */
+ os_file_get_last_error(TRUE);
+ fprintf(stderr, "InnoDB: Error: failed flushing "
+ "changed page bitmap file \'%s\'\n",
+ log_bmp_sys->out_name);
+ return;
+ }
+
+ log_bmp_sys->out_offset += MODIFIED_PAGE_BLOCK_SIZE;
+}
+
+/*********************************************************************//**
+Append the current changed page bitmap to the bitmap file. Clears the
+bitmap tree and recycles its nodes to the free list. */
+static
+void
+log_online_write_bitmap()
+/*=====================*/
+{
+ ib_rbt_node_t *bmp_tree_node;
+ const ib_rbt_node_t *last_bmp_tree_node;
+
+ bmp_tree_node = (ib_rbt_node_t *)
+ rbt_first(log_bmp_sys->modified_pages);
+ last_bmp_tree_node = rbt_last(log_bmp_sys->modified_pages);
+
+ while (bmp_tree_node) {
+
+ byte *page = rbt_value(byte, bmp_tree_node);
+
+ if (bmp_tree_node == last_bmp_tree_node) {
+ mach_write_to_4(page + MODIFIED_PAGE_IS_LAST_BLOCK, 1);
+ }
+
+ mach_write_to_8(page + MODIFIED_PAGE_START_LSN,
+ log_bmp_sys->start_lsn);
+ mach_write_to_8(page + MODIFIED_PAGE_END_LSN,
+ log_bmp_sys->end_lsn);
+ mach_write_to_4(page + MODIFIED_PAGE_BLOCK_CHECKSUM,
+ log_online_calc_checksum(page));
+
+ log_online_write_bitmap_page(page);
+
+ bmp_tree_node->left = log_bmp_sys->page_free_list;
+ log_bmp_sys->page_free_list = bmp_tree_node;
+
+ bmp_tree_node = (ib_rbt_node_t*)
+ rbt_next(log_bmp_sys->modified_pages, bmp_tree_node);
+ }
+
+ rbt_reset(log_bmp_sys->modified_pages);
+}
+
+/*********************************************************************//**
+Read and parse the redo log up to last checkpoint LSN to build the changed
+page bitmap which is then written to disk. */
+UNIV_INTERN
+void
+log_online_follow_redo_log()
+/*========================*/
+{
+ ib_uint64_t contiguous_start_lsn;
+ log_group_t* group;
+
+ /* Grab the LSN of the last checkpoint, we will parse up to it */
+ mutex_enter(&(log_sys->mutex));
+ log_bmp_sys->end_lsn = log_sys->last_checkpoint_lsn;
+ mutex_exit(&(log_sys->mutex));
+
+ if (log_bmp_sys->end_lsn == log_bmp_sys->start_lsn) {
+ return;
+ }
+
+ group = UT_LIST_GET_FIRST(log_sys->log_groups);
+ ut_a(group);
+
+ contiguous_start_lsn = ut_uint64_align_down(log_bmp_sys->start_lsn,
+ OS_FILE_LOG_BLOCK_SIZE);
+
+ while (group) {
+ log_online_follow_log_group(group, contiguous_start_lsn);
+ group = UT_LIST_GET_NEXT(log_groups, group);
+ }
+
+ /* A crash injection site that ensures last checkpoint LSN > last
+ tracked LSN, so that LSN tracking for this interval is tested. */
+ DBUG_EXECUTE_IF("crash_before_bitmap_write", DBUG_SUICIDE(););
+
+ log_online_write_bitmap();
+ log_bmp_sys->start_lsn = log_bmp_sys->end_lsn;
+ log_set_tracked_lsn(log_bmp_sys->start_lsn);
+}
+
+/*********************************************************************//**
+Initializes log bitmap iterator.
+@return TRUE if the iterator is initialized OK, FALSE otherwise. */
+UNIV_INTERN
+ibool
+log_online_bitmap_iterator_init(
+/*============================*/
+ log_bitmap_iterator_t *i) /*!<in/out: iterator */
+{
+ ibool success;
+
+ ut_a(i);
+ ut_snprintf(i->in_name, FN_REFLEN, "%s%s%d", srv_data_home,
+ modified_page_stem, 1);
+ i->in_offset = 0;
+ /*
+ Set up bit offset out of the reasonable limit
+ to intiate reading block from file in
+ log_online_bitmap_iterator_next()
+ */
+ i->bit_offset = MODIFIED_PAGE_BLOCK_BITMAP_LEN;
+ i->in =
+ os_file_create_simple_no_error_handling(innodb_file_bmp_key,
+ i->in_name,
+ OS_FILE_OPEN,
+ OS_FILE_READ_ONLY,
+ &success);
+
+ if (!success) {
+ /* The following call prints an error message */
+ os_file_get_last_error(TRUE);
+ fprintf(stderr,
+ "InnoDB: Error: Cannot open \'%s\'\n",
+ i->in_name);
+ return FALSE;
+ }
+
+ i->page = ut_malloc(MODIFIED_PAGE_BLOCK_SIZE);
+
+ i->start_lsn = i->end_lsn = 0;
+ i->space_id = 0;
+ i->first_page_id = 0;
+ i->changed = FALSE;
+
+ return TRUE;
+}
+
+/*********************************************************************//**
+Releases log bitmap iterator. */
+UNIV_INTERN
+void
+log_online_bitmap_iterator_release(
+/*===============================*/
+ log_bitmap_iterator_t *i) /*!<in/out: iterator */
+{
+ ut_a(i);
+ os_file_close(i->in);
+ ut_free(i->page);
+}
+
+/*********************************************************************//**
+Iterates through bits of saved bitmap blocks.
+Sequentially reads blocks from bitmap file(s) and interates through
+their bits. Ignores blocks with wrong checksum.
+@return TRUE if iteration is successful, FALSE if all bits are iterated. */
+UNIV_INTERN
+ibool
+log_online_bitmap_iterator_next(
+/*============================*/
+ log_bitmap_iterator_t *i) /*!<in/out: iterator */
+{
+ ulint offset_low;
+ ulint offset_high;
+ ulint size_low;
+ ulint size_high;
+ ulint checksum = 0;
+ ulint actual_checksum = !checksum;
+
+ ibool success;
+
+ ut_a(i);
+
+ if (i->bit_offset < MODIFIED_PAGE_BLOCK_BITMAP_LEN)
+ {
+ ++i->bit_offset;
+ i->changed =
+ IS_BIT_SET(i->page + MODIFIED_PAGE_BLOCK_BITMAP,
+ i->bit_offset);
+ return TRUE;
+ }
+
+ while (checksum != actual_checksum)
+ {
+ success = os_file_get_size(i->in,
+ &size_low,
+ &size_high);
+ if (!success) {
+ os_file_get_last_error(TRUE);
+ fprintf(stderr,
+ "InnoDB: Warning: can't get size of "
+ "page bitmap file \'%s\'\n",
+ i->in_name);
+ return FALSE;
+ }
+
+ if (i->in_offset >=
+ (ib_uint64_t)(size_low) +
+ ((ib_uint64_t)(size_high) << 32))
+ return FALSE;
+
+ offset_high = (ulint)(i->in_offset >> 32);
+ offset_low = (ulint)(i->in_offset & 0xFFFFFFFF);
+
+ success = os_file_read(
+ i->in,
+ i->page,
+ offset_low,
+ offset_high,
+ MODIFIED_PAGE_BLOCK_SIZE);
+
+ if (!success) {
+ os_file_get_last_error(TRUE);
+ fprintf(stderr,
+ "InnoDB: Warning: failed reading "
+ "changed page bitmap file \'%s\'\n",
+ i->in_name);
+ return FALSE;
+ }
+
+ checksum = mach_read_from_4(
+ i->page + MODIFIED_PAGE_BLOCK_CHECKSUM);
+
+ actual_checksum = log_online_calc_checksum(i->page);
+
+ i->in_offset += MODIFIED_PAGE_BLOCK_SIZE;
+ }
+
+ i->start_lsn =
+ mach_read_from_8(i->page + MODIFIED_PAGE_START_LSN);
+ i->end_lsn =
+ mach_read_from_8(i->page + MODIFIED_PAGE_END_LSN);
+ i->space_id =
+ mach_read_from_4(i->page + MODIFIED_PAGE_SPACE_ID);
+ i->first_page_id =
+ mach_read_from_4(i->page + MODIFIED_PAGE_1ST_PAGE_ID);
+ i->bit_offset =
+ 0;
+ i->changed =
+ IS_BIT_SET(i->page + MODIFIED_PAGE_BLOCK_BITMAP,
+ i->bit_offset);
+
+ return TRUE;
+}
+
diff --git a/storage/xtradb/log/log0recv.c b/storage/xtradb/log/log0recv.c
index a554c576b6d..5ab8c14ae2e 100644
--- a/storage/xtradb/log/log0recv.c
+++ b/storage/xtradb/log/log0recv.c
@@ -857,7 +857,7 @@ block. We also accept a log block in the old format before
InnoDB-3.23.52 where the checksum field contains the log block number.
@return TRUE if ok, or if the log block may be in the format of InnoDB
version predating 3.23.52 */
-static
+UNIV_INTERN
ibool
log_block_checksum_is_ok_or_old_format(
/*===================================*/
@@ -2102,7 +2102,7 @@ skip_this_recv_addr:
/*******************************************************************//**
Tries to parse a single log record and returns its length.
@return length of the record, or 0 if the record was not complete */
-static
+UNIV_INTERN
ulint
recv_parse_log_rec(
/*===============*/
@@ -2173,7 +2173,7 @@ recv_parse_log_rec(
/*******************************************************//**
Calculates the new value for lsn when more data is added to the log. */
-static
+UNIV_INTERN
ib_uint64_t
recv_calc_lsn_on_data_add(
/*======================*/
@@ -3570,6 +3570,8 @@ recv_reset_logs(
log_sys->archived_lsn = log_sys->lsn;
#endif /* UNIV_LOG_ARCHIVE */
+ log_sys->tracked_lsn = log_sys->lsn;
+
log_block_init(log_sys->buf, log_sys->lsn);
log_block_set_first_rec_group(log_sys->buf, LOG_BLOCK_HDR_SIZE);
diff --git a/storage/xtradb/os/os0file.c b/storage/xtradb/os/os0file.c
index 061d556c6e7..2555c010027 100644
--- a/storage/xtradb/os/os0file.c
+++ b/storage/xtradb/os/os0file.c
@@ -158,6 +158,7 @@ UNIV_INTERN ibool os_aio_print_debug = FALSE;
UNIV_INTERN mysql_pfs_key_t innodb_file_data_key;
UNIV_INTERN mysql_pfs_key_t innodb_file_log_key;
UNIV_INTERN mysql_pfs_key_t innodb_file_temp_key;
+UNIV_INTERN mysql_pfs_key_t innodb_file_bmp_key;
#endif /* UNIV_PFS_IO */
/** The asynchronous i/o array slot structure */
@@ -1869,7 +1870,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);
@@ -2147,6 +2148,25 @@ os_file_set_eof(
#endif /* __WIN__ */
}
+/***********************************************************************//**
+Truncates a file at the specified position.
+@return TRUE if success */
+UNIV_INTERN
+ibool
+os_file_set_eof_at(
+ os_file_t file, /*!< in: handle to a file */
+ ib_uint64_t new_len)/*!< in: new file length */
+{
+#ifdef __WIN__
+ /* TODO: untested! */
+ return(!_chsize_s(file, new_len));
+#else
+ /* TODO: works only with -D_FILE_OFFSET_BITS=64 ? */
+ return(!ftruncate(file, new_len));
+#endif
+}
+
+
#ifndef __WIN__
/***********************************************************************//**
Wrapper to fsync(2) that retries the call on some errors.
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 b21d48c7552..3ae4c227ddc 100644
--- a/storage/xtradb/row/row0ins.c
+++ b/storage/xtradb/row/row0ins.c
@@ -2181,9 +2181,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 0a545a8247a..9d479ac6c87 100644
--- a/storage/xtradb/srv/srv0srv.c
+++ b/storage/xtradb/srv/srv0srv.c
@@ -67,6 +67,7 @@ Created 10/8/1995 Heikki Tuuri
#include "mem0pool.h"
#include "sync0sync.h"
#include "que0que.h"
+#include "log0online.h"
#include "log0recv.h"
#include "pars0pars.h"
#include "usr0sess.h"
@@ -176,6 +177,10 @@ UNIV_INTERN char* srv_doublewrite_file = NULL;
UNIV_INTERN ibool srv_recovery_stats = FALSE;
+UNIV_INTERN my_bool srv_track_changed_pages = TRUE;
+
+UNIV_INTERN ulonglong srv_changed_pages_limit = 0;
+
/* if TRUE, then we auto-extend the last data file */
UNIV_INTERN ibool srv_auto_extend_last_data_file = FALSE;
/* if != 0, this tells the max size auto-extending may increase the
@@ -227,6 +232,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 */
@@ -771,6 +778,10 @@ UNIV_INTERN os_event_t srv_lock_timeout_thread_event;
UNIV_INTERN os_event_t srv_shutdown_event;
+UNIV_INTERN os_event_t srv_checkpoint_completed_event;
+
+UNIV_INTERN os_event_t srv_redo_log_thread_finished_event;
+
UNIV_INTERN srv_sys_t* srv_sys = NULL;
/* padding to prevent other memory update hotspots from residing on
@@ -1110,6 +1121,9 @@ srv_init(void)
srv_lock_timeout_thread_event = os_event_create(NULL);
srv_shutdown_event = os_event_create(NULL);
+ srv_checkpoint_completed_event = os_event_create(NULL);
+ srv_redo_log_thread_finished_event = os_event_create(NULL);
+
for (i = 0; i < SRV_MASTER + 1; i++) {
srv_n_threads_active[i] = 0;
srv_n_threads[i] = 0;
@@ -3034,6 +3048,46 @@ srv_shutdown_print_master_pending(
}
}
+/******************************************************************//**
+A thread which follows the redo log and outputs the changed page bitmap.
+@return a dummy value */
+os_thread_ret_t
+srv_redo_log_follow_thread(
+/*=======================*/
+ void* arg __attribute__((unused))) /*!< in: a dummy parameter
+ required by
+ os_thread_create */
+{
+#ifdef UNIV_DEBUG_THREAD_CREATION
+ fprintf(stderr, "Redo log follower thread starts, id %lu\n",
+ os_thread_pf(os_thread_get_curr_id()));
+#endif
+
+#ifdef UNIV_PFS_THREAD
+ pfs_register_thread(srv_log_tracking_thread_key);
+#endif
+
+ my_thread_init();
+
+ do {
+ os_event_wait(srv_checkpoint_completed_event);
+ os_event_reset(srv_checkpoint_completed_event);
+
+ if (srv_shutdown_state < SRV_SHUTDOWN_LAST_PHASE) {
+ log_online_follow_redo_log();
+ }
+
+ } while (srv_shutdown_state < SRV_SHUTDOWN_LAST_PHASE);
+
+ log_online_read_shutdown();
+ os_event_set(srv_redo_log_thread_finished_event);
+
+ my_thread_end();
+ os_thread_exit(NULL);
+
+ OS_THREAD_DUMMY_RETURN;
+}
+
/*******************************************************************//**
Tells the InnoDB server that there has been activity in the database
and wakes up the master thread if it is suspended (not sleeping). Used
diff --git a/storage/xtradb/srv/srv0start.c b/storage/xtradb/srv/srv0start.c
index d1329f445aa..65a775b56da 100644
--- a/storage/xtradb/srv/srv0start.c
+++ b/storage/xtradb/srv/srv0start.c
@@ -51,6 +51,7 @@ Created 2/16/1996 Heikki Tuuri
#include "rem0rec.h"
#include "mtr0mtr.h"
#include "log0log.h"
+#include "log0online.h"
#include "log0recv.h"
#include "page0page.h"
#include "page0cur.h"
@@ -121,9 +122,9 @@ UNIV_INTERN enum srv_shutdown_state srv_shutdown_state = SRV_SHUTDOWN_NONE;
static os_file_t files[1000];
/** io_handler_thread parameters for thread identification */
-static ulint n[SRV_MAX_N_IO_THREADS + 7];
+static ulint n[SRV_MAX_N_IO_THREADS + 8];
/** io_handler_thread identifiers */
-static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 7];
+static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 8];
/** We use this mutex to test the return value of pthread_mutex_trylock
on successful locking. HP-UX does NOT return 0, though Linux et al do. */
@@ -145,6 +146,7 @@ UNIV_INTERN mysql_pfs_key_t srv_error_monitor_thread_key;
UNIV_INTERN mysql_pfs_key_t srv_monitor_thread_key;
UNIV_INTERN mysql_pfs_key_t srv_master_thread_key;
UNIV_INTERN mysql_pfs_key_t srv_purge_thread_key;
+UNIV_INTERN mysql_pfs_key_t srv_log_tracking_thread_key;
#endif /* UNIV_PFS_THREAD */
/*********************************************************************//**
@@ -1541,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,
@@ -2037,6 +2040,19 @@ innobase_start_or_create_for_mysql(void)
if (srv_auto_lru_dump && srv_blocking_lru_restore)
buf_LRU_file_restore();
+ if (srv_track_changed_pages) {
+
+ /* Initialize the log tracking subsystem here to block
+ server startup until it's completed due to the potential
+ need to re-read previous server run's log. */
+ log_online_read_init();
+
+ /* Create the thread that follows the redo log to output the
+ changed page bitmap */
+ os_thread_create(&srv_redo_log_follow_thread, NULL,
+ thread_ids + 6 + SRV_MAX_N_IO_THREADS);
+ }
+
srv_is_being_started = FALSE;
err = dict_create_or_check_foreign_constraint_tables();
diff --git a/storage/xtradb/trx/trx0sys.c b/storage/xtradb/trx/trx0sys.c
index 7d303c2563c..c40bf02a7a2 100644
--- a/storage/xtradb/trx/trx0sys.c
+++ b/storage/xtradb/trx/trx0sys.c
@@ -959,8 +959,31 @@ trx_sys_print_mysql_binlog_offset(void)
}
/*****************************************************************//**
-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)
@@ -982,60 +1005,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 b703a04b1b0..99b4276fbee 100644
--- a/storage/xtradb/trx/trx0trx.c
+++ b/storage/xtradb/trx/trx0trx.c
@@ -938,13 +938,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 = "";
}
@@ -2055,6 +2055,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/storage/xtradb/ut/ut0rbt.c b/storage/xtradb/ut/ut0rbt.c
index 3d7cfa7636f..a5e9081b951 100644
--- a/storage/xtradb/ut/ut0rbt.c
+++ b/storage/xtradb/ut/ut0rbt.c
@@ -55,7 +55,6 @@ red-black properties:
#endif
#define ROOT(t) (t->root->left)
-#define SIZEOF_NODE(t) ((sizeof(ib_rbt_node_t) + t->sizeof_value) - 1)
/**********************************************************************//**
Print out the sub-tree recursively. */
@@ -834,6 +833,21 @@ rbt_add_node(
node = (ib_rbt_node_t*) ut_malloc(SIZEOF_NODE(tree));
memcpy(node->value, value, tree->sizeof_value);
+ return(rbt_add_preallocated_node(tree, parent, node));
+}
+
+/****************************************************************//**
+Add a new caller-provided node to tree at the specified position.
+The node must have its key fields initialized correctly.
+@return added node */
+UNIV_INTERN
+const ib_rbt_node_t*
+rbt_add_preallocated_node(
+/*======================*/
+ ib_rbt_t* tree, /*!< in: rb tree */
+ ib_rbt_bound_t* parent, /*!< in: parent */
+ ib_rbt_node_t* node) /*!< in: node */
+{
node->parent = node->left = node->right = tree->nil;
/* If tree is empty */
@@ -842,7 +856,7 @@ rbt_add_node(
}
/* Append the node, the hope here is that the caller knows
- what s/he is doing. */
+ what s/he is doing. */
rbt_tree_add_child(tree, parent, node);
rbt_balance_tree(tree, node);
@@ -854,6 +868,7 @@ rbt_add_node(
return(node);
}
+
/**********************************************************************//**
Find a matching node in the rb tree.
@return NULL if not found else the node where key was found */
@@ -1142,7 +1157,17 @@ rbt_clear(
ib_rbt_t* tree) /*!< in: rb tree */
{
rbt_free_node(ROOT(tree), tree->nil);
+ rbt_reset(tree);
+}
+/****************************************************************//**
+Clear the tree without deleting and freeing its nodes. */
+UNIV_INTERN
+void
+rbt_reset(
+/*======*/
+ ib_rbt_t* tree) /*!< in: rb tree */
+{
tree->n_nodes = 0;
tree->root->left = tree->root->right = tree->nil;
}
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/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index 5b9a296d90a..0d673e5b339 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -252,6 +252,9 @@ Vendor: %{mysql_vendor}
Provides: msqlormysql MySQL-server mysql
BuildRequires: %{distro_buildreq}
+# Regression tests may take a long time, override the default to skip them
+%{!?runselftest:%global runselftest 1}
+
# Think about what you use here since the first step is to
# run a rm -rf
BuildRoot: %{_tmppath}/%{name}-%{version}-build
@@ -403,6 +406,16 @@ For a description of MySQL see the base MySQL RPM or http://www.mysql.com/
##############################################################################
%build
+# Fail quickly and obviously if user tries to build as root
+%if %runselftest
+ if [ x"`id -u`" = x0 ]; then
+ echo "The MySQL regression tests may fail if run as root."
+ echo "If you really need to build the RPM as root, use"
+ echo "--define='runselftest 0' to skip the regression tests."
+ exit 1
+ fi
+%endif
+
# Be strict about variables, bail at earliest opportunity, etc.
set -eu
@@ -480,6 +493,13 @@ mkdir release
make ${MAKE_JFLAG} VERBOSE=1
)
+%if %runselftest
+ MTR_BUILD_THREAD=auto
+ export MTR_BUILD_THREAD
+
+ (cd release && make test-bt-fast || true)
+%endif
+
##############################################################################
%install
@@ -1146,6 +1166,14 @@ echo "=====" >> $STATUS_HISTORY
# merging BK trees)
##############################################################################
%changelog
+* Tue Jul 24 2012 Joerg Bruehe <joerg.bruehe@oracle.com>
+
+- Add a macro "runselftest":
+ if set to 1 (default), the test suite will be run during the RPM build;
+ this can be oveeridden via the command line by adding
+ --define "runselftest 0"
+ Failures of the test suite will NOT make the RPM build fail!
+
* Wed Sep 28 2011 Joerg Bruehe <joerg.bruehe@oracle.com>
- Fix duplicate mentioning of "mysql_plugin" and its manual page,
diff --git a/support-files/rpm/server-postin.sh b/support-files/rpm/server-postin.sh
index 88ff059ff22..156865b61ad 100644
--- a/support-files/rpm/server-postin.sh
+++ b/support-files/rpm/server-postin.sh
@@ -1,37 +1,46 @@
-mysql_datadir=%{mysqldatadir}
-
-# Create data directory
-mkdir -p $mysql_datadir/{mysql,test}
# Make MySQL start/shutdown automatically when the machine does it.
if [ $1 = 1 ] ; then
if [ -x /sbin/chkconfig ] ; then
/sbin/chkconfig --add mysql
fi
-fi
-# Create a MySQL user and group. Do not report any problems if it already
-# exists.
-groupadd -r %{mysqld_group} 2> /dev/null || true
-useradd -M -r -d $mysql_datadir -s /bin/bash -c "MySQL server" -g %{mysqld_group} %{mysqld_user} 2> /dev/null || true
-# The user may already exist, make sure it has the proper group nevertheless (BUG#12823)
-usermod -g %{mysqld_group} %{mysqld_user} 2> /dev/null || true
+ mysql_dirs=(`%{_sbindir}/mysqld --verbose --help 2>/dev/null|sed -ne 's/^\(basedir\|datadir\)[[:space:]]*\(.*\)$/\2/p'`)
+ basedir="${mysql_dirs[0]}"
+ datadir="${mysql_dirs[1]}"
+ # datadir may be relative to a basedir!
+ if expr $datadir : / > /dev/null; then
+ mysql_datadir=$datadir
+ else
+ mysql_datadir=$basedir/$datadir
+ fi
+
+ # Create a MySQL user and group. Do not report any problems if it already
+ # exists.
+ groupadd -r %{mysqld_group} 2> /dev/null || true
+ useradd -M -r -d $mysql_datadir -s /bin/bash -c "MySQL server" -g %{mysqld_group} %{mysqld_user} 2> /dev/null || true
+ # The user may already exist, make sure it has the proper group nevertheless (BUG#12823)
+ usermod -g %{mysqld_group} %{mysqld_user} 2> /dev/null || true
-# Change permissions so that the user that will run the MySQL daemon
-# owns all database files.
-chown -R %{mysqld_user}:%{mysqld_group} $mysql_datadir
+ # Change permissions so that the user that will run the MySQL daemon
+ # owns all database files.
+ chown -R %{mysqld_user}:%{mysqld_group} $mysql_datadir
-# Initiate databases
-%{_bindir}/mysql_install_db --rpm --user=%{mysqld_user}
+ if [ ! -e $mysql_datadir ]; then
+ # Create data directory
+ mkdir -p $mysql_datadir/{mysql,test}
-# Upgrade databases if needed would go here - but it cannot be automated yet
+ # Initiate databases
+ %{_bindir}/mysql_install_db --rpm --user=%{mysqld_user}
+ fi
-# Change permissions again to fix any new files.
-chown -R %{mysqld_user}:%{mysqld_group} $mysql_datadir
+ # Change permissions again to fix any new files.
+ chown -R %{mysqld_user}:%{mysqld_group} $mysql_datadir
-# Fix permissions for the permission database so that only the user
-# can read them.
-chmod -R og-rw $mysql_datadir/mysql
+ # Fix permissions for the permission database so that only the user
+ # can read them.
+ chmod -R og-rw $mysql_datadir/mysql
+fi
# install SELinux files - but don't override existing ones
SETARGETDIR=/etc/selinux/targeted/src/policy
diff --git a/tests/mysql_client_fw.c b/tests/mysql_client_fw.c
index 979d47cb0b8..207eaead135 100644
--- a/tests/mysql_client_fw.c
+++ b/tests/mysql_client_fw.c
@@ -61,6 +61,7 @@ static unsigned int opt_count= 0;
static unsigned int iter_count= 0;
static my_bool have_innodb= FALSE;
static char *opt_plugin_dir= 0, *opt_default_auth= 0;
+static unsigned int opt_drop_db= 1;
static const char *opt_basedir= "./";
static const char *opt_vardir= "mysql-test/var";
@@ -109,7 +110,7 @@ DBUG_PRINT("test", ("name: %s", str)); \
static void print_error(const char *msg);
static void print_st_error(MYSQL_STMT *stmt, const char *msg);
-static void client_disconnect(MYSQL* mysql, my_bool drop_db);
+static void client_disconnect(MYSQL* mysql);
/*
@@ -134,6 +135,7 @@ static void die(const char *file, int line, const char *expr)
{
fflush(stdout);
fprintf(stderr, "%s:%d: check failed: '%s'\n", file, line, expr);
+ fprintf(stderr, "MySQL error %d: %s\n", mysql_errno(0), mysql_error(0));
fflush(stderr);
exit(1);
}
@@ -385,31 +387,31 @@ static MYSQL* client_connect(ulong flag, uint protocol, my_bool auto_reconnect)
/* Close the connection */
-static void client_disconnect(MYSQL* mysql, my_bool drop_db)
+static void client_disconnect(MYSQL* mysql)
{
- static char query[MAX_TEST_QUERY_LENGTH];
+ static char query[MAX_TEST_QUERY_LENGTH];
- myheader_r("client_disconnect");
+ myheader_r("client_disconnect");
- if (mysql)
- {
- if (drop_db)
- {
- if (!opt_silent)
- fprintf(stdout, "\n dropping the test database '%s' ...", current_db);
- strxmov(query, "DROP DATABASE IF EXISTS ", current_db, NullS);
+ if (mysql)
+ {
+ if (opt_drop_db)
+ {
+ if (!opt_silent)
+ fprintf(stdout, "\n dropping the test database '%s' ...", current_db);
+ strxmov(query, "DROP DATABASE IF EXISTS ", current_db, NullS);
- mysql_query(mysql, query);
- if (!opt_silent)
- fprintf(stdout, "OK");
- }
+ mysql_query(mysql, query);
+ if (!opt_silent)
+ fprintf(stdout, "OK");
+ }
- if (!opt_silent)
- fprintf(stdout, "\n closing the connection ...");
- mysql_close(mysql);
- if (!opt_silent)
- fprintf(stdout, "OK\n");
- }
+ if (!opt_silent)
+ fprintf(stdout, "\n closing the connection ...");
+ mysql_close(mysql);
+ if (!opt_silent)
+ fprintf(stdout, "OK\n");
+ }
}
@@ -1174,14 +1176,16 @@ static char **defaults_argv;
static struct my_option client_test_long_options[] =
{
- {"basedir", 'b', "Basedir for tests.", (char**) &opt_basedir,
- (char**) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"basedir", 'b', "Basedir for tests.", &opt_basedir,
+ &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"count", 't', "Number of times test to be executed", &opt_count,
&opt_count, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
{"database", 'D', "Database to use", &opt_db, &opt_db,
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"debug", '#', "Output debug log", (char**) &default_dbug_option,
- (char**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+ {"do-not-drop-database", 'd', "Do not drop database while disconnecting",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"debug", '#', "Output debug log", &default_dbug_option,
+ &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
0, 0, 0, 0, 0},
{"host", 'h', "Connect to host", &opt_host, &opt_host,
@@ -1217,8 +1221,8 @@ static struct my_option client_test_long_options[] =
{"user", 'u', "User for login if not current user", &opt_user,
&opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
- {"vardir", 'v', "Data dir for tests.", (char**) &opt_vardir,
- (char**) &opt_vardir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"vardir", 'v', "Data dir for tests.", &opt_vardir,
+ &opt_vardir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"non-blocking-api", 'n',
"Use the non-blocking client API for communication.",
&non_blocking_api_enabled, &non_blocking_api_enabled, 0,
@@ -1287,6 +1291,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
else
opt_silent++;
break;
+ case 'd':
+ opt_drop_db= 0;
+ break;
case 'A':
/*
When the embedded server is being tested, the test suite needs to be
@@ -1411,7 +1418,7 @@ int main(int argc, char **argv)
fprintf(stderr, "\n\nGiven test not found: '%s'\n", *argv);
fprintf(stderr, "See legal test names with %s -T\n\nAborting!\n",
my_progname);
- client_disconnect(mysql, 1);
+ client_disconnect(mysql);
free_defaults(defaults_argv);
exit(1);
}
@@ -1424,7 +1431,7 @@ int main(int argc, char **argv)
/* End of tests */
}
- client_disconnect(mysql, 1); /* disconnect from server */
+ client_disconnect(mysql); /* disconnect from server */
free_defaults(defaults_argv);
print_test_output();
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index a0b18f1f717..91e7da6ff32 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -17691,7 +17691,8 @@ static void test_bug43560(void)
const char* values[] = {"eins", "zwei", "drei", "viele", NULL};
const char insert_str[] = "INSERT INTO t1 (c2) VALUES (?)";
unsigned long length;
-
+ const unsigned int drop_db= opt_drop_db;
+
DBUG_ENTER("test_bug43560");
myheader("test_bug43560");
@@ -17756,9 +17757,11 @@ static void test_bug43560(void)
rc= mysql_stmt_execute(stmt);
DIE_UNLESS(rc && mysql_stmt_errno(stmt) == CR_SERVER_LOST);
- client_disconnect(conn, 0);
+ opt_drop_db= 0;
+ client_disconnect(conn);
rc= mysql_query(mysql, "DROP TABLE t1");
myquery(rc);
+ opt_drop_db= drop_db;
DBUG_VOID_RETURN;
}
@@ -18548,7 +18551,23 @@ static void test_progress_reporting()
myquery(rc);
rc= mysql_query(conn, "set @@global.progress_report_time=@save");
myquery(rc);
- client_disconnect(conn, 0);
+ 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);
}
@@ -19053,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 },
diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c
index a1c2010912b..5c4e2e89d10 100644
--- a/vio/viosslfactories.c
+++ b/vio/viosslfactories.c
@@ -78,7 +78,7 @@ ssl_error_string[] =
"No error",
"Unable to get certificate",
"Unable to get private key",
- "Private key does not match the certificate public key"
+ "Private key does not match the certificate public key",
"SSL_CTX_set_default_verify_paths failed",
"Failed to set ciphers to use",
"SSL_CTX_new failed"
@@ -98,47 +98,51 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file,
DBUG_ENTER("vio_set_cert_stuff");
DBUG_PRINT("enter", ("ctx: 0x%lx cert_file: %s key_file: %s",
(long) ctx, cert_file, key_file));
- if (cert_file)
- {
- if (SSL_CTX_use_certificate_chain_file(ctx, cert_file) <= 0)
- {
- *error= SSL_INITERR_CERT;
- DBUG_PRINT("error",("%s from file '%s'", sslGetErrString(*error), cert_file));
- DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE););
- fprintf(stderr, "SSL error: %s from '%s'\n", sslGetErrString(*error),
- cert_file);
- fflush(stderr);
- DBUG_RETURN(1);
- }
- if (!key_file)
- key_file= cert_file;
+ if (!cert_file && key_file)
+ cert_file= key_file;
+
+ if (!key_file && cert_file)
+ key_file= cert_file;
- if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0)
- {
- *error= SSL_INITERR_KEY;
- DBUG_PRINT("error", ("%s from file '%s'", sslGetErrString(*error), key_file));
- DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE););
- fprintf(stderr, "SSL error: %s from '%s'\n", sslGetErrString(*error),
- key_file);
- fflush(stderr);
- DBUG_RETURN(1);
- }
+ if (cert_file &&
+ SSL_CTX_use_certificate_chain_file(ctx, cert_file) <= 0)
+ {
+ *error= SSL_INITERR_CERT;
+ DBUG_PRINT("error",("%s from file '%s'", sslGetErrString(*error), cert_file));
+ DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE););
+ fprintf(stderr, "SSL error: %s from '%s'\n", sslGetErrString(*error),
+ cert_file);
+ fflush(stderr);
+ DBUG_RETURN(1);
+ }
- /*
- If we are using DSA, we can copy the parameters from the private key
- Now we know that a key and cert have been set against the SSL context
- */
- if (!SSL_CTX_check_private_key(ctx))
- {
- *error= SSL_INITERR_NOMATCH;
- DBUG_PRINT("error", ("%s",sslGetErrString(*error)));
- DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE););
- fprintf(stderr, "SSL error: %s\n", sslGetErrString(*error));
- fflush(stderr);
- DBUG_RETURN(1);
- }
+ if (key_file &&
+ SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0)
+ {
+ *error= SSL_INITERR_KEY;
+ DBUG_PRINT("error", ("%s from file '%s'", sslGetErrString(*error), key_file));
+ DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE););
+ fprintf(stderr, "SSL error: %s from '%s'\n", sslGetErrString(*error),
+ key_file);
+ fflush(stderr);
+ DBUG_RETURN(1);
+ }
+
+ /*
+ If we are using DSA, we can copy the parameters from the private key
+ Now we know that a key and cert have been set against the SSL context
+ */
+ if (cert_file && !SSL_CTX_check_private_key(ctx))
+ {
+ *error= SSL_INITERR_NOMATCH;
+ DBUG_PRINT("error", ("%s",sslGetErrString(*error)));
+ DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE););
+ fprintf(stderr, "SSL error: %s\n", sslGetErrString(*error));
+ fflush(stderr);
+ DBUG_RETURN(1);
}
+
DBUG_RETURN(0);
}
@@ -216,6 +220,20 @@ new_VioSSLFd(const char *key_file, const char *cert_file,
if (SSL_CTX_load_verify_locations(ssl_fd->ssl_context, ca_file, ca_path) == 0)
{
DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed"));
+ if (ca_file || ca_path)
+ {
+ /* fail only if ca file or ca path were supplied and looking into
+ them fails. */
+ *error= SSL_INITERR_BAD_PATHS;
+ DBUG_PRINT("error", ("SSL_CTX_load_verify_locations failed : %s",
+ sslGetErrString(*error)));
+ report_errors();
+ SSL_CTX_free(ssl_fd->ssl_context);
+ my_free(ssl_fd);
+ DBUG_RETURN(0);
+ }
+
+ /* otherwise go use the defaults */
if (SSL_CTX_set_default_verify_paths(ssl_fd->ssl_context) == 0)
{
*error= SSL_INITERR_BAD_PATHS;