summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <knielsen@knielsen-hq.org>2012-12-18 15:01:58 +0100
committerunknown <knielsen@knielsen-hq.org>2012-12-18 15:01:58 +0100
commit701419b02f12688188a7d4183523e0f5ee9ae09a (patch)
tree9cad9901bbf188c5ab30aeb31f10c71f61921312
parent4923d19b7c3c4c034f70ac1411837afa75c4b6ad (diff)
parent6c3de76ad5cb8683ab8b049e0bbba670115d304a (diff)
downloadmariadb-git-701419b02f12688188a7d4183523e0f5ee9ae09a.tar.gz
Merge MariaDB 10.0-base to MariaDB 10.0
-rw-r--r--client/mysqlshow.c3
-rw-r--r--cmake/mysql_version.cmake2
-rw-r--r--config.h.cmake1
-rw-r--r--extra/perror.c2
-rw-r--r--extra/yassl/CMakeLists.txt4
-rw-r--r--extra/yassl/src/crypto_wrapper.cpp21
-rw-r--r--extra/yassl/src/template_instnt.cpp110
-rw-r--r--extra/yassl/src/yassl_int.cpp10
-rw-r--r--extra/yassl/taocrypt/CMakeLists.txt4
-rw-r--r--extra/yassl/taocrypt/src/algebra.cpp10
-rw-r--r--extra/yassl/taocrypt/src/integer.cpp12
-rw-r--r--extra/yassl/taocrypt/src/template_instnt.cpp81
-rw-r--r--include/my_base.h3
-rw-r--r--include/mysql.h11
-rw-r--r--include/mysql_com.h5
-rw-r--r--include/welcome_copyright_notice.h3
-rw-r--r--libmysqld/lib_sql.cc2
-rw-r--r--mysql-test/extra/rpl_tests/rpl_insert_delayed.test2
-rw-r--r--mysql-test/extra/rpl_tests/rpl_log.test1
-rw-r--r--mysql-test/extra/rpl_tests/rpl_show_relaylog_events.inc2
-rw-r--r--mysql-test/include/function_defaults.inc1166
-rw-r--r--mysql-test/include/function_defaults_notembedded.inc94
-rw-r--r--mysql-test/include/have_debug_sync.inc8
-rw-r--r--mysql-test/include/have_innodb.combinations9
-rw-r--r--mysql-test/include/wait_for_binlog_checkpoint.inc53
-rw-r--r--mysql-test/r/create.result4
-rw-r--r--mysql-test/r/derived_opt.result70
-rw-r--r--mysql-test/r/function_defaults.result3067
-rw-r--r--mysql-test/r/function_defaults_notembedded.result171
-rw-r--r--mysql-test/r/group_by.result11
-rw-r--r--mysql-test/r/have_debug_sync.require2
-rw-r--r--mysql-test/r/information_schema.result6
-rw-r--r--mysql-test/r/innodb_ext_key.result48
-rw-r--r--mysql-test/r/is_debug_build.require2
-rw-r--r--mysql-test/r/log_slow.result2
-rw-r--r--mysql-test/r/log_tables.result16
-rw-r--r--mysql-test/r/mysqldump.result4
-rw-r--r--mysql-test/r/openssl_1.result2
-rw-r--r--mysql-test/r/order_by.result76
-rw-r--r--mysql-test/r/partition.result6
-rw-r--r--mysql-test/r/range_vs_index_merge.result147
-rw-r--r--mysql-test/r/range_vs_index_merge_innodb,innodb_plugin.rdiff13
-rw-r--r--mysql-test/r/range_vs_index_merge_innodb.result147
-rw-r--r--mysql-test/r/server_id.require2
-rw-r--r--mysql-test/r/server_id1.require2
-rw-r--r--mysql-test/r/sql_mode.result2
-rw-r--r--mysql-test/r/subselect.result114
-rw-r--r--mysql-test/r/subselect_no_mat.result114
-rw-r--r--mysql-test/r/subselect_no_opts.result114
-rw-r--r--mysql-test/r/subselect_no_scache.result114
-rw-r--r--mysql-test/r/subselect_no_semijoin.result114
-rw-r--r--mysql-test/r/system_mysql_db.result4
-rw-r--r--mysql-test/r/system_mysql_db_fix40123.result4
-rw-r--r--mysql-test/r/system_mysql_db_fix50030.result4
-rw-r--r--mysql-test/r/system_mysql_db_fix50117.result4
-rw-r--r--mysql-test/r/testdb_only.require2
-rw-r--r--mysql-test/r/type_timestamp.result10
-rw-r--r--mysql-test/r/type_timestamp_hires.result28
-rw-r--r--mysql-test/r/user_var.result32
-rw-r--r--mysql-test/r/variables.result4
-rw-r--r--mysql-test/r/view.result32
-rw-r--r--mysql-test/r/windows.require2
-rw-r--r--mysql-test/std_data/onerow.xml13
-rw-r--r--mysql-test/suite/binlog/r/binlog_checkpoint.result6
-rw-r--r--mysql-test/suite/binlog/r/binlog_xa_recover.result4
-rw-r--r--mysql-test/suite/binlog/t/binlog_checkpoint.test12
-rw-r--r--mysql-test/suite/binlog/t/binlog_xa_recover.test38
-rw-r--r--mysql-test/suite/federated/federatedx.test2
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_mysql.result4
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result4
-rw-r--r--mysql-test/suite/funcs_1/r/is_engines_merge.result2
-rw-r--r--mysql-test/suite/heap/heap_hash.result20
-rw-r--r--mysql-test/suite/heap/heap_hash.test17
-rw-r--r--mysql-test/suite/innodb/t/binlog_consistent.test1
-rw-r--r--mysql-test/suite/innodb/t/innodb_information_schema_buffer.test5
-rw-r--r--mysql-test/suite/multi_source/multisource.test1
-rw-r--r--mysql-test/suite/perfschema/r/relaylog.result8
-rw-r--r--mysql-test/suite/plugins/r/audit_null.result29
-rw-r--r--mysql-test/suite/plugins/t/audit_null.test30
-rw-r--r--mysql-test/suite/rpl/r/rpl_function_defaults.result132
-rw-r--r--mysql-test/suite/rpl/t/rpl_function_defaults.test93
-rw-r--r--mysql-test/suite/sys_vars/r/default_storage_engine_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_buffer_pool_populate_basic.result1
-rw-r--r--mysql-test/suite/sys_vars/r/storage_engine_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_buffer_pool_populate_basic.test1
-rw-r--r--mysql-test/suite/vcol/inc/vcol_trigger_sp.inc41
-rw-r--r--mysql-test/suite/vcol/r/vcol_merge.result2
-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/create.test4
-rw-r--r--mysql-test/t/derived_opt.test60
-rw-r--r--mysql-test/t/function_defaults.test23
-rw-r--r--mysql-test/t/function_defaults_notembedded.test18
-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/order_by.test65
-rw-r--r--mysql-test/t/partition.test8
-rw-r--r--mysql-test/t/range_vs_index_merge.test58
-rw-r--r--mysql-test/t/subselect.test76
-rw-r--r--mysql-test/t/type_timestamp.test11
-rw-r--r--mysql-test/t/type_timestamp_hires.test15
-rw-r--r--mysql-test/t/user_var.test28
-rw-r--r--mysql-test/t/view.test34
-rw-r--r--mysys/mf_pack.c15
-rw-r--r--mysys/my_context.c2
-rw-r--r--plugin/audit_null/audit_null.c2
-rw-r--r--plugin/feedback/CMakeLists.txt12
-rw-r--r--plugin/feedback/url_http.cc36
-rw-r--r--scripts/mysql_config.sh11
-rwxr-xr-xscripts/mysql_secure_installation.pl.in2
-rw-r--r--scripts/mysql_secure_installation.sh2
-rwxr-xr-xsql-bench/test-table-elimination.sh9
-rw-r--r--sql/debug_sync.cc1
-rw-r--r--sql/event_db_repository.cc5
-rw-r--r--sql/field.cc213
-rw-r--r--sql/field.h81
-rw-r--r--sql/filesort.cc4
-rw-r--r--sql/ha_ndbcluster.cc7
-rw-r--r--sql/ha_partition.cc33
-rw-r--r--sql/ha_partition.h3
-rw-r--r--sql/handler.cc7
-rw-r--r--sql/handler.h2
-rw-r--r--sql/item.cc11
-rw-r--r--sql/item_buff.cc9
-rw-r--r--sql/item_func.h9
-rw-r--r--sql/item_sum.cc6
-rw-r--r--sql/keycaches.cc4
-rw-r--r--sql/log.cc221
-rw-r--r--sql/log.h57
-rw-r--r--sql/log_event.cc19
-rw-r--r--sql/log_event_old.cc36
-rw-r--r--sql/mysqld.cc11
-rw-r--r--sql/mysqld.h6
-rw-r--r--sql/opt_range.cc8
-rw-r--r--sql/rpl_rli.cc3
-rw-r--r--sql/slave.cc5
-rw-r--r--sql/sp.cc1
-rw-r--r--sql/sp_head.cc7
-rw-r--r--sql/sql_acl.cc31
-rw-r--r--sql/sql_audit.h18
-rw-r--r--sql/sql_base.cc164
-rw-r--r--sql/sql_base.h13
-rw-r--r--sql/sql_class.cc38
-rw-r--r--sql/sql_class.h13
-rw-r--r--sql/sql_delete.cc4
-rw-r--r--sql/sql_expression_cache.cc2
-rw-r--r--sql/sql_insert.cc160
-rw-r--r--sql/sql_lex.cc3
-rw-r--r--sql/sql_load.cc62
-rw-r--r--sql/sql_parse.cc41
-rw-r--r--sql/sql_partition.cc3
-rw-r--r--sql/sql_prepare.cc14
-rw-r--r--sql/sql_select.cc261
-rw-r--r--sql/sql_select.h20
-rw-r--r--sql/sql_show.cc77
-rw-r--r--sql/sql_string.cc18
-rw-r--r--sql/sql_string.h1
-rw-r--r--sql/sql_table.cc89
-rw-r--r--sql/sql_table.h4
-rw-r--r--sql/sql_union.cc2
-rw-r--r--sql/sql_update.cc54
-rw-r--r--sql/sql_yacc.yy15
-rw-r--r--sql/sys_vars.h15
-rw-r--r--sql/table.cc175
-rw-r--r--sql/table.h47
-rw-r--r--storage/archive/ha_archive.h1
-rw-r--r--storage/blackhole/ha_blackhole.h2
-rw-r--r--storage/csv/ha_tina.h1
-rw-r--r--storage/example/ha_example.h5
-rw-r--r--storage/federated/ha_federated.h2
-rw-r--r--storage/federatedx/ha_federatedx.h2
-rw-r--r--storage/heap/ha_heap.h5
-rw-r--r--storage/heap/hp_rkey.c2
-rw-r--r--storage/innobase/handler/ha_innodb.cc142
-rw-r--r--storage/innobase/include/ha_prototypes.h11
-rw-r--r--storage/innobase/include/log0log.h7
-rw-r--r--storage/innobase/include/log0log.ic19
-rw-r--r--storage/innobase/log/log0log.cc7
-rw-r--r--storage/maria/ha_maria.cc7
-rw-r--r--storage/maria/ha_maria.h2
-rw-r--r--storage/maria/ma_blockrec.c8
-rw-r--r--storage/maria/ma_rrnd.c4
-rw-r--r--storage/maria/ma_test2.c65
-rw-r--r--storage/myisam/ha_myisam.h1
-rw-r--r--storage/myisammrg/ha_myisammrg.cc19
-rw-r--r--storage/myisammrg/ha_myisammrg.h1
-rw-r--r--storage/oqgraph/ha_oqgraph.h4
-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/ha_perfschema.h2
-rw-r--r--storage/xtradb/btr/btr0btr.c21
-rw-r--r--storage/xtradb/btr/btr0cur.c39
-rw-r--r--storage/xtradb/btr/btr0pcur.c67
-rw-r--r--storage/xtradb/buf/buf0buf.c22
-rw-r--r--storage/xtradb/buf/buf0lru.c2
-rw-r--r--storage/xtradb/buf/buf0rea.c4
-rw-r--r--storage/xtradb/handler/ha_innodb.cc480
-rw-r--r--storage/xtradb/handler/ha_innodb.h1
-rw-r--r--storage/xtradb/handler/i_s.cc1836
-rw-r--r--storage/xtradb/handler/i_s.h3
-rw-r--r--storage/xtradb/ibuf/ibuf0ibuf.c17
-rw-r--r--storage/xtradb/include/buf0buf.h34
-rw-r--r--storage/xtradb/include/buf0buf.ic19
-rw-r--r--storage/xtradb/include/fil0fil.h2
-rw-r--r--storage/xtradb/include/ha_prototypes.h13
-rw-r--r--storage/xtradb/include/log0log.h10
-rw-r--r--storage/xtradb/include/log0log.ic19
-rw-r--r--storage/xtradb/include/os0proc.h3
-rw-r--r--storage/xtradb/include/srv0srv.h1
-rw-r--r--storage/xtradb/include/trx0sys.h16
-rw-r--r--storage/xtradb/include/univ.i2
-rw-r--r--storage/xtradb/log/log0log.c7
-rw-r--r--storage/xtradb/os/os0proc.c58
-rw-r--r--storage/xtradb/page/page0page.c21
-rw-r--r--storage/xtradb/row/row0ins.c9
-rw-r--r--storage/xtradb/row/row0merge.c16
-rw-r--r--storage/xtradb/srv/srv0srv.c2
-rw-r--r--storage/xtradb/srv/srv0start.c3
-rw-r--r--storage/xtradb/trx/trx0sys.c132
-rw-r--r--storage/xtradb/trx/trx0trx.c21
-rw-r--r--strings/decimal.c2
-rw-r--r--tests/mysql_client_test.c17
-rw-r--r--vio/viosslfactories.c2
225 files changed, 10935 insertions, 1682 deletions
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index 9febcc118fa..5abeed107c2 100644
--- a/client/mysqlshow.c
+++ b/client/mysqlshow.c
@@ -1,5 +1,6 @@
/*
- Copyright (c) 2000, 2011, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2012, Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/cmake/mysql_version.cmake b/cmake/mysql_version.cmake
index 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/config.h.cmake b/config.h.cmake
index b70bf690d5b..803a21ee74f 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -41,7 +41,6 @@
#cmakedefine HAVE_FNMATCH_H 1
#cmakedefine HAVE_FPU_CONTROL_H 1
#cmakedefine HAVE_GRP_H 1
-#cmakedefine HAVE_EXPLICIT_TEMPLATE_INSTANTIATION 1
#cmakedefine HAVE_IA64INTRIN_H 1
#cmakedefine HAVE_IEEEFP_H 1
#cmakedefine HAVE_INTTYPES_H 1
diff --git a/extra/perror.c b/extra/perror.c
index c7dd6f0c205..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
diff --git a/extra/yassl/CMakeLists.txt b/extra/yassl/CMakeLists.txt
index 46e1abbc08e..5f2f1956803 100644
--- a/extra/yassl/CMakeLists.txt
+++ b/extra/yassl/CMakeLists.txt
@@ -30,10 +30,6 @@ SET(YASSL_SOURCES src/buffer.cpp src/cert_wrapper.cpp src/crypto_wrapper.cpp sr
src/log.cpp src/socket_wrapper.cpp src/ssl.cpp src/timer.cpp src/yassl_error.cpp
src/yassl_imp.cpp src/yassl_int.cpp)
-IF(HAVE_EXPLICIT_TEMPLATE_INSTANTIATION)
- SET(YASSL_SOURCES ${YASSL_SOURCES} src/template_instnt.cpp)
-ENDIF()
-
ADD_CONVENIENCE_LIBRARY(yassl ${YASSL_SOURCES})
RESTRICT_SYMBOL_EXPORTS(yassl)
diff --git a/extra/yassl/src/crypto_wrapper.cpp b/extra/yassl/src/crypto_wrapper.cpp
index afb492c83c5..42a43627760 100644
--- a/extra/yassl/src/crypto_wrapper.cpp
+++ b/extra/yassl/src/crypto_wrapper.cpp
@@ -993,25 +993,4 @@ x509* PemToDer(FILE* file, CertType type, EncryptedInfo* info)
} // namespace
-
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-namespace yaSSL {
-template void ysDelete<DiffieHellman::DHImpl>(DiffieHellman::DHImpl*);
-template void ysDelete<Integer::IntegerImpl>(Integer::IntegerImpl*);
-template void ysDelete<RSA::RSAImpl>(RSA::RSAImpl*);
-template void ysDelete<DSS::DSSImpl>(DSS::DSSImpl*);
-template void ysDelete<RandomPool::RandomImpl>(RandomPool::RandomImpl*);
-template void ysDelete<AES::AESImpl>(AES::AESImpl*);
-template void ysDelete<RC4::RC4Impl>(RC4::RC4Impl*);
-template void ysDelete<DES_EDE::DES_EDEImpl>(DES_EDE::DES_EDEImpl*);
-template void ysDelete<DES::DESImpl>(DES::DESImpl*);
-template void ysDelete<HMAC_RMD::HMAC_RMDImpl>(HMAC_RMD::HMAC_RMDImpl*);
-template void ysDelete<HMAC_SHA::HMAC_SHAImpl>(HMAC_SHA::HMAC_SHAImpl*);
-template void ysDelete<HMAC_MD5::HMAC_MD5Impl>(HMAC_MD5::HMAC_MD5Impl*);
-template void ysDelete<RMD::RMDImpl>(RMD::RMDImpl*);
-template void ysDelete<SHA::SHAImpl>(SHA::SHAImpl*);
-template void ysDelete<MD5::MD5Impl>(MD5::MD5Impl*);
-}
-#endif // HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-
#endif // !USE_CRYPTOPP_LIB
diff --git a/extra/yassl/src/template_instnt.cpp b/extra/yassl/src/template_instnt.cpp
deleted file mode 100644
index fe3a251b865..00000000000
--- a/extra/yassl/src/template_instnt.cpp
+++ /dev/null
@@ -1,110 +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.
-*/
-
-
-/* Explicit template instantiation requests
- */
-
-
-#include "runtime.hpp"
-#include "handshake.hpp"
-#include "yassl_int.hpp"
-#include "crypto_wrapper.hpp"
-#include "hmac.hpp"
-#include "md5.hpp"
-#include "sha.hpp"
-#include "ripemd.hpp"
-#include "openssl/ssl.h"
-
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-
-namespace mySTL {
-template class list<unsigned char*>;
-template yaSSL::del_ptr_zero for_each(mySTL::list<unsigned char*>::iterator, mySTL::list<unsigned char*>::iterator, yaSSL::del_ptr_zero);
-template pair<int, yaSSL::Message* (*)()>* uninit_copy<mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*>(mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*);
-template pair<int, yaSSL::HandShakeBase* (*)()>* uninit_copy<mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*>(mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*);
-template void destroy<mySTL::pair<int, yaSSL::Message* (*)()>*>(mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*);
-template void destroy<mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*>(mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*);
-template pair<int, yaSSL::ServerKeyBase* (*)()>* uninit_copy<mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*);
-template void destroy<mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*);
-template pair<int, yaSSL::ClientKeyBase* (*)()>* uninit_copy<mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*);
-template class list<TaoCrypt::Signer*>;
-template class list<yaSSL::SSL_SESSION*>;
-template class list<yaSSL::input_buffer*>;
-template class list<yaSSL::output_buffer*>;
-template class list<yaSSL::x509*>;
-template class list<yaSSL::Digest*>;
-template class list<yaSSL::BulkCipher*>;
-template void destroy<mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*);
-template yaSSL::del_ptr_zero for_each<mySTL::list<TaoCrypt::Signer*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<TaoCrypt::Signer*>::iterator, mySTL::list<TaoCrypt::Signer*>::iterator, yaSSL::del_ptr_zero);
-template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::SSL_SESSION*>::iterator, mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::del_ptr_zero);
-template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::input_buffer*>::iterator, mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::del_ptr_zero);
-template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::output_buffer*>::iterator, mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::del_ptr_zero);
-template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::x509*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::x509*>::iterator, mySTL::list<yaSSL::x509*>::iterator, yaSSL::del_ptr_zero);
-template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::Digest*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::Digest*>::iterator, mySTL::list<yaSSL::Digest*>::iterator, yaSSL::del_ptr_zero);
-template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::BulkCipher*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::BulkCipher*>::iterator, mySTL::list<yaSSL::BulkCipher*>::iterator, yaSSL::del_ptr_zero);
-template bool list<yaSSL::ThreadError>::erase(list<yaSSL::ThreadError>::iterator);
-template void list<yaSSL::ThreadError>::push_back(yaSSL::ThreadError);
-template void list<yaSSL::ThreadError>::pop_front();
-template void list<yaSSL::ThreadError>::pop_back();
-template list<yaSSL::ThreadError>::~list();
-template pair<int, yaSSL::Message* (*)()>* GetArrayMemory<pair<int, yaSSL::Message* (*)()> >(size_t);
-template void FreeArrayMemory<pair<int, yaSSL::Message* (*)()> >(pair<int, yaSSL::Message* (*)()>*);
-template pair<int, yaSSL::HandShakeBase* (*)()>* GetArrayMemory<pair<int, yaSSL::HandShakeBase* (*)()> >(size_t);
-template void FreeArrayMemory<pair<int, yaSSL::HandShakeBase* (*)()> >(pair<int, yaSSL::HandShakeBase* (*)()>*);
-template pair<int, yaSSL::ServerKeyBase* (*)()>* GetArrayMemory<pair<int, yaSSL::ServerKeyBase* (*)()> >(size_t);
-template void FreeArrayMemory<pair<int, yaSSL::ServerKeyBase* (*)()> >(pair<int, yaSSL::ServerKeyBase* (*)()>*);
-template pair<int, yaSSL::ClientKeyBase* (*)()>* GetArrayMemory<pair<int, yaSSL::ClientKeyBase* (*)()> >(size_t);
-template void FreeArrayMemory<pair<int, yaSSL::ClientKeyBase* (*)()> >(pair<int, yaSSL::ClientKeyBase* (*)()>*);
-}
-
-namespace yaSSL {
-template void ysDelete<SSL_CTX>(yaSSL::SSL_CTX*);
-template void ysDelete<SSL>(yaSSL::SSL*);
-template void ysDelete<BIGNUM>(yaSSL::BIGNUM*);
-template void ysDelete<unsigned char>(unsigned char*);
-template void ysDelete<DH>(yaSSL::DH*);
-template void ysDelete<TaoCrypt::Signer>(TaoCrypt::Signer*);
-template void ysDelete<SSL_SESSION>(yaSSL::SSL_SESSION*);
-template void ysDelete<input_buffer>(input_buffer*);
-template void ysDelete<output_buffer>(output_buffer*);
-template void ysDelete<x509>(x509*);
-template void ysDelete<Auth>(Auth*);
-template void ysDelete<HandShakeBase>(HandShakeBase*);
-template void ysDelete<ServerKeyBase>(ServerKeyBase*);
-template void ysDelete<ClientKeyBase>(ClientKeyBase*);
-template void ysDelete<SSL_METHOD>(SSL_METHOD*);
-template void ysDelete<DiffieHellman>(DiffieHellman*);
-template void ysDelete<BulkCipher>(BulkCipher*);
-template void ysDelete<Digest>(Digest*);
-template void ysDelete<X509>(X509*);
-template void ysDelete<Message>(Message*);
-template void ysDelete<sslFactory>(sslFactory*);
-template void ysDelete<Sessions>(Sessions*);
-template void ysDelete<Errors>(Errors*);
-template void ysArrayDelete<unsigned char>(unsigned char*);
-template void ysArrayDelete<char>(char*);
-
-template int min<int>(int, int);
-template uint16 min<uint16>(uint16, uint16);
-template unsigned int min<unsigned int>(unsigned int, unsigned int);
-template unsigned long min<unsigned long>(unsigned long, unsigned long);
-}
-
-#endif // HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-
diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp
index 8de24850223..162d457b380 100644
--- a/extra/yassl/src/yassl_int.cpp
+++ b/extra/yassl/src/yassl_int.cpp
@@ -2601,13 +2601,3 @@ extern "C" void yaSSL_CleanUp()
yaSSL::errorsInstance = 0;
}
-
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-namespace mySTL {
-template yaSSL::yassl_int_cpp_local1::SumData for_each<mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumData>(mySTL::list<yaSSL::input_buffer*>::iterator, mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumData);
-template yaSSL::yassl_int_cpp_local1::SumBuffer for_each<mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumBuffer>(mySTL::list<yaSSL::output_buffer*>::iterator, mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumBuffer);
-template mySTL::list<yaSSL::SSL_SESSION*>::iterator find_if<mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::yassl_int_cpp_local2::sess_match>(mySTL::list<yaSSL::SSL_SESSION*>::iterator, mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::yassl_int_cpp_local2::sess_match);
-template mySTL::list<yaSSL::ThreadError>::iterator find_if<mySTL::list<yaSSL::ThreadError>::iterator, yaSSL::yassl_int_cpp_local2::thr_match>(mySTL::list<yaSSL::ThreadError>::iterator, mySTL::list<yaSSL::ThreadError>::iterator, yaSSL::yassl_int_cpp_local2::thr_match);
-}
-#endif
-
diff --git a/extra/yassl/taocrypt/CMakeLists.txt b/extra/yassl/taocrypt/CMakeLists.txt
index 10ed614445e..b75d478037e 100644
--- a/extra/yassl/taocrypt/CMakeLists.txt
+++ b/extra/yassl/taocrypt/CMakeLists.txt
@@ -29,10 +29,6 @@ SET(TAOCRYPT_SOURCES src/aes.cpp src/aestables.cpp src/algebra.cpp src/arc4.cpp
include/random.hpp include/ripemd.hpp include/rsa.hpp include/sha.hpp
include/rabbit.hpp include/hc128.hpp)
-IF(HAVE_EXPLICIT_TEMPLATE_INSTANTIATION)
- SET(TAOCRYPT_SOURCES ${TAOCRYPT_SOURCES} src/template_instnt.cpp)
-ENDIF()
-
ADD_CONVENIENCE_LIBRARY(taocrypt ${TAOCRYPT_SOURCES})
RESTRICT_SYMBOL_EXPORTS(taocrypt)
diff --git a/extra/yassl/taocrypt/src/algebra.cpp b/extra/yassl/taocrypt/src/algebra.cpp
index 29754b27b5e..b2bebfe8b94 100644
--- a/extra/yassl/taocrypt/src/algebra.cpp
+++ b/extra/yassl/taocrypt/src/algebra.cpp
@@ -325,13 +325,3 @@ void AbstractRing::SimultaneousExponentiate(Integer *results,
} // namespace
-
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-namespace mySTL {
-template TaoCrypt::WindowSlider* uninit_copy<TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*>(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*);
-template void destroy<TaoCrypt::WindowSlider*>(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*);
-template TaoCrypt::WindowSlider* GetArrayMemory<TaoCrypt::WindowSlider>(size_t);
-template void FreeArrayMemory<TaoCrypt::WindowSlider>(TaoCrypt::WindowSlider*);
-}
-#endif
-
diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp
index 15deb59d4f3..8dccf1a1340 100644
--- a/extra/yassl/taocrypt/src/integer.cpp
+++ b/extra/yassl/taocrypt/src/integer.cpp
@@ -3890,17 +3890,5 @@ Integer CRT(const Integer &xp, const Integer &p, const Integer &xq,
return p * (u * (xq-xp) % q) + xp;
}
-
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-#ifndef TAOCRYPT_NATIVE_DWORD_AVAILABLE
-template hword DivideThreeWordsByTwo<hword, Word>(hword*, hword, hword, Word*);
-#endif
-template word DivideThreeWordsByTwo<word, DWord>(word*, word, word, DWord*);
-#ifdef SSE2_INTRINSICS_AVAILABLE
-template class AlignedAllocator<word>;
-#endif
-#endif
-
-
} // namespace
diff --git a/extra/yassl/taocrypt/src/template_instnt.cpp b/extra/yassl/taocrypt/src/template_instnt.cpp
deleted file mode 100644
index b472d18236f..00000000000
--- a/extra/yassl/taocrypt/src/template_instnt.cpp
+++ /dev/null
@@ -1,81 +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.
-*/
-
-
-/* Explicit template instantiation requests
- */
-
-
-#include "runtime.hpp"
-#include "integer.hpp"
-#include "rsa.hpp"
-#include "sha.hpp"
-#include "md5.hpp"
-#include "hmac.hpp"
-#include "ripemd.hpp"
-#include "pwdbased.hpp"
-#include "algebra.hpp"
-#include "vector.hpp"
-#include "hash.hpp"
-
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-namespace TaoCrypt {
-
-#if defined(SSE2_INTRINSICS_AVAILABLE)
-template AlignedAllocator<unsigned int>::pointer StdReallocate<unsigned int, AlignedAllocator<unsigned int> >(AlignedAllocator<unsigned int>&, unsigned int*, AlignedAllocator<unsigned int>::size_type, AlignedAllocator<unsigned int>::size_type, bool);
-#endif
-
-template class RSA_Decryptor<RSA_BlockType2>;
-template class RSA_Encryptor<RSA_BlockType1>;
-template class RSA_Encryptor<RSA_BlockType2>;
-template void tcDelete<HASH>(HASH*);
-template void tcDelete<Integer>(Integer*);
-template void tcArrayDelete<byte>(byte*);
-template AllocatorWithCleanup<byte>::pointer StdReallocate<byte, AllocatorWithCleanup<byte> >(AllocatorWithCleanup<byte>&, byte*, AllocatorWithCleanup<byte>::size_type, AllocatorWithCleanup<byte>::size_type, bool);
-template void tcArrayDelete<word>(word*);
-template AllocatorWithCleanup<word>::pointer StdReallocate<word, AllocatorWithCleanup<word> >(AllocatorWithCleanup<word>&, word*, AllocatorWithCleanup<word>::size_type, AllocatorWithCleanup<word>::size_type, bool);
-
-#ifndef TAOCRYPT_SLOW_WORD64 // defined when word != word32
-template void tcArrayDelete<word32>(word32*);
-template AllocatorWithCleanup<word32>::pointer StdReallocate<word32, AllocatorWithCleanup<word32> >(AllocatorWithCleanup<word32>&, word32*, AllocatorWithCleanup<word32>::size_type, AllocatorWithCleanup<word32>::size_type, bool);
-#endif
-
-template void tcArrayDelete<char>(char*);
-
-template class PBKDF2_HMAC<SHA>;
-template class HMAC<MD5>;
-template class HMAC<SHA>;
-template class HMAC<RIPEMD160>;
-}
-
-namespace mySTL {
-template vector<TaoCrypt::Integer>* uninit_fill_n<vector<TaoCrypt::Integer>*, size_t, vector<TaoCrypt::Integer> >(vector<TaoCrypt::Integer>*, size_t, vector<TaoCrypt::Integer> const&);
-template void destroy<vector<TaoCrypt::Integer>*>(vector<TaoCrypt::Integer>*, vector<TaoCrypt::Integer>*);
-template TaoCrypt::Integer* uninit_copy<TaoCrypt::Integer*, TaoCrypt::Integer*>(TaoCrypt::Integer*, TaoCrypt::Integer*, TaoCrypt::Integer*);
-template TaoCrypt::Integer* uninit_fill_n<TaoCrypt::Integer*, size_t, TaoCrypt::Integer>(TaoCrypt::Integer*, size_t, TaoCrypt::Integer const&);
-template void destroy<TaoCrypt::Integer*>(TaoCrypt::Integer*, TaoCrypt::Integer*);
-template TaoCrypt::byte* GetArrayMemory<TaoCrypt::byte>(size_t);
-template void FreeArrayMemory<TaoCrypt::byte>(TaoCrypt::byte*);
-template TaoCrypt::Integer* GetArrayMemory<TaoCrypt::Integer>(size_t);
-template void FreeArrayMemory<TaoCrypt::Integer>(TaoCrypt::Integer*);
-template vector<TaoCrypt::Integer>* GetArrayMemory<vector<TaoCrypt::Integer> >(size_t);
-template void FreeArrayMemory<vector<TaoCrypt::Integer> >(vector<TaoCrypt::Integer>*);
-template void FreeArrayMemory<void>(void*);
-}
-
-#endif
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 046d093dc47..c761938c39b 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 /* MY_GLOBAL_INCLUDED */
diff --git a/include/mysql_com.h b/include/mysql_com.h
index f02f5baab09..b5b4dc585b8 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"
@@ -128,6 +125,8 @@ enum enum_server_command
reserved by MySQL Cluster */
#define FIELD_FLAGS_COLUMN_FORMAT 24 /* Field column format, bit 24-25,
reserved by MySQL Cluster */
+#define HAS_EXPLICIT_VALUE (1 << 26) /* An INSERT/UPDATE operation supplied
+ an explicit default value */
#define REFRESH_GRANT 1 /* Refresh grant tables */
#define REFRESH_LOG 2 /* Start on new log file */
diff --git a/include/welcome_copyright_notice.h b/include/welcome_copyright_notice.h
index adb7b9f9c20..01139677b7d 100644
--- a/include/welcome_copyright_notice.h
+++ b/include/welcome_copyright_notice.h
@@ -1,4 +1,5 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates.
+/* Copyright (c) 2011, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2011, 2012, Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 75e5fcb692c..0a7853e3640 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/extra/rpl_tests/rpl_insert_delayed.test b/mysql-test/extra/rpl_tests/rpl_insert_delayed.test
index 2dbba38166b..3d7d3600199 100644
--- a/mysql-test/extra/rpl_tests/rpl_insert_delayed.test
+++ b/mysql-test/extra/rpl_tests/rpl_insert_delayed.test
@@ -94,8 +94,10 @@ if (`SELECT @@global.binlog_format = 'STATEMENT'`)
#flush the logs before the test
connection slave;
FLUSH LOGS;
+ source include/wait_for_binlog_checkpoint.inc;
connection master;
FLUSH LOGS;
+ source include/wait_for_binlog_checkpoint.inc;
}
CREATE TABLE t1(a int, UNIQUE(a));
diff --git a/mysql-test/extra/rpl_tests/rpl_log.test b/mysql-test/extra/rpl_tests/rpl_log.test
index 892d926a156..961996bb265 100644
--- a/mysql-test/extra/rpl_tests/rpl_log.test
+++ b/mysql-test/extra/rpl_tests/rpl_log.test
@@ -43,6 +43,7 @@ let $binlog_limit= 1,4;
source include/show_binlog_events.inc;
let $binlog_limit=;
flush logs;
+--source include/wait_for_binlog_checkpoint.inc
# We need an extra update before doing save_master_pos.
# Otherwise, an unlikely scenario may occur:
diff --git a/mysql-test/extra/rpl_tests/rpl_show_relaylog_events.inc b/mysql-test/extra/rpl_tests/rpl_show_relaylog_events.inc
index a56e08ece42..d0a905d3b7d 100644
--- a/mysql-test/extra/rpl_tests/rpl_show_relaylog_events.inc
+++ b/mysql-test/extra/rpl_tests/rpl_show_relaylog_events.inc
@@ -41,8 +41,10 @@ INSERT INTO t1 VALUES (3);
#
FLUSH LOGS;
+--source include/wait_for_binlog_checkpoint.inc
-- connection master
FLUSH LOGS;
+--source include/wait_for_binlog_checkpoint.inc
DROP TABLE t1;
--let $is_relay_log= 0
diff --git a/mysql-test/include/function_defaults.inc b/mysql-test/include/function_defaults.inc
new file mode 100644
index 00000000000..e588c82df1b
--- /dev/null
+++ b/mysql-test/include/function_defaults.inc
@@ -0,0 +1,1166 @@
+SET TIME_ZONE = "+00:00";
+
+--echo #
+--echo # Test of errors for column data types that dont support function
+--echo # defaults.
+--echo #
+--error ER_INVALID_DEFAULT
+eval CREATE TABLE t1( a BIT DEFAULT $current_timestamp );
+--error ER_INVALID_DEFAULT
+eval CREATE TABLE t1( a TINYINT DEFAULT $current_timestamp );
+--error ER_INVALID_DEFAULT
+eval CREATE TABLE t1( a SMALLINT DEFAULT $current_timestamp );
+--error ER_INVALID_DEFAULT
+eval CREATE TABLE t1( a MEDIUMINT DEFAULT $current_timestamp );
+--error ER_INVALID_DEFAULT
+eval CREATE TABLE t1( a INT DEFAULT $current_timestamp );
+--error ER_INVALID_DEFAULT
+eval CREATE TABLE t1( a BIGINT DEFAULT $current_timestamp );
+--error ER_INVALID_DEFAULT
+eval CREATE TABLE t1( a FLOAT DEFAULT $current_timestamp );
+--error ER_INVALID_DEFAULT
+eval CREATE TABLE t1( a DECIMAL DEFAULT $current_timestamp );
+--error ER_INVALID_DEFAULT
+eval CREATE TABLE t1( a DATE DEFAULT $current_timestamp );
+--error ER_INVALID_DEFAULT
+eval CREATE TABLE t1( a TIME DEFAULT $current_timestamp );
+--error ER_INVALID_DEFAULT
+eval CREATE TABLE t1( a YEAR DEFAULT $current_timestamp );
+
+--error ER_INVALID_ON_UPDATE
+eval CREATE TABLE t1( a BIT ON UPDATE $current_timestamp );
+--error ER_INVALID_ON_UPDATE
+eval CREATE TABLE t1( a TINYINT ON UPDATE $current_timestamp );
+--error ER_INVALID_ON_UPDATE
+eval CREATE TABLE t1( a SMALLINT ON UPDATE $current_timestamp );
+--error ER_INVALID_ON_UPDATE
+eval CREATE TABLE t1( a MEDIUMINT ON UPDATE $current_timestamp );
+--error ER_INVALID_ON_UPDATE
+eval CREATE TABLE t1( a INT ON UPDATE $current_timestamp );
+--error ER_INVALID_ON_UPDATE
+eval CREATE TABLE t1( a BIGINT ON UPDATE $current_timestamp );
+--error ER_INVALID_ON_UPDATE
+eval CREATE TABLE t1( a FLOAT ON UPDATE $current_timestamp );
+--error ER_INVALID_ON_UPDATE
+eval CREATE TABLE t1( a DECIMAL ON UPDATE $current_timestamp );
+--error ER_INVALID_ON_UPDATE
+eval CREATE TABLE t1( a DATE ON UPDATE $current_timestamp );
+--error ER_INVALID_ON_UPDATE
+eval CREATE TABLE t1( a TIME ON UPDATE $current_timestamp );
+--error ER_INVALID_ON_UPDATE
+eval CREATE TABLE t1( a YEAR ON UPDATE $current_timestamp );
+
+--echo #
+--echo # Test that the default clause behaves like NOW() regarding time zones.
+--echo #
+eval CREATE TABLE t1 (
+ a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ b $timestamp NOT NULL DEFAULT $current_timestamp,
+ c $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp,
+ d $timestamp NULL,
+ e $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ f $datetime DEFAULT $current_timestamp,
+ g $datetime ON UPDATE $current_timestamp,
+ h $datetime
+);
+
+--echo # 2011-09-27 14:11:08 UTC
+SET TIMESTAMP = 1317132668.654321;
+SET @old_time_zone = @@TIME_ZONE;
+SET TIME_ZONE = "+05:00";
+
+eval INSERT INTO t1( d, h ) VALUES ( $now, $now );
+SELECT * FROM t1;
+
+--echo # 1989-05-13 01:02:03
+SET TIMESTAMP = 611017323.543212;
+eval UPDATE t1 SET d = $now, h = $now;
+SELECT * FROM t1;
+
+SET TIME_ZONE = @old_time_zone;
+DROP TABLE t1;
+
+--echo #
+--echo # Test of several TIMESTAMP columns with different function defaults.
+--echo #
+eval CREATE TABLE t1 (
+ a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ c $timestamp NOT NULL DEFAULT $current_timestamp,
+ d $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp,
+ e $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp,
+ f INT
+);
+
+--echo # 2011-04-19 07:22:02 UTC
+SET TIMESTAMP = 1303197722.534231;
+
+INSERT INTO t1 ( f ) VALUES (1);
+SELECT * FROM t1;
+
+--echo # 2011-04-19 07:23:18 UTC
+SET TIMESTAMP = 1303197798.132435;
+
+UPDATE t1 SET f = 2;
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+--echo #
+--echo # Test of inserted values out of order.
+--echo #
+eval CREATE TABLE t1 (
+ a INT,
+ b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ c $timestamp NOT NULL DEFAULT $current_timestamp,
+ d $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp,
+ e $timestamp NULL,
+ f $datetime,
+ g $datetime DEFAULT $current_timestamp,
+ h $datetime ON UPDATE $current_timestamp,
+ i $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ j INT
+);
+
+--echo # 2011-04-19 07:22:02 UTC
+SET TIMESTAMP = 1303197722.534231;
+
+INSERT INTO t1 ( j, a ) VALUES ( 1, 1 );
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+--echo #
+--echo # Test of ON DUPLICATE KEY UPDATE
+--echo #
+eval CREATE TABLE t1 (
+ a INT PRIMARY KEY,
+ b INT,
+ c $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ d $timestamp NOT NULL DEFAULT $current_timestamp,
+ e $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp,
+ f $timestamp NOT NULL DEFAULT '1986-09-27 03:00:00.098765',
+ g $timestamp NULL,
+ h $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ i $datetime DEFAULT $current_timestamp,
+ j $datetime ON UPDATE $current_timestamp,
+ k $datetime NULL,
+ l $datetime DEFAULT '1986-09-27 03:00:00.098765'
+);
+
+--echo # 1977-12-21 23:00:00 UTC
+SET TIMESTAMP = 251593200.192837;
+INSERT INTO t1(a) VALUES (1) ON DUPLICATE KEY UPDATE b = 2;
+SELECT * FROM t1;
+
+--echo # 1975-05-21 23:00:00 UTC
+SET TIMESTAMP = 169945200.918273;
+INSERT INTO t1(a) VALUES (1) ON DUPLICATE KEY UPDATE b = 2;
+SELECT * FROM t1;
+
+--echo # 1973-08-14 09:11:22 UTC
+SET TIMESTAMP = 114167482.534231;
+INSERT INTO t1(a) VALUES (2) ON DUPLICATE KEY UPDATE b = 2;
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+eval CREATE TABLE t1 ( a INT PRIMARY KEY, b INT, c $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp );
+
+--echo # 2011-04-19 07:23:18 UTC
+SET TIMESTAMP = 1303197798.945156;
+
+INSERT INTO t1 VALUES
+ (1, 0, '2001-01-01 01:01:01.111111'),
+ (2, 0, '2002-02-02 02:02:02.222222'),
+ (3, 0, '2003-03-03 03:03:03.333333');
+SELECT * FROM t1;
+
+UPDATE t1 SET b = 2, c = c WHERE a = 2;
+SELECT * FROM t1;
+
+INSERT INTO t1 (a) VALUES (4);
+SELECT * FROM t1;
+
+UPDATE t1 SET c = '2004-04-04 04:04:04.444444' WHERE a = 4;
+SELECT * FROM t1;
+
+INSERT INTO t1 ( a ) VALUES ( 3 ), ( 5 ) ON DUPLICATE KEY UPDATE b = 3, c = c;
+SELECT * FROM t1;
+
+INSERT INTO t1 (a, c) VALUES
+ (4, '2004-04-04 00:00:00.444444'),
+ (6, '2006-06-06 06:06:06.666666')
+ON DUPLICATE KEY UPDATE b = 4;
+
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+
+--echo #
+--echo # Test of REPLACE INTO executed as UPDATE.
+--echo #
+eval CREATE TABLE t1 (
+ a INT PRIMARY KEY,
+ b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ c $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ d $timestamp NOT NULL DEFAULT $current_timestamp,
+ e $datetime DEFAULT $current_timestamp,
+ f $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp,
+ g $datetime ON UPDATE $current_timestamp,
+ h $timestamp NULL,
+ i $datetime
+);
+
+--echo # 1970-09-21 09:11:12 UTC
+SET TIMESTAMP = 22756272.163584;
+
+REPLACE INTO t1 ( a ) VALUES ( 1 );
+SELECT * FROM t1;
+
+--echo # 1970-11-10 14:16:17 UTC
+SET TIMESTAMP = 27094577.852954;
+
+
+REPLACE INTO t1 ( a ) VALUES ( 1 );
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+
+--echo #
+--echo # Test of insertion of NULL, DEFAULT and an empty row for DEFAULT
+--echo # CURRENT_TIMESTAMP.
+--echo #
+eval CREATE TABLE t1 (
+ a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ b $datetime DEFAULT $current_timestamp,
+ c INT
+);
+
+--echo # 2011-04-20 09:53:41 UTC
+SET TIMESTAMP = 1303293221.163578;
+
+INSERT INTO t1 VALUES (NULL, NULL, 1), (DEFAULT, DEFAULT, 2);
+INSERT INTO t1 ( a, b, c ) VALUES (NULL, NULL, 3), (DEFAULT, DEFAULT, 4);
+SELECT * FROM t1;
+
+SET TIME_ZONE = "+03:00";
+SELECT * FROM t1;
+SET TIME_ZONE = "+00:00";
+
+DROP TABLE t1;
+
+--echo # 2011-04-20 07:05:39 UTC
+SET TIMESTAMP = 1303283139.195624;
+eval CREATE TABLE t1 (
+ a $timestamp NOT NULL DEFAULT '2010-10-11 12:34:56' ON UPDATE $current_timestamp,
+ b $datetime DEFAULT '2010-10-11 12:34:56'
+);
+
+INSERT INTO t1 VALUES (NULL, NULL), (DEFAULT, DEFAULT);
+INSERT INTO t1 ( a, b ) VALUES (NULL, NULL), (DEFAULT, DEFAULT);
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+--echo # 2011-04-20 09:53:41 UTC
+SET TIMESTAMP = 1303293221.136952;
+
+eval CREATE TABLE t1 (
+a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+b $timestamp NOT NULL DEFAULT $current_timestamp,
+c $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp,
+d $timestamp NOT NULL DEFAULT '1986-09-27 03:00:00.098765',
+e $timestamp NULL,
+f $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+g $datetime DEFAULT $current_timestamp,
+h $datetime ON UPDATE $current_timestamp,
+i $datetime NULL,
+j $datetime DEFAULT '1986-09-27 03:00:00.098765'
+);
+
+INSERT INTO t1 VALUES ();
+
+INSERT INTO t1 SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL;
+
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+--echo #
+--echo # Test of multiple-table UPDATE for DEFAULT CURRENT_TIMESTAMP
+--echo #
+eval CREATE TABLE t1 (
+ a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ b $datetime DEFAULT $current_timestamp,
+ c INT
+);
+
+INSERT INTO t1 ( c ) VALUES (1);
+SELECT * FROM t1;
+
+--echo # 2011-04-20 17:06:13 UTC
+SET TIMESTAMP = 1303311973.163587;
+
+UPDATE t1 t11, t1 t12 SET t11.c = 1;
+SELECT * FROM t1;
+
+UPDATE t1 t11, t1 t12 SET t11.c = 2;
+
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+eval CREATE TABLE t1 (
+ a $timestamp NOT NULL DEFAULT $current_timestamp,
+ b $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp,
+ c $datetime DEFAULT $current_timestamp,
+ d $datetime ON UPDATE $current_timestamp,
+ e INT
+);
+
+eval CREATE TABLE t2 (
+ f INT,
+ g $datetime ON UPDATE $current_timestamp,
+ h $datetime DEFAULT $current_timestamp,
+ i $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp,
+ j $timestamp NOT NULL DEFAULT $current_timestamp
+);
+
+--echo # 1995-03-11 00:02:03 UTC
+SET TIMESTAMP = 794880123.195676;
+
+INSERT INTO t1 ( e ) VALUES ( 1 ), ( 2 );
+
+INSERT INTO t2 ( f ) VALUES ( 1 ), ( 2 );
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+--echo # 1980-12-13 02:02:01 UTC
+SET TIMESTAMP = 345520921.196755;
+
+UPDATE t1, t2 SET t1.e = 3, t2.f = 4;
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+DROP TABLE t1, t2;
+
+--echo #
+--echo # Test of multiple table update with temporary table and on the fly.
+--echo #
+eval CREATE TABLE t1 (
+ a $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp,
+ b $datetime ON UPDATE $current_timestamp,
+ c INT,
+ d INT
+);
+
+eval CREATE TABLE t2 (
+ a $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp,
+ b $datetime ON UPDATE $current_timestamp,
+ c INT KEY,
+ d INT
+);
+
+INSERT INTO t1 ( c ) VALUES (1), (2);
+INSERT INTO t2 ( c ) VALUES (1), (2);
+
+--echo # Test of multiple table update done on the fly
+--echo # 2011-04-20 15:06:13 UTC
+SET TIMESTAMP = 1303311973.194685;
+UPDATE t1 JOIN t2 USING ( c ) SET t2.d = 1;
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+--echo # Test of multiple table update done with temporary table.
+--echo # 1979-01-15 03:02:01
+SET TIMESTAMP = 285213721.134679;
+UPDATE t1 JOIN t2 USING ( c ) SET t1.d = 1;
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+DROP TABLE t1, t2;
+
+
+--echo #
+--echo # Test of ON UPDATE CURRENT_TIMESTAMP.
+--echo #
+eval CREATE TABLE t1 (
+ a $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp,
+ b $datetime ON UPDATE $current_timestamp,
+ c INT
+);
+
+--echo # 2011-04-20 09:53:41 UTC
+SET TIMESTAMP = 1303293221.794613;
+
+INSERT INTO t1 ( c ) VALUES ( 1 );
+SELECT * FROM t1;
+
+UPDATE t1 SET c = 1;
+SELECT * FROM t1;
+
+UPDATE t1 SET c = 2;
+SELECT * FROM t1;
+
+--echo #
+--echo # Test of multiple-table UPDATE for ON UPDATE CURRENT_TIMESTAMP
+--echo #
+--echo # 2011-04-20 15:06:13 UTC
+SET TIMESTAMP = 1303311973.534231;
+
+UPDATE t1 t11, t1 t12 SET t11.c = 2;
+SELECT * FROM t1;
+
+UPDATE t1 t11, t1 t12 SET t11.c = 3;
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+--echo #
+--echo # Test of a multiple-table update where only one table is updated and
+--echo # the updated table has a primary key.
+--echo #
+eval CREATE TABLE t1 ( a INT, b INT, PRIMARY KEY (a) );
+INSERT INTO t1 VALUES (1, 1),(2, 2),(3, 3),(4, 4);
+
+eval CREATE TABLE t2 ( a INT, b INT );
+INSERT INTO t2 VALUES (1, 1),(2, 2),(3, 3),(4, 4),(5, 5);
+
+UPDATE t1, t2 SET t1.b = 100 WHERE t1.a = t2.a;
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+DROP TABLE t1, t2;
+
+--echo #
+--echo # Test of ALTER TABLE, reordering columns.
+--echo #
+eval CREATE TABLE t1 ( a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, b INT );eval ALTER TABLE t1 MODIFY a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp AFTER b;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+eval CREATE TABLE t1 ( a INT, b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, c $timestamp NULL );eval ALTER TABLE t1 MODIFY b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp FIRST;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+eval CREATE TABLE t1 ( a INT, b $timestamp NULL );eval ALTER TABLE t1 MODIFY b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp FIRST;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+eval CREATE TABLE t1 ( a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, b $timestamp NULL );eval ALTER TABLE t1 MODIFY a $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER b;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+eval CREATE TABLE t1 ( a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, b $timestamp NULL );eval ALTER TABLE t1 MODIFY a $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER b;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+eval CREATE TABLE t1 ( a $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $now, b INT, c $timestamp NULL );
+SHOW CREATE TABLE t1;eval ALTER TABLE t1 MODIFY a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp AFTER b;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+eval CREATE TABLE t1 ( a $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $now, b INT, c $timestamp NULL );eval ALTER TABLE t1 MODIFY c $timestamp NULL FIRST;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+eval CREATE TABLE t1 ( a $timestamp NOT NULL DEFAULT $now ON UPDATE $current_timestamp, b INT, c $timestamp NULL );
+SHOW CREATE TABLE t1;eval ALTER TABLE t1 MODIFY a $timestamp NOT NULL DEFAULT $now ON UPDATE $current_timestamp AFTER b;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+eval CREATE TABLE t1 ( a $timestamp NOT NULL DEFAULT $now ON UPDATE $current_timestamp, b INT, c $timestamp NULL );eval ALTER TABLE t1 MODIFY c $timestamp NULL FIRST;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Test of ALTER TABLE, adding columns.
+--echo #
+eval CREATE TABLE t1 ( a INT );
+eval ALTER TABLE t1 ADD COLUMN b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+--echo #
+--echo # Test of INSERT SELECT.
+--echo #
+eval CREATE TABLE t1 (
+ a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ c $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ d $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp
+);
+
+eval CREATE TABLE t2 (
+ placeholder1 INT,
+ placeholder2 INT,
+ placeholder3 INT,
+ placeholder4 INT,
+ a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ b $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
+ c $datetime,
+ d $datetime
+);
+
+--echo # 1977-08-16 15:30:01 UTC
+SET TIMESTAMP = 240589801.654312;
+
+INSERT INTO t2 (a, b, c, d) VALUES (
+ '1977-08-16 15:30:01.123456',
+ '1977-08-16 15:30:01.234567',
+ '1977-08-16 15:30:01.345678',
+ '1977-08-16 15:30:01.456789'
+);
+
+--echo # 1986-09-27 01:00:00 UTC
+SET TIMESTAMP = 528166800.132435;
+
+INSERT INTO t1 ( a, c ) SELECT a, c FROM t2;
+
+SELECT * FROM t1;
+
+DROP TABLE t1, t2;
+
+--echo #
+--echo # Test of CREATE TABLE SELECT.
+--echo #
+--echo # We test that the columns of the source table are not used to determine
+--echo # function defaults for the receiving table.
+--echo #
+
+--echo # 1970-04-11 20:13:57 UTC
+SET TIMESTAMP = 8712837.657898;
+eval CREATE TABLE t1 (
+ a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ b $timestamp NOT NULL DEFAULT $current_timestamp,
+ c $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp,
+ d $timestamp NOT NULL DEFAULT '1986-09-27 03:00:00.098765',
+ e $timestamp NULL,
+ f $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ g $datetime DEFAULT $current_timestamp,
+ h $datetime ON UPDATE $current_timestamp,
+ i $datetime NULL,
+ j $datetime DEFAULT '1986-09-27 03:00:00.098765'
+);
+
+INSERT INTO t1 VALUES ();
+
+--echo # 1971-01-31 21:13:57 UTC
+SET TIMESTAMP = 34200837.164937;
+
+eval CREATE TABLE t2 SELECT a FROM t1; SHOW CREATE TABLE t2; SELECT * FROM t2;
+eval CREATE TABLE t3 SELECT b FROM t1; SHOW CREATE TABLE t3; SELECT * FROM t3;
+eval CREATE TABLE t4 SELECT c FROM t1; SHOW CREATE TABLE t4; SELECT * FROM t4;
+eval CREATE TABLE t5 SELECT d FROM t1; SHOW CREATE TABLE t5; SELECT * FROM t5;
+eval CREATE TABLE t6 SELECT e FROM t1; SHOW CREATE TABLE t6; SELECT * FROM t6;
+eval CREATE TABLE t7 SELECT f FROM t1; SHOW CREATE TABLE t7; SELECT * FROM t7;
+eval CREATE TABLE t8 SELECT g FROM t1; SHOW CREATE TABLE t8; SELECT * FROM t8;
+eval CREATE TABLE t9 SELECT h FROM t1; SHOW CREATE TABLE t9; SELECT * FROM t9;
+eval CREATE TABLE t10 SELECT i FROM t1; SHOW CREATE TABLE t10; SELECT * FROM t10;
+eval CREATE TABLE t11 SELECT j FROM t1; SHOW CREATE TABLE t11; SELECT * FROM t11;
+
+eval CREATE TABLE t12 (
+ k $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ l $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ m $timestamp NOT NULL DEFAULT $current_timestamp,
+ n $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp,
+ o $timestamp NOT NULL DEFAULT '1986-09-27 03:00:00.098765',
+ p $timestamp NULL,
+ q $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ r $datetime DEFAULT $current_timestamp,
+ s $datetime ON UPDATE $current_timestamp,
+ t $datetime NULL,
+ u $datetime DEFAULT '1986-09-27 03:00:00.098765'
+)
+SELECT * FROM t1;
+
+SHOW CREATE TABLE t12;
+
+DROP TABLE t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12;
+
+--echo # 1970-04-11 20:13:57 UTC
+SET TIMESTAMP = 8712837.164953;
+eval CREATE TABLE t1 (
+ a $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ b $datetime DEFAULT $current_timestamp,
+ c $datetime ON UPDATE $current_timestamp,
+ d $datetime NULL,
+ e $datetime DEFAULT '1986-09-27 03:00:00.098765'
+);
+
+INSERT INTO t1 VALUES ();
+
+--echo # 1971-01-31 20:13:57 UTC
+SET TIMESTAMP = 34200837.915736;
+
+eval CREATE TABLE t2 SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+
+eval CREATE TABLE t3 SELECT b FROM t1;
+SHOW CREATE TABLE t3;
+SELECT * FROM t3;
+
+eval CREATE TABLE t4 SELECT c FROM t1;
+SHOW CREATE TABLE t4;
+SELECT * FROM t4;
+
+eval CREATE TABLE t5 SELECT d FROM t1;
+SHOW CREATE TABLE t5;
+SELECT * FROM t5;
+
+eval CREATE TABLE t6 SELECT e FROM t1;
+SHOW CREATE TABLE t6;
+SELECT * FROM t6;
+
+DROP TABLE t1, t2, t3, t4, t5, t6;
+
+--echo #
+--echo # Test of a CREATE TABLE SELECT that also declared columns. In this case
+--echo # the function default should be de-activated during the execution of the
+--echo # CREATE TABLE statement.
+--echo #
+--echo # 1970-01-01 03:16:40
+SET TIMESTAMP = 1000.987654;
+eval CREATE TABLE t1 ( a INT );
+INSERT INTO t1 VALUES ( 1 ), ( 2 );
+
+eval CREATE TABLE t2 ( b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp) SELECT a FROM t1;
+
+SHOW CREATE TABLE t2;
+SET TIMESTAMP = 2000.876543;
+INSERT INTO t2( a ) VALUES ( 3 );
+SELECT * FROM t2;
+
+DROP TABLE t1, t2;
+
+--echo #
+--echo # Test of updating a view.
+--echo #
+eval CREATE TABLE t1 ( a INT, b $datetime DEFAULT $current_timestamp );
+eval CREATE TABLE t2 ( a INT, b $datetime ON UPDATE $current_timestamp );
+
+eval CREATE VIEW v1 AS SELECT * FROM t1;
+SHOW CREATE VIEW v1;
+
+eval CREATE VIEW v2 AS SELECT * FROM t2;
+SHOW CREATE VIEW v2;
+
+--echo # 1971-01-31 21:13:57 UTC
+SET TIMESTAMP = 34200837.348564;
+
+INSERT INTO v1 ( a ) VALUES ( 1 );
+INSERT INTO v2 ( a ) VALUES ( 1 );
+
+SELECT * FROM t1;
+SELECT * FROM v1;
+
+SELECT * FROM t2;
+SELECT * FROM v2;
+
+--echo # 1970-04-11 20:13:57 UTC
+SET TIMESTAMP = 8712837.567332;
+UPDATE v1 SET a = 2;
+UPDATE v2 SET a = 2;
+
+SELECT * FROM t1;
+SELECT * FROM v1;
+
+SELECT * FROM t2;
+SELECT * FROM v2;
+
+DROP VIEW v1, v2;
+DROP TABLE t1, t2;
+
+--echo #
+--echo # Test with stored procedures.
+--echo #
+eval CREATE TABLE t1 (
+ a INT,
+ b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ c $timestamp NOT NULL DEFAULT $current_timestamp,
+ d $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp,
+ e $timestamp NULL,
+ f $datetime DEFAULT $current_timestamp,
+ g $datetime ON UPDATE $current_timestamp
+);
+CREATE PROCEDURE p1() INSERT INTO test.t1( a ) VALUES ( 1 );
+CREATE PROCEDURE p2() UPDATE t1 SET a = 2 WHERE a = 1;
+
+--echo # 1971-01-31 20:13:57 UTC
+SET TIMESTAMP = 34200837.876544;
+CALL p1();
+SELECT * FROM t1;
+
+--echo # 1970-04-11 21:13:57 UTC
+SET TIMESTAMP = 8712837.143546;
+CALL p2();
+SELECT * FROM t1;
+
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+DROP TABLE t1;
+
+--echo #
+--echo # Test with triggers.
+--echo #
+eval CREATE TABLE t1 (
+ a INT,
+ b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ c $timestamp NOT NULL DEFAULT $current_timestamp,
+ d $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp,
+ e $timestamp NULL,
+ f $datetime,
+ g $datetime DEFAULT $current_timestamp,
+ h $datetime ON UPDATE $current_timestamp,
+ i $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp
+);
+
+eval CREATE TABLE t2 ( a INT );
+
+DELIMITER |;
+eval CREATE TRIGGER t2_trg BEFORE INSERT ON t2 FOR EACH ROW
+BEGIN
+ INSERT INTO t1 ( a ) VALUES ( 1 );
+END|
+DELIMITER ;|
+
+--echo # 1971-01-31 21:13:57 UTC
+SET TIMESTAMP = 34200837.978675;
+
+INSERT INTO t2 ( a ) VALUES ( 1 );
+SELECT * FROM t1;
+
+DROP TRIGGER t2_trg;
+
+DELIMITER |;
+eval CREATE TRIGGER t2_trg BEFORE INSERT ON t2 FOR EACH ROW
+BEGIN
+ UPDATE t1 SET a = 2;
+END|
+DELIMITER ;|
+
+--echo # 1970-04-11 21:13:57 UTC
+SET TIMESTAMP = 8712837.456789;
+
+INSERT INTO t2 ( a ) VALUES ( 1 );
+SELECT * FROM t1;
+
+DROP TABLE t1, t2;
+
+--echo #
+--echo # Test where the assignment target is not a column.
+--echo #
+eval CREATE TABLE t1 ( a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp );
+eval CREATE TABLE t2 ( a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp );
+eval CREATE TABLE t3 ( a $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp );
+eval CREATE TABLE t4 ( a $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp );
+
+eval CREATE VIEW v1 AS SELECT a COLLATE latin1_german1_ci AS b FROM t1;
+eval CREATE VIEW v2 ( b ) AS SELECT a COLLATE latin1_german1_ci FROM t2;
+eval CREATE VIEW v3 AS SELECT a COLLATE latin1_german1_ci AS b FROM t3;
+eval CREATE VIEW v4 ( b ) AS SELECT a COLLATE latin1_german1_ci FROM t4;
+
+INSERT INTO v1 ( b ) VALUES ( '2007-10-24 00:03:34.010203' );
+SELECT a FROM t1;
+
+INSERT INTO v2 ( b ) VALUES ( '2007-10-24 00:03:34.010203' );
+SELECT a FROM t2;
+
+INSERT INTO t3 VALUES ();
+UPDATE v3 SET b = '2007-10-24 00:03:34.010203';
+SELECT a FROM t3;
+
+INSERT INTO t4 VALUES ();
+UPDATE v4 SET b = '2007-10-24 00:03:34.010203';
+SELECT a FROM t4;
+
+DROP VIEW v1, v2, v3, v4;
+DROP TABLE t1, t2, t3, t4;
+
+--echo #
+--echo # Test of LOAD DATA/XML INFILE
+--echo # This tests behavior of function defaults for TIMESTAMP and DATETIME
+--echo # columns. during LOAD ... INFILE.
+--echo # As can be seen here, a TIMESTAMP column with only ON UPDATE
+--echo # CURRENT_TIMESTAMP will still have CURRENT_TIMESTAMP inserted on LOAD
+--echo # ... INFILE if the value is missing. For DATETIME columns a NULL value
+--echo # is inserted instead.
+--echo #
+
+eval CREATE TABLE t1 (
+ a INT,
+ b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ c $timestamp NOT NULL DEFAULT $current_timestamp,
+ d $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp,
+ e $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ f $datetime,
+ g $datetime DEFAULT $current_timestamp,
+ h $datetime ON UPDATE $current_timestamp,
+ i $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp
+);
+
+eval CREATE TABLE t2 (
+ a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ b $timestamp NOT NULL DEFAULT $current_timestamp,
+ c $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp,
+ d $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ e $datetime NOT NULL,
+ f $datetime NOT NULL DEFAULT '1977-01-02 12:13:14',
+ g $datetime DEFAULT $current_timestamp NOT NULL,
+ h $datetime ON UPDATE $current_timestamp NOT NULL,
+ i $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp NOT NULL
+);
+
+SELECT 1 INTO OUTFILE 't3.dat' FROM dual;
+
+SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+INTO OUTFILE 't4.dat'
+FROM dual;
+
+SELECT 1, 2 INTO OUTFILE 't5.dat' FROM dual;
+
+--echo # Mon Aug 1 15:11:19 2011 UTC
+SET TIMESTAMP = 1312211479.918273;
+
+LOAD DATA INFILE 't3.dat' INTO TABLE t1;
+--query_vertical SELECT * FROM t1
+
+LOAD DATA INFILE 't4.dat' INTO TABLE t2;
+SELECT a FROM t2;
+SELECT b FROM t2;
+SELECT c FROM t2;
+SELECT d FROM t2;
+--echo # As shown here, supplying a NULL value to a non-nullable
+--echo # column with no default value results in the zero date.
+SELECT e FROM t2;
+--echo # As shown here, supplying a NULL value to a non-nullable column with a
+--echo # default value results in the zero date.
+SELECT f FROM t2;
+--echo # As shown here, supplying a NULL value to a non-nullable column with a
+--echo # default function results in the zero date.
+SELECT g FROM t2;
+--echo # As shown here, supplying a NULL value to a non-nullable DATETIME ON
+--echo # UPDATE CURRENT_TIMESTAMP column with no default value results in the
+--echo # zero date.
+SELECT h FROM t2;
+SELECT i FROM t2;
+
+DELETE FROM t1;
+DELETE FROM t2;
+
+--echo # Read t3 file into t1
+--echo # The syntax will cause a different code path to be taken
+--echo # (read_fixed_length()) than under the LOAD ... INTO TABLE t1 command
+--echo # above. The code in this path is copy-pasted code from the path taken
+--echo # under the syntax used in the previous LOAD command.
+LOAD DATA INFILE 't3.dat' INTO TABLE t1
+FIELDS TERMINATED BY '' ENCLOSED BY '';
+
+SELECT b FROM t1;
+SELECT c FROM t1;
+SELECT d FROM t1;
+SELECT e FROM t1;
+--echo # Yes, a missing field cannot be NULL using this syntax, so it will
+--echo # zero date instead. Says a comment in read_fixed_length() : "No fields
+--echo # specified in fields_vars list can be NULL in this format."
+--echo # It appears to be by design. This is inconsistent with LOAD DATA INFILE
+--echo # syntax in previous test.
+SELECT f FROM t1;
+SELECT g FROM t1;
+--echo # See comment above "SELECT f FROM f1".
+SELECT h FROM t1;
+SELECT i FROM t1;
+DELETE FROM t1;
+
+LOAD DATA INFILE 't5.dat' INTO TABLE t1 ( a, @dummy );
+SELECT * FROM t1;
+SELECT @dummy;
+DELETE FROM t1;
+
+LOAD DATA INFILE 't3.dat' INTO TABLE t1 ( a ) SET c = '2005-06-06 08:09:10';
+SELECT * FROM t1;
+DELETE FROM t1;
+
+LOAD DATA INFILE 't3.dat' INTO TABLE t1 ( a ) SET g = '2005-06-06 08:09:10';
+SELECT * FROM t1;
+DELETE FROM t1;
+
+--echo # Load a static XML file
+LOAD XML INFILE '../../std_data/onerow.xml' INTO TABLE t1
+ROWS IDENTIFIED BY '<row>';
+
+--echo Missing tags are treated as NULL
+--query_vertical SELECT * FROM t1
+
+DROP TABLE t1, t2;
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+remove_file $MYSQLD_DATADIR/test/t3.dat;
+remove_file $MYSQLD_DATADIR/test/t4.dat;
+remove_file $MYSQLD_DATADIR/test/t5.dat;
+
+
+--echo #
+--echo # Similar LOAD DATA tests in another form
+--echo #
+--echo # All of this test portion has been run on a pre-WL5874 trunk
+--echo # (except that like_b and like_c didn't exist) and all result
+--echo # differences are a bug.
+--echo # Regarding like_b its definition is the same as b's except
+--echo # that the constant default is replaced with a function
+--echo # default. Our expectation is that like_b would behave
+--echo # like b: if b is set to NULL, or set to 0000-00-00, or set to
+--echo # its default, then the same should apply to like_b. Same for
+--echo # like_c vs c.
+
+--echo # Mon Aug 1 15:11:19 2011 UTC
+SET TIMESTAMP = 1312211479.089786;
+
+SELECT 1 INTO OUTFILE "file1.dat" FROM dual;
+SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+ INTO OUTFILE "file2.dat" FROM dual;
+
+--echo # Too short row
+
+eval
+CREATE TABLE t1 (
+ dummy INT,
+ a $datetime NULL DEFAULT NULL,
+ b $datetime NULL DEFAULT "2011-11-18",
+ like_b $datetime NULL DEFAULT $current_timestamp,
+ c $datetime NOT NULL DEFAULT "2011-11-18",
+ like_c $datetime NOT NULL DEFAULT $current_timestamp,
+ d $timestamp NULL DEFAULT "2011-05-03" ON UPDATE $current_timestamp,
+ e $timestamp NOT NULL DEFAULT "2011-05-03",
+ f $timestamp NOT NULL DEFAULT $current_timestamp,
+ g $timestamp NULL DEFAULT NULL,
+ h INT NULL,
+ i INT NOT NULL DEFAULT 42
+);
+
+--echo # There is no promotion
+SHOW CREATE TABLE t1;
+
+LOAD DATA INFILE "file1.dat" INTO table t1;
+
+--echo # It is strange that "like_b" gets NULL when "b" gets 0. But
+--echo # this is consistent with how "a" gets NULL when "b" gets 0,
+--echo # with how "g" gets NULL when "d" gets 0, and with how "h" gets
+--echo # NULL when "i" gets 0. Looks like "DEFAULT
+--echo # <non-NULL-constant>" is changed to 0, whereas DEFAULT NULL
+--echo # and DEFAULT NOW are changed to NULL.
+--query_vertical SELECT * FROM t1
+delete from t1;
+
+alter table t1
+modify f TIMESTAMP NULL default CURRENT_TIMESTAMP;
+
+--echo # There is no promotion
+SHOW CREATE TABLE t1;
+
+LOAD DATA INFILE "file1.dat" INTO table t1;
+
+--query_vertical SELECT * FROM t1
+delete from t1;
+
+drop table t1;
+
+--echo # Conclusion derived from trunk's results:
+--echo # DATETIME DEFAULT <non-NULL-constant> (b,c) gets 0000-00-00,
+--echo # DATETIME DEFAULT NULL (a) gets NULL,
+--echo # TIMESTAMP NULL DEFAULT <non-NULL-constant> (d) gets 0000-00-00,
+--echo # TIMESTAMP NULL DEFAULT NULL (g) gets NULL,
+--echo # TIMESTAMP NULL DEFAULT NOW (f after ALTER) gets NULL,
+--echo # TIMESTAMP NOT NULL (f before ALTER, e) gets NOW.
+
+--echo ### Loading NULL ###
+
+eval
+CREATE TABLE t1 (
+ dummy INT,
+ a $datetime NULL DEFAULT NULL,
+ b $datetime NULL DEFAULT "2011-11-18",
+ like_b $datetime NULL DEFAULT $current_timestamp,
+ c $datetime NOT NULL DEFAULT "2011-11-18",
+ like_c $datetime NOT NULL DEFAULT $current_timestamp,
+ d $timestamp NULL DEFAULT "2011-05-03" ON UPDATE $current_timestamp,
+ e $timestamp NOT NULL DEFAULT "2011-05-03",
+ f $timestamp NOT NULL DEFAULT $current_timestamp,
+ g $timestamp NULL DEFAULT NULL,
+ h INT NULL,
+ i INT NOT NULL DEFAULT 42
+);
+
+--echo # There is no promotion
+SHOW CREATE TABLE t1;
+
+LOAD DATA INFILE "file2.dat" INTO table t1;
+
+--query_vertical SELECT * FROM t1
+delete from t1;
+
+alter table t1
+modify f TIMESTAMP NULL default CURRENT_TIMESTAMP;
+
+--echo # There is no promotion
+SHOW CREATE TABLE t1;
+
+LOAD DATA INFILE "file2.dat" INTO table t1;
+
+--query_vertical SELECT * FROM t1
+delete from t1;
+
+--echo # Conclusion derived from trunk's results:
+--echo # DATETIME NULL (a,b) gets NULL,
+--echo # DATETIME NOT NULL (c) gets 0000-00-00,
+--echo # TIMESTAMP NULL (d,f,g) gets NULL,
+--echo # TIMESTAMP NOT NULL (e) gets NOW.
+
+drop table t1;
+remove_file $MYSQLD_DATADIR/test/file1.dat;
+remove_file $MYSQLD_DATADIR/test/file2.dat;
+
+--echo #
+--echo # Test of updatable views with check options. The option can be violated
+--echo # using ON UPDATE updates which is very strange as this offers a loophole
+--echo # in this integrity check.
+--echo #
+SET TIME_ZONE = "+03:00";
+--echo # 1970-01-01 03:16:40
+SET TIMESTAMP = 1000.123456;
+
+eval CREATE TABLE t1 ( a INT, b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp) ENGINE = INNODB;
+
+SHOW CREATE TABLE t1;
+
+INSERT INTO t1 ( a ) VALUES ( 1 );
+
+SELECT * FROM t1;
+
+eval CREATE VIEW v1 AS SELECT * FROM t1 WHERE b <= '1970-01-01 03:16:40.123456'
+WITH CHECK OPTION;
+
+SELECT * FROM v1;
+
+--echo # 1970-01-01 03:33:20
+SET TIMESTAMP = 2000.000234;
+
+--error ER_VIEW_CHECK_FAILED
+UPDATE v1 SET a = 2;
+SELECT * FROM t1;
+
+DROP VIEW v1;
+DROP TABLE t1;
+
+eval CREATE TABLE t1 (
+ a $timestamp NOT NULL DEFAULT '1973-08-14 09:11:22.089786' ON UPDATE $current_timestamp,
+ c INT KEY
+);
+--echo # 1973-08-14 09:11:22 UTC
+SET TIMESTAMP = 114167482.534231;
+INSERT INTO t1 ( c ) VALUES ( 1 );
+
+eval CREATE VIEW v1 AS
+SELECT *
+FROM t1
+WHERE a >= '1973-08-14 09:11:22'
+WITH LOCAL CHECK OPTION;
+
+SELECT * FROM v1;
+
+SET TIMESTAMP = 1.126789;
+
+--error ER_VIEW_CHECK_FAILED
+INSERT INTO v1 ( c ) VALUES ( 1 ) ON DUPLICATE KEY UPDATE c = 2;
+
+SELECT * FROM v1;
+
+DROP VIEW v1;
+DROP TABLE t1;
+
+--echo #
+--echo # Bug 13095459 - MULTI-TABLE UPDATE MODIFIES A ROW TWICE
+--echo #
+eval CREATE TABLE t1 (
+ a INT,
+ b INT,
+ ts $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp,
+ PRIMARY KEY ( a, ts )
+) ENGINE = INNODB;
+INSERT INTO t1( a, b, ts ) VALUES ( 1, 0, '2000-09-28 17:44:34' );
+
+eval CREATE TABLE t2 ( a INT ) ENGINE = INNODB;
+INSERT INTO t2 VALUES ( 1 );
+
+UPDATE t1 STRAIGHT_JOIN t2
+SET t1.b = t1.b + 1
+WHERE t1.a = 1 AND t1.ts >= '2000-09-28 00:00:00';
+
+SELECT b FROM t1;
+
+DROP TABLE t1, t2;
+
+--echo #
+--echo # Bug#11745578: 17392: ALTER TABLE ADD COLUMN TIMESTAMP DEFAULT
+--echo # CURRENT_TIMESTAMP INSERTS ZERO
+--echo #
+SET timestamp = 1000;
+
+CREATE TABLE t1 ( b INT );
+INSERT INTO t1 VALUES (1);
+
+eval ALTER TABLE t1 ADD COLUMN a6 $datetime DEFAULT $now ON UPDATE $now FIRST;
+eval ALTER TABLE t1 ADD COLUMN a5 $datetime DEFAULT $now FIRST;
+eval ALTER TABLE t1 ADD COLUMN a4 $datetime ON UPDATE $now FIRST;
+
+eval ALTER TABLE t1 ADD COLUMN a3 $timestamp NOT NULL DEFAULT $now ON UPDATE $now FIRST;
+eval ALTER TABLE t1 ADD COLUMN a2 $timestamp NOT NULL DEFAULT $now FIRST;
+eval ALTER TABLE t1 ADD COLUMN a1 $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $now FIRST;
+
+eval ALTER TABLE t1 ADD COLUMN c1 $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $now AFTER b;
+eval ALTER TABLE t1 ADD COLUMN c2 $timestamp NOT NULL DEFAULT $now AFTER c1;
+eval ALTER TABLE t1 ADD COLUMN c3 $timestamp NOT NULL DEFAULT $now ON UPDATE $now AFTER c2;
+
+eval ALTER TABLE t1 ADD COLUMN c4 $datetime ON UPDATE $now AFTER c3;
+eval ALTER TABLE t1 ADD COLUMN c5 $datetime DEFAULT $now AFTER c4;
+eval ALTER TABLE t1 ADD COLUMN c6 $datetime DEFAULT $now ON UPDATE $now AFTER c5;
+
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+
+eval CREATE TABLE t1 ( a $timestamp NOT NULL DEFAULT $now ON UPDATE $current_timestamp, b $datetime DEFAULT $now );
+INSERT INTO t1 VALUES ();
+
+SET timestamp = 1000000000;
+
+ALTER TABLE t1 MODIFY COLUMN a TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3);
+ALTER TABLE t1 MODIFY COLUMN b DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3);
+
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+
+eval CREATE TABLE t1 (
+ a $timestamp NOT NULL DEFAULT '1999-12-01 11:22:33' ON UPDATE $current_timestamp,
+ b $datetime DEFAULT '1999-12-01 11:22:33'
+);
+INSERT INTO t1 VALUES ();
+
+eval ALTER TABLE t1 MODIFY COLUMN a $timestamp DEFAULT $now;
+eval ALTER TABLE t1 MODIFY COLUMN b $datetime DEFAULT $now;
+INSERT INTO t1 VALUES ();
+
+SELECT * FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/include/function_defaults_notembedded.inc b/mysql-test/include/function_defaults_notembedded.inc
new file mode 100644
index 00000000000..d9708c13da5
--- /dev/null
+++ b/mysql-test/include/function_defaults_notembedded.inc
@@ -0,0 +1,94 @@
+SET TIME_ZONE = "+00:00";
+
+--echo #
+--echo # Test of INSERT DELAYED ... SET ...
+--echo #
+
+--echo # 2011-04-19 08:02:40 UTC
+SET TIMESTAMP = 1303200160.123456;
+
+eval CREATE TABLE t1 ( a INT, b $timestamp NOT NULL DEFAULT CURRENT_$timestamp ON UPDATE CURRENT_$timestamp);
+
+INSERT DELAYED INTO t1 SET a = 1;
+FLUSH TABLE t1;
+
+SELECT * FROM t1;
+SELECT * FROM t1 WHERE b = 0;
+
+INSERT DELAYED INTO t1 SET a = 2, b = '1980-01-02 10:20:30.405060';
+FLUSH TABLE t1;
+
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+--echo #
+--echo # Test of INSERT DELAYED ... VALUES ...
+--echo #
+
+--echo # 2011-04-19 08:04:01 UTC
+SET TIMESTAMP = 1303200241.234567;
+
+eval CREATE TABLE t1 ( a INT, b $timestamp NOT NULL DEFAULT CURRENT_$timestamp ON UPDATE CURRENT_$timestamp);
+
+INSERT DELAYED INTO t1 ( a ) VALUES (1);
+FLUSH TABLE t1;
+SELECT * FROM t1;
+
+INSERT DELAYED INTO t1 VALUES (2, '1977-12-19 12:34:56.789123');
+FLUSH TABLE t1;
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+--echo #
+--echo # Test of a delayed insert handler servicing two insert operations
+--echo # with different sets of active defaults.
+--echo #
+eval CREATE TABLE t1 ( a INT, b $timestamp NOT NULL DEFAULT CURRENT_$timestamp ON UPDATE CURRENT_$timestamp);
+
+--connect(con1, localhost, root,,)
+--echo # 2011-04-19 08:04:01 UTC
+SET TIMESTAMP = 1303200241.345678;
+SET debug_sync = 'before_write_delayed SIGNAL parked WAIT_FOR go';
+--send INSERT DELAYED INTO t1 ( a ) VALUES (1), (2), (3)
+
+--connection default
+SET debug_sync = 'now WAIT_FOR parked';
+
+--connect(con2, localhost, root,,)
+--echo # 2011-04-19 08:04:01 UTC
+SET TIME_ZONE="+03:00";
+SET TIMESTAMP = 1303200241.456789;
+--send INSERT DELAYED INTO t1 ( a, b ) VALUES (4, '1977-12-19 12:34:56.789123'), (5, '1977-12-19 12:34:57.891234'), (6, '1977-12-19 12:34:58.912345')
+
+--connection default
+SET debug_sync = 'now SIGNAL go';
+
+--let $wait_condition= SELECT COUNT(*) = 6 FROM t1
+--source include/wait_condition.inc
+
+--sorted_result
+SELECT * FROM t1;
+
+--disconnect con1
+--disconnect con2
+
+DROP TABLE t1;
+
+--echo #
+--echo # Test of early activation of function defaults.
+--echo #
+
+eval CREATE TABLE t1 ( a INT, b $timestamp NOT NULL DEFAULT CURRENT_$timestamp ON UPDATE CURRENT_$timestamp);
+
+SET TIMESTAMP = 1317235172.987654; # 2011-09-28 18:39:32 UTC
+INSERT DELAYED INTO t1 ( a ) VALUES (1), (2), (3);
+
+SET TIMESTAMP = 385503754.876543; # 1982-03-20 20:22:34 UTC
+INSERT DELAYED INTO t1 ( a ) VALUES (4), (5), (6);
+
+FLUSH TABLE t1;
+SELECT * FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/include/have_debug_sync.inc b/mysql-test/include/have_debug_sync.inc
index 7aa5baf3342..ea2247a2746 100644
--- a/mysql-test/include/have_debug_sync.inc
+++ b/mysql-test/include/have_debug_sync.inc
@@ -1,5 +1,3 @@
---require r/have_debug_sync.require
-disable_query_log;
-let $value= query_get_value(SHOW VARIABLES LIKE 'debug_sync', Value, 1);
-eval SELECT ('$value' LIKE 'ON %') AS debug_sync;
-enable_query_log;
+if (`select @@debug_sync not like 'ON %'`) {
+ --skip Needs a debug_sync enabled
+}
diff --git a/mysql-test/include/have_innodb.combinations b/mysql-test/include/have_innodb.combinations
index d47d2c81a71..55107204097 100644
--- a/mysql-test/include/have_innodb.combinations
+++ b/mysql-test/include/have_innodb.combinations
@@ -4,6 +4,9 @@ plugin-load-add=$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,9 +14,15 @@ plugin-load-add=$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-metrics
+innodb-buffer-pool-stats
+innodb-buffer-page
+innodb-buffer-page-lru
diff --git a/mysql-test/include/wait_for_binlog_checkpoint.inc b/mysql-test/include/wait_for_binlog_checkpoint.inc
new file mode 100644
index 00000000000..960cf4e41b1
--- /dev/null
+++ b/mysql-test/include/wait_for_binlog_checkpoint.inc
@@ -0,0 +1,53 @@
+# include/wait_for_binlog_checkpoint.inc
+#
+# SUMMARY
+#
+# Wait until binlog checkpoint has been logged for current binlog file.
+# This is useful to avoid races with output difference for binlog
+# checkpoints, as these are logged asynchronously from the binlog
+# background thread.
+#
+# USAGE:
+#
+# --source include/wait_for_binlog_checkpoint.inc
+
+let $_wait_count= 300;
+
+let $_found= 0;
+
+while ($_wait_count)
+{
+ dec $_wait_count;
+ let $_cur_binlog= query_get_value(SHOW MASTER STATUS, File, 1);
+ let $_more= 1;
+ let $_row= 1;
+ while ($_more)
+ {
+ let $_event= query_get_value(SHOW BINLOG EVENTS IN "$_cur_binlog", Event_type, $_row);
+ if ($_event == "No such row")
+ {
+ let $_more= 0;
+ }
+ if ($_event == "Binlog_checkpoint")
+ {
+ let $_info= query_get_value(SHOW BINLOG EVENTS IN "$_cur_binlog", Info, $_row);
+ if (`SELECT INSTR("$_info", "$_cur_binlog") != 0`)
+ {
+ let $_more= 0;
+ let $_wait_count= 0;
+ let $_found= 1;
+ }
+ }
+ inc $_row;
+ }
+ if ($_wait_count)
+ {
+ real_sleep 0.1;
+ }
+}
+
+if (!$_found)
+{
+ eval SHOW BINLOG EVENTS IN "$_cur_binlog";
+ --die ERROR: failed while waiting for binlog checkpoint $_cur_binlog
+}
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index ba52959be84..7102968a8d7 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -55,9 +55,9 @@ ERROR 42000: Incorrect table name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
create table a (`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` int);
ERROR 42000: Identifier name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' is too long
create table t1 (a datetime default now());
-ERROR 42000: Invalid default value for 'a'
+drop table t1;
create table t1 (a datetime on update now());
-ERROR HY000: Invalid ON UPDATE clause for 'a' column
+drop table t1;
create table t1 (a int default 100 auto_increment);
ERROR 42000: Invalid default value for 'a'
create table t1 (a tinyint default 1000);
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/function_defaults.result b/mysql-test/r/function_defaults.result
new file mode 100644
index 00000000000..27b9ee0a323
--- /dev/null
+++ b/mysql-test/r/function_defaults.result
@@ -0,0 +1,3067 @@
+#
+# Test of function defaults for any server, including embedded.
+#
+#
+# Function defaults run 1. No microsecond precision.
+#
+SET TIME_ZONE = "+00:00";
+#
+# Test of errors for column data types that dont support function
+# defaults.
+#
+CREATE TABLE t1( a BIT DEFAULT CURRENT_TIMESTAMP );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a TINYINT DEFAULT CURRENT_TIMESTAMP );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a SMALLINT DEFAULT CURRENT_TIMESTAMP );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a MEDIUMINT DEFAULT CURRENT_TIMESTAMP );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a INT DEFAULT CURRENT_TIMESTAMP );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a BIGINT DEFAULT CURRENT_TIMESTAMP );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a FLOAT DEFAULT CURRENT_TIMESTAMP );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a DECIMAL DEFAULT CURRENT_TIMESTAMP );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a DATE DEFAULT CURRENT_TIMESTAMP );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a TIME DEFAULT CURRENT_TIMESTAMP );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a YEAR DEFAULT CURRENT_TIMESTAMP );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a BIT ON UPDATE CURRENT_TIMESTAMP );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a TINYINT ON UPDATE CURRENT_TIMESTAMP );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a SMALLINT ON UPDATE CURRENT_TIMESTAMP );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a MEDIUMINT ON UPDATE CURRENT_TIMESTAMP );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a INT ON UPDATE CURRENT_TIMESTAMP );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a BIGINT ON UPDATE CURRENT_TIMESTAMP );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a FLOAT ON UPDATE CURRENT_TIMESTAMP );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a DECIMAL ON UPDATE CURRENT_TIMESTAMP );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a DATE ON UPDATE CURRENT_TIMESTAMP );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a TIME ON UPDATE CURRENT_TIMESTAMP );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a YEAR ON UPDATE CURRENT_TIMESTAMP );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+#
+# Test that the default clause behaves like NOW() regarding time zones.
+#
+CREATE TABLE t1 (
+a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+c TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+d TIMESTAMP NULL,
+e DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+f DATETIME DEFAULT CURRENT_TIMESTAMP,
+g DATETIME ON UPDATE CURRENT_TIMESTAMP,
+h DATETIME
+);
+# 2011-09-27 14:11:08 UTC
+SET TIMESTAMP = 1317132668.654321;
+SET @old_time_zone = @@TIME_ZONE;
+SET TIME_ZONE = "+05:00";
+INSERT INTO t1( d, h ) VALUES ( NOW(), NOW() );
+SELECT * FROM t1;
+a b c d e f g h
+2011-09-27 19:11:08 2011-09-27 19:11:08 0000-00-00 00:00:00 2011-09-27 19:11:08 2011-09-27 19:11:08 2011-09-27 19:11:08 NULL 2011-09-27 19:11:08
+# 1989-05-13 01:02:03
+SET TIMESTAMP = 611017323.543212;
+UPDATE t1 SET d = NOW(), h = NOW();
+SELECT * FROM t1;
+a b c d e f g h
+1989-05-13 04:02:03 2011-09-27 19:11:08 1989-05-13 04:02:03 1989-05-13 04:02:03 1989-05-13 04:02:03 2011-09-27 19:11:08 1989-05-13 04:02:03 1989-05-13 04:02:03
+SET TIME_ZONE = @old_time_zone;
+DROP TABLE t1;
+#
+# Test of several TIMESTAMP columns with different function defaults.
+#
+CREATE TABLE t1 (
+a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+c TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+d TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+e TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+f INT
+);
+# 2011-04-19 07:22:02 UTC
+SET TIMESTAMP = 1303197722.534231;
+INSERT INTO t1 ( f ) VALUES (1);
+SELECT * FROM t1;
+a b c d e f
+2011-04-19 07:22:02 2011-04-19 07:22:02 2011-04-19 07:22:02 0000-00-00 00:00:00 0000-00-00 00:00:00 1
+# 2011-04-19 07:23:18 UTC
+SET TIMESTAMP = 1303197798.132435;
+UPDATE t1 SET f = 2;
+SELECT * FROM t1;
+a b c d e f
+2011-04-19 07:23:18 2011-04-19 07:23:18 2011-04-19 07:22:02 2011-04-19 07:23:18 2011-04-19 07:23:18 2
+DROP TABLE t1;
+#
+# Test of inserted values out of order.
+#
+CREATE TABLE t1 (
+a INT,
+b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+c TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+d TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+e TIMESTAMP NULL,
+f DATETIME,
+g DATETIME DEFAULT CURRENT_TIMESTAMP,
+h DATETIME ON UPDATE CURRENT_TIMESTAMP,
+i DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+j INT
+);
+# 2011-04-19 07:22:02 UTC
+SET TIMESTAMP = 1303197722.534231;
+INSERT INTO t1 ( j, a ) VALUES ( 1, 1 );
+SELECT * FROM t1;
+a b c d e f g h i j
+1 2011-04-19 07:22:02 2011-04-19 07:22:02 0000-00-00 00:00:00 NULL NULL 2011-04-19 07:22:02 NULL 2011-04-19 07:22:02 1
+DROP TABLE t1;
+#
+# Test of ON DUPLICATE KEY UPDATE
+#
+CREATE TABLE t1 (
+a INT PRIMARY KEY,
+b INT,
+c TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+d TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+e TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+f TIMESTAMP NOT NULL DEFAULT '1986-09-27 03:00:00.098765',
+g TIMESTAMP NULL,
+h DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+i DATETIME DEFAULT CURRENT_TIMESTAMP,
+j DATETIME ON UPDATE CURRENT_TIMESTAMP,
+k DATETIME NULL,
+l DATETIME DEFAULT '1986-09-27 03:00:00.098765'
+);
+# 1977-12-21 23:00:00 UTC
+SET TIMESTAMP = 251593200.192837;
+INSERT INTO t1(a) VALUES (1) ON DUPLICATE KEY UPDATE b = 2;
+SELECT * FROM t1;
+a b c d e f g h i j k l
+1 NULL 1977-12-21 23:00:00 1977-12-21 23:00:00 0000-00-00 00:00:00 1986-09-27 03:00:00 NULL 1977-12-21 23:00:00 1977-12-21 23:00:00 NULL NULL 1986-09-27 03:00:00
+# 1975-05-21 23:00:00 UTC
+SET TIMESTAMP = 169945200.918273;
+INSERT INTO t1(a) VALUES (1) ON DUPLICATE KEY UPDATE b = 2;
+SELECT * FROM t1;
+a b c d e f g h i j k l
+1 2 1975-05-21 23:00:00 1977-12-21 23:00:00 1975-05-21 23:00:00 1986-09-27 03:00:00 NULL 1975-05-21 23:00:00 1977-12-21 23:00:00 1975-05-21 23:00:00 NULL 1986-09-27 03:00:00
+# 1973-08-14 09:11:22 UTC
+SET TIMESTAMP = 114167482.534231;
+INSERT INTO t1(a) VALUES (2) ON DUPLICATE KEY UPDATE b = 2;
+SELECT * FROM t1;
+a b c d e f g h i j k l
+1 2 1975-05-21 23:00:00 1977-12-21 23:00:00 1975-05-21 23:00:00 1986-09-27 03:00:00 NULL 1975-05-21 23:00:00 1977-12-21 23:00:00 1975-05-21 23:00:00 NULL 1986-09-27 03:00:00
+2 NULL 1973-08-14 09:11:22 1973-08-14 09:11:22 0000-00-00 00:00:00 1986-09-27 03:00:00 NULL 1973-08-14 09:11:22 1973-08-14 09:11:22 NULL NULL 1986-09-27 03:00:00
+DROP TABLE t1;
+CREATE TABLE t1 ( a INT PRIMARY KEY, b INT, c TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );
+# 2011-04-19 07:23:18 UTC
+SET TIMESTAMP = 1303197798.945156;
+INSERT INTO t1 VALUES
+(1, 0, '2001-01-01 01:01:01.111111'),
+(2, 0, '2002-02-02 02:02:02.222222'),
+(3, 0, '2003-03-03 03:03:03.333333');
+SELECT * FROM t1;
+a b c
+1 0 2001-01-01 01:01:01
+2 0 2002-02-02 02:02:02
+3 0 2003-03-03 03:03:03
+UPDATE t1 SET b = 2, c = c WHERE a = 2;
+SELECT * FROM t1;
+a b c
+1 0 2001-01-01 01:01:01
+2 2 2002-02-02 02:02:02
+3 0 2003-03-03 03:03:03
+INSERT INTO t1 (a) VALUES (4);
+SELECT * FROM t1;
+a b c
+1 0 2001-01-01 01:01:01
+2 2 2002-02-02 02:02:02
+3 0 2003-03-03 03:03:03
+4 NULL 2011-04-19 07:23:18
+UPDATE t1 SET c = '2004-04-04 04:04:04.444444' WHERE a = 4;
+SELECT * FROM t1;
+a b c
+1 0 2001-01-01 01:01:01
+2 2 2002-02-02 02:02:02
+3 0 2003-03-03 03:03:03
+4 NULL 2004-04-04 04:04:04
+INSERT INTO t1 ( a ) VALUES ( 3 ), ( 5 ) ON DUPLICATE KEY UPDATE b = 3, c = c;
+SELECT * FROM t1;
+a b c
+1 0 2001-01-01 01:01:01
+2 2 2002-02-02 02:02:02
+3 3 2003-03-03 03:03:03
+4 NULL 2004-04-04 04:04:04
+5 NULL 2011-04-19 07:23:18
+INSERT INTO t1 (a, c) VALUES
+(4, '2004-04-04 00:00:00.444444'),
+(6, '2006-06-06 06:06:06.666666')
+ON DUPLICATE KEY UPDATE b = 4;
+SELECT * FROM t1;
+a b c
+1 0 2001-01-01 01:01:01
+2 2 2002-02-02 02:02:02
+3 3 2003-03-03 03:03:03
+4 4 2011-04-19 07:23:18
+5 NULL 2011-04-19 07:23:18
+6 NULL 2006-06-06 06:06:06
+DROP TABLE t1;
+#
+# Test of REPLACE INTO executed as UPDATE.
+#
+CREATE TABLE t1 (
+a INT PRIMARY KEY,
+b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+c DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+d TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+e DATETIME DEFAULT CURRENT_TIMESTAMP,
+f TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+g DATETIME ON UPDATE CURRENT_TIMESTAMP,
+h TIMESTAMP NULL,
+i DATETIME
+);
+# 1970-09-21 09:11:12 UTC
+SET TIMESTAMP = 22756272.163584;
+REPLACE INTO t1 ( a ) VALUES ( 1 );
+SELECT * FROM t1;
+a b c d e f g h i
+1 1970-09-21 09:11:12 1970-09-21 09:11:12 1970-09-21 09:11:12 1970-09-21 09:11:12 0000-00-00 00:00:00 NULL NULL NULL
+# 1970-11-10 14:16:17 UTC
+SET TIMESTAMP = 27094577.852954;
+REPLACE INTO t1 ( a ) VALUES ( 1 );
+SELECT * FROM t1;
+a b c d e f g h i
+1 1970-11-10 14:16:17 1970-11-10 14:16:17 1970-11-10 14:16:17 1970-11-10 14:16:17 0000-00-00 00:00:00 NULL NULL NULL
+DROP TABLE t1;
+#
+# Test of insertion of NULL, DEFAULT and an empty row for DEFAULT
+# CURRENT_TIMESTAMP.
+#
+CREATE TABLE t1 (
+a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+b DATETIME DEFAULT CURRENT_TIMESTAMP,
+c INT
+);
+# 2011-04-20 09:53:41 UTC
+SET TIMESTAMP = 1303293221.163578;
+INSERT INTO t1 VALUES (NULL, NULL, 1), (DEFAULT, DEFAULT, 2);
+INSERT INTO t1 ( a, b, c ) VALUES (NULL, NULL, 3), (DEFAULT, DEFAULT, 4);
+SELECT * FROM t1;
+a b c
+2011-04-20 09:53:41 NULL 1
+2011-04-20 09:53:41 2011-04-20 09:53:41 2
+2011-04-20 09:53:41 NULL 3
+2011-04-20 09:53:41 2011-04-20 09:53:41 4
+SET TIME_ZONE = "+03:00";
+SELECT * FROM t1;
+a b c
+2011-04-20 12:53:41 NULL 1
+2011-04-20 12:53:41 2011-04-20 09:53:41 2
+2011-04-20 12:53:41 NULL 3
+2011-04-20 12:53:41 2011-04-20 09:53:41 4
+SET TIME_ZONE = "+00:00";
+DROP TABLE t1;
+# 2011-04-20 07:05:39 UTC
+SET TIMESTAMP = 1303283139.195624;
+CREATE TABLE t1 (
+a TIMESTAMP NOT NULL DEFAULT '2010-10-11 12:34:56' ON UPDATE CURRENT_TIMESTAMP,
+b DATETIME DEFAULT '2010-10-11 12:34:56'
+);
+INSERT INTO t1 VALUES (NULL, NULL), (DEFAULT, DEFAULT);
+INSERT INTO t1 ( a, b ) VALUES (NULL, NULL), (DEFAULT, DEFAULT);
+SELECT * FROM t1;
+a b
+2011-04-20 07:05:39 NULL
+2010-10-11 12:34:56 2010-10-11 12:34:56
+2011-04-20 07:05:39 NULL
+2010-10-11 12:34:56 2010-10-11 12:34:56
+DROP TABLE t1;
+# 2011-04-20 09:53:41 UTC
+SET TIMESTAMP = 1303293221.136952;
+CREATE TABLE t1 (
+a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+c TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+d TIMESTAMP NOT NULL DEFAULT '1986-09-27 03:00:00.098765',
+e TIMESTAMP NULL,
+f DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+g DATETIME DEFAULT CURRENT_TIMESTAMP,
+h DATETIME ON UPDATE CURRENT_TIMESTAMP,
+i DATETIME NULL,
+j DATETIME DEFAULT '1986-09-27 03:00:00.098765'
+);
+INSERT INTO t1 VALUES ();
+INSERT INTO t1 SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL;
+SELECT * FROM t1;
+a b c d e f g h i j
+2011-04-20 09:53:41 2011-04-20 09:53:41 0000-00-00 00:00:00 1986-09-27 03:00:00 NULL 2011-04-20 09:53:41 2011-04-20 09:53:41 NULL NULL 1986-09-27 03:00:00
+2011-04-20 09:53:41 2011-04-20 09:53:41 2011-04-20 09:53:41 2011-04-20 09:53:41 NULL NULL NULL NULL NULL NULL
+DROP TABLE t1;
+#
+# Test of multiple-table UPDATE for DEFAULT CURRENT_TIMESTAMP
+#
+CREATE TABLE t1 (
+a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+b DATETIME DEFAULT CURRENT_TIMESTAMP,
+c INT
+);
+INSERT INTO t1 ( c ) VALUES (1);
+SELECT * FROM t1;
+a b c
+2011-04-20 09:53:41 2011-04-20 09:53:41 1
+# 2011-04-20 17:06:13 UTC
+SET TIMESTAMP = 1303311973.163587;
+UPDATE t1 t11, t1 t12 SET t11.c = 1;
+SELECT * FROM t1;
+a b c
+2011-04-20 09:53:41 2011-04-20 09:53:41 1
+UPDATE t1 t11, t1 t12 SET t11.c = 2;
+SELECT * FROM t1;
+a b c
+2011-04-20 15:06:13 2011-04-20 09:53:41 2
+DROP TABLE t1;
+CREATE TABLE t1 (
+a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+b TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+c DATETIME DEFAULT CURRENT_TIMESTAMP,
+d DATETIME ON UPDATE CURRENT_TIMESTAMP,
+e INT
+);
+CREATE TABLE t2 (
+f INT,
+g DATETIME ON UPDATE CURRENT_TIMESTAMP,
+h DATETIME DEFAULT CURRENT_TIMESTAMP,
+i TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+j TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+# 1995-03-11 00:02:03 UTC
+SET TIMESTAMP = 794880123.195676;
+INSERT INTO t1 ( e ) VALUES ( 1 ), ( 2 );
+INSERT INTO t2 ( f ) VALUES ( 1 ), ( 2 );
+SELECT * FROM t1;
+a b c d e
+1995-03-11 00:02:03 0000-00-00 00:00:00 1995-03-11 00:02:03 NULL 1
+1995-03-11 00:02:03 0000-00-00 00:00:00 1995-03-11 00:02:03 NULL 2
+SELECT * FROM t2;
+f g h i j
+1 NULL 1995-03-11 00:02:03 0000-00-00 00:00:00 1995-03-11 00:02:03
+2 NULL 1995-03-11 00:02:03 0000-00-00 00:00:00 1995-03-11 00:02:03
+# 1980-12-13 02:02:01 UTC
+SET TIMESTAMP = 345520921.196755;
+UPDATE t1, t2 SET t1.e = 3, t2.f = 4;
+SELECT * FROM t1;
+a b c d e
+1995-03-11 00:02:03 1980-12-13 02:02:01 1995-03-11 00:02:03 1980-12-13 02:02:01 3
+1995-03-11 00:02:03 1980-12-13 02:02:01 1995-03-11 00:02:03 1980-12-13 02:02:01 3
+SELECT * FROM t2;
+f g h i j
+4 1980-12-13 02:02:01 1995-03-11 00:02:03 1980-12-13 02:02:01 1995-03-11 00:02:03
+4 1980-12-13 02:02:01 1995-03-11 00:02:03 1980-12-13 02:02:01 1995-03-11 00:02:03
+DROP TABLE t1, t2;
+#
+# Test of multiple table update with temporary table and on the fly.
+#
+CREATE TABLE t1 (
+a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+b DATETIME ON UPDATE CURRENT_TIMESTAMP,
+c INT,
+d INT
+);
+CREATE TABLE t2 (
+a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+b DATETIME ON UPDATE CURRENT_TIMESTAMP,
+c INT KEY,
+d INT
+);
+INSERT INTO t1 ( c ) VALUES (1), (2);
+INSERT INTO t2 ( c ) VALUES (1), (2);
+# Test of multiple table update done on the fly
+# 2011-04-20 15:06:13 UTC
+SET TIMESTAMP = 1303311973.194685;
+UPDATE t1 JOIN t2 USING ( c ) SET t2.d = 1;
+SELECT * FROM t1;
+a b c d
+0000-00-00 00:00:00 NULL 1 NULL
+0000-00-00 00:00:00 NULL 2 NULL
+SELECT * FROM t2;
+a b c d
+2011-04-20 15:06:13 2011-04-20 15:06:13 1 1
+2011-04-20 15:06:13 2011-04-20 15:06:13 2 1
+# Test of multiple table update done with temporary table.
+# 1979-01-15 03:02:01
+SET TIMESTAMP = 285213721.134679;
+UPDATE t1 JOIN t2 USING ( c ) SET t1.d = 1;
+SELECT * FROM t1;
+a b c d
+1979-01-15 02:02:01 1979-01-15 02:02:01 1 1
+1979-01-15 02:02:01 1979-01-15 02:02:01 2 1
+SELECT * FROM t2;
+a b c d
+2011-04-20 15:06:13 2011-04-20 15:06:13 1 1
+2011-04-20 15:06:13 2011-04-20 15:06:13 2 1
+DROP TABLE t1, t2;
+#
+# Test of ON UPDATE CURRENT_TIMESTAMP.
+#
+CREATE TABLE t1 (
+a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+b DATETIME ON UPDATE CURRENT_TIMESTAMP,
+c INT
+);
+# 2011-04-20 09:53:41 UTC
+SET TIMESTAMP = 1303293221.794613;
+INSERT INTO t1 ( c ) VALUES ( 1 );
+SELECT * FROM t1;
+a b c
+0000-00-00 00:00:00 NULL 1
+UPDATE t1 SET c = 1;
+SELECT * FROM t1;
+a b c
+0000-00-00 00:00:00 NULL 1
+UPDATE t1 SET c = 2;
+SELECT * FROM t1;
+a b c
+2011-04-20 09:53:41 2011-04-20 09:53:41 2
+#
+# Test of multiple-table UPDATE for ON UPDATE CURRENT_TIMESTAMP
+#
+# 2011-04-20 15:06:13 UTC
+SET TIMESTAMP = 1303311973.534231;
+UPDATE t1 t11, t1 t12 SET t11.c = 2;
+SELECT * FROM t1;
+a b c
+2011-04-20 09:53:41 2011-04-20 09:53:41 2
+UPDATE t1 t11, t1 t12 SET t11.c = 3;
+SELECT * FROM t1;
+a b c
+2011-04-20 15:06:13 2011-04-20 15:06:13 3
+DROP TABLE t1;
+#
+# Test of a multiple-table update where only one table is updated and
+# the updated table has a primary key.
+#
+CREATE TABLE t1 ( a INT, b INT, PRIMARY KEY (a) );
+INSERT INTO t1 VALUES (1, 1),(2, 2),(3, 3),(4, 4);
+CREATE TABLE t2 ( a INT, b INT );
+INSERT INTO t2 VALUES (1, 1),(2, 2),(3, 3),(4, 4),(5, 5);
+UPDATE t1, t2 SET t1.b = 100 WHERE t1.a = t2.a;
+SELECT * FROM t1;
+a b
+1 100
+2 100
+3 100
+4 100
+SELECT * FROM t2;
+a b
+1 1
+2 2
+3 3
+4 4
+5 5
+DROP TABLE t1, t2;
+#
+# Test of ALTER TABLE, reordering columns.
+#
+CREATE TABLE t1 ( a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, b INT );
+ALTER TABLE t1 MODIFY a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP AFTER b;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 ( a INT, b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, c TIMESTAMP NULL );
+ALTER TABLE t1 MODIFY b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP FIRST;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `a` int(11) DEFAULT NULL,
+ `c` timestamp NULL DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 ( a INT, b TIMESTAMP NULL );
+ALTER TABLE t1 MODIFY b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP FIRST;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 ( a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, b TIMESTAMP NULL );
+ALTER TABLE t1 MODIFY a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER b;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` timestamp NULL DEFAULT NULL,
+ `a` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 ( a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, b TIMESTAMP NULL );
+ALTER TABLE t1 MODIFY a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER b;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` timestamp NULL DEFAULT NULL,
+ `a` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 ( a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE NOW(), b INT, c TIMESTAMP NULL );
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+ `b` int(11) DEFAULT NULL,
+ `c` timestamp NULL DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+ALTER TABLE t1 MODIFY a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP AFTER b;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `c` timestamp NULL DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 ( a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE NOW(), b INT, c TIMESTAMP NULL );
+ALTER TABLE t1 MODIFY c TIMESTAMP NULL FIRST;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c` timestamp NULL DEFAULT NULL,
+ `a` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+ `b` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 ( a TIMESTAMP NOT NULL DEFAULT NOW() ON UPDATE CURRENT_TIMESTAMP, b INT, c TIMESTAMP NULL );
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `b` int(11) DEFAULT NULL,
+ `c` timestamp NULL DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+ALTER TABLE t1 MODIFY a TIMESTAMP NOT NULL DEFAULT NOW() ON UPDATE CURRENT_TIMESTAMP AFTER b;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `c` timestamp NULL DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 ( a TIMESTAMP NOT NULL DEFAULT NOW() ON UPDATE CURRENT_TIMESTAMP, b INT, c TIMESTAMP NULL );
+ALTER TABLE t1 MODIFY c TIMESTAMP NULL FIRST;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c` timestamp NULL DEFAULT NULL,
+ `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `b` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+#
+# Test of ALTER TABLE, adding columns.
+#
+CREATE TABLE t1 ( a INT );
+ALTER TABLE t1 ADD COLUMN b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+#
+# Test of INSERT SELECT.
+#
+CREATE TABLE t1 (
+a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+c DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+d DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
+);
+CREATE TABLE t2 (
+placeholder1 INT,
+placeholder2 INT,
+placeholder3 INT,
+placeholder4 INT,
+a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+b TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
+c DATETIME,
+d DATETIME
+);
+# 1977-08-16 15:30:01 UTC
+SET TIMESTAMP = 240589801.654312;
+INSERT INTO t2 (a, b, c, d) VALUES (
+'1977-08-16 15:30:01.123456',
+'1977-08-16 15:30:01.234567',
+'1977-08-16 15:30:01.345678',
+'1977-08-16 15:30:01.456789'
+);
+# 1986-09-27 01:00:00 UTC
+SET TIMESTAMP = 528166800.132435;
+INSERT INTO t1 ( a, c ) SELECT a, c FROM t2;
+SELECT * FROM t1;
+a b c d
+1977-08-16 15:30:01 1986-09-27 01:00:00 1977-08-16 15:30:01 1986-09-27 01:00:00
+DROP TABLE t1, t2;
+#
+# Test of CREATE TABLE SELECT.
+#
+# We test that the columns of the source table are not used to determine
+# function defaults for the receiving table.
+#
+# 1970-04-11 20:13:57 UTC
+SET TIMESTAMP = 8712837.657898;
+CREATE TABLE t1 (
+a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+c TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+d TIMESTAMP NOT NULL DEFAULT '1986-09-27 03:00:00.098765',
+e TIMESTAMP NULL,
+f DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+g DATETIME DEFAULT CURRENT_TIMESTAMP,
+h DATETIME ON UPDATE CURRENT_TIMESTAMP,
+i DATETIME NULL,
+j DATETIME DEFAULT '1986-09-27 03:00:00.098765'
+);
+INSERT INTO t1 VALUES ();
+# 1971-01-31 21:13:57 UTC
+SET TIMESTAMP = 34200837.164937;
+CREATE TABLE t2 SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t2;
+a
+1970-04-11 20:13:57
+CREATE TABLE t3 SELECT b FROM t1;
+SHOW CREATE TABLE t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `b` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t3;
+b
+1970-04-11 20:13:57
+CREATE TABLE t4 SELECT c FROM t1;
+SHOW CREATE TABLE t4;
+Table Create Table
+t4 CREATE TABLE `t4` (
+ `c` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t4;
+c
+0000-00-00 00:00:00
+CREATE TABLE t5 SELECT d FROM t1;
+SHOW CREATE TABLE t5;
+Table Create Table
+t5 CREATE TABLE `t5` (
+ `d` timestamp NOT NULL DEFAULT '1986-09-27 03:00:00'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t5;
+d
+1986-09-27 03:00:00
+CREATE TABLE t6 SELECT e FROM t1;
+SHOW CREATE TABLE t6;
+Table Create Table
+t6 CREATE TABLE `t6` (
+ `e` timestamp NULL DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t6;
+e
+NULL
+CREATE TABLE t7 SELECT f FROM t1;
+SHOW CREATE TABLE t7;
+Table Create Table
+t7 CREATE TABLE `t7` (
+ `f` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t7;
+f
+1970-04-11 20:13:57
+CREATE TABLE t8 SELECT g FROM t1;
+SHOW CREATE TABLE t8;
+Table Create Table
+t8 CREATE TABLE `t8` (
+ `g` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t8;
+g
+1970-04-11 20:13:57
+CREATE TABLE t9 SELECT h FROM t1;
+SHOW CREATE TABLE t9;
+Table Create Table
+t9 CREATE TABLE `t9` (
+ `h` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t9;
+h
+NULL
+CREATE TABLE t10 SELECT i FROM t1;
+SHOW CREATE TABLE t10;
+Table Create Table
+t10 CREATE TABLE `t10` (
+ `i` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t10;
+i
+NULL
+CREATE TABLE t11 SELECT j FROM t1;
+SHOW CREATE TABLE t11;
+Table Create Table
+t11 CREATE TABLE `t11` (
+ `j` datetime DEFAULT '1986-09-27 03:00:00'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t11;
+j
+1986-09-27 03:00:00
+CREATE TABLE t12 (
+k TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+l TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+m TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+n TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+o TIMESTAMP NOT NULL DEFAULT '1986-09-27 03:00:00.098765',
+p TIMESTAMP NULL,
+q DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+r DATETIME DEFAULT CURRENT_TIMESTAMP,
+s DATETIME ON UPDATE CURRENT_TIMESTAMP,
+t DATETIME NULL,
+u DATETIME DEFAULT '1986-09-27 03:00:00.098765'
+)
+SELECT * FROM t1;
+SHOW CREATE TABLE t12;
+Table Create Table
+t12 CREATE TABLE `t12` (
+ `k` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `l` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `m` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `n` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+ `o` timestamp NOT NULL DEFAULT '1986-09-27 03:00:00',
+ `p` timestamp NULL DEFAULT NULL,
+ `q` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `r` datetime DEFAULT CURRENT_TIMESTAMP,
+ `s` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+ `t` datetime DEFAULT NULL,
+ `u` datetime DEFAULT '1986-09-27 03:00:00',
+ `a` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `b` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `c` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `d` timestamp NOT NULL DEFAULT '1986-09-27 03:00:00',
+ `e` timestamp NULL DEFAULT NULL,
+ `f` datetime DEFAULT NULL,
+ `g` datetime DEFAULT NULL,
+ `h` datetime DEFAULT NULL,
+ `i` datetime DEFAULT NULL,
+ `j` datetime DEFAULT '1986-09-27 03:00:00'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12;
+# 1970-04-11 20:13:57 UTC
+SET TIMESTAMP = 8712837.164953;
+CREATE TABLE t1 (
+a DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+b DATETIME DEFAULT CURRENT_TIMESTAMP,
+c DATETIME ON UPDATE CURRENT_TIMESTAMP,
+d DATETIME NULL,
+e DATETIME DEFAULT '1986-09-27 03:00:00.098765'
+);
+INSERT INTO t1 VALUES ();
+# 1971-01-31 20:13:57 UTC
+SET TIMESTAMP = 34200837.915736;
+CREATE TABLE t2 SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t2;
+a
+1970-04-11 20:13:57
+CREATE TABLE t3 SELECT b FROM t1;
+SHOW CREATE TABLE t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `b` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t3;
+b
+1970-04-11 20:13:57
+CREATE TABLE t4 SELECT c FROM t1;
+SHOW CREATE TABLE t4;
+Table Create Table
+t4 CREATE TABLE `t4` (
+ `c` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t4;
+c
+NULL
+CREATE TABLE t5 SELECT d FROM t1;
+SHOW CREATE TABLE t5;
+Table Create Table
+t5 CREATE TABLE `t5` (
+ `d` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t5;
+d
+NULL
+CREATE TABLE t6 SELECT e FROM t1;
+SHOW CREATE TABLE t6;
+Table Create Table
+t6 CREATE TABLE `t6` (
+ `e` datetime DEFAULT '1986-09-27 03:00:00'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t6;
+e
+1986-09-27 03:00:00
+DROP TABLE t1, t2, t3, t4, t5, t6;
+#
+# Test of a CREATE TABLE SELECT that also declared columns. In this case
+# the function default should be de-activated during the execution of the
+# CREATE TABLE statement.
+#
+# 1970-01-01 03:16:40
+SET TIMESTAMP = 1000.987654;
+CREATE TABLE t1 ( a INT );
+INSERT INTO t1 VALUES ( 1 ), ( 2 );
+CREATE TABLE t2 ( b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP) SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SET TIMESTAMP = 2000.876543;
+INSERT INTO t2( a ) VALUES ( 3 );
+SELECT * FROM t2;
+b a
+0000-00-00 00:00:00 1
+0000-00-00 00:00:00 2
+1970-01-01 00:33:20 3
+DROP TABLE t1, t2;
+#
+# Test of updating a view.
+#
+CREATE TABLE t1 ( a INT, b DATETIME DEFAULT CURRENT_TIMESTAMP );
+CREATE TABLE t2 ( a INT, b DATETIME ON UPDATE CURRENT_TIMESTAMP );
+CREATE VIEW v1 AS SELECT * FROM t1;
+SHOW CREATE VIEW v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` latin1 latin1_swedish_ci
+CREATE VIEW v2 AS SELECT * FROM t2;
+SHOW CREATE VIEW v2;
+View Create View character_set_client collation_connection
+v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t2`.`a` AS `a`,`t2`.`b` AS `b` from `t2` latin1 latin1_swedish_ci
+# 1971-01-31 21:13:57 UTC
+SET TIMESTAMP = 34200837.348564;
+INSERT INTO v1 ( a ) VALUES ( 1 );
+INSERT INTO v2 ( a ) VALUES ( 1 );
+SELECT * FROM t1;
+a b
+1 1971-01-31 20:13:57
+SELECT * FROM v1;
+a b
+1 1971-01-31 20:13:57
+SELECT * FROM t2;
+a b
+1 NULL
+SELECT * FROM v2;
+a b
+1 NULL
+# 1970-04-11 20:13:57 UTC
+SET TIMESTAMP = 8712837.567332;
+UPDATE v1 SET a = 2;
+UPDATE v2 SET a = 2;
+SELECT * FROM t1;
+a b
+2 1971-01-31 20:13:57
+SELECT * FROM v1;
+a b
+2 1971-01-31 20:13:57
+SELECT * FROM t2;
+a b
+2 1970-04-11 20:13:57
+SELECT * FROM v2;
+a b
+2 1970-04-11 20:13:57
+DROP VIEW v1, v2;
+DROP TABLE t1, t2;
+#
+# Test with stored procedures.
+#
+CREATE TABLE t1 (
+a INT,
+b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+c TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+d TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+e TIMESTAMP NULL,
+f DATETIME DEFAULT CURRENT_TIMESTAMP,
+g DATETIME ON UPDATE CURRENT_TIMESTAMP
+);
+CREATE PROCEDURE p1() INSERT INTO test.t1( a ) VALUES ( 1 );
+CREATE PROCEDURE p2() UPDATE t1 SET a = 2 WHERE a = 1;
+# 1971-01-31 20:13:57 UTC
+SET TIMESTAMP = 34200837.876544;
+CALL p1();
+SELECT * FROM t1;
+a b c d e f g
+1 1971-01-31 20:13:57 1971-01-31 20:13:57 0000-00-00 00:00:00 NULL 1971-01-31 20:13:57 NULL
+# 1970-04-11 21:13:57 UTC
+SET TIMESTAMP = 8712837.143546;
+CALL p2();
+SELECT * FROM t1;
+a b c d e f g
+2 1970-04-11 20:13:57 1971-01-31 20:13:57 1970-04-11 20:13:57 NULL 1971-01-31 20:13:57 1970-04-11 20:13:57
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+DROP TABLE t1;
+#
+# Test with triggers.
+#
+CREATE TABLE t1 (
+a INT,
+b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+c TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+d TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+e TIMESTAMP NULL,
+f DATETIME,
+g DATETIME DEFAULT CURRENT_TIMESTAMP,
+h DATETIME ON UPDATE CURRENT_TIMESTAMP,
+i DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
+);
+CREATE TABLE t2 ( a INT );
+CREATE TRIGGER t2_trg BEFORE INSERT ON t2 FOR EACH ROW
+BEGIN
+INSERT INTO t1 ( a ) VALUES ( 1 );
+END|
+# 1971-01-31 21:13:57 UTC
+SET TIMESTAMP = 34200837.978675;
+INSERT INTO t2 ( a ) VALUES ( 1 );
+SELECT * FROM t1;
+a b c d e f g h i
+1 1971-01-31 20:13:57 1971-01-31 20:13:57 0000-00-00 00:00:00 NULL NULL 1971-01-31 20:13:57 NULL 1971-01-31 20:13:57
+DROP TRIGGER t2_trg;
+CREATE TRIGGER t2_trg BEFORE INSERT ON t2 FOR EACH ROW
+BEGIN
+UPDATE t1 SET a = 2;
+END|
+# 1970-04-11 21:13:57 UTC
+SET TIMESTAMP = 8712837.456789;
+INSERT INTO t2 ( a ) VALUES ( 1 );
+SELECT * FROM t1;
+a b c d e f g h i
+2 1970-04-11 20:13:57 1971-01-31 20:13:57 1970-04-11 20:13:57 NULL NULL 1971-01-31 20:13:57 1970-04-11 20:13:57 1970-04-11 20:13:57
+DROP TABLE t1, t2;
+#
+# Test where the assignment target is not a column.
+#
+CREATE TABLE t1 ( a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );
+CREATE TABLE t2 ( a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );
+CREATE TABLE t3 ( a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP );
+CREATE TABLE t4 ( a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP );
+CREATE VIEW v1 AS SELECT a COLLATE latin1_german1_ci AS b FROM t1;
+CREATE VIEW v2 ( b ) AS SELECT a COLLATE latin1_german1_ci FROM t2;
+CREATE VIEW v3 AS SELECT a COLLATE latin1_german1_ci AS b FROM t3;
+CREATE VIEW v4 ( b ) AS SELECT a COLLATE latin1_german1_ci FROM t4;
+INSERT INTO v1 ( b ) VALUES ( '2007-10-24 00:03:34.010203' );
+SELECT a FROM t1;
+a
+2007-10-24 00:03:34
+INSERT INTO v2 ( b ) VALUES ( '2007-10-24 00:03:34.010203' );
+SELECT a FROM t2;
+a
+2007-10-24 00:03:34
+INSERT INTO t3 VALUES ();
+UPDATE v3 SET b = '2007-10-24 00:03:34.010203';
+SELECT a FROM t3;
+a
+2007-10-24 00:03:34
+INSERT INTO t4 VALUES ();
+UPDATE v4 SET b = '2007-10-24 00:03:34.010203';
+SELECT a FROM t4;
+a
+2007-10-24 00:03:34
+DROP VIEW v1, v2, v3, v4;
+DROP TABLE t1, t2, t3, t4;
+#
+# Test of LOAD DATA/XML INFILE
+# This tests behavior of function defaults for TIMESTAMP and DATETIME
+# columns. during LOAD ... INFILE.
+# As can be seen here, a TIMESTAMP column with only ON UPDATE
+# CURRENT_TIMESTAMP will still have CURRENT_TIMESTAMP inserted on LOAD
+# ... INFILE if the value is missing. For DATETIME columns a NULL value
+# is inserted instead.
+#
+CREATE TABLE t1 (
+a INT,
+b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+c TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+d TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+e TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+f DATETIME,
+g DATETIME DEFAULT CURRENT_TIMESTAMP,
+h DATETIME ON UPDATE CURRENT_TIMESTAMP,
+i DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
+);
+CREATE TABLE t2 (
+a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+c TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+d TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+e DATETIME NOT NULL,
+f DATETIME NOT NULL DEFAULT '1977-01-02 12:13:14',
+g DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
+h DATETIME ON UPDATE CURRENT_TIMESTAMP NOT NULL,
+i DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL
+);
+SELECT 1 INTO OUTFILE 't3.dat' FROM dual;
+SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+INTO OUTFILE 't4.dat'
+FROM dual;
+SELECT 1, 2 INTO OUTFILE 't5.dat' FROM dual;
+# Mon Aug 1 15:11:19 2011 UTC
+SET TIMESTAMP = 1312211479.918273;
+LOAD DATA INFILE 't3.dat' INTO TABLE t1;
+Warnings:
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+SELECT * FROM t1;
+a 1
+b 2011-08-01 15:11:19
+c 2011-08-01 15:11:19
+d 2011-08-01 15:11:19
+e 2011-08-01 15:11:19
+f NULL
+g NULL
+h NULL
+i NULL
+LOAD DATA INFILE 't4.dat' INTO TABLE t2;
+Warnings:
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'e' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'f' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'g' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'h' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'i' at row 1
+SELECT a FROM t2;
+a
+2011-08-01 15:11:19
+SELECT b FROM t2;
+b
+2011-08-01 15:11:19
+SELECT c FROM t2;
+c
+2011-08-01 15:11:19
+SELECT d FROM t2;
+d
+2011-08-01 15:11:19
+# As shown here, supplying a NULL value to a non-nullable
+# column with no default value results in the zero date.
+SELECT e FROM t2;
+e
+0000-00-00 00:00:00
+# As shown here, supplying a NULL value to a non-nullable column with a
+# default value results in the zero date.
+SELECT f FROM t2;
+f
+0000-00-00 00:00:00
+# As shown here, supplying a NULL value to a non-nullable column with a
+# default function results in the zero date.
+SELECT g FROM t2;
+g
+0000-00-00 00:00:00
+# As shown here, supplying a NULL value to a non-nullable DATETIME ON
+# UPDATE CURRENT_TIMESTAMP column with no default value results in the
+# zero date.
+SELECT h FROM t2;
+h
+0000-00-00 00:00:00
+SELECT i FROM t2;
+i
+0000-00-00 00:00:00
+DELETE FROM t1;
+DELETE FROM t2;
+# Read t3 file into t1
+# The syntax will cause a different code path to be taken
+# (read_fixed_length()) than under the LOAD ... INTO TABLE t1 command
+# above. The code in this path is copy-pasted code from the path taken
+# under the syntax used in the previous LOAD command.
+LOAD DATA INFILE 't3.dat' INTO TABLE t1
+FIELDS TERMINATED BY '' ENCLOSED BY '';
+Warnings:
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+SELECT b FROM t1;
+b
+2011-08-01 15:11:19
+SELECT c FROM t1;
+c
+2011-08-01 15:11:19
+SELECT d FROM t1;
+d
+2011-08-01 15:11:19
+SELECT e FROM t1;
+e
+2011-08-01 15:11:19
+# Yes, a missing field cannot be NULL using this syntax, so it will
+# zero date instead. Says a comment in read_fixed_length() : "No fields
+# specified in fields_vars list can be NULL in this format."
+# It appears to be by design. This is inconsistent with LOAD DATA INFILE
+# syntax in previous test.
+SELECT f FROM t1;
+f
+0000-00-00 00:00:00
+SELECT g FROM t1;
+g
+0000-00-00 00:00:00
+# See comment above "SELECT f FROM f1".
+SELECT h FROM t1;
+h
+0000-00-00 00:00:00
+SELECT i FROM t1;
+i
+0000-00-00 00:00:00
+DELETE FROM t1;
+LOAD DATA INFILE 't5.dat' INTO TABLE t1 ( a, @dummy );
+SELECT * FROM t1;
+a b c d e f g h i
+1 2011-08-01 15:11:19 2011-08-01 15:11:19 0000-00-00 00:00:00 2011-08-01 15:11:19 NULL 2011-08-01 15:11:19 NULL 2011-08-01 15:11:19
+SELECT @dummy;
+@dummy
+2
+DELETE FROM t1;
+LOAD DATA INFILE 't3.dat' INTO TABLE t1 ( a ) SET c = '2005-06-06 08:09:10';
+SELECT * FROM t1;
+a b c d e f g h i
+1 2011-08-01 15:11:19 2005-06-06 08:09:10 0000-00-00 00:00:00 2011-08-01 15:11:19 NULL 2011-08-01 15:11:19 NULL 2011-08-01 15:11:19
+DELETE FROM t1;
+LOAD DATA INFILE 't3.dat' INTO TABLE t1 ( a ) SET g = '2005-06-06 08:09:10';
+SELECT * FROM t1;
+a b c d e f g h i
+1 2011-08-01 15:11:19 2011-08-01 15:11:19 0000-00-00 00:00:00 2011-08-01 15:11:19 NULL 2005-06-06 08:09:10 NULL 2011-08-01 15:11:19
+DELETE FROM t1;
+# Load a static XML file
+LOAD XML INFILE '../../std_data/onerow.xml' INTO TABLE t1
+ROWS IDENTIFIED BY '<row>';
+Missing tags are treated as NULL
+SELECT * FROM t1;
+a 1
+b 2011-08-01 15:11:19
+c 2011-08-01 15:11:19
+d 2011-08-01 15:11:19
+e 2011-08-01 15:11:19
+f NULL
+g NULL
+h NULL
+i NULL
+DROP TABLE t1, t2;
+#
+# Similar LOAD DATA tests in another form
+#
+# All of this test portion has been run on a pre-WL5874 trunk
+# (except that like_b and like_c didn't exist) and all result
+# differences are a bug.
+# Regarding like_b its definition is the same as b's except
+# that the constant default is replaced with a function
+# default. Our expectation is that like_b would behave
+# like b: if b is set to NULL, or set to 0000-00-00, or set to
+# its default, then the same should apply to like_b. Same for
+# like_c vs c.
+# Mon Aug 1 15:11:19 2011 UTC
+SET TIMESTAMP = 1312211479.089786;
+SELECT 1 INTO OUTFILE "file1.dat" FROM dual;
+SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+INTO OUTFILE "file2.dat" FROM dual;
+# Too short row
+CREATE TABLE t1 (
+dummy INT,
+a DATETIME NULL DEFAULT NULL,
+b DATETIME NULL DEFAULT "2011-11-18",
+like_b DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
+c DATETIME NOT NULL DEFAULT "2011-11-18",
+like_c DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+d TIMESTAMP NULL DEFAULT "2011-05-03" ON UPDATE CURRENT_TIMESTAMP,
+e TIMESTAMP NOT NULL DEFAULT "2011-05-03",
+f TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+g TIMESTAMP NULL DEFAULT NULL,
+h INT NULL,
+i INT NOT NULL DEFAULT 42
+);
+# There is no promotion
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `dummy` int(11) DEFAULT NULL,
+ `a` datetime DEFAULT NULL,
+ `b` datetime DEFAULT '2011-11-18 00:00:00',
+ `like_b` datetime DEFAULT CURRENT_TIMESTAMP,
+ `c` datetime NOT NULL DEFAULT '2011-11-18 00:00:00',
+ `like_c` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `d` timestamp NULL DEFAULT '2011-05-03 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+ `e` timestamp NOT NULL DEFAULT '2011-05-03 00:00:00',
+ `f` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `g` timestamp NULL DEFAULT NULL,
+ `h` int(11) DEFAULT NULL,
+ `i` int(11) NOT NULL DEFAULT '42'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+LOAD DATA INFILE "file1.dat" INTO table t1;
+Warnings:
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+# It is strange that "like_b" gets NULL when "b" gets 0. But
+# this is consistent with how "a" gets NULL when "b" gets 0,
+# with how "g" gets NULL when "d" gets 0, and with how "h" gets
+# NULL when "i" gets 0. Looks like "DEFAULT
+# <non-NULL-constant>" is changed to 0, whereas DEFAULT NULL
+# and DEFAULT NOW are changed to NULL.
+SELECT * FROM t1;
+dummy 1
+a NULL
+b 0000-00-00 00:00:00
+like_b NULL
+c 0000-00-00 00:00:00
+like_c 0000-00-00 00:00:00
+d 0000-00-00 00:00:00
+e 2011-08-01 15:11:19
+f 2011-08-01 15:11:19
+g NULL
+h NULL
+i 0
+delete from t1;
+alter table t1
+modify f TIMESTAMP NULL default CURRENT_TIMESTAMP;
+# There is no promotion
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `dummy` int(11) DEFAULT NULL,
+ `a` datetime DEFAULT NULL,
+ `b` datetime DEFAULT '2011-11-18 00:00:00',
+ `like_b` datetime DEFAULT CURRENT_TIMESTAMP,
+ `c` datetime NOT NULL DEFAULT '2011-11-18 00:00:00',
+ `like_c` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `d` timestamp NULL DEFAULT '2011-05-03 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+ `e` timestamp NOT NULL DEFAULT '2011-05-03 00:00:00',
+ `f` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
+ `g` timestamp NULL DEFAULT NULL,
+ `h` int(11) DEFAULT NULL,
+ `i` int(11) NOT NULL DEFAULT '42'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+LOAD DATA INFILE "file1.dat" INTO table t1;
+Warnings:
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+SELECT * FROM t1;
+dummy 1
+a NULL
+b 0000-00-00 00:00:00
+like_b NULL
+c 0000-00-00 00:00:00
+like_c 0000-00-00 00:00:00
+d 0000-00-00 00:00:00
+e 2011-08-01 15:11:19
+f NULL
+g NULL
+h NULL
+i 0
+delete from t1;
+drop table t1;
+# Conclusion derived from trunk's results:
+# DATETIME DEFAULT <non-NULL-constant> (b,c) gets 0000-00-00,
+# DATETIME DEFAULT NULL (a) gets NULL,
+# TIMESTAMP NULL DEFAULT <non-NULL-constant> (d) gets 0000-00-00,
+# TIMESTAMP NULL DEFAULT NULL (g) gets NULL,
+# TIMESTAMP NULL DEFAULT NOW (f after ALTER) gets NULL,
+# TIMESTAMP NOT NULL (f before ALTER, e) gets NOW.
+### Loading NULL ###
+CREATE TABLE t1 (
+dummy INT,
+a DATETIME NULL DEFAULT NULL,
+b DATETIME NULL DEFAULT "2011-11-18",
+like_b DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
+c DATETIME NOT NULL DEFAULT "2011-11-18",
+like_c DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+d TIMESTAMP NULL DEFAULT "2011-05-03" ON UPDATE CURRENT_TIMESTAMP,
+e TIMESTAMP NOT NULL DEFAULT "2011-05-03",
+f TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+g TIMESTAMP NULL DEFAULT NULL,
+h INT NULL,
+i INT NOT NULL DEFAULT 42
+);
+# There is no promotion
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `dummy` int(11) DEFAULT NULL,
+ `a` datetime DEFAULT NULL,
+ `b` datetime DEFAULT '2011-11-18 00:00:00',
+ `like_b` datetime DEFAULT CURRENT_TIMESTAMP,
+ `c` datetime NOT NULL DEFAULT '2011-11-18 00:00:00',
+ `like_c` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `d` timestamp NULL DEFAULT '2011-05-03 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+ `e` timestamp NOT NULL DEFAULT '2011-05-03 00:00:00',
+ `f` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `g` timestamp NULL DEFAULT NULL,
+ `h` int(11) DEFAULT NULL,
+ `i` int(11) NOT NULL DEFAULT '42'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+LOAD DATA INFILE "file2.dat" INTO table t1;
+Warnings:
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'c' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'like_c' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'i' at row 1
+SELECT * FROM t1;
+dummy NULL
+a NULL
+b NULL
+like_b NULL
+c 0000-00-00 00:00:00
+like_c 0000-00-00 00:00:00
+d NULL
+e 2011-08-01 15:11:19
+f 2011-08-01 15:11:19
+g NULL
+h NULL
+i 0
+delete from t1;
+alter table t1
+modify f TIMESTAMP NULL default CURRENT_TIMESTAMP;
+# There is no promotion
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `dummy` int(11) DEFAULT NULL,
+ `a` datetime DEFAULT NULL,
+ `b` datetime DEFAULT '2011-11-18 00:00:00',
+ `like_b` datetime DEFAULT CURRENT_TIMESTAMP,
+ `c` datetime NOT NULL DEFAULT '2011-11-18 00:00:00',
+ `like_c` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `d` timestamp NULL DEFAULT '2011-05-03 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+ `e` timestamp NOT NULL DEFAULT '2011-05-03 00:00:00',
+ `f` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
+ `g` timestamp NULL DEFAULT NULL,
+ `h` int(11) DEFAULT NULL,
+ `i` int(11) NOT NULL DEFAULT '42'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+LOAD DATA INFILE "file2.dat" INTO table t1;
+Warnings:
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'c' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'like_c' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'i' at row 1
+SELECT * FROM t1;
+dummy NULL
+a NULL
+b NULL
+like_b NULL
+c 0000-00-00 00:00:00
+like_c 0000-00-00 00:00:00
+d NULL
+e 2011-08-01 15:11:19
+f NULL
+g NULL
+h NULL
+i 0
+delete from t1;
+# Conclusion derived from trunk's results:
+# DATETIME NULL (a,b) gets NULL,
+# DATETIME NOT NULL (c) gets 0000-00-00,
+# TIMESTAMP NULL (d,f,g) gets NULL,
+# TIMESTAMP NOT NULL (e) gets NOW.
+drop table t1;
+#
+# Test of updatable views with check options. The option can be violated
+# using ON UPDATE updates which is very strange as this offers a loophole
+# in this integrity check.
+#
+SET TIME_ZONE = "+03:00";
+# 1970-01-01 03:16:40
+SET TIMESTAMP = 1000.123456;
+CREATE TABLE t1 ( a INT, b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP) ENGINE = INNODB;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+INSERT INTO t1 ( a ) VALUES ( 1 );
+SELECT * FROM t1;
+a b
+1 1970-01-01 03:16:40
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE b <= '1970-01-01 03:16:40.123456'
+WITH CHECK OPTION;
+SELECT * FROM v1;
+a b
+1 1970-01-01 03:16:40
+# 1970-01-01 03:33:20
+SET TIMESTAMP = 2000.000234;
+UPDATE v1 SET a = 2;
+ERROR HY000: CHECK OPTION failed 'test.v1'
+SELECT * FROM t1;
+a b
+1 1970-01-01 03:16:40
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (
+a TIMESTAMP NOT NULL DEFAULT '1973-08-14 09:11:22.089786' ON UPDATE CURRENT_TIMESTAMP,
+c INT KEY
+);
+# 1973-08-14 09:11:22 UTC
+SET TIMESTAMP = 114167482.534231;
+INSERT INTO t1 ( c ) VALUES ( 1 );
+CREATE VIEW v1 AS
+SELECT *
+FROM t1
+WHERE a >= '1973-08-14 09:11:22'
+WITH LOCAL CHECK OPTION;
+SELECT * FROM v1;
+a c
+1973-08-14 09:11:22 1
+SET TIMESTAMP = 1.126789;
+INSERT INTO v1 ( c ) VALUES ( 1 ) ON DUPLICATE KEY UPDATE c = 2;
+ERROR HY000: CHECK OPTION failed 'test.v1'
+SELECT * FROM v1;
+a c
+1973-08-14 09:11:22 1
+DROP VIEW v1;
+DROP TABLE t1;
+#
+# Bug 13095459 - MULTI-TABLE UPDATE MODIFIES A ROW TWICE
+#
+CREATE TABLE t1 (
+a INT,
+b INT,
+ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+PRIMARY KEY ( a, ts )
+) ENGINE = INNODB;
+INSERT INTO t1( a, b, ts ) VALUES ( 1, 0, '2000-09-28 17:44:34' );
+CREATE TABLE t2 ( a INT ) ENGINE = INNODB;
+INSERT INTO t2 VALUES ( 1 );
+UPDATE t1 STRAIGHT_JOIN t2
+SET t1.b = t1.b + 1
+WHERE t1.a = 1 AND t1.ts >= '2000-09-28 00:00:00';
+SELECT b FROM t1;
+b
+1
+DROP TABLE t1, t2;
+#
+# Bug#11745578: 17392: ALTER TABLE ADD COLUMN TIMESTAMP DEFAULT
+# CURRENT_TIMESTAMP INSERTS ZERO
+#
+SET timestamp = 1000;
+CREATE TABLE t1 ( b INT );
+INSERT INTO t1 VALUES (1);
+ALTER TABLE t1 ADD COLUMN a6 DATETIME DEFAULT NOW() ON UPDATE NOW() FIRST;
+ALTER TABLE t1 ADD COLUMN a5 DATETIME DEFAULT NOW() FIRST;
+ALTER TABLE t1 ADD COLUMN a4 DATETIME ON UPDATE NOW() FIRST;
+ALTER TABLE t1 ADD COLUMN a3 TIMESTAMP NOT NULL DEFAULT NOW() ON UPDATE NOW() FIRST;
+ALTER TABLE t1 ADD COLUMN a2 TIMESTAMP NOT NULL DEFAULT NOW() FIRST;
+ALTER TABLE t1 ADD COLUMN a1 TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE NOW() FIRST;
+ALTER TABLE t1 ADD COLUMN c1 TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE NOW() AFTER b;
+ALTER TABLE t1 ADD COLUMN c2 TIMESTAMP NOT NULL DEFAULT NOW() AFTER c1;
+ALTER TABLE t1 ADD COLUMN c3 TIMESTAMP NOT NULL DEFAULT NOW() ON UPDATE NOW() AFTER c2;
+ALTER TABLE t1 ADD COLUMN c4 DATETIME ON UPDATE NOW() AFTER c3;
+ALTER TABLE t1 ADD COLUMN c5 DATETIME DEFAULT NOW() AFTER c4;
+ALTER TABLE t1 ADD COLUMN c6 DATETIME DEFAULT NOW() ON UPDATE NOW() AFTER c5;
+SELECT * FROM t1;
+a1 a2 a3 a4 a5 a6 b c1 c2 c3 c4 c5 c6
+0000-00-00 00:00:00 1970-01-01 03:16:40 1970-01-01 03:16:40 NULL 1970-01-01 03:16:40 1970-01-01 03:16:40 1 0000-00-00 00:00:00 1970-01-01 03:16:40 1970-01-01 03:16:40 NULL 1970-01-01 03:16:40 1970-01-01 03:16:40
+DROP TABLE t1;
+CREATE TABLE t1 ( a TIMESTAMP NOT NULL DEFAULT NOW() ON UPDATE CURRENT_TIMESTAMP, b DATETIME DEFAULT NOW() );
+INSERT INTO t1 VALUES ();
+SET timestamp = 1000000000;
+ALTER TABLE t1 MODIFY COLUMN a TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3);
+ALTER TABLE t1 MODIFY COLUMN b DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3);
+SELECT * FROM t1;
+a b
+1970-01-01 03:16:40.000 1970-01-01 03:16:40.000
+DROP TABLE t1;
+CREATE TABLE t1 (
+a TIMESTAMP NOT NULL DEFAULT '1999-12-01 11:22:33' ON UPDATE CURRENT_TIMESTAMP,
+b DATETIME DEFAULT '1999-12-01 11:22:33'
+);
+INSERT INTO t1 VALUES ();
+ALTER TABLE t1 MODIFY COLUMN a TIMESTAMP DEFAULT NOW();
+ALTER TABLE t1 MODIFY COLUMN b DATETIME DEFAULT NOW();
+INSERT INTO t1 VALUES ();
+SELECT * FROM t1;
+a b
+1999-12-01 11:22:33 1999-12-01 11:22:33
+2001-09-09 04:46:40 2001-09-09 04:46:40
+DROP TABLE t1;
+#
+# Function defaults run 2. Six digits scale on seconds precision.
+#
+SET TIME_ZONE = "+00:00";
+#
+# Test of errors for column data types that dont support function
+# defaults.
+#
+CREATE TABLE t1( a BIT DEFAULT CURRENT_TIMESTAMP(6) );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a TINYINT DEFAULT CURRENT_TIMESTAMP(6) );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a SMALLINT DEFAULT CURRENT_TIMESTAMP(6) );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a MEDIUMINT DEFAULT CURRENT_TIMESTAMP(6) );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a INT DEFAULT CURRENT_TIMESTAMP(6) );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a BIGINT DEFAULT CURRENT_TIMESTAMP(6) );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a FLOAT DEFAULT CURRENT_TIMESTAMP(6) );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a DECIMAL DEFAULT CURRENT_TIMESTAMP(6) );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a DATE DEFAULT CURRENT_TIMESTAMP(6) );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a TIME DEFAULT CURRENT_TIMESTAMP(6) );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a YEAR DEFAULT CURRENT_TIMESTAMP(6) );
+ERROR 42000: Invalid default value for 'a'
+CREATE TABLE t1( a BIT ON UPDATE CURRENT_TIMESTAMP(6) );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a TINYINT ON UPDATE CURRENT_TIMESTAMP(6) );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a SMALLINT ON UPDATE CURRENT_TIMESTAMP(6) );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a MEDIUMINT ON UPDATE CURRENT_TIMESTAMP(6) );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a INT ON UPDATE CURRENT_TIMESTAMP(6) );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a BIGINT ON UPDATE CURRENT_TIMESTAMP(6) );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a FLOAT ON UPDATE CURRENT_TIMESTAMP(6) );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a DECIMAL ON UPDATE CURRENT_TIMESTAMP(6) );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a DATE ON UPDATE CURRENT_TIMESTAMP(6) );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a TIME ON UPDATE CURRENT_TIMESTAMP(6) );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+CREATE TABLE t1( a YEAR ON UPDATE CURRENT_TIMESTAMP(6) );
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+#
+# Test that the default clause behaves like NOW() regarding time zones.
+#
+CREATE TABLE t1 (
+a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+c TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+d TIMESTAMP(6) NULL,
+e DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+f DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
+g DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
+h DATETIME(6)
+);
+# 2011-09-27 14:11:08 UTC
+SET TIMESTAMP = 1317132668.654321;
+SET @old_time_zone = @@TIME_ZONE;
+SET TIME_ZONE = "+05:00";
+INSERT INTO t1( d, h ) VALUES ( NOW(6), NOW(6) );
+SELECT * FROM t1;
+a b c d e f g h
+2011-09-27 19:11:08.654321 2011-09-27 19:11:08.654321 0000-00-00 00:00:00.000000 2011-09-27 19:11:08.654321 2011-09-27 19:11:08.654321 2011-09-27 19:11:08.654321 NULL 2011-09-27 19:11:08.654321
+# 1989-05-13 01:02:03
+SET TIMESTAMP = 611017323.543212;
+UPDATE t1 SET d = NOW(6), h = NOW(6);
+SELECT * FROM t1;
+a b c d e f g h
+1989-05-13 04:02:03.543212 2011-09-27 19:11:08.654321 1989-05-13 04:02:03.543212 1989-05-13 04:02:03.543212 1989-05-13 04:02:03.543212 2011-09-27 19:11:08.654321 1989-05-13 04:02:03.543212 1989-05-13 04:02:03.543212
+SET TIME_ZONE = @old_time_zone;
+DROP TABLE t1;
+#
+# Test of several TIMESTAMP columns with different function defaults.
+#
+CREATE TABLE t1 (
+a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+c TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+d TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+e TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+f INT
+);
+# 2011-04-19 07:22:02 UTC
+SET TIMESTAMP = 1303197722.534231;
+INSERT INTO t1 ( f ) VALUES (1);
+SELECT * FROM t1;
+a b c d e f
+2011-04-19 07:22:02.534231 2011-04-19 07:22:02.534231 2011-04-19 07:22:02.534231 0000-00-00 00:00:00.000000 0000-00-00 00:00:00.000000 1
+# 2011-04-19 07:23:18 UTC
+SET TIMESTAMP = 1303197798.132435;
+UPDATE t1 SET f = 2;
+SELECT * FROM t1;
+a b c d e f
+2011-04-19 07:23:18.132435 2011-04-19 07:23:18.132435 2011-04-19 07:22:02.534231 2011-04-19 07:23:18.132435 2011-04-19 07:23:18.132435 2
+DROP TABLE t1;
+#
+# Test of inserted values out of order.
+#
+CREATE TABLE t1 (
+a INT,
+b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+c TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+d TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+e TIMESTAMP(6) NULL,
+f DATETIME(6),
+g DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
+h DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
+i DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+j INT
+);
+# 2011-04-19 07:22:02 UTC
+SET TIMESTAMP = 1303197722.534231;
+INSERT INTO t1 ( j, a ) VALUES ( 1, 1 );
+SELECT * FROM t1;
+a b c d e f g h i j
+1 2011-04-19 07:22:02.534231 2011-04-19 07:22:02.534231 0000-00-00 00:00:00.000000 NULL NULL 2011-04-19 07:22:02.534231 NULL 2011-04-19 07:22:02.534231 1
+DROP TABLE t1;
+#
+# Test of ON DUPLICATE KEY UPDATE
+#
+CREATE TABLE t1 (
+a INT PRIMARY KEY,
+b INT,
+c TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+d TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+e TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+f TIMESTAMP(6) NOT NULL DEFAULT '1986-09-27 03:00:00.098765',
+g TIMESTAMP(6) NULL,
+h DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+i DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
+j DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
+k DATETIME(6) NULL,
+l DATETIME(6) DEFAULT '1986-09-27 03:00:00.098765'
+);
+# 1977-12-21 23:00:00 UTC
+SET TIMESTAMP = 251593200.192837;
+INSERT INTO t1(a) VALUES (1) ON DUPLICATE KEY UPDATE b = 2;
+SELECT * FROM t1;
+a b c d e f g h i j k l
+1 NULL 1977-12-21 23:00:00.192837 1977-12-21 23:00:00.192837 0000-00-00 00:00:00.000000 1986-09-27 03:00:00.098765 NULL 1977-12-21 23:00:00.192837 1977-12-21 23:00:00.192837 NULL NULL 1986-09-27 03:00:00.098765
+# 1975-05-21 23:00:00 UTC
+SET TIMESTAMP = 169945200.918273;
+INSERT INTO t1(a) VALUES (1) ON DUPLICATE KEY UPDATE b = 2;
+SELECT * FROM t1;
+a b c d e f g h i j k l
+1 2 1975-05-21 23:00:00.918273 1977-12-21 23:00:00.192837 1975-05-21 23:00:00.918273 1986-09-27 03:00:00.098765 NULL 1975-05-21 23:00:00.918273 1977-12-21 23:00:00.192837 1975-05-21 23:00:00.918273 NULL 1986-09-27 03:00:00.098765
+# 1973-08-14 09:11:22 UTC
+SET TIMESTAMP = 114167482.534231;
+INSERT INTO t1(a) VALUES (2) ON DUPLICATE KEY UPDATE b = 2;
+SELECT * FROM t1;
+a b c d e f g h i j k l
+1 2 1975-05-21 23:00:00.918273 1977-12-21 23:00:00.192837 1975-05-21 23:00:00.918273 1986-09-27 03:00:00.098765 NULL 1975-05-21 23:00:00.918273 1977-12-21 23:00:00.192837 1975-05-21 23:00:00.918273 NULL 1986-09-27 03:00:00.098765
+2 NULL 1973-08-14 09:11:22.534231 1973-08-14 09:11:22.534231 0000-00-00 00:00:00.000000 1986-09-27 03:00:00.098765 NULL 1973-08-14 09:11:22.534231 1973-08-14 09:11:22.534231 NULL NULL 1986-09-27 03:00:00.098765
+DROP TABLE t1;
+CREATE TABLE t1 ( a INT PRIMARY KEY, b INT, c TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) );
+# 2011-04-19 07:23:18 UTC
+SET TIMESTAMP = 1303197798.945156;
+INSERT INTO t1 VALUES
+(1, 0, '2001-01-01 01:01:01.111111'),
+(2, 0, '2002-02-02 02:02:02.222222'),
+(3, 0, '2003-03-03 03:03:03.333333');
+SELECT * FROM t1;
+a b c
+1 0 2001-01-01 01:01:01.111111
+2 0 2002-02-02 02:02:02.222222
+3 0 2003-03-03 03:03:03.333333
+UPDATE t1 SET b = 2, c = c WHERE a = 2;
+SELECT * FROM t1;
+a b c
+1 0 2001-01-01 01:01:01.111111
+2 2 2002-02-02 02:02:02.222222
+3 0 2003-03-03 03:03:03.333333
+INSERT INTO t1 (a) VALUES (4);
+SELECT * FROM t1;
+a b c
+1 0 2001-01-01 01:01:01.111111
+2 2 2002-02-02 02:02:02.222222
+3 0 2003-03-03 03:03:03.333333
+4 NULL 2011-04-19 07:23:18.945156
+UPDATE t1 SET c = '2004-04-04 04:04:04.444444' WHERE a = 4;
+SELECT * FROM t1;
+a b c
+1 0 2001-01-01 01:01:01.111111
+2 2 2002-02-02 02:02:02.222222
+3 0 2003-03-03 03:03:03.333333
+4 NULL 2004-04-04 04:04:04.444444
+INSERT INTO t1 ( a ) VALUES ( 3 ), ( 5 ) ON DUPLICATE KEY UPDATE b = 3, c = c;
+SELECT * FROM t1;
+a b c
+1 0 2001-01-01 01:01:01.111111
+2 2 2002-02-02 02:02:02.222222
+3 3 2003-03-03 03:03:03.333333
+4 NULL 2004-04-04 04:04:04.444444
+5 NULL 2011-04-19 07:23:18.945156
+INSERT INTO t1 (a, c) VALUES
+(4, '2004-04-04 00:00:00.444444'),
+(6, '2006-06-06 06:06:06.666666')
+ON DUPLICATE KEY UPDATE b = 4;
+SELECT * FROM t1;
+a b c
+1 0 2001-01-01 01:01:01.111111
+2 2 2002-02-02 02:02:02.222222
+3 3 2003-03-03 03:03:03.333333
+4 4 2011-04-19 07:23:18.945156
+5 NULL 2011-04-19 07:23:18.945156
+6 NULL 2006-06-06 06:06:06.666666
+DROP TABLE t1;
+#
+# Test of REPLACE INTO executed as UPDATE.
+#
+CREATE TABLE t1 (
+a INT PRIMARY KEY,
+b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+c DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+d TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+e DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
+f TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+g DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
+h TIMESTAMP(6) NULL,
+i DATETIME(6)
+);
+# 1970-09-21 09:11:12 UTC
+SET TIMESTAMP = 22756272.163584;
+REPLACE INTO t1 ( a ) VALUES ( 1 );
+SELECT * FROM t1;
+a b c d e f g h i
+1 1970-09-21 09:11:12.163584 1970-09-21 09:11:12.163584 1970-09-21 09:11:12.163584 1970-09-21 09:11:12.163584 0000-00-00 00:00:00.000000 NULL NULL NULL
+# 1970-11-10 14:16:17 UTC
+SET TIMESTAMP = 27094577.852954;
+REPLACE INTO t1 ( a ) VALUES ( 1 );
+SELECT * FROM t1;
+a b c d e f g h i
+1 1970-11-10 14:16:17.852954 1970-11-10 14:16:17.852954 1970-11-10 14:16:17.852954 1970-11-10 14:16:17.852954 0000-00-00 00:00:00.000000 NULL NULL NULL
+DROP TABLE t1;
+#
+# Test of insertion of NULL, DEFAULT and an empty row for DEFAULT
+# CURRENT_TIMESTAMP.
+#
+CREATE TABLE t1 (
+a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+b DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
+c INT
+);
+# 2011-04-20 09:53:41 UTC
+SET TIMESTAMP = 1303293221.163578;
+INSERT INTO t1 VALUES (NULL, NULL, 1), (DEFAULT, DEFAULT, 2);
+INSERT INTO t1 ( a, b, c ) VALUES (NULL, NULL, 3), (DEFAULT, DEFAULT, 4);
+SELECT * FROM t1;
+a b c
+2011-04-20 09:53:41.163578 NULL 1
+2011-04-20 09:53:41.163578 2011-04-20 09:53:41.163578 2
+2011-04-20 09:53:41.163578 NULL 3
+2011-04-20 09:53:41.163578 2011-04-20 09:53:41.163578 4
+SET TIME_ZONE = "+03:00";
+SELECT * FROM t1;
+a b c
+2011-04-20 12:53:41.163578 NULL 1
+2011-04-20 12:53:41.163578 2011-04-20 09:53:41.163578 2
+2011-04-20 12:53:41.163578 NULL 3
+2011-04-20 12:53:41.163578 2011-04-20 09:53:41.163578 4
+SET TIME_ZONE = "+00:00";
+DROP TABLE t1;
+# 2011-04-20 07:05:39 UTC
+SET TIMESTAMP = 1303283139.195624;
+CREATE TABLE t1 (
+a TIMESTAMP(6) NOT NULL DEFAULT '2010-10-11 12:34:56' ON UPDATE CURRENT_TIMESTAMP(6),
+b DATETIME(6) DEFAULT '2010-10-11 12:34:56'
+);
+INSERT INTO t1 VALUES (NULL, NULL), (DEFAULT, DEFAULT);
+INSERT INTO t1 ( a, b ) VALUES (NULL, NULL), (DEFAULT, DEFAULT);
+SELECT * FROM t1;
+a b
+2011-04-20 07:05:39.195624 NULL
+2010-10-11 12:34:56.000000 2010-10-11 12:34:56.000000
+2011-04-20 07:05:39.195624 NULL
+2010-10-11 12:34:56.000000 2010-10-11 12:34:56.000000
+DROP TABLE t1;
+# 2011-04-20 09:53:41 UTC
+SET TIMESTAMP = 1303293221.136952;
+CREATE TABLE t1 (
+a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+c TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+d TIMESTAMP(6) NOT NULL DEFAULT '1986-09-27 03:00:00.098765',
+e TIMESTAMP(6) NULL,
+f DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+g DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
+h DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
+i DATETIME(6) NULL,
+j DATETIME(6) DEFAULT '1986-09-27 03:00:00.098765'
+);
+INSERT INTO t1 VALUES ();
+INSERT INTO t1 SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL;
+SELECT * FROM t1;
+a b c d e f g h i j
+2011-04-20 09:53:41.136952 2011-04-20 09:53:41.136952 0000-00-00 00:00:00.000000 1986-09-27 03:00:00.098765 NULL 2011-04-20 09:53:41.136952 2011-04-20 09:53:41.136952 NULL NULL 1986-09-27 03:00:00.098765
+2011-04-20 09:53:41.136952 2011-04-20 09:53:41.136952 2011-04-20 09:53:41.136952 2011-04-20 09:53:41.136952 NULL NULL NULL NULL NULL NULL
+DROP TABLE t1;
+#
+# Test of multiple-table UPDATE for DEFAULT CURRENT_TIMESTAMP
+#
+CREATE TABLE t1 (
+a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+b DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
+c INT
+);
+INSERT INTO t1 ( c ) VALUES (1);
+SELECT * FROM t1;
+a b c
+2011-04-20 09:53:41.136952 2011-04-20 09:53:41.136952 1
+# 2011-04-20 17:06:13 UTC
+SET TIMESTAMP = 1303311973.163587;
+UPDATE t1 t11, t1 t12 SET t11.c = 1;
+SELECT * FROM t1;
+a b c
+2011-04-20 09:53:41.136952 2011-04-20 09:53:41.136952 1
+UPDATE t1 t11, t1 t12 SET t11.c = 2;
+SELECT * FROM t1;
+a b c
+2011-04-20 15:06:13.163587 2011-04-20 09:53:41.136952 2
+DROP TABLE t1;
+CREATE TABLE t1 (
+a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+b TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+c DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
+d DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
+e INT
+);
+CREATE TABLE t2 (
+f INT,
+g DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
+h DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
+i TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+j TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
+);
+# 1995-03-11 00:02:03 UTC
+SET TIMESTAMP = 794880123.195676;
+INSERT INTO t1 ( e ) VALUES ( 1 ), ( 2 );
+INSERT INTO t2 ( f ) VALUES ( 1 ), ( 2 );
+SELECT * FROM t1;
+a b c d e
+1995-03-11 00:02:03.195676 0000-00-00 00:00:00.000000 1995-03-11 00:02:03.195676 NULL 1
+1995-03-11 00:02:03.195676 0000-00-00 00:00:00.000000 1995-03-11 00:02:03.195676 NULL 2
+SELECT * FROM t2;
+f g h i j
+1 NULL 1995-03-11 00:02:03.195676 0000-00-00 00:00:00.000000 1995-03-11 00:02:03.195676
+2 NULL 1995-03-11 00:02:03.195676 0000-00-00 00:00:00.000000 1995-03-11 00:02:03.195676
+# 1980-12-13 02:02:01 UTC
+SET TIMESTAMP = 345520921.196755;
+UPDATE t1, t2 SET t1.e = 3, t2.f = 4;
+SELECT * FROM t1;
+a b c d e
+1995-03-11 00:02:03.195676 1980-12-13 02:02:01.196755 1995-03-11 00:02:03.195676 1980-12-13 02:02:01.196755 3
+1995-03-11 00:02:03.195676 1980-12-13 02:02:01.196755 1995-03-11 00:02:03.195676 1980-12-13 02:02:01.196755 3
+SELECT * FROM t2;
+f g h i j
+4 1980-12-13 02:02:01.196755 1995-03-11 00:02:03.195676 1980-12-13 02:02:01.196755 1995-03-11 00:02:03.195676
+4 1980-12-13 02:02:01.196755 1995-03-11 00:02:03.195676 1980-12-13 02:02:01.196755 1995-03-11 00:02:03.195676
+DROP TABLE t1, t2;
+#
+# Test of multiple table update with temporary table and on the fly.
+#
+CREATE TABLE t1 (
+a TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+b DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
+c INT,
+d INT
+);
+CREATE TABLE t2 (
+a TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+b DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
+c INT KEY,
+d INT
+);
+INSERT INTO t1 ( c ) VALUES (1), (2);
+INSERT INTO t2 ( c ) VALUES (1), (2);
+# Test of multiple table update done on the fly
+# 2011-04-20 15:06:13 UTC
+SET TIMESTAMP = 1303311973.194685;
+UPDATE t1 JOIN t2 USING ( c ) SET t2.d = 1;
+SELECT * FROM t1;
+a b c d
+0000-00-00 00:00:00.000000 NULL 1 NULL
+0000-00-00 00:00:00.000000 NULL 2 NULL
+SELECT * FROM t2;
+a b c d
+2011-04-20 15:06:13.194685 2011-04-20 15:06:13.194685 1 1
+2011-04-20 15:06:13.194685 2011-04-20 15:06:13.194685 2 1
+# Test of multiple table update done with temporary table.
+# 1979-01-15 03:02:01
+SET TIMESTAMP = 285213721.134679;
+UPDATE t1 JOIN t2 USING ( c ) SET t1.d = 1;
+SELECT * FROM t1;
+a b c d
+1979-01-15 02:02:01.134679 1979-01-15 02:02:01.134679 1 1
+1979-01-15 02:02:01.134679 1979-01-15 02:02:01.134679 2 1
+SELECT * FROM t2;
+a b c d
+2011-04-20 15:06:13.194685 2011-04-20 15:06:13.194685 1 1
+2011-04-20 15:06:13.194685 2011-04-20 15:06:13.194685 2 1
+DROP TABLE t1, t2;
+#
+# Test of ON UPDATE CURRENT_TIMESTAMP.
+#
+CREATE TABLE t1 (
+a TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+b DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
+c INT
+);
+# 2011-04-20 09:53:41 UTC
+SET TIMESTAMP = 1303293221.794613;
+INSERT INTO t1 ( c ) VALUES ( 1 );
+SELECT * FROM t1;
+a b c
+0000-00-00 00:00:00.000000 NULL 1
+UPDATE t1 SET c = 1;
+SELECT * FROM t1;
+a b c
+0000-00-00 00:00:00.000000 NULL 1
+UPDATE t1 SET c = 2;
+SELECT * FROM t1;
+a b c
+2011-04-20 09:53:41.794613 2011-04-20 09:53:41.794613 2
+#
+# Test of multiple-table UPDATE for ON UPDATE CURRENT_TIMESTAMP
+#
+# 2011-04-20 15:06:13 UTC
+SET TIMESTAMP = 1303311973.534231;
+UPDATE t1 t11, t1 t12 SET t11.c = 2;
+SELECT * FROM t1;
+a b c
+2011-04-20 09:53:41.794613 2011-04-20 09:53:41.794613 2
+UPDATE t1 t11, t1 t12 SET t11.c = 3;
+SELECT * FROM t1;
+a b c
+2011-04-20 15:06:13.534231 2011-04-20 15:06:13.534231 3
+DROP TABLE t1;
+#
+# Test of a multiple-table update where only one table is updated and
+# the updated table has a primary key.
+#
+CREATE TABLE t1 ( a INT, b INT, PRIMARY KEY (a) );
+INSERT INTO t1 VALUES (1, 1),(2, 2),(3, 3),(4, 4);
+CREATE TABLE t2 ( a INT, b INT );
+INSERT INTO t2 VALUES (1, 1),(2, 2),(3, 3),(4, 4),(5, 5);
+UPDATE t1, t2 SET t1.b = 100 WHERE t1.a = t2.a;
+SELECT * FROM t1;
+a b
+1 100
+2 100
+3 100
+4 100
+SELECT * FROM t2;
+a b
+1 1
+2 2
+3 3
+4 4
+5 5
+DROP TABLE t1, t2;
+#
+# Test of ALTER TABLE, reordering columns.
+#
+CREATE TABLE t1 ( a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), b INT );
+ALTER TABLE t1 MODIFY a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) AFTER b;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `a` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 ( a INT, b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), c TIMESTAMP(6) NULL );
+ALTER TABLE t1 MODIFY b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) FIRST;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+ `a` int(11) DEFAULT NULL,
+ `c` timestamp(6) NULL DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 ( a INT, b TIMESTAMP(6) NULL );
+ALTER TABLE t1 MODIFY b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) FIRST;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 ( a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), b TIMESTAMP(6) NULL );
+ALTER TABLE t1 MODIFY a TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER b;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` timestamp(6) NULL DEFAULT NULL,
+ `a` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 ( a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), b TIMESTAMP(6) NULL );
+ALTER TABLE t1 MODIFY a TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER b;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` timestamp(6) NULL DEFAULT NULL,
+ `a` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 ( a TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE NOW(6), b INT, c TIMESTAMP(6) NULL );
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000' ON UPDATE CURRENT_TIMESTAMP(6),
+ `b` int(11) DEFAULT NULL,
+ `c` timestamp(6) NULL DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+ALTER TABLE t1 MODIFY a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) AFTER b;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `a` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+ `c` timestamp(6) NULL DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 ( a TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE NOW(6), b INT, c TIMESTAMP(6) NULL );
+ALTER TABLE t1 MODIFY c TIMESTAMP(6) NULL FIRST;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c` timestamp(6) NULL DEFAULT NULL,
+ `a` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000' ON UPDATE CURRENT_TIMESTAMP(6),
+ `b` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 ( a TIMESTAMP(6) NOT NULL DEFAULT NOW(6) ON UPDATE CURRENT_TIMESTAMP(6), b INT, c TIMESTAMP(6) NULL );
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+ `b` int(11) DEFAULT NULL,
+ `c` timestamp(6) NULL DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+ALTER TABLE t1 MODIFY a TIMESTAMP(6) NOT NULL DEFAULT NOW(6) ON UPDATE CURRENT_TIMESTAMP(6) AFTER b;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `a` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+ `c` timestamp(6) NULL DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 ( a TIMESTAMP(6) NOT NULL DEFAULT NOW(6) ON UPDATE CURRENT_TIMESTAMP(6), b INT, c TIMESTAMP(6) NULL );
+ALTER TABLE t1 MODIFY c TIMESTAMP(6) NULL FIRST;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c` timestamp(6) NULL DEFAULT NULL,
+ `a` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+ `b` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+#
+# Test of ALTER TABLE, adding columns.
+#
+CREATE TABLE t1 ( a INT );
+ALTER TABLE t1 ADD COLUMN b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+#
+# Test of INSERT SELECT.
+#
+CREATE TABLE t1 (
+a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+c DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+d DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)
+);
+CREATE TABLE t2 (
+placeholder1 INT,
+placeholder2 INT,
+placeholder3 INT,
+placeholder4 INT,
+a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+b TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00',
+c DATETIME(6),
+d DATETIME(6)
+);
+# 1977-08-16 15:30:01 UTC
+SET TIMESTAMP = 240589801.654312;
+INSERT INTO t2 (a, b, c, d) VALUES (
+'1977-08-16 15:30:01.123456',
+'1977-08-16 15:30:01.234567',
+'1977-08-16 15:30:01.345678',
+'1977-08-16 15:30:01.456789'
+);
+# 1986-09-27 01:00:00 UTC
+SET TIMESTAMP = 528166800.132435;
+INSERT INTO t1 ( a, c ) SELECT a, c FROM t2;
+SELECT * FROM t1;
+a b c d
+1977-08-16 15:30:01.123456 1986-09-27 01:00:00.132435 1977-08-16 15:30:01.345678 1986-09-27 01:00:00.132435
+DROP TABLE t1, t2;
+#
+# Test of CREATE TABLE SELECT.
+#
+# We test that the columns of the source table are not used to determine
+# function defaults for the receiving table.
+#
+# 1970-04-11 20:13:57 UTC
+SET TIMESTAMP = 8712837.657898;
+CREATE TABLE t1 (
+a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+c TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+d TIMESTAMP(6) NOT NULL DEFAULT '1986-09-27 03:00:00.098765',
+e TIMESTAMP(6) NULL,
+f DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+g DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
+h DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
+i DATETIME(6) NULL,
+j DATETIME(6) DEFAULT '1986-09-27 03:00:00.098765'
+);
+INSERT INTO t1 VALUES ();
+# 1971-01-31 21:13:57 UTC
+SET TIMESTAMP = 34200837.164937;
+CREATE TABLE t2 SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t2;
+a
+1970-04-11 20:13:57.657897
+CREATE TABLE t3 SELECT b FROM t1;
+SHOW CREATE TABLE t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `b` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t3;
+b
+1970-04-11 20:13:57.657897
+CREATE TABLE t4 SELECT c FROM t1;
+SHOW CREATE TABLE t4;
+Table Create Table
+t4 CREATE TABLE `t4` (
+ `c` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t4;
+c
+0000-00-00 00:00:00.000000
+CREATE TABLE t5 SELECT d FROM t1;
+SHOW CREATE TABLE t5;
+Table Create Table
+t5 CREATE TABLE `t5` (
+ `d` timestamp(6) NOT NULL DEFAULT '1986-09-27 03:00:00.098765'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t5;
+d
+1986-09-27 03:00:00.098765
+CREATE TABLE t6 SELECT e FROM t1;
+SHOW CREATE TABLE t6;
+Table Create Table
+t6 CREATE TABLE `t6` (
+ `e` timestamp(6) NULL DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t6;
+e
+NULL
+CREATE TABLE t7 SELECT f FROM t1;
+SHOW CREATE TABLE t7;
+Table Create Table
+t7 CREATE TABLE `t7` (
+ `f` datetime(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t7;
+f
+1970-04-11 20:13:57.657897
+CREATE TABLE t8 SELECT g FROM t1;
+SHOW CREATE TABLE t8;
+Table Create Table
+t8 CREATE TABLE `t8` (
+ `g` datetime(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t8;
+g
+1970-04-11 20:13:57.657897
+CREATE TABLE t9 SELECT h FROM t1;
+SHOW CREATE TABLE t9;
+Table Create Table
+t9 CREATE TABLE `t9` (
+ `h` datetime(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t9;
+h
+NULL
+CREATE TABLE t10 SELECT i FROM t1;
+SHOW CREATE TABLE t10;
+Table Create Table
+t10 CREATE TABLE `t10` (
+ `i` datetime(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t10;
+i
+NULL
+CREATE TABLE t11 SELECT j FROM t1;
+SHOW CREATE TABLE t11;
+Table Create Table
+t11 CREATE TABLE `t11` (
+ `j` datetime(6) DEFAULT '1986-09-27 03:00:00.098765'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t11;
+j
+1986-09-27 03:00:00.098765
+CREATE TABLE t12 (
+k TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+l TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+m TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+n TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+o TIMESTAMP(6) NOT NULL DEFAULT '1986-09-27 03:00:00.098765',
+p TIMESTAMP(6) NULL,
+q DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+r DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
+s DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
+t DATETIME(6) NULL,
+u DATETIME(6) DEFAULT '1986-09-27 03:00:00.098765'
+)
+SELECT * FROM t1;
+SHOW CREATE TABLE t12;
+Table Create Table
+t12 CREATE TABLE `t12` (
+ `k` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+ `l` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+ `m` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+ `n` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000' ON UPDATE CURRENT_TIMESTAMP(6),
+ `o` timestamp(6) NOT NULL DEFAULT '1986-09-27 03:00:00.098765',
+ `p` timestamp(6) NULL DEFAULT NULL,
+ `q` datetime(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+ `r` datetime(6) DEFAULT CURRENT_TIMESTAMP(6),
+ `s` datetime(6) DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(6),
+ `t` datetime(6) DEFAULT NULL,
+ `u` datetime(6) DEFAULT '1986-09-27 03:00:00.098765',
+ `a` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000',
+ `b` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000',
+ `c` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000',
+ `d` timestamp(6) NOT NULL DEFAULT '1986-09-27 03:00:00.098765',
+ `e` timestamp(6) NULL DEFAULT NULL,
+ `f` datetime(6) DEFAULT NULL,
+ `g` datetime(6) DEFAULT NULL,
+ `h` datetime(6) DEFAULT NULL,
+ `i` datetime(6) DEFAULT NULL,
+ `j` datetime(6) DEFAULT '1986-09-27 03:00:00.098765'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12;
+# 1970-04-11 20:13:57 UTC
+SET TIMESTAMP = 8712837.164953;
+CREATE TABLE t1 (
+a DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+b DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
+c DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
+d DATETIME(6) NULL,
+e DATETIME(6) DEFAULT '1986-09-27 03:00:00.098765'
+);
+INSERT INTO t1 VALUES ();
+# 1971-01-31 20:13:57 UTC
+SET TIMESTAMP = 34200837.915736;
+CREATE TABLE t2 SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` datetime(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t2;
+a
+1970-04-11 20:13:57.164953
+CREATE TABLE t3 SELECT b FROM t1;
+SHOW CREATE TABLE t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `b` datetime(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t3;
+b
+1970-04-11 20:13:57.164953
+CREATE TABLE t4 SELECT c FROM t1;
+SHOW CREATE TABLE t4;
+Table Create Table
+t4 CREATE TABLE `t4` (
+ `c` datetime(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t4;
+c
+NULL
+CREATE TABLE t5 SELECT d FROM t1;
+SHOW CREATE TABLE t5;
+Table Create Table
+t5 CREATE TABLE `t5` (
+ `d` datetime(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t5;
+d
+NULL
+CREATE TABLE t6 SELECT e FROM t1;
+SHOW CREATE TABLE t6;
+Table Create Table
+t6 CREATE TABLE `t6` (
+ `e` datetime(6) DEFAULT '1986-09-27 03:00:00.098765'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t6;
+e
+1986-09-27 03:00:00.098765
+DROP TABLE t1, t2, t3, t4, t5, t6;
+#
+# Test of a CREATE TABLE SELECT that also declared columns. In this case
+# the function default should be de-activated during the execution of the
+# CREATE TABLE statement.
+#
+# 1970-01-01 03:16:40
+SET TIMESTAMP = 1000.987654;
+CREATE TABLE t1 ( a INT );
+INSERT INTO t1 VALUES ( 1 ), ( 2 );
+CREATE TABLE t2 ( b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)) SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `b` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SET TIMESTAMP = 2000.876543;
+INSERT INTO t2( a ) VALUES ( 3 );
+SELECT * FROM t2;
+b a
+0000-00-00 00:00:00.000000 1
+0000-00-00 00:00:00.000000 2
+1970-01-01 00:33:20.876543 3
+DROP TABLE t1, t2;
+#
+# Test of updating a view.
+#
+CREATE TABLE t1 ( a INT, b DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) );
+CREATE TABLE t2 ( a INT, b DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6) );
+CREATE VIEW v1 AS SELECT * FROM t1;
+SHOW CREATE VIEW v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` latin1 latin1_swedish_ci
+CREATE VIEW v2 AS SELECT * FROM t2;
+SHOW CREATE VIEW v2;
+View Create View character_set_client collation_connection
+v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t2`.`a` AS `a`,`t2`.`b` AS `b` from `t2` latin1 latin1_swedish_ci
+# 1971-01-31 21:13:57 UTC
+SET TIMESTAMP = 34200837.348564;
+INSERT INTO v1 ( a ) VALUES ( 1 );
+INSERT INTO v2 ( a ) VALUES ( 1 );
+SELECT * FROM t1;
+a b
+1 1971-01-31 20:13:57.348564
+SELECT * FROM v1;
+a b
+1 1971-01-31 20:13:57.348564
+SELECT * FROM t2;
+a b
+1 NULL
+SELECT * FROM v2;
+a b
+1 NULL
+# 1970-04-11 20:13:57 UTC
+SET TIMESTAMP = 8712837.567332;
+UPDATE v1 SET a = 2;
+UPDATE v2 SET a = 2;
+SELECT * FROM t1;
+a b
+2 1971-01-31 20:13:57.348564
+SELECT * FROM v1;
+a b
+2 1971-01-31 20:13:57.348564
+SELECT * FROM t2;
+a b
+2 1970-04-11 20:13:57.567332
+SELECT * FROM v2;
+a b
+2 1970-04-11 20:13:57.567332
+DROP VIEW v1, v2;
+DROP TABLE t1, t2;
+#
+# Test with stored procedures.
+#
+CREATE TABLE t1 (
+a INT,
+b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+c TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+d TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+e TIMESTAMP(6) NULL,
+f DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
+g DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6)
+);
+CREATE PROCEDURE p1() INSERT INTO test.t1( a ) VALUES ( 1 );
+CREATE PROCEDURE p2() UPDATE t1 SET a = 2 WHERE a = 1;
+# 1971-01-31 20:13:57 UTC
+SET TIMESTAMP = 34200837.876544;
+CALL p1();
+SELECT * FROM t1;
+a b c d e f g
+1 1971-01-31 20:13:57.876544 1971-01-31 20:13:57.876544 0000-00-00 00:00:00.000000 NULL 1971-01-31 20:13:57.876544 NULL
+# 1970-04-11 21:13:57 UTC
+SET TIMESTAMP = 8712837.143546;
+CALL p2();
+SELECT * FROM t1;
+a b c d e f g
+2 1970-04-11 20:13:57.143546 1971-01-31 20:13:57.876544 1970-04-11 20:13:57.143546 NULL 1971-01-31 20:13:57.876544 1970-04-11 20:13:57.143546
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+DROP TABLE t1;
+#
+# Test with triggers.
+#
+CREATE TABLE t1 (
+a INT,
+b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+c TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+d TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+e TIMESTAMP(6) NULL,
+f DATETIME(6),
+g DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
+h DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
+i DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)
+);
+CREATE TABLE t2 ( a INT );
+CREATE TRIGGER t2_trg BEFORE INSERT ON t2 FOR EACH ROW
+BEGIN
+INSERT INTO t1 ( a ) VALUES ( 1 );
+END|
+# 1971-01-31 21:13:57 UTC
+SET TIMESTAMP = 34200837.978675;
+INSERT INTO t2 ( a ) VALUES ( 1 );
+SELECT * FROM t1;
+a b c d e f g h i
+1 1971-01-31 20:13:57.978675 1971-01-31 20:13:57.978675 0000-00-00 00:00:00.000000 NULL NULL 1971-01-31 20:13:57.978675 NULL 1971-01-31 20:13:57.978675
+DROP TRIGGER t2_trg;
+CREATE TRIGGER t2_trg BEFORE INSERT ON t2 FOR EACH ROW
+BEGIN
+UPDATE t1 SET a = 2;
+END|
+# 1970-04-11 21:13:57 UTC
+SET TIMESTAMP = 8712837.456789;
+INSERT INTO t2 ( a ) VALUES ( 1 );
+SELECT * FROM t1;
+a b c d e f g h i
+2 1970-04-11 20:13:57.456789 1971-01-31 20:13:57.978675 1970-04-11 20:13:57.456789 NULL NULL 1971-01-31 20:13:57.978675 1970-04-11 20:13:57.456789 1970-04-11 20:13:57.456789
+DROP TABLE t1, t2;
+#
+# Test where the assignment target is not a column.
+#
+CREATE TABLE t1 ( a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) );
+CREATE TABLE t2 ( a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) );
+CREATE TABLE t3 ( a TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6) );
+CREATE TABLE t4 ( a TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6) );
+CREATE VIEW v1 AS SELECT a COLLATE latin1_german1_ci AS b FROM t1;
+CREATE VIEW v2 ( b ) AS SELECT a COLLATE latin1_german1_ci FROM t2;
+CREATE VIEW v3 AS SELECT a COLLATE latin1_german1_ci AS b FROM t3;
+CREATE VIEW v4 ( b ) AS SELECT a COLLATE latin1_german1_ci FROM t4;
+INSERT INTO v1 ( b ) VALUES ( '2007-10-24 00:03:34.010203' );
+SELECT a FROM t1;
+a
+2007-10-24 00:03:34.010203
+INSERT INTO v2 ( b ) VALUES ( '2007-10-24 00:03:34.010203' );
+SELECT a FROM t2;
+a
+2007-10-24 00:03:34.010203
+INSERT INTO t3 VALUES ();
+UPDATE v3 SET b = '2007-10-24 00:03:34.010203';
+SELECT a FROM t3;
+a
+2007-10-24 00:03:34.010203
+INSERT INTO t4 VALUES ();
+UPDATE v4 SET b = '2007-10-24 00:03:34.010203';
+SELECT a FROM t4;
+a
+2007-10-24 00:03:34.010203
+DROP VIEW v1, v2, v3, v4;
+DROP TABLE t1, t2, t3, t4;
+#
+# Test of LOAD DATA/XML INFILE
+# This tests behavior of function defaults for TIMESTAMP and DATETIME
+# columns. during LOAD ... INFILE.
+# As can be seen here, a TIMESTAMP column with only ON UPDATE
+# CURRENT_TIMESTAMP will still have CURRENT_TIMESTAMP inserted on LOAD
+# ... INFILE if the value is missing. For DATETIME columns a NULL value
+# is inserted instead.
+#
+CREATE TABLE t1 (
+a INT,
+b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+c TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+d TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+e TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+f DATETIME(6),
+g DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
+h DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
+i DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)
+);
+CREATE TABLE t2 (
+a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+c TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+d TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+e DATETIME(6) NOT NULL,
+f DATETIME(6) NOT NULL DEFAULT '1977-01-02 12:13:14',
+g DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL,
+h DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6) NOT NULL,
+i DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) NOT NULL
+);
+SELECT 1 INTO OUTFILE 't3.dat' FROM dual;
+SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+INTO OUTFILE 't4.dat'
+FROM dual;
+SELECT 1, 2 INTO OUTFILE 't5.dat' FROM dual;
+# Mon Aug 1 15:11:19 2011 UTC
+SET TIMESTAMP = 1312211479.918273;
+LOAD DATA INFILE 't3.dat' INTO TABLE t1;
+Warnings:
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+SELECT * FROM t1;
+a 1
+b 2011-08-01 15:11:19.918273
+c 2011-08-01 15:11:19.918273
+d 2011-08-01 15:11:19.918273
+e 2011-08-01 15:11:19.918273
+f NULL
+g NULL
+h NULL
+i NULL
+LOAD DATA INFILE 't4.dat' INTO TABLE t2;
+Warnings:
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'e' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'f' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'g' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'h' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'i' at row 1
+SELECT a FROM t2;
+a
+2011-08-01 15:11:19.918273
+SELECT b FROM t2;
+b
+2011-08-01 15:11:19.918273
+SELECT c FROM t2;
+c
+2011-08-01 15:11:19.918273
+SELECT d FROM t2;
+d
+2011-08-01 15:11:19.918273
+# As shown here, supplying a NULL value to a non-nullable
+# column with no default value results in the zero date.
+SELECT e FROM t2;
+e
+0000-00-00 00:00:00.000000
+# As shown here, supplying a NULL value to a non-nullable column with a
+# default value results in the zero date.
+SELECT f FROM t2;
+f
+0000-00-00 00:00:00.000000
+# As shown here, supplying a NULL value to a non-nullable column with a
+# default function results in the zero date.
+SELECT g FROM t2;
+g
+0000-00-00 00:00:00.000000
+# As shown here, supplying a NULL value to a non-nullable DATETIME ON
+# UPDATE CURRENT_TIMESTAMP column with no default value results in the
+# zero date.
+SELECT h FROM t2;
+h
+0000-00-00 00:00:00.000000
+SELECT i FROM t2;
+i
+0000-00-00 00:00:00.000000
+DELETE FROM t1;
+DELETE FROM t2;
+# Read t3 file into t1
+# The syntax will cause a different code path to be taken
+# (read_fixed_length()) than under the LOAD ... INTO TABLE t1 command
+# above. The code in this path is copy-pasted code from the path taken
+# under the syntax used in the previous LOAD command.
+LOAD DATA INFILE 't3.dat' INTO TABLE t1
+FIELDS TERMINATED BY '' ENCLOSED BY '';
+Warnings:
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+SELECT b FROM t1;
+b
+2011-08-01 15:11:19.918273
+SELECT c FROM t1;
+c
+2011-08-01 15:11:19.918273
+SELECT d FROM t1;
+d
+2011-08-01 15:11:19.918273
+SELECT e FROM t1;
+e
+2011-08-01 15:11:19.918273
+# Yes, a missing field cannot be NULL using this syntax, so it will
+# zero date instead. Says a comment in read_fixed_length() : "No fields
+# specified in fields_vars list can be NULL in this format."
+# It appears to be by design. This is inconsistent with LOAD DATA INFILE
+# syntax in previous test.
+SELECT f FROM t1;
+f
+0000-00-00 00:00:00.000000
+SELECT g FROM t1;
+g
+0000-00-00 00:00:00.000000
+# See comment above "SELECT f FROM f1".
+SELECT h FROM t1;
+h
+0000-00-00 00:00:00.000000
+SELECT i FROM t1;
+i
+0000-00-00 00:00:00.000000
+DELETE FROM t1;
+LOAD DATA INFILE 't5.dat' INTO TABLE t1 ( a, @dummy );
+SELECT * FROM t1;
+a b c d e f g h i
+1 2011-08-01 15:11:19.918273 2011-08-01 15:11:19.918273 0000-00-00 00:00:00.000000 2011-08-01 15:11:19.918273 NULL 2011-08-01 15:11:19.918273 NULL 2011-08-01 15:11:19.918273
+SELECT @dummy;
+@dummy
+2
+DELETE FROM t1;
+LOAD DATA INFILE 't3.dat' INTO TABLE t1 ( a ) SET c = '2005-06-06 08:09:10';
+SELECT * FROM t1;
+a b c d e f g h i
+1 2011-08-01 15:11:19.918273 2005-06-06 08:09:10.000000 0000-00-00 00:00:00.000000 2011-08-01 15:11:19.918273 NULL 2011-08-01 15:11:19.918273 NULL 2011-08-01 15:11:19.918273
+DELETE FROM t1;
+LOAD DATA INFILE 't3.dat' INTO TABLE t1 ( a ) SET g = '2005-06-06 08:09:10';
+SELECT * FROM t1;
+a b c d e f g h i
+1 2011-08-01 15:11:19.918273 2011-08-01 15:11:19.918273 0000-00-00 00:00:00.000000 2011-08-01 15:11:19.918273 NULL 2005-06-06 08:09:10.000000 NULL 2011-08-01 15:11:19.918273
+DELETE FROM t1;
+# Load a static XML file
+LOAD XML INFILE '../../std_data/onerow.xml' INTO TABLE t1
+ROWS IDENTIFIED BY '<row>';
+Missing tags are treated as NULL
+SELECT * FROM t1;
+a 1
+b 2011-08-01 15:11:19.918273
+c 2011-08-01 15:11:19.918273
+d 2011-08-01 15:11:19.918273
+e 2011-08-01 15:11:19.918273
+f NULL
+g NULL
+h NULL
+i NULL
+DROP TABLE t1, t2;
+#
+# Similar LOAD DATA tests in another form
+#
+# All of this test portion has been run on a pre-WL5874 trunk
+# (except that like_b and like_c didn't exist) and all result
+# differences are a bug.
+# Regarding like_b its definition is the same as b's except
+# that the constant default is replaced with a function
+# default. Our expectation is that like_b would behave
+# like b: if b is set to NULL, or set to 0000-00-00, or set to
+# its default, then the same should apply to like_b. Same for
+# like_c vs c.
+# Mon Aug 1 15:11:19 2011 UTC
+SET TIMESTAMP = 1312211479.089786;
+SELECT 1 INTO OUTFILE "file1.dat" FROM dual;
+SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+INTO OUTFILE "file2.dat" FROM dual;
+# Too short row
+CREATE TABLE t1 (
+dummy INT,
+a DATETIME(6) NULL DEFAULT NULL,
+b DATETIME(6) NULL DEFAULT "2011-11-18",
+like_b DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6),
+c DATETIME(6) NOT NULL DEFAULT "2011-11-18",
+like_c DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+d TIMESTAMP(6) NULL DEFAULT "2011-05-03" ON UPDATE CURRENT_TIMESTAMP(6),
+e TIMESTAMP(6) NOT NULL DEFAULT "2011-05-03",
+f TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+g TIMESTAMP(6) NULL DEFAULT NULL,
+h INT NULL,
+i INT NOT NULL DEFAULT 42
+);
+# There is no promotion
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `dummy` int(11) DEFAULT NULL,
+ `a` datetime(6) DEFAULT NULL,
+ `b` datetime(6) DEFAULT '2011-11-18 00:00:00.000000',
+ `like_b` datetime(6) DEFAULT CURRENT_TIMESTAMP(6),
+ `c` datetime(6) NOT NULL DEFAULT '2011-11-18 00:00:00.000000',
+ `like_c` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+ `d` timestamp(6) NULL DEFAULT '2011-05-03 00:00:00.000000' ON UPDATE CURRENT_TIMESTAMP(6),
+ `e` timestamp(6) NOT NULL DEFAULT '2011-05-03 00:00:00.000000',
+ `f` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+ `g` timestamp(6) NULL DEFAULT NULL,
+ `h` int(11) DEFAULT NULL,
+ `i` int(11) NOT NULL DEFAULT '42'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+LOAD DATA INFILE "file1.dat" INTO table t1;
+Warnings:
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+# It is strange that "like_b" gets NULL when "b" gets 0. But
+# this is consistent with how "a" gets NULL when "b" gets 0,
+# with how "g" gets NULL when "d" gets 0, and with how "h" gets
+# NULL when "i" gets 0. Looks like "DEFAULT
+# <non-NULL-constant>" is changed to 0, whereas DEFAULT NULL
+# and DEFAULT NOW are changed to NULL.
+SELECT * FROM t1;
+dummy 1
+a NULL
+b 0000-00-00 00:00:00.000000
+like_b NULL
+c 0000-00-00 00:00:00.000000
+like_c 0000-00-00 00:00:00.000000
+d 0000-00-00 00:00:00.000000
+e 2011-08-01 15:11:19.089786
+f 2011-08-01 15:11:19.089786
+g NULL
+h NULL
+i 0
+delete from t1;
+alter table t1
+modify f TIMESTAMP NULL default CURRENT_TIMESTAMP;
+# There is no promotion
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `dummy` int(11) DEFAULT NULL,
+ `a` datetime(6) DEFAULT NULL,
+ `b` datetime(6) DEFAULT '2011-11-18 00:00:00.000000',
+ `like_b` datetime(6) DEFAULT CURRENT_TIMESTAMP(6),
+ `c` datetime(6) NOT NULL DEFAULT '2011-11-18 00:00:00.000000',
+ `like_c` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+ `d` timestamp(6) NULL DEFAULT '2011-05-03 00:00:00.000000' ON UPDATE CURRENT_TIMESTAMP(6),
+ `e` timestamp(6) NOT NULL DEFAULT '2011-05-03 00:00:00.000000',
+ `f` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
+ `g` timestamp(6) NULL DEFAULT NULL,
+ `h` int(11) DEFAULT NULL,
+ `i` int(11) NOT NULL DEFAULT '42'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+LOAD DATA INFILE "file1.dat" INTO table t1;
+Warnings:
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+Warning 1261 Row 1 doesn't contain data for all columns
+SELECT * FROM t1;
+dummy 1
+a NULL
+b 0000-00-00 00:00:00.000000
+like_b NULL
+c 0000-00-00 00:00:00.000000
+like_c 0000-00-00 00:00:00.000000
+d 0000-00-00 00:00:00.000000
+e 2011-08-01 15:11:19.089786
+f NULL
+g NULL
+h NULL
+i 0
+delete from t1;
+drop table t1;
+# Conclusion derived from trunk's results:
+# DATETIME DEFAULT <non-NULL-constant> (b,c) gets 0000-00-00,
+# DATETIME DEFAULT NULL (a) gets NULL,
+# TIMESTAMP NULL DEFAULT <non-NULL-constant> (d) gets 0000-00-00,
+# TIMESTAMP NULL DEFAULT NULL (g) gets NULL,
+# TIMESTAMP NULL DEFAULT NOW (f after ALTER) gets NULL,
+# TIMESTAMP NOT NULL (f before ALTER, e) gets NOW.
+### Loading NULL ###
+CREATE TABLE t1 (
+dummy INT,
+a DATETIME(6) NULL DEFAULT NULL,
+b DATETIME(6) NULL DEFAULT "2011-11-18",
+like_b DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6),
+c DATETIME(6) NOT NULL DEFAULT "2011-11-18",
+like_c DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+d TIMESTAMP(6) NULL DEFAULT "2011-05-03" ON UPDATE CURRENT_TIMESTAMP(6),
+e TIMESTAMP(6) NOT NULL DEFAULT "2011-05-03",
+f TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+g TIMESTAMP(6) NULL DEFAULT NULL,
+h INT NULL,
+i INT NOT NULL DEFAULT 42
+);
+# There is no promotion
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `dummy` int(11) DEFAULT NULL,
+ `a` datetime(6) DEFAULT NULL,
+ `b` datetime(6) DEFAULT '2011-11-18 00:00:00.000000',
+ `like_b` datetime(6) DEFAULT CURRENT_TIMESTAMP(6),
+ `c` datetime(6) NOT NULL DEFAULT '2011-11-18 00:00:00.000000',
+ `like_c` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+ `d` timestamp(6) NULL DEFAULT '2011-05-03 00:00:00.000000' ON UPDATE CURRENT_TIMESTAMP(6),
+ `e` timestamp(6) NOT NULL DEFAULT '2011-05-03 00:00:00.000000',
+ `f` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+ `g` timestamp(6) NULL DEFAULT NULL,
+ `h` int(11) DEFAULT NULL,
+ `i` int(11) NOT NULL DEFAULT '42'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+LOAD DATA INFILE "file2.dat" INTO table t1;
+Warnings:
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'c' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'like_c' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'i' at row 1
+SELECT * FROM t1;
+dummy NULL
+a NULL
+b NULL
+like_b NULL
+c 0000-00-00 00:00:00.000000
+like_c 0000-00-00 00:00:00.000000
+d NULL
+e 2011-08-01 15:11:19.089786
+f 2011-08-01 15:11:19.089786
+g NULL
+h NULL
+i 0
+delete from t1;
+alter table t1
+modify f TIMESTAMP NULL default CURRENT_TIMESTAMP;
+# There is no promotion
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `dummy` int(11) DEFAULT NULL,
+ `a` datetime(6) DEFAULT NULL,
+ `b` datetime(6) DEFAULT '2011-11-18 00:00:00.000000',
+ `like_b` datetime(6) DEFAULT CURRENT_TIMESTAMP(6),
+ `c` datetime(6) NOT NULL DEFAULT '2011-11-18 00:00:00.000000',
+ `like_c` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+ `d` timestamp(6) NULL DEFAULT '2011-05-03 00:00:00.000000' ON UPDATE CURRENT_TIMESTAMP(6),
+ `e` timestamp(6) NOT NULL DEFAULT '2011-05-03 00:00:00.000000',
+ `f` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
+ `g` timestamp(6) NULL DEFAULT NULL,
+ `h` int(11) DEFAULT NULL,
+ `i` int(11) NOT NULL DEFAULT '42'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+LOAD DATA INFILE "file2.dat" INTO table t1;
+Warnings:
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'c' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'like_c' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'i' at row 1
+SELECT * FROM t1;
+dummy NULL
+a NULL
+b NULL
+like_b NULL
+c 0000-00-00 00:00:00.000000
+like_c 0000-00-00 00:00:00.000000
+d NULL
+e 2011-08-01 15:11:19.089786
+f NULL
+g NULL
+h NULL
+i 0
+delete from t1;
+# Conclusion derived from trunk's results:
+# DATETIME NULL (a,b) gets NULL,
+# DATETIME NOT NULL (c) gets 0000-00-00,
+# TIMESTAMP NULL (d,f,g) gets NULL,
+# TIMESTAMP NOT NULL (e) gets NOW.
+drop table t1;
+#
+# Test of updatable views with check options. The option can be violated
+# using ON UPDATE updates which is very strange as this offers a loophole
+# in this integrity check.
+#
+SET TIME_ZONE = "+03:00";
+# 1970-01-01 03:16:40
+SET TIMESTAMP = 1000.123456;
+CREATE TABLE t1 ( a INT, b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)) ENGINE = INNODB;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+INSERT INTO t1 ( a ) VALUES ( 1 );
+SELECT * FROM t1;
+a b
+1 1970-01-01 03:16:40.123456
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE b <= '1970-01-01 03:16:40.123456'
+WITH CHECK OPTION;
+SELECT * FROM v1;
+a b
+1 1970-01-01 03:16:40.123456
+# 1970-01-01 03:33:20
+SET TIMESTAMP = 2000.000234;
+UPDATE v1 SET a = 2;
+ERROR HY000: CHECK OPTION failed 'test.v1'
+SELECT * FROM t1;
+a b
+1 1970-01-01 03:16:40.123456
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (
+a TIMESTAMP(6) NOT NULL DEFAULT '1973-08-14 09:11:22.089786' ON UPDATE CURRENT_TIMESTAMP(6),
+c INT KEY
+);
+# 1973-08-14 09:11:22 UTC
+SET TIMESTAMP = 114167482.534231;
+INSERT INTO t1 ( c ) VALUES ( 1 );
+CREATE VIEW v1 AS
+SELECT *
+FROM t1
+WHERE a >= '1973-08-14 09:11:22'
+WITH LOCAL CHECK OPTION;
+SELECT * FROM v1;
+a c
+1973-08-14 09:11:22.089786 1
+SET TIMESTAMP = 1.126789;
+INSERT INTO v1 ( c ) VALUES ( 1 ) ON DUPLICATE KEY UPDATE c = 2;
+ERROR HY000: CHECK OPTION failed 'test.v1'
+SELECT * FROM v1;
+a c
+1973-08-14 09:11:22.089786 1
+DROP VIEW v1;
+DROP TABLE t1;
+#
+# Bug 13095459 - MULTI-TABLE UPDATE MODIFIES A ROW TWICE
+#
+CREATE TABLE t1 (
+a INT,
+b INT,
+ts TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
+PRIMARY KEY ( a, ts )
+) ENGINE = INNODB;
+INSERT INTO t1( a, b, ts ) VALUES ( 1, 0, '2000-09-28 17:44:34' );
+CREATE TABLE t2 ( a INT ) ENGINE = INNODB;
+INSERT INTO t2 VALUES ( 1 );
+UPDATE t1 STRAIGHT_JOIN t2
+SET t1.b = t1.b + 1
+WHERE t1.a = 1 AND t1.ts >= '2000-09-28 00:00:00';
+SELECT b FROM t1;
+b
+1
+DROP TABLE t1, t2;
+#
+# Bug#11745578: 17392: ALTER TABLE ADD COLUMN TIMESTAMP DEFAULT
+# CURRENT_TIMESTAMP INSERTS ZERO
+#
+SET timestamp = 1000;
+CREATE TABLE t1 ( b INT );
+INSERT INTO t1 VALUES (1);
+ALTER TABLE t1 ADD COLUMN a6 DATETIME(6) DEFAULT NOW(6) ON UPDATE NOW(6) FIRST;
+ALTER TABLE t1 ADD COLUMN a5 DATETIME(6) DEFAULT NOW(6) FIRST;
+ALTER TABLE t1 ADD COLUMN a4 DATETIME(6) ON UPDATE NOW(6) FIRST;
+ALTER TABLE t1 ADD COLUMN a3 TIMESTAMP(6) NOT NULL DEFAULT NOW(6) ON UPDATE NOW(6) FIRST;
+ALTER TABLE t1 ADD COLUMN a2 TIMESTAMP(6) NOT NULL DEFAULT NOW(6) FIRST;
+ALTER TABLE t1 ADD COLUMN a1 TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE NOW(6) FIRST;
+ALTER TABLE t1 ADD COLUMN c1 TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE NOW(6) AFTER b;
+ALTER TABLE t1 ADD COLUMN c2 TIMESTAMP(6) NOT NULL DEFAULT NOW(6) AFTER c1;
+ALTER TABLE t1 ADD COLUMN c3 TIMESTAMP(6) NOT NULL DEFAULT NOW(6) ON UPDATE NOW(6) AFTER c2;
+ALTER TABLE t1 ADD COLUMN c4 DATETIME(6) ON UPDATE NOW(6) AFTER c3;
+ALTER TABLE t1 ADD COLUMN c5 DATETIME(6) DEFAULT NOW(6) AFTER c4;
+ALTER TABLE t1 ADD COLUMN c6 DATETIME(6) DEFAULT NOW(6) ON UPDATE NOW(6) AFTER c5;
+SELECT * FROM t1;
+a1 a2 a3 a4 a5 a6 b c1 c2 c3 c4 c5 c6
+0000-00-00 00:00:00.000000 1970-01-01 03:16:40.000000 1970-01-01 03:16:40.000000 NULL 1970-01-01 03:16:40.000000 1970-01-01 03:16:40.000000 1 0000-00-00 00:00:00.000000 1970-01-01 03:16:40.000000 1970-01-01 03:16:40.000000 NULL 1970-01-01 03:16:40.000000 1970-01-01 03:16:40.000000
+DROP TABLE t1;
+CREATE TABLE t1 ( a TIMESTAMP(6) NOT NULL DEFAULT NOW(6) ON UPDATE CURRENT_TIMESTAMP(6), b DATETIME(6) DEFAULT NOW(6) );
+INSERT INTO t1 VALUES ();
+SET timestamp = 1000000000;
+ALTER TABLE t1 MODIFY COLUMN a TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3);
+ALTER TABLE t1 MODIFY COLUMN b DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3);
+SELECT * FROM t1;
+a b
+1970-01-01 03:16:40.000 1970-01-01 03:16:40.000
+DROP TABLE t1;
+CREATE TABLE t1 (
+a TIMESTAMP(6) NOT NULL DEFAULT '1999-12-01 11:22:33' ON UPDATE CURRENT_TIMESTAMP(6),
+b DATETIME(6) DEFAULT '1999-12-01 11:22:33'
+);
+INSERT INTO t1 VALUES ();
+ALTER TABLE t1 MODIFY COLUMN a TIMESTAMP(6) DEFAULT NOW(6);
+ALTER TABLE t1 MODIFY COLUMN b DATETIME(6) DEFAULT NOW(6);
+INSERT INTO t1 VALUES ();
+SELECT * FROM t1;
+a b
+1999-12-01 11:22:33.000000 1999-12-01 11:22:33.000000
+2001-09-09 04:46:40.000000 2001-09-09 04:46:40.000000
+DROP TABLE t1;
diff --git a/mysql-test/r/function_defaults_notembedded.result b/mysql-test/r/function_defaults_notembedded.result
new file mode 100644
index 00000000000..c54ae14aef4
--- /dev/null
+++ b/mysql-test/r/function_defaults_notembedded.result
@@ -0,0 +1,171 @@
+#
+# Test of function defaults for non-embedded server.
+#
+#
+# Function defaults run 1. No microsecond precision.
+#
+SET TIME_ZONE = "+00:00";
+#
+# Test of INSERT DELAYED ... SET ...
+#
+# 2011-04-19 08:02:40 UTC
+SET TIMESTAMP = 1303200160.123456;
+CREATE TABLE t1 ( a INT, b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
+INSERT DELAYED INTO t1 SET a = 1;
+FLUSH TABLE t1;
+SELECT * FROM t1;
+a b
+1 2011-04-19 08:02:40
+SELECT * FROM t1 WHERE b = 0;
+a b
+INSERT DELAYED INTO t1 SET a = 2, b = '1980-01-02 10:20:30.405060';
+FLUSH TABLE t1;
+SELECT * FROM t1;
+a b
+1 2011-04-19 08:02:40
+2 1980-01-02 10:20:30
+DROP TABLE t1;
+#
+# Test of INSERT DELAYED ... VALUES ...
+#
+# 2011-04-19 08:04:01 UTC
+SET TIMESTAMP = 1303200241.234567;
+CREATE TABLE t1 ( a INT, b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
+INSERT DELAYED INTO t1 ( a ) VALUES (1);
+FLUSH TABLE t1;
+SELECT * FROM t1;
+a b
+1 2011-04-19 08:04:01
+INSERT DELAYED INTO t1 VALUES (2, '1977-12-19 12:34:56.789123');
+FLUSH TABLE t1;
+SELECT * FROM t1;
+a b
+1 2011-04-19 08:04:01
+2 1977-12-19 12:34:56
+DROP TABLE t1;
+#
+# Test of a delayed insert handler servicing two insert operations
+# with different sets of active defaults.
+#
+CREATE TABLE t1 ( a INT, b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
+# 2011-04-19 08:04:01 UTC
+SET TIMESTAMP = 1303200241.345678;
+SET debug_sync = 'before_write_delayed SIGNAL parked WAIT_FOR go';
+INSERT DELAYED INTO t1 ( a ) VALUES (1), (2), (3);
+SET debug_sync = 'now WAIT_FOR parked';
+# 2011-04-19 08:04:01 UTC
+SET TIME_ZONE="+03:00";
+SET TIMESTAMP = 1303200241.456789;
+INSERT DELAYED INTO t1 ( a, b ) VALUES (4, '1977-12-19 12:34:56.789123'), (5, '1977-12-19 12:34:57.891234'), (6, '1977-12-19 12:34:58.912345');
+SET debug_sync = 'now SIGNAL go';
+SELECT * FROM t1;
+a b
+1 2011-04-19 08:04:01
+2 2011-04-19 08:04:01
+3 2011-04-19 08:04:01
+4 1977-12-19 09:34:56
+5 1977-12-19 09:34:57
+6 1977-12-19 09:34:58
+DROP TABLE t1;
+#
+# Test of early activation of function defaults.
+#
+CREATE TABLE t1 ( a INT, b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
+SET TIMESTAMP = 1317235172.987654;
+INSERT DELAYED INTO t1 ( a ) VALUES (1), (2), (3);
+SET TIMESTAMP = 385503754.876543;
+INSERT DELAYED INTO t1 ( a ) VALUES (4), (5), (6);
+FLUSH TABLE t1;
+SELECT * FROM t1;
+a b
+1 2011-09-28 18:39:32
+2 2011-09-28 18:39:32
+3 2011-09-28 18:39:32
+4 1982-03-20 20:22:34
+5 1982-03-20 20:22:34
+6 1982-03-20 20:22:34
+DROP TABLE t1;
+#
+# Function defaults run 2. Six digits scale on seconds precision.
+#
+SET TIME_ZONE = "+00:00";
+#
+# Test of INSERT DELAYED ... SET ...
+#
+# 2011-04-19 08:02:40 UTC
+SET TIMESTAMP = 1303200160.123456;
+CREATE TABLE t1 ( a INT, b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6));
+INSERT DELAYED INTO t1 SET a = 1;
+FLUSH TABLE t1;
+SELECT * FROM t1;
+a b
+1 2011-04-19 08:02:40.123456
+SELECT * FROM t1 WHERE b = 0;
+a b
+INSERT DELAYED INTO t1 SET a = 2, b = '1980-01-02 10:20:30.405060';
+FLUSH TABLE t1;
+SELECT * FROM t1;
+a b
+1 2011-04-19 08:02:40.123456
+2 1980-01-02 10:20:30.405060
+DROP TABLE t1;
+#
+# Test of INSERT DELAYED ... VALUES ...
+#
+# 2011-04-19 08:04:01 UTC
+SET TIMESTAMP = 1303200241.234567;
+CREATE TABLE t1 ( a INT, b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6));
+INSERT DELAYED INTO t1 ( a ) VALUES (1);
+FLUSH TABLE t1;
+SELECT * FROM t1;
+a b
+1 2011-04-19 08:04:01.234567
+INSERT DELAYED INTO t1 VALUES (2, '1977-12-19 12:34:56.789123');
+FLUSH TABLE t1;
+SELECT * FROM t1;
+a b
+1 2011-04-19 08:04:01.234567
+2 1977-12-19 12:34:56.789123
+DROP TABLE t1;
+#
+# Test of a delayed insert handler servicing two insert operations
+# with different sets of active defaults.
+#
+CREATE TABLE t1 ( a INT, b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6));
+# 2011-04-19 08:04:01 UTC
+SET TIMESTAMP = 1303200241.345678;
+SET debug_sync = 'before_write_delayed SIGNAL parked WAIT_FOR go';
+INSERT DELAYED INTO t1 ( a ) VALUES (1), (2), (3);
+SET debug_sync = 'now WAIT_FOR parked';
+# 2011-04-19 08:04:01 UTC
+SET TIME_ZONE="+03:00";
+SET TIMESTAMP = 1303200241.456789;
+INSERT DELAYED INTO t1 ( a, b ) VALUES (4, '1977-12-19 12:34:56.789123'), (5, '1977-12-19 12:34:57.891234'), (6, '1977-12-19 12:34:58.912345');
+SET debug_sync = 'now SIGNAL go';
+SELECT * FROM t1;
+a b
+1 2011-04-19 08:04:01.345678
+2 2011-04-19 08:04:01.345678
+3 2011-04-19 08:04:01.345678
+4 1977-12-19 09:34:56.789123
+5 1977-12-19 09:34:57.891234
+6 1977-12-19 09:34:58.912345
+DROP TABLE t1;
+#
+# Test of early activation of function defaults.
+#
+CREATE TABLE t1 ( a INT, b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6));
+SET TIMESTAMP = 1317235172.987654;
+INSERT DELAYED INTO t1 ( a ) VALUES (1), (2), (3);
+SET TIMESTAMP = 385503754.876543;
+INSERT DELAYED INTO t1 ( a ) VALUES (4), (5), (6);
+FLUSH TABLE t1;
+SELECT * FROM t1;
+a b
+1 2011-09-28 18:39:32.987654
+2 2011-09-28 18:39:32.987654
+3 2011-09-28 18:39:32.987654
+4 1982-03-20 20:22:34.876543
+5 1982-03-20 20:22:34.876543
+6 1982-03-20 20:22:34.876543
+DROP TABLE t1;
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 72c53697e61..1983d1cc784 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/have_debug_sync.require b/mysql-test/r/have_debug_sync.require
deleted file mode 100644
index c2090bc5657..00000000000
--- a/mysql-test/r/have_debug_sync.require
+++ /dev/null
@@ -1,2 +0,0 @@
-debug_sync
-1
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
index fcb40dae4ff..9d993e723c2 100644
--- a/mysql-test/r/information_schema.result
+++ b/mysql-test/r/information_schema.result
@@ -1678,6 +1678,12 @@ SELECT length(CAST(b AS CHAR)) FROM ubig;
length(CAST(b AS CHAR))
20
DROP TABLE ubig;
+select 1 from information_schema.tables where table_schema=repeat('a', 2000);
+1
+grant usage on *.* to mysqltest_1@localhost;
+select 1 from information_schema.tables where table_schema=repeat('a', 2000);
+1
+drop user mysqltest_1@localhost;
End of 5.1 tests.
#
# Additional test for WL#3726 "DDL locking for all metadata objects"
diff --git a/mysql-test/r/innodb_ext_key.result b/mysql-test/r/innodb_ext_key.result
index d2fb29a023c..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/is_debug_build.require b/mysql-test/r/is_debug_build.require
deleted file mode 100644
index 4d77bcdc1ed..00000000000
--- a/mysql-test/r/is_debug_build.require
+++ /dev/null
@@ -1,2 +0,0 @@
-instr(version(), "debug") > 0
-1
diff --git a/mysql-test/r/log_slow.result b/mysql-test/r/log_slow.result
index 75e92e7a0b5..76cf45631bd 100644
--- a/mysql-test/r/log_slow.result
+++ b/mysql-test/r/log_slow.result
@@ -44,7 +44,7 @@ select @@log_slow_verbosity;
innodb
show fields from mysql.slow_log;
Field Type Null Key Default Extra
-start_time timestamp(6) NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP
+start_time timestamp(6) NO CURRENT_TIMESTAMP(6) on update CURRENT_TIMESTAMP
user_host mediumtext NO NULL
query_time time(6) NO NULL
lock_time time(6) NO NULL
diff --git a/mysql-test/r/log_tables.result b/mysql-test/r/log_tables.result
index c25bd6727df..76784be1e16 100644
--- a/mysql-test/r/log_tables.result
+++ b/mysql-test/r/log_tables.result
@@ -53,7 +53,7 @@ ERROR HY000: You can't use locks with log tables.
show create table mysql.general_log;
Table Create Table
general_log CREATE TABLE `general_log` (
- `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`thread_id` int(11) NOT NULL,
`server_id` int(10) unsigned NOT NULL,
@@ -62,7 +62,7 @@ general_log CREATE TABLE `general_log` (
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'
show fields from mysql.general_log;
Field Type Null Key Default Extra
-event_time timestamp(6) NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP
+event_time timestamp(6) NO CURRENT_TIMESTAMP(6) on update CURRENT_TIMESTAMP
user_host mediumtext NO NULL
thread_id int(11) NO NULL
server_id int(10) unsigned NO NULL
@@ -71,7 +71,7 @@ argument mediumtext NO NULL
show create table mysql.slow_log;
Table Create Table
slow_log CREATE TABLE `slow_log` (
- `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`query_time` time(6) NOT NULL,
`lock_time` time(6) NOT NULL,
@@ -85,7 +85,7 @@ slow_log CREATE TABLE `slow_log` (
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'
show fields from mysql.slow_log;
Field Type Null Key Default Extra
-start_time timestamp(6) NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP
+start_time timestamp(6) NO CURRENT_TIMESTAMP(6) on update CURRENT_TIMESTAMP
user_host mediumtext NO NULL
query_time time(6) NO NULL
lock_time time(6) NO NULL
@@ -164,7 +164,7 @@ set global slow_query_log='OFF';
show create table mysql.general_log;
Table Create Table
general_log CREATE TABLE `general_log` (
- `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`thread_id` int(11) NOT NULL,
`server_id` int(10) unsigned NOT NULL,
@@ -174,7 +174,7 @@ general_log CREATE TABLE `general_log` (
show create table mysql.slow_log;
Table Create Table
slow_log CREATE TABLE `slow_log` (
- `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`query_time` time(6) NOT NULL,
`lock_time` time(6) NOT NULL,
@@ -191,7 +191,7 @@ alter table mysql.slow_log engine=myisam;
show create table mysql.general_log;
Table Create Table
general_log CREATE TABLE `general_log` (
- `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`thread_id` int(11) NOT NULL,
`server_id` int(10) unsigned NOT NULL,
@@ -201,7 +201,7 @@ general_log CREATE TABLE `general_log` (
show create table mysql.slow_log;
Table Create Table
slow_log CREATE TABLE `slow_log` (
- `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`query_time` time(6) NOT NULL,
`lock_time` time(6) NOT NULL,
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index b58a904bc1f..6b0e044a491 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -5239,7 +5239,7 @@ Error 1146 Table 'mysql.event' doesn't exist
SHOW CREATE TABLE mysql.general_log;
Table Create Table
general_log CREATE TABLE `general_log` (
- `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`thread_id` int(11) NOT NULL,
`server_id` int(10) unsigned NOT NULL,
@@ -5249,7 +5249,7 @@ general_log CREATE TABLE `general_log` (
SHOW CREATE TABLE mysql.slow_log;
Table Create Table
slow_log CREATE TABLE `slow_log` (
- `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`query_time` time(6) NOT NULL,
`lock_time` time(6) NOT NULL,
diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result
index b86925e0eb8..76b8e887d89 100644
--- a/mysql-test/r/openssl_1.result
+++ b/mysql-test/r/openssl_1.result
@@ -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/partition.result b/mysql-test/r/partition.result
index 40586b8d54b..86425825601 100644
--- a/mysql-test/r/partition.result
+++ b/mysql-test/r/partition.result
@@ -2394,6 +2394,12 @@ HAVING b > geomfromtext("")
);
1
DROP TABLE t1;
+
+MDEV-612 Valgrind error in ha_maria::check_if_incompatible_data
+
+CREATE TABLE t1 (a INT, b INT, KEY(a)) ENGINE=Aria PARTITION BY KEY(a) PARTITIONS 2;
+ALTER TABLE t1 ADD KEY (b);
+drop table t1;
End of 5.1 tests
#
# BUG#55385: UPDATE statement throws an error, but still updates
diff --git a/mysql-test/r/range_vs_index_merge.result b/mysql-test/r/range_vs_index_merge.result
index faaa6d2429e..cc8a345a2ff 100644
--- a/mysql-test/r/range_vs_index_merge.result
+++ b/mysql-test/r/range_vs_index_merge.result
@@ -1221,6 +1221,153 @@ Lugansk UKR 469000
Seattle USA 563374
Caracas VEN 1975294
set optimizer_switch=@save_optimizer_switch;
+#
+# Bug mdev-585: range vs index-merge with ORDER BY ... LIMIT n
+# (LP bug #637962)
+#
+DROP INDEX CountryPopulation ON City;
+DROP INDEX CountryName ON City;
+DROP INDEX CityName on City;
+CREATE INDEX Name ON City(Name);
+CREATE INDEX Population ON City(Population);
+EXPLAIN
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE City index_merge Country,Name,Population Name,Country 35,3 NULL # Using sort_union(Name,Country); Using where
+FLUSH STATUS;
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000);
+ID Name Country Population
+384 Cabo Frio BRA 119503
+387 Camaragibe BRA 118968
+403 Catanduva BRA 107761
+412 Cachoeirinha BRA 103240
+508 Watford GBR 113080
+509 Ipswich GBR 114000
+510 Slough GBR 112000
+511 Exeter GBR 111000
+512 Cheltenham GBR 106000
+513 Gloucester GBR 107000
+514 Saint Helens GBR 106293
+515 Sutton Coldfield GBR 106001
+516 York GBR 104425
+517 Oldham GBR 103931
+518 Basildon GBR 100924
+519 Worthing GBR 100000
+635 Mallawi EGY 119283
+636 Bilbays EGY 113608
+637 Mit Ghamr EGY 101801
+638 al-Arish EGY 100447
+701 Tarragona ESP 113016
+702 Lleida (Lérida) ESP 112207
+703 Jaén ESP 109247
+704 Ourense (Orense) ESP 109120
+705 Mataró ESP 104095
+706 Algeciras ESP 103106
+707 Marbella ESP 101144
+759 Gonder ETH 112249
+869 Cabuyao PHL 106630
+870 Calapan PHL 105910
+873 Cauayan PHL 103952
+903 Serekunda GMB 102600
+909 Sohumi GEO 111700
+913 Tema GHA 109975
+914 Sekondi-Takoradi GHA 103653
+924 Villa Nueva GTM 101295
+1844 Cape Breton CAN 114733
+1847 Cambridge CAN 109186
+2406 Herakleion GRC 116178
+2407 Kallithea GRC 114233
+2408 Larisa GRC 113090
+2908 Cajamarca PER 108009
+3002 Besançon FRA 117733
+3003 Caen FRA 113987
+3004 Orléans FRA 113126
+3005 Mulhouse FRA 110359
+3006 Rouen FRA 106592
+3007 Boulogne-Billancourt FRA 106367
+3008 Perpignan FRA 105115
+3009 Nancy FRA 103605
+3411 Ceyhan TUR 102412
+3567 Carúpano VEN 119639
+3568 Catia La Mar VEN 117012
+3571 Calabozo VEN 107146
+3786 Cam Ranh VNM 114041
+3792 Tartu EST 101246
+4002 Carrollton USA 109576
+4027 Cape Coral USA 102286
+4032 Cambridge USA 101355
+SHOW STATUS LIKE 'Handler_read_%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 2
+Handler_read_last 0
+Handler_read_next 385
+Handler_read_prev 0
+Handler_read_rnd 377
+Handler_read_rnd_deleted 0
+Handler_read_rnd_next 0
+EXPLAIN
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE City range Country,Name,Population Population 4 NULL # Using where
+FLUSH STATUS;
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+ID Name Country Population
+519 Worthing GBR 100000
+638 al-Arish EGY 100447
+518 Basildon GBR 100924
+707 Marbella ESP 101144
+3792 Tartu EST 101246
+SHOW STATUS LIKE 'Handler_read_%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 1
+Handler_read_last 0
+Handler_read_next 59
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_deleted 0
+Handler_read_rnd_next 0
+set optimizer_switch='index_merge=off';
+EXPLAIN
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE City range Country,Name,Population Population 4 NULL # Using index condition; Using where
+FLUSH STATUS;
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+ID Name Country Population
+519 Worthing GBR 100000
+638 al-Arish EGY 100447
+518 Basildon GBR 100924
+707 Marbella ESP 101144
+3792 Tartu EST 101246
+SHOW STATUS LIKE 'Handler_read_%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 1
+Handler_read_last 0
+Handler_read_next 59
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_deleted 0
+Handler_read_rnd_next 0
+set optimizer_switch=@save_optimizer_switch;
DROP DATABASE world;
use test;
CREATE TABLE t1 (
diff --git a/mysql-test/r/range_vs_index_merge_innodb,innodb_plugin.rdiff b/mysql-test/r/range_vs_index_merge_innodb,innodb_plugin.rdiff
index 5913434caae..ecae2c809c1 100644
--- a/mysql-test/r/range_vs_index_merge_innodb,innodb_plugin.rdiff
+++ b/mysql-test/r/range_vs_index_merge_innodb,innodb_plugin.rdiff
@@ -1,5 +1,5 @@
---- r/range_vs_index_merge_innodb.result 2012-03-24 17:12:02.124422000 +0100
-+++ r/range_vs_index_merge_innodb,innodb_plugin.reject 2012-03-24 18:00:13.647902620 +0100
+--- ./r/range_vs_index_merge_innodb.result 2012-11-21 19:35:14.000000000 +0100
++++ ./r/range_vs_index_merge_innodb,innodb_plugin.reject 2012-11-21 20:56:00.000000000 +0100
@@ -50,14 +50,14 @@
WHERE (Population >= 100000 OR Name LIKE 'P%') AND Country='CAN' OR
(Population < 100000 OR Name Like 'T%') AND Country='ARG';
@@ -269,3 +269,12 @@
SELECT Name, Country, Population FROM City WHERE
(Name='Manila' AND Country='PHL') OR
(Name='Addis Abeba' AND Country='ETH') OR
+@@ -1346,7 +1346,7 @@
+ AND (Population >= 100000 AND Population < 120000)
+ ORDER BY Population LIMIT 5;
+ id select_type table type possible_keys key key_len ref rows Extra
+-1 SIMPLE City range Country,Name,Population Population 4 NULL # Using index condition; Using where
++1 SIMPLE City range Country,Name,Population Population 4 NULL # Using where
+ FLUSH STATUS;
+ SELECT * FROM City
+ WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
diff --git a/mysql-test/r/range_vs_index_merge_innodb.result b/mysql-test/r/range_vs_index_merge_innodb.result
index df3a2af0753..67e341192da 100644
--- a/mysql-test/r/range_vs_index_merge_innodb.result
+++ b/mysql-test/r/range_vs_index_merge_innodb.result
@@ -1222,6 +1222,153 @@ Lugansk UKR 469000
Seattle USA 563374
Caracas VEN 1975294
set optimizer_switch=@save_optimizer_switch;
+#
+# Bug mdev-585: range vs index-merge with ORDER BY ... LIMIT n
+# (LP bug #637962)
+#
+DROP INDEX CountryPopulation ON City;
+DROP INDEX CountryName ON City;
+DROP INDEX CityName on City;
+CREATE INDEX Name ON City(Name);
+CREATE INDEX Population ON City(Population);
+EXPLAIN
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE City index_merge Country,Name,Population Name,Country 35,3 NULL # Using sort_union(Name,Country); Using where
+FLUSH STATUS;
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000);
+ID Name Country Population
+384 Cabo Frio BRA 119503
+387 Camaragibe BRA 118968
+403 Catanduva BRA 107761
+412 Cachoeirinha BRA 103240
+508 Watford GBR 113080
+509 Ipswich GBR 114000
+510 Slough GBR 112000
+511 Exeter GBR 111000
+512 Cheltenham GBR 106000
+513 Gloucester GBR 107000
+514 Saint Helens GBR 106293
+515 Sutton Coldfield GBR 106001
+516 York GBR 104425
+517 Oldham GBR 103931
+518 Basildon GBR 100924
+519 Worthing GBR 100000
+635 Mallawi EGY 119283
+636 Bilbays EGY 113608
+637 Mit Ghamr EGY 101801
+638 al-Arish EGY 100447
+701 Tarragona ESP 113016
+702 Lleida (Lérida) ESP 112207
+703 Jaén ESP 109247
+704 Ourense (Orense) ESP 109120
+705 Mataró ESP 104095
+706 Algeciras ESP 103106
+707 Marbella ESP 101144
+759 Gonder ETH 112249
+869 Cabuyao PHL 106630
+870 Calapan PHL 105910
+873 Cauayan PHL 103952
+903 Serekunda GMB 102600
+909 Sohumi GEO 111700
+913 Tema GHA 109975
+914 Sekondi-Takoradi GHA 103653
+924 Villa Nueva GTM 101295
+1844 Cape Breton CAN 114733
+1847 Cambridge CAN 109186
+2406 Herakleion GRC 116178
+2407 Kallithea GRC 114233
+2408 Larisa GRC 113090
+2908 Cajamarca PER 108009
+3002 Besançon FRA 117733
+3003 Caen FRA 113987
+3004 Orléans FRA 113126
+3005 Mulhouse FRA 110359
+3006 Rouen FRA 106592
+3007 Boulogne-Billancourt FRA 106367
+3008 Perpignan FRA 105115
+3009 Nancy FRA 103605
+3411 Ceyhan TUR 102412
+3567 Carúpano VEN 119639
+3568 Catia La Mar VEN 117012
+3571 Calabozo VEN 107146
+3786 Cam Ranh VNM 114041
+3792 Tartu EST 101246
+4002 Carrollton USA 109576
+4027 Cape Coral USA 102286
+4032 Cambridge USA 101355
+SHOW STATUS LIKE 'Handler_read_%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 2
+Handler_read_last 0
+Handler_read_next 385
+Handler_read_prev 0
+Handler_read_rnd 377
+Handler_read_rnd_deleted 0
+Handler_read_rnd_next 0
+EXPLAIN
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE City range Country,Name,Population Population 4 NULL # Using where
+FLUSH STATUS;
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+ID Name Country Population
+519 Worthing GBR 100000
+638 al-Arish EGY 100447
+518 Basildon GBR 100924
+707 Marbella ESP 101144
+3792 Tartu EST 101246
+SHOW STATUS LIKE 'Handler_read_%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 1
+Handler_read_last 0
+Handler_read_next 59
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_deleted 0
+Handler_read_rnd_next 0
+set optimizer_switch='index_merge=off';
+EXPLAIN
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE City range Country,Name,Population Population 4 NULL # Using index condition; Using where
+FLUSH STATUS;
+SELECT * FROM City
+WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+ID Name Country Population
+519 Worthing GBR 100000
+638 al-Arish EGY 100447
+518 Basildon GBR 100924
+707 Marbella ESP 101144
+3792 Tartu EST 101246
+SHOW STATUS LIKE 'Handler_read_%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 1
+Handler_read_last 0
+Handler_read_next 59
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_deleted 0
+Handler_read_rnd_next 0
+set optimizer_switch=@save_optimizer_switch;
DROP DATABASE world;
use test;
CREATE TABLE t1 (
diff --git a/mysql-test/r/server_id.require b/mysql-test/r/server_id.require
deleted file mode 100644
index adffcc483b1..00000000000
--- a/mysql-test/r/server_id.require
+++ /dev/null
@@ -1,2 +0,0 @@
-Variable_name Value
-server_id 1
diff --git a/mysql-test/r/server_id1.require b/mysql-test/r/server_id1.require
deleted file mode 100644
index 666c94ef633..00000000000
--- a/mysql-test/r/server_id1.require
+++ /dev/null
@@ -1,2 +0,0 @@
-Variable_name Value
-server_id 102
diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result
index 6736ca7f541..4fdac6b9cea 100644
--- a/mysql-test/r/sql_mode.result
+++ b/mysql-test/r/sql_mode.result
@@ -71,7 +71,7 @@ t1 CREATE TABLE `t1` (
`email` varchar(60) NOT NULL DEFAULT '',
PRIMARY KEY (`a`),
UNIQUE KEY `email` (`email`)
-) TYPE=HEAP ROW_FORMAT=DYNAMIC
+) TYPE=MEMORY ROW_FORMAT=DYNAMIC
set sql_mode="postgresql,oracle,mssql,db2,maxdb";
select @@sql_mode;
@@sql_mode
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index a4bad836d1f..14347e9b899 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -6060,6 +6060,116 @@ WHERE (col_varchar_nokey, 'x') IN
col_int_nokey
1
DROP TABLE ot,it1,it2;
+#
+# MDEV-746
+# Bug#13651009 WRONG RESULT FROM DERIVED TABLE IF THE SUBQUERY
+# HAS AN EMPTY RESULT
+#
+CREATE TABLE t1 (
+pk int NOT NULL,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+CREATE TABLE t2 (
+pk int NOT NULL AUTO_INCREMENT,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,4,4,'00:00:00','b','b');
+SET @var2:=4, @var3:=8;
+
+Testcase without inner subquery
+EXPLAIN SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+EXPLAIN SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE <derived2> system NULL NULL NULL NULL 0 const row not found
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+
+Testcase with inner subquery; crashed WL#6095
+SET @var3=8;
+EXPLAIN SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+EXPLAIN SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+3 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+DROP TABLE t1,t2;
End of 5.2 tests
#
# BUG#779885: Crash in eliminate_item_equal with materialization=on in
@@ -6860,7 +6970,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
@@ -6894,6 +7004,6 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result
index cb9847a0d99..c307a68f64d 100644
--- a/mysql-test/r/subselect_no_mat.result
+++ b/mysql-test/r/subselect_no_mat.result
@@ -6059,6 +6059,116 @@ WHERE (col_varchar_nokey, 'x') IN
col_int_nokey
1
DROP TABLE ot,it1,it2;
+#
+# MDEV-746
+# Bug#13651009 WRONG RESULT FROM DERIVED TABLE IF THE SUBQUERY
+# HAS AN EMPTY RESULT
+#
+CREATE TABLE t1 (
+pk int NOT NULL,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+CREATE TABLE t2 (
+pk int NOT NULL AUTO_INCREMENT,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,4,4,'00:00:00','b','b');
+SET @var2:=4, @var3:=8;
+
+Testcase without inner subquery
+EXPLAIN SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+EXPLAIN SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE <derived2> system NULL NULL NULL NULL 0 const row not found
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+
+Testcase with inner subquery; crashed WL#6095
+SET @var3=8;
+EXPLAIN SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+EXPLAIN SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+3 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+DROP TABLE t1,t2;
End of 5.2 tests
#
# BUG#779885: Crash in eliminate_item_equal with materialization=on in
@@ -6858,7 +6968,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
@@ -6891,7 +7001,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
set optimizer_switch=default;
diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result
index 63eeb816b38..d1590b0df51 100644
--- a/mysql-test/r/subselect_no_opts.result
+++ b/mysql-test/r/subselect_no_opts.result
@@ -6055,6 +6055,116 @@ WHERE (col_varchar_nokey, 'x') IN
col_int_nokey
1
DROP TABLE ot,it1,it2;
+#
+# MDEV-746
+# Bug#13651009 WRONG RESULT FROM DERIVED TABLE IF THE SUBQUERY
+# HAS AN EMPTY RESULT
+#
+CREATE TABLE t1 (
+pk int NOT NULL,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+CREATE TABLE t2 (
+pk int NOT NULL AUTO_INCREMENT,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,4,4,'00:00:00','b','b');
+SET @var2:=4, @var3:=8;
+
+Testcase without inner subquery
+EXPLAIN SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+EXPLAIN SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE <derived2> system NULL NULL NULL NULL 0 const row not found
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+
+Testcase with inner subquery; crashed WL#6095
+SET @var3=8;
+EXPLAIN SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+EXPLAIN SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+3 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+DROP TABLE t1,t2;
End of 5.2 tests
#
# BUG#779885: Crash in eliminate_item_equal with materialization=on in
@@ -6855,7 +6965,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
@@ -6889,7 +6999,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
set @optimizer_switch_for_subselect_test=null;
diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result
index 6fd21f8d0b0..b6b5572815a 100644
--- a/mysql-test/r/subselect_no_scache.result
+++ b/mysql-test/r/subselect_no_scache.result
@@ -6066,6 +6066,116 @@ WHERE (col_varchar_nokey, 'x') IN
col_int_nokey
1
DROP TABLE ot,it1,it2;
+#
+# MDEV-746
+# Bug#13651009 WRONG RESULT FROM DERIVED TABLE IF THE SUBQUERY
+# HAS AN EMPTY RESULT
+#
+CREATE TABLE t1 (
+pk int NOT NULL,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+CREATE TABLE t2 (
+pk int NOT NULL AUTO_INCREMENT,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,4,4,'00:00:00','b','b');
+SET @var2:=4, @var3:=8;
+
+Testcase without inner subquery
+EXPLAIN SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+EXPLAIN SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE <derived2> system NULL NULL NULL NULL 0 const row not found
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+
+Testcase with inner subquery; crashed WL#6095
+SET @var3=8;
+EXPLAIN SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+EXPLAIN SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+3 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+DROP TABLE t1,t2;
End of 5.2 tests
#
# BUG#779885: Crash in eliminate_item_equal with materialization=on in
@@ -6866,7 +6976,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
@@ -6900,7 +7010,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
set optimizer_switch=default;
diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result
index b924a18ca8f..34cdb17e23e 100644
--- a/mysql-test/r/subselect_no_semijoin.result
+++ b/mysql-test/r/subselect_no_semijoin.result
@@ -6055,6 +6055,116 @@ WHERE (col_varchar_nokey, 'x') IN
col_int_nokey
1
DROP TABLE ot,it1,it2;
+#
+# MDEV-746
+# Bug#13651009 WRONG RESULT FROM DERIVED TABLE IF THE SUBQUERY
+# HAS AN EMPTY RESULT
+#
+CREATE TABLE t1 (
+pk int NOT NULL,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+CREATE TABLE t2 (
+pk int NOT NULL AUTO_INCREMENT,
+col_int_nokey int NOT NULL,
+col_int_key int NOT NULL,
+col_time_key time NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_time_key (col_time_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,4,4,'00:00:00','b','b');
+SET @var2:=4, @var3:=8;
+
+Testcase without inner subquery
+EXPLAIN SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+EXPLAIN SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE <derived2> system NULL NULL NULL NULL 0 const row not found
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+SELECT * FROM ( SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+sq4_alias1.col_varchar_key = @var3 ) AS alias3;
+@var3:=12 pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+SELECT @var3;
+@var3
+8
+
+Testcase with inner subquery; crashed WL#6095
+SET @var3=8;
+EXPLAIN SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3));
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+EXPLAIN SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+3 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
+SELECT * FROM ( SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+NOT IN
+(SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+FROM t2 AS c_sq1_alias1
+WHERE (c_sq1_alias1.col_int_nokey != @var2
+OR c_sq1_alias1.pk != @var3)) ) AS alias3;
+pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
+DROP TABLE t1,t2;
End of 5.2 tests
#
# BUG#779885: Crash in eliminate_item_equal with materialization=on in
@@ -6855,7 +6965,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
@@ -6889,7 +6999,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index a a 5 NULL 1 Using where; Using index
+2 SUBQUERY t1 index a a 5 NULL 2 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
set @optimizer_switch_for_subselect_test=null;
diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result
index 4d458e7284c..be43ef65701 100644
--- a/mysql-test/r/system_mysql_db.result
+++ b/mysql-test/r/system_mysql_db.result
@@ -247,7 +247,7 @@ event CREATE TABLE `event` (
show create table general_log;
Table Create Table
general_log CREATE TABLE `general_log` (
- `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`thread_id` int(11) NOT NULL,
`server_id` int(10) unsigned NOT NULL,
@@ -257,7 +257,7 @@ general_log CREATE TABLE `general_log` (
show create table slow_log;
Table Create Table
slow_log CREATE TABLE `slow_log` (
- `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`query_time` time(6) NOT NULL,
`lock_time` time(6) NOT NULL,
diff --git a/mysql-test/r/system_mysql_db_fix40123.result b/mysql-test/r/system_mysql_db_fix40123.result
index 4d458e7284c..be43ef65701 100644
--- a/mysql-test/r/system_mysql_db_fix40123.result
+++ b/mysql-test/r/system_mysql_db_fix40123.result
@@ -247,7 +247,7 @@ event CREATE TABLE `event` (
show create table general_log;
Table Create Table
general_log CREATE TABLE `general_log` (
- `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`thread_id` int(11) NOT NULL,
`server_id` int(10) unsigned NOT NULL,
@@ -257,7 +257,7 @@ general_log CREATE TABLE `general_log` (
show create table slow_log;
Table Create Table
slow_log CREATE TABLE `slow_log` (
- `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`query_time` time(6) NOT NULL,
`lock_time` time(6) NOT NULL,
diff --git a/mysql-test/r/system_mysql_db_fix50030.result b/mysql-test/r/system_mysql_db_fix50030.result
index 4d458e7284c..be43ef65701 100644
--- a/mysql-test/r/system_mysql_db_fix50030.result
+++ b/mysql-test/r/system_mysql_db_fix50030.result
@@ -247,7 +247,7 @@ event CREATE TABLE `event` (
show create table general_log;
Table Create Table
general_log CREATE TABLE `general_log` (
- `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`thread_id` int(11) NOT NULL,
`server_id` int(10) unsigned NOT NULL,
@@ -257,7 +257,7 @@ general_log CREATE TABLE `general_log` (
show create table slow_log;
Table Create Table
slow_log CREATE TABLE `slow_log` (
- `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`query_time` time(6) NOT NULL,
`lock_time` time(6) NOT NULL,
diff --git a/mysql-test/r/system_mysql_db_fix50117.result b/mysql-test/r/system_mysql_db_fix50117.result
index 4d458e7284c..be43ef65701 100644
--- a/mysql-test/r/system_mysql_db_fix50117.result
+++ b/mysql-test/r/system_mysql_db_fix50117.result
@@ -247,7 +247,7 @@ event CREATE TABLE `event` (
show create table general_log;
Table Create Table
general_log CREATE TABLE `general_log` (
- `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`thread_id` int(11) NOT NULL,
`server_id` int(10) unsigned NOT NULL,
@@ -257,7 +257,7 @@ general_log CREATE TABLE `general_log` (
show create table slow_log;
Table Create Table
slow_log CREATE TABLE `slow_log` (
- `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`query_time` time(6) NOT NULL,
`lock_time` time(6) NOT NULL,
diff --git a/mysql-test/r/testdb_only.require b/mysql-test/r/testdb_only.require
deleted file mode 100644
index e717418fdb6..00000000000
--- a/mysql-test/r/testdb_only.require
+++ /dev/null
@@ -1,2 +0,0 @@
-Variable_name Value
-use extern server NO
diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result
index 52c7f05839e..e7add0d80a7 100644
--- a/mysql-test/r/type_timestamp.result
+++ b/mysql-test/r/type_timestamp.result
@@ -148,15 +148,15 @@ ix+0
20030101000000
drop table t1;
create table t1 (t1 timestamp, t2 timestamp default now());
-ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
+drop table t1;
create table t1 (t1 timestamp, t2 timestamp on update now());
-ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
+drop table t1;
create table t1 (t1 timestamp, t2 timestamp default now() on update now());
-ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
+drop table t1;
create table t1 (t1 timestamp default now(), t2 timestamp on update now());
-ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
+drop table t1;
create table t1 (t1 timestamp on update now(), t2 timestamp default now() on update now());
-ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
+drop table t1;
create table t1 (t1 timestamp default '2003-01-01 00:00:00', t2 datetime, t3 timestamp);
SET TIMESTAMP=1000000000;
insert into t1 values ();
diff --git a/mysql-test/r/type_timestamp_hires.result b/mysql-test/r/type_timestamp_hires.result
index 3f1e05f4870..cc2cb6a403d 100644
--- a/mysql-test/r/type_timestamp_hires.result
+++ b/mysql-test/r/type_timestamp_hires.result
@@ -63,15 +63,15 @@ a
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` timestamp(4) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
+ `a` timestamp(4) NOT NULL DEFAULT CURRENT_TIMESTAMP(4) ON UPDATE CURRENT_TIMESTAMP(4)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
show columns from t1;
Field Type Null Key Default Extra
-a timestamp(4) NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP
+a timestamp(4) NO CURRENT_TIMESTAMP(4) on update CURRENT_TIMESTAMP
select table_name, column_name, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, datetime_precision, character_set_name, collation_name, column_type, column_key, extra from information_schema.columns where table_name='t1';
table_name t1
column_name a
-column_default CURRENT_TIMESTAMP
+column_default CURRENT_TIMESTAMP(4)
is_nullable NO
data_type timestamp
character_maximum_length NULL
@@ -113,7 +113,7 @@ t2 CREATE TABLE `t2` (
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
- `a` timestamp(4) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
+ `a` timestamp(4) NOT NULL DEFAULT CURRENT_TIMESTAMP(4) ON UPDATE CURRENT_TIMESTAMP(4)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t2, t3;
insert t1 values ('2010-12-13 14:15:16.222222');
@@ -278,3 +278,23 @@ select * from t1;
a
2011-01-01 01:01:01.12345
drop table t1;
+create table t1 (a timestamp(5) default current_timestamp);
+drop table t1;
+create table t1 (a timestamp(5) default current_timestamp());
+drop table t1;
+create table t1 (a timestamp(5) default current_timestamp(2));
+ERROR 42000: Invalid default value for 'a'
+create table t1 (a timestamp(5) default current_timestamp(5));
+drop table t1;
+create table t1 (a timestamp(5) default current_timestamp(6));
+drop table t1;
+create table t1 (a timestamp(5) on update current_timestamp);
+drop table t1;
+create table t1 (a timestamp(5) on update current_timestamp());
+drop table t1;
+create table t1 (a timestamp(5) on update current_timestamp(3));
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
+create table t1 (a timestamp(5) on update current_timestamp(5));
+drop table t1;
+create table t1 (a timestamp(5) on update current_timestamp(6));
+drop table t1;
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 ad5e39a2851..29986344f88 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -211,10 +211,10 @@ VARIABLE_NAME VARIABLE_VALUE
DEFAULT_STORAGE_ENGINE MEMORY
show global variables like 'default_storage_engine';
Variable_name Value
-default_storage_engine MRG_MYISAM
+default_storage_engine MRG_MyISAM
select * from information_schema.global_variables where variable_name like 'default_storage_engine';
VARIABLE_NAME VARIABLE_VALUE
-DEFAULT_STORAGE_ENGINE MRG_MYISAM
+DEFAULT_STORAGE_ENGINE MRG_MyISAM
set GLOBAL myisam_max_sort_file_size=2000000;
Warnings:
Warning 1292 Truncated incorrect myisam_max_sort_file_size value: '2000000'
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index d8f2c62e7e2..622cc001f63 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -4825,6 +4825,38 @@ 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.
+# -----------------------------------------------------------------
# some subqueries in SELECT list test
create table t1 (a int, b int);
create table t2 (a int, b int);
diff --git a/mysql-test/r/windows.require b/mysql-test/r/windows.require
deleted file mode 100644
index 09aae1ed1d0..00000000000
--- a/mysql-test/r/windows.require
+++ /dev/null
@@ -1,2 +0,0 @@
-TRUE
-1
diff --git a/mysql-test/std_data/onerow.xml b/mysql-test/std_data/onerow.xml
new file mode 100644
index 00000000000..094dd813b2d
--- /dev/null
+++ b/mysql-test/std_data/onerow.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<database name="test">
+ <table_structure name="onerow">
+ <field Field="a" Type="int(11)" Null="YES" Key="" Extra="" />
+ </table_structure>
+ <table_data name="onerow">
+ <row>
+ <field name="a">1</field>
+ </row>
+ </table_data>
+</database>
+</mysqldump>
diff --git a/mysql-test/suite/binlog/r/binlog_checkpoint.result b/mysql-test/suite/binlog/r/binlog_checkpoint.result
index 8a4a3af115d..02fa8c12310 100644
--- a/mysql-test/suite/binlog/r/binlog_checkpoint.result
+++ b/mysql-test/suite/binlog/r/binlog_checkpoint.result
@@ -70,8 +70,14 @@ include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000003 # Format_desc # # SERVER_VERSION, BINLOG_VERSION
master-bin.000003 # Binlog_checkpoint # # master-bin.000001
+SET DEBUG_SYNC= "RESET";
+SET @old_dbug= @@global.DEBUG_DBUG;
+SET GLOBAL debug_dbug="+d,binlog_background_checkpoint_processed";
SET DEBUG_SYNC= "now SIGNAL con2_continue";
con1 is still pending, no new binlog checkpoint should have been logged.
+SET DEBUG_SYNC= "now WAIT_FOR binlog_background_checkpoint_processed";
+SET GLOBAL debug_dbug= @old_dbug;
+SET DEBUG_SYNC= "RESET";
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000003 # Format_desc # # SERVER_VERSION, BINLOG_VERSION
diff --git a/mysql-test/suite/binlog/r/binlog_xa_recover.result b/mysql-test/suite/binlog/r/binlog_xa_recover.result
index 1231a034ec6..e635fc314b0 100644
--- a/mysql-test/suite/binlog/r/binlog_xa_recover.result
+++ b/mysql-test/suite/binlog/r/binlog_xa_recover.result
@@ -118,7 +118,11 @@ master-bin.000004 # Table_map # # table_id: # (test.t1)
master-bin.000004 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000004 # Xid # # COMMIT /* XID */
SET DEBUG_SYNC= "now SIGNAL con10_cont";
+SET @old_dbug= @@global.DEBUG_DBUG;
+SET GLOBAL debug_dbug="+d,binlog_background_checkpoint_processed";
SET DEBUG_SYNC= "now SIGNAL con12_cont";
+SET DEBUG_SYNC= "now WAIT_FOR binlog_background_checkpoint_processed";
+SET GLOBAL debug_dbug= @old_dbug;
SET DEBUG_SYNC= "now SIGNAL con11_cont";
Checking that master-bin.000004 is the last binlog checkpoint
include/show_binlog_events.inc
diff --git a/mysql-test/suite/binlog/t/binlog_checkpoint.test b/mysql-test/suite/binlog/t/binlog_checkpoint.test
index 557791c77e5..8c84e51c4df 100644
--- a/mysql-test/suite/binlog/t/binlog_checkpoint.test
+++ b/mysql-test/suite/binlog/t/binlog_checkpoint.test
@@ -71,6 +71,12 @@ SET DEBUG_SYNC= "now WAIT_FOR con2_ready";
--let $binlog_file= master-bin.000003
--source include/show_binlog_events.inc
+# We need to sync the test case with the background processing of the
+# commit checkpoint, otherwise we get nondeterministic results.
+SET DEBUG_SYNC= "RESET";
+SET @old_dbug= @@global.DEBUG_DBUG;
+SET GLOBAL debug_dbug="+d,binlog_background_checkpoint_processed";
+
SET DEBUG_SYNC= "now SIGNAL con2_continue";
connection con2;
@@ -78,6 +84,12 @@ reap;
connection default;
--echo con1 is still pending, no new binlog checkpoint should have been logged.
+# Make sure commit checkpoint is processed before we check that no checkpoint
+# event has been binlogged.
+SET DEBUG_SYNC= "now WAIT_FOR binlog_background_checkpoint_processed";
+SET GLOBAL debug_dbug= @old_dbug;
+SET DEBUG_SYNC= "RESET";
+
--let $binlog_file= master-bin.000003
--source include/show_binlog_events.inc
diff --git a/mysql-test/suite/binlog/t/binlog_xa_recover.test b/mysql-test/suite/binlog/t/binlog_xa_recover.test
index b4d44664f1a..d3914e60b10 100644
--- a/mysql-test/suite/binlog/t/binlog_xa_recover.test
+++ b/mysql-test/suite/binlog/t/binlog_xa_recover.test
@@ -14,8 +14,24 @@ CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb;
# Insert some data to force a couple binlog rotations (3), so we get some
# normal binlog checkpoints before starting the test.
INSERT INTO t1 VALUES (100, REPEAT("x", 4100));
+# Wait for the master-bin.000002 binlog checkpoint to appear.
+--let $wait_for_all= 0
+--let $show_statement= SHOW BINLOG EVENTS IN "master-bin.000002"
+--let $field= Info
+--let $condition= = "master-bin.000002"
+--source include/wait_show_condition.inc
INSERT INTO t1 VALUES (101, REPEAT("x", 4100));
+--let $wait_for_all= 0
+--let $show_statement= SHOW BINLOG EVENTS IN "master-bin.000003"
+--let $field= Info
+--let $condition= = "master-bin.000003"
+--source include/wait_show_condition.inc
INSERT INTO t1 VALUES (102, REPEAT("x", 4100));
+--let $wait_for_all= 0
+--let $show_statement= SHOW BINLOG EVENTS IN "master-bin.000004"
+--let $field= Info
+--let $condition= = "master-bin.000004"
+--source include/wait_show_condition.inc
# Now start a bunch of transactions that span multiple binlog
# files. Leave then in the state prepared-but-not-committed in the engine
@@ -154,10 +170,19 @@ SET DEBUG_SYNC= "now SIGNAL con10_cont";
connection con10;
reap;
connection default;
+
+# We need to sync the test case with the background processing of the
+# commit checkpoint, otherwise we get nondeterministic results.
+SET @old_dbug= @@global.DEBUG_DBUG;
+SET GLOBAL debug_dbug="+d,binlog_background_checkpoint_processed";
+
SET DEBUG_SYNC= "now SIGNAL con12_cont";
connection con12;
reap;
connection default;
+SET DEBUG_SYNC= "now WAIT_FOR binlog_background_checkpoint_processed";
+SET GLOBAL debug_dbug= @old_dbug;
+
SET DEBUG_SYNC= "now SIGNAL con11_cont";
connection con11;
reap;
@@ -211,7 +236,20 @@ RESET MASTER;
# crash recovery fails due to the error insert used for previous test.
INSERT INTO t1 VALUES (21, REPEAT("x", 4100));
INSERT INTO t1 VALUES (22, REPEAT("x", 4100));
+# Wait for the master-bin.000003 binlog checkpoint to appear.
+--let $wait_for_all= 0
+--let $show_statement= SHOW BINLOG EVENTS IN "master-bin.000003"
+--let $field= Info
+--let $condition= = "master-bin.000003"
+--source include/wait_show_condition.inc
INSERT INTO t1 VALUES (23, REPEAT("x", 4100));
+# Wait for the last (master-bin.000004) binlog checkpoint to appear.
+--let $wait_for_all= 0
+--let $show_statement= SHOW BINLOG EVENTS IN "master-bin.000004"
+--let $field= Info
+--let $condition= = "master-bin.000004"
+--source include/wait_show_condition.inc
+
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
wait-binlog_xa_recover.test
EOF
diff --git a/mysql-test/suite/federated/federatedx.test b/mysql-test/suite/federated/federatedx.test
index fd2f363ff90..15fdd47c4da 100644
--- a/mysql-test/suite/federated/federatedx.test
+++ b/mysql-test/suite/federated/federatedx.test
@@ -1999,4 +1999,4 @@ connection slave;
SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT;
connection default;
-source suite/federated/include/federated_cleanup.inc;
+source include/federated_cleanup.inc;
diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql.result b/mysql-test/suite/funcs_1/r/is_columns_mysql.result
index 074a1089e52..d925b9008c1 100644
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result
@@ -59,7 +59,7 @@ def mysql func ret 2 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(1) sele
def mysql func type 4 NULL NO enum 9 27 NULL NULL NULL utf8 utf8_general_ci enum('function','aggregate') select,insert,update,references
def mysql general_log argument 6 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext select,insert,update,references
def mysql general_log command_type 5 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select,insert,update,references
-def mysql general_log event_time 1 CURRENT_TIMESTAMP NO timestamp NULL NULL NULL NULL 6 NULL NULL timestamp(6) on update CURRENT_TIMESTAMP select,insert,update,references
+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 select,insert,update,references
def mysql general_log server_id 4 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references
def mysql general_log thread_id 3 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references
def mysql general_log user_host 2 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext select,insert,update,references
@@ -203,7 +203,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) select,insert,update,references
def mysql slow_log server_id 10 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references
def mysql slow_log sql_text 11 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext select,insert,update,references
-def mysql slow_log start_time 1 CURRENT_TIMESTAMP NO timestamp NULL NULL NULL NULL 6 NULL NULL timestamp(6) on update CURRENT_TIMESTAMP select,insert,update,references
+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 select,insert,update,references
def mysql slow_log user_host 2 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext select,insert,update,references
def mysql tables_priv Column_priv 8 NO set 31 93 NULL NULL NULL utf8 utf8_general_ci set('Select','Insert','Update','References') select,insert,update,references
def mysql tables_priv Db 2 NO char 64 192 NULL NULL NULL utf8 utf8_bin char(64) PRI select,insert,update,references
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 d54656c9a3f..81bceb84f73 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
@@ -203,7 +203,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/funcs_1/r/is_engines_merge.result b/mysql-test/suite/funcs_1/r/is_engines_merge.result
index 3bc7a498581..b72c98bfd7e 100644
--- a/mysql-test/suite/funcs_1/r/is_engines_merge.result
+++ b/mysql-test/suite/funcs_1/r/is_engines_merge.result
@@ -1,6 +1,6 @@
SELECT * FROM information_schema.engines
WHERE ENGINE = 'MRG_MYISAM';
-ENGINE MRG_MYISAM
+ENGINE MRG_MyISAM
SUPPORT YES
COMMENT Collection of identical MyISAM tables
TRANSACTIONS NO
diff --git a/mysql-test/suite/heap/heap_hash.result b/mysql-test/suite/heap/heap_hash.result
index ac62427c81c..55d43588403 100644
--- a/mysql-test/suite/heap/heap_hash.result
+++ b/mysql-test/suite/heap/heap_hash.result
@@ -382,6 +382,26 @@ INSERT INTO t1 VALUES('A ', 'A ');
ERROR 23000: Duplicate entry 'A -A ' for key 'key1'
DROP TABLE t1;
End of 5.0 tests
+#
+# MDEV-568 (AKA LP BUG#1007981, AKA MySQL bug#44771)
+# Wrong result for a hash index look-up if the index is unique and
+# the key is NULL
+#
+CREATE TABLE t1 ( pk INT PRIMARY KEY, val INT, UNIQUE KEY USING HASH(val)) ENGINE=MEMORY;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (2, NULL);
+INSERT INTO t1 VALUES (3, 1);
+INSERT INTO t1 VALUES (4, NULL);
+EXPLAIN SELECT * FROM t1 WHERE val IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref val val 5 const 1 Using where
+SELECT * FROM t1 WHERE val IS NULL;
+pk val
+4 NULL
+2 NULL
+1 NULL
+drop table t1;
+End of 5.2 tests
# bit index in heap tables
create table t1 (a bit(63) not null) engine=heap;
insert into t1 values (869751),(736494),(226312),(802616),(728912);
diff --git a/mysql-test/suite/heap/heap_hash.test b/mysql-test/suite/heap/heap_hash.test
index 80d6ef9c8f2..3fe95e14205 100644
--- a/mysql-test/suite/heap/heap_hash.test
+++ b/mysql-test/suite/heap/heap_hash.test
@@ -285,6 +285,23 @@ DROP TABLE t1;
--echo End of 5.0 tests
+--echo #
+--echo # MDEV-568 (AKA LP BUG#1007981, AKA MySQL bug#44771)
+--echo # Wrong result for a hash index look-up if the index is unique and
+--echo # the key is NULL
+--echo #
+CREATE TABLE t1 ( pk INT PRIMARY KEY, val INT, UNIQUE KEY USING HASH(val)) ENGINE=MEMORY;
+
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (2, NULL);
+INSERT INTO t1 VALUES (3, 1);
+INSERT INTO t1 VALUES (4, NULL);
+EXPLAIN SELECT * FROM t1 WHERE val IS NULL;
+SELECT * FROM t1 WHERE val IS NULL;
+drop table t1;
+
+--echo End of 5.2 tests
+
-- echo # bit index in heap tables
create table t1 (a bit(63) not null) engine=heap;
diff --git a/mysql-test/suite/innodb/t/binlog_consistent.test b/mysql-test/suite/innodb/t/binlog_consistent.test
index f4babb8bad7..20023871093 100644
--- a/mysql-test/suite/innodb/t/binlog_consistent.test
+++ b/mysql-test/suite/innodb/t/binlog_consistent.test
@@ -72,6 +72,7 @@ connection con3;
--echo # Connection con3
COMMIT;
FLUSH LOGS;
+--source include/wait_for_binlog_checkpoint.inc
connection default;
--echo # Connection default
diff --git a/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test b/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test
index b9c6aecd177..751a2bd6b5e 100644
--- a/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test
+++ b/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test
@@ -3,11 +3,6 @@
-- source include/have_innodb.inc
-if (`select plugin_auth_version <= "1.1.8-29.0" from information_schema.plugins where plugin_name='innodb'`)
-{
- --skip Not fixed in XtraDB 1.1.8-29.0 or earlier
-}
-
-- disable_result_log
SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS;
diff --git a/mysql-test/suite/multi_source/multisource.test b/mysql-test/suite/multi_source/multisource.test
index e9d672a9ae3..7a9ee166ec2 100644
--- a/mysql-test/suite/multi_source/multisource.test
+++ b/mysql-test/suite/multi_source/multisource.test
@@ -169,6 +169,7 @@ select * from db2.t1;
--connection master1
flush logs;
+--source include/wait_for_binlog_checkpoint.inc
--save_master_pos
--connection slave
--sync_with_master 0, 'master1'
diff --git a/mysql-test/suite/perfschema/r/relaylog.result b/mysql-test/suite/perfschema/r/relaylog.result
index 8e4039c00c6..a05b0f9a85b 100644
--- a/mysql-test/suite/perfschema/r/relaylog.result
+++ b/mysql-test/suite/perfschema/r/relaylog.result
@@ -56,8 +56,11 @@ where event_name like "%MYSQL_BIN_LOG%"
and event_name not like "%MYSQL_BIN_LOG::update_cond"
order by event_name;
EVENT_NAME COUNT_STAR
+wait/synch/cond/sql/MYSQL_BIN_LOG::COND_binlog_background_thread NONE
+wait/synch/cond/sql/MYSQL_BIN_LOG::COND_binlog_background_thread_end NONE
wait/synch/cond/sql/MYSQL_BIN_LOG::COND_queue_busy NONE
wait/synch/cond/sql/MYSQL_BIN_LOG::COND_xid_list NONE
+wait/synch/mutex/sql/MYSQL_BIN_LOG::LOCK_binlog_background_thread MANY
wait/synch/mutex/sql/MYSQL_BIN_LOG::LOCK_index MANY
wait/synch/mutex/sql/MYSQL_BIN_LOG::LOCK_xid_list MANY
"Expect no slave relay log"
@@ -131,8 +134,11 @@ where event_name like "%MYSQL_BIN_LOG%"
and event_name not like "%MYSQL_BIN_LOG::update_cond"
order by event_name;
EVENT_NAME COUNT_STAR
+wait/synch/cond/sql/MYSQL_BIN_LOG::COND_binlog_background_thread MANY
+wait/synch/cond/sql/MYSQL_BIN_LOG::COND_binlog_background_thread_end NONE
wait/synch/cond/sql/MYSQL_BIN_LOG::COND_queue_busy NONE
-wait/synch/cond/sql/MYSQL_BIN_LOG::COND_xid_list NONE
+wait/synch/cond/sql/MYSQL_BIN_LOG::COND_xid_list MANY
+wait/synch/mutex/sql/MYSQL_BIN_LOG::LOCK_binlog_background_thread MANY
wait/synch/mutex/sql/MYSQL_BIN_LOG::LOCK_index MANY
wait/synch/mutex/sql/MYSQL_BIN_LOG::LOCK_xid_list MANY
"Expect a slave relay log"
diff --git a/mysql-test/suite/plugins/r/audit_null.result b/mysql-test/suite/plugins/r/audit_null.result
new file mode 100644
index 00000000000..4cf648510e6
--- /dev/null
+++ b/mysql-test/suite/plugins/r/audit_null.result
@@ -0,0 +1,29 @@
+set @old_global_general_log=@@global.general_log;
+set global general_log=OFF;
+install plugin audit_null soname 'adt_null';
+select 1;
+1
+1
+select foobar;
+ERROR 42S22: Unknown column 'foobar' in 'field list'
+show status like 'audit_null%';
+Variable_name Value
+Audit_null_called 9
+Audit_null_general_error 1
+Audit_null_general_log 3
+Audit_null_general_result 2
+create procedure au1(x char(16)) select concat("test1", x);
+call au1("-12");
+concat("test1", x)
+test1-12
+show status like 'audit_null%';
+Variable_name Value
+Audit_null_called 19
+Audit_null_general_error 1
+Audit_null_general_log 7
+Audit_null_general_result 5
+uninstall plugin audit_null;
+Warnings:
+Warning 1620 Plugin is busy and will be uninstalled on shutdown
+drop procedure au1;
+set global general_log=@old_global_general_log;
diff --git a/mysql-test/suite/plugins/t/audit_null.test b/mysql-test/suite/plugins/t/audit_null.test
new file mode 100644
index 00000000000..428fd0c276e
--- /dev/null
+++ b/mysql-test/suite/plugins/t/audit_null.test
@@ -0,0 +1,30 @@
+
+--source include/not_embedded.inc
+
+if (!$ADT_NULL_SO) {
+ skip No NULL_AUDIT plugin;
+}
+
+set @old_global_general_log=@@global.general_log;
+set global general_log=OFF;
+
+--disable_ps_protocol
+install plugin audit_null soname 'adt_null';
+
+select 1;
+--error 1054
+select foobar;
+
+show status like 'audit_null%';
+
+create procedure au1(x char(16)) select concat("test1", x);
+call au1("-12");
+
+show status like 'audit_null%';
+
+uninstall plugin audit_null;
+--enable_ps_protocol
+
+drop procedure au1;
+set global general_log=@old_global_general_log;
+
diff --git a/mysql-test/suite/rpl/r/rpl_function_defaults.result b/mysql-test/suite/rpl/r/rpl_function_defaults.result
new file mode 100644
index 00000000000..264bb3c9c6d
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_function_defaults.result
@@ -0,0 +1,132 @@
+#
+# Test of function defaults on replicated tables.
+#
+include/master-slave.inc
+[connection master]
+connection master
+SET TIME_ZONE="+10:30";
+SET TIMESTAMP=123456.789123;
+SELECT CURRENT_TIMESTAMP;
+CURRENT_TIMESTAMP
+1970-01-02 20:47:36
+connection slave
+SET TIME_ZONE="+00:00";
+SET TIMESTAMP=987654321.123456;
+SELECT CURRENT_TIMESTAMP;
+CURRENT_TIMESTAMP
+2001-04-19 04:25:21
+connection master
+CREATE TABLE t1 (
+a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+b TIMESTAMP(1) NOT NULL DEFAULT CURRENT_TIMESTAMP(1),
+c TIMESTAMP(2) NOT NULL DEFAULT CURRENT_TIMESTAMP(2),
+d TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
+e TIMESTAMP(4) NOT NULL DEFAULT CURRENT_TIMESTAMP(4),
+f TIMESTAMP(5) NOT NULL DEFAULT CURRENT_TIMESTAMP(5),
+g TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+h DATETIME DEFAULT CURRENT_TIMESTAMP,
+i DATETIME(1) DEFAULT CURRENT_TIMESTAMP(1),
+j DATETIME(2) DEFAULT CURRENT_TIMESTAMP(2),
+k DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3),
+l DATETIME(4) DEFAULT CURRENT_TIMESTAMP(4),
+m DATETIME(5) DEFAULT CURRENT_TIMESTAMP(5),
+n DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
+o INT
+);
+INSERT INTO t1 ( o ) VALUES ( 1 );
+CREATE TABLE t2 (
+a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+b TIMESTAMP(1) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(1),
+c TIMESTAMP(2) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(2),
+d TIMESTAMP(3) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(3),
+e TIMESTAMP(4) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(4),
+f TIMESTAMP(5) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(5),
+g TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+h DATETIME ON UPDATE CURRENT_TIMESTAMP,
+i DATETIME(1) ON UPDATE CURRENT_TIMESTAMP(1),
+j DATETIME(2) ON UPDATE CURRENT_TIMESTAMP(2),
+k DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3),
+l DATETIME(4) ON UPDATE CURRENT_TIMESTAMP(4),
+m DATETIME(5) ON UPDATE CURRENT_TIMESTAMP(5),
+n DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
+o INT
+);
+INSERT INTO t2 ( o ) VALUES ( 1 );
+sync_slave_with_master
+connection slave
+SELECT * FROM t1;
+a 1970-01-02 10:17:36
+b 1970-01-02 10:17:36.7
+c 1970-01-02 10:17:36.78
+d 1970-01-02 10:17:36.789
+e 1970-01-02 10:17:36.7891
+f 1970-01-02 10:17:36.78912
+g 1970-01-02 10:17:36.789123
+h 1970-01-02 20:47:36
+i 1970-01-02 20:47:36.7
+j 1970-01-02 20:47:36.78
+k 1970-01-02 20:47:36.789
+l 1970-01-02 20:47:36.7891
+m 1970-01-02 20:47:36.78912
+n 1970-01-02 20:47:36.789123
+o 1
+SELECT * FROM t2;
+a 0000-00-00 00:00:00
+b 0000-00-00 00:00:00.0
+c 0000-00-00 00:00:00.00
+d 0000-00-00 00:00:00.000
+e 0000-00-00 00:00:00.0000
+f 0000-00-00 00:00:00.00000
+g 0000-00-00 00:00:00.000000
+h NULL
+i NULL
+j NULL
+k NULL
+l NULL
+m NULL
+n NULL
+o 1
+connection master
+SET TIMESTAMP=1234567890.123456;
+SELECT CURRENT_TIMESTAMP;
+CURRENT_TIMESTAMP
+2009-02-14 10:01:30
+UPDATE t1 SET o = 2;
+UPDATE t2 SET o = 2;
+sync_slave_with_master
+connection slave
+SELECT * FROM t1;
+a 1970-01-02 10:17:36
+b 1970-01-02 10:17:36.7
+c 1970-01-02 10:17:36.78
+d 1970-01-02 10:17:36.789
+e 1970-01-02 10:17:36.7891
+f 1970-01-02 10:17:36.78912
+g 1970-01-02 10:17:36.789123
+h 1970-01-02 20:47:36
+i 1970-01-02 20:47:36.7
+j 1970-01-02 20:47:36.78
+k 1970-01-02 20:47:36.789
+l 1970-01-02 20:47:36.7891
+m 1970-01-02 20:47:36.78912
+n 1970-01-02 20:47:36.789123
+o 2
+SELECT * FROM t2;
+a 2009-02-13 23:31:30
+b 2009-02-13 23:31:30.1
+c 2009-02-13 23:31:30.12
+d 2009-02-13 23:31:30.123
+e 2009-02-13 23:31:30.1234
+f 2009-02-13 23:31:30.12345
+g 2009-02-13 23:31:30.123456
+h 2009-02-14 10:01:30
+i 2009-02-14 10:01:30.1
+j 2009-02-14 10:01:30.12
+k 2009-02-14 10:01:30.123
+l 2009-02-14 10:01:30.1234
+m 2009-02-14 10:01:30.12345
+n 2009-02-14 10:01:30.123456
+o 2
+connection master
+DROP TABLE t1, t2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_function_defaults.test b/mysql-test/suite/rpl/t/rpl_function_defaults.test
new file mode 100644
index 00000000000..24bec10d305
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_function_defaults.test
@@ -0,0 +1,93 @@
+--echo #
+--echo # Test of function defaults on replicated tables.
+--echo #
+
+source include/master-slave.inc;
+
+--echo connection master
+connection master;
+SET TIME_ZONE="+10:30";
+SET TIMESTAMP=123456.789123;
+SELECT CURRENT_TIMESTAMP;
+
+--echo connection slave
+connection slave;
+SET TIME_ZONE="+00:00";
+SET TIMESTAMP=987654321.123456;
+SELECT CURRENT_TIMESTAMP;
+
+--echo connection master
+connection master;
+CREATE TABLE t1 (
+ a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ b TIMESTAMP(1) NOT NULL DEFAULT CURRENT_TIMESTAMP(1),
+ c TIMESTAMP(2) NOT NULL DEFAULT CURRENT_TIMESTAMP(2),
+ d TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
+ e TIMESTAMP(4) NOT NULL DEFAULT CURRENT_TIMESTAMP(4),
+ f TIMESTAMP(5) NOT NULL DEFAULT CURRENT_TIMESTAMP(5),
+ g TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+ h DATETIME DEFAULT CURRENT_TIMESTAMP,
+ i DATETIME(1) DEFAULT CURRENT_TIMESTAMP(1),
+ j DATETIME(2) DEFAULT CURRENT_TIMESTAMP(2),
+ k DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3),
+ l DATETIME(4) DEFAULT CURRENT_TIMESTAMP(4),
+ m DATETIME(5) DEFAULT CURRENT_TIMESTAMP(5),
+ n DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
+ o INT
+);
+
+INSERT INTO t1 ( o ) VALUES ( 1 );
+
+CREATE TABLE t2 (
+ a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+ b TIMESTAMP(1) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(1),
+ c TIMESTAMP(2) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(2),
+ d TIMESTAMP(3) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(3),
+ e TIMESTAMP(4) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(4),
+ f TIMESTAMP(5) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(5),
+ g TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
+ h DATETIME ON UPDATE CURRENT_TIMESTAMP,
+ i DATETIME(1) ON UPDATE CURRENT_TIMESTAMP(1),
+ j DATETIME(2) ON UPDATE CURRENT_TIMESTAMP(2),
+ k DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3),
+ l DATETIME(4) ON UPDATE CURRENT_TIMESTAMP(4),
+ m DATETIME(5) ON UPDATE CURRENT_TIMESTAMP(5),
+ n DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
+ o INT
+);
+
+INSERT INTO t2 ( o ) VALUES ( 1 );
+
+--echo sync_slave_with_master
+sync_slave_with_master;
+
+--echo connection slave
+connection slave;
+
+query_vertical SELECT * FROM t1;
+query_vertical SELECT * FROM t2;
+
+--echo connection master
+connection master;
+
+SET TIMESTAMP=1234567890.123456;
+SELECT CURRENT_TIMESTAMP;
+
+UPDATE t1 SET o = 2;
+UPDATE t2 SET o = 2;
+
+--echo sync_slave_with_master
+sync_slave_with_master;
+
+--echo connection slave
+connection slave;
+
+query_vertical SELECT * FROM t1;
+query_vertical SELECT * FROM t2;
+
+--echo connection master
+connection master;
+
+DROP TABLE t1, t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/sys_vars/r/default_storage_engine_basic.result b/mysql-test/suite/sys_vars/r/default_storage_engine_basic.result
index 727e6ca88f2..7e12c7dc477 100644
--- a/mysql-test/suite/sys_vars/r/default_storage_engine_basic.result
+++ b/mysql-test/suite/sys_vars/r/default_storage_engine_basic.result
@@ -19,7 +19,7 @@ MyISAM
SET @@global.default_storage_engine = MERGE;
SELECT @@global.default_storage_engine;
@@global.default_storage_engine
-MRG_MYISAM
+MRG_MyISAM
SET @@global.default_storage_engine = MEMORY;
SELECT @@global.default_storage_engine;
@@global.default_storage_engine
@@ -36,7 +36,7 @@ MyISAM
SET @@session.default_storage_engine = MERGE;
SELECT @@session.default_storage_engine;
@@session.default_storage_engine
-MRG_MYISAM
+MRG_MyISAM
SET @@session.default_storage_engine = MEMORY;
SELECT @@session.default_storage_engine;
@@session.default_storage_engine
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/storage_engine_basic.result b/mysql-test/suite/sys_vars/r/storage_engine_basic.result
index 2831ebaa500..9461707dd79 100644
--- a/mysql-test/suite/sys_vars/r/storage_engine_basic.result
+++ b/mysql-test/suite/sys_vars/r/storage_engine_basic.result
@@ -19,7 +19,7 @@ MyISAM
SET @@global.storage_engine = MERGE;
SELECT @@global.storage_engine;
@@global.storage_engine
-MRG_MYISAM
+MRG_MyISAM
SET @@global.storage_engine = MEMORY;
SELECT @@global.storage_engine;
@@global.storage_engine
@@ -36,7 +36,7 @@ MyISAM
SET @@session.storage_engine = MERGE;
SELECT @@session.storage_engine;
@@session.storage_engine
-MRG_MYISAM
+MRG_MyISAM
SET @@session.storage_engine = MEMORY;
SELECT @@session.storage_engine;
@@session.storage_engine
diff --git a/mysql-test/suite/sys_vars/t/innodb_buffer_pool_populate_basic.test b/mysql-test/suite/sys_vars/t/innodb_buffer_pool_populate_basic.test
new file mode 100644
index 00000000000..00aa476e8d2
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/innodb_buffer_pool_populate_basic.test
@@ -0,0 +1 @@
+--echo XtraDB extension
diff --git a/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc b/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc
index ddf13fef6a1..eb7e6ad32b9 100644
--- a/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc
+++ b/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc
@@ -108,3 +108,44 @@ select * from t1;
drop table t1,t2;
drop procedure p1;
+
+--echo #
+--echo # Bug mdev-3845: values of virtual columns are not computed for triggers
+--echo #
+
+CREATE TABLE t1 (
+ a INTEGER UNSIGNED NULL DEFAULT NULL,
+ b INTEGER UNSIGNED GENERATED ALWAYS AS (a) VIRTUAL
+);
+
+CREATE TABLE t2 (c INTEGER UNSIGNED NOT NULL);
+
+DELIMITER |;
+
+CREATE TRIGGER t1_ins_aft
+ AFTER INSERT
+ ON t1
+ FOR EACH ROW
+BEGIN
+ INSERT INTO t2 (c) VALUES (NEW.b);
+END |
+
+CREATE TRIGGER t1_del_bef
+ BEFORE DELETE
+ ON t1
+ FOR EACH ROW
+BEGIN
+ INSERT INTO t2 (c) VALUES (OLD.b);
+END |
+
+DELIMITER ;|
+
+INSERT INTO t1 (a) VALUES (1), (2), (3);
+SELECT * FROM t2;
+DELETE FROM t1;
+SELECT * FROM t2;
+
+DROP TRIGGER t1_ins_aft;
+DROP TRIGGER t1_del_bef;
+DROP TABLE t1,t2;
+
diff --git a/mysql-test/suite/vcol/r/vcol_merge.result b/mysql-test/suite/vcol/r/vcol_merge.result
index 4b5ed838c3a..e127ec35e8c 100644
--- a/mysql-test/suite/vcol/r/vcol_merge.result
+++ b/mysql-test/suite/vcol/r/vcol_merge.result
@@ -4,5 +4,5 @@ create table t2 (a int, b int as (a % 10));
insert into t1 values (1,default);
insert into t2 values (2,default);
create table t3 (a int, b int as (a % 10)) engine=MERGE UNION=(t1,t2);
-ERROR HY000: MRG_MYISAM storage engine does not support computed columns
+ERROR HY000: MRG_MyISAM storage engine does not support computed columns
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/create.test b/mysql-test/t/create.test
index d80127df860..258213620ce 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -55,10 +55,10 @@ create table a (`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
#
# Some wrong defaults, so these creates should fail too (Bug #5902)
#
---error 1067
create table t1 (a datetime default now());
---error 1294
+drop table t1;
create table t1 (a datetime on update now());
+drop table t1;
--error 1067
create table t1 (a int default 100 auto_increment);
--error 1067
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/function_defaults.test b/mysql-test/t/function_defaults.test
new file mode 100644
index 00000000000..dd29b4609cb
--- /dev/null
+++ b/mysql-test/t/function_defaults.test
@@ -0,0 +1,23 @@
+--echo #
+--echo # Test of function defaults for any server, including embedded.
+--echo #
+
+--source include/have_innodb.inc
+
+--echo #
+--echo # Function defaults run 1. No microsecond precision.
+--echo #
+let $current_timestamp=CURRENT_TIMESTAMP;
+let $now=NOW();
+let $timestamp=TIMESTAMP;
+let $datetime=DATETIME;
+source 'include/function_defaults.inc';
+
+--echo #
+--echo # Function defaults run 2. Six digits scale on seconds precision.
+--echo #
+let $current_timestamp=CURRENT_TIMESTAMP(6);
+let $now=NOW(6);
+let $timestamp=TIMESTAMP(6);
+let $datetime=DATETIME(6);
+source 'include/function_defaults.inc';
diff --git a/mysql-test/t/function_defaults_notembedded.test b/mysql-test/t/function_defaults_notembedded.test
new file mode 100644
index 00000000000..3d686c4b272
--- /dev/null
+++ b/mysql-test/t/function_defaults_notembedded.test
@@ -0,0 +1,18 @@
+--echo #
+--echo # Test of function defaults for non-embedded server.
+--echo #
+
+--source include/not_embedded.inc
+--source include/have_debug_sync.inc
+
+--echo #
+--echo # Function defaults run 1. No microsecond precision.
+--echo #
+let $timestamp=TIMESTAMP;
+--source include/function_defaults_notembedded.inc
+
+--echo #
+--echo # Function defaults run 2. Six digits scale on seconds precision.
+--echo #
+let $timestamp=TIMESTAMP(6);
+--source include/function_defaults_notembedded.inc
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index 2a346867da2..854023052cf 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/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/partition.test b/mysql-test/t/partition.test
index ef0d3df6661..038907702d5 100644
--- a/mysql-test/t/partition.test
+++ b/mysql-test/t/partition.test
@@ -2395,6 +2395,14 @@ SELECT 1 FROM t1 WHERE b < SOME
DROP TABLE t1;
+--echo
+--echo MDEV-612 Valgrind error in ha_maria::check_if_incompatible_data
+--echo
+
+CREATE TABLE t1 (a INT, b INT, KEY(a)) ENGINE=Aria PARTITION BY KEY(a) PARTITIONS 2;
+ALTER TABLE t1 ADD KEY (b);
+drop table t1;
+
--echo End of 5.1 tests
--echo #
diff --git a/mysql-test/t/range_vs_index_merge.test b/mysql-test/t/range_vs_index_merge.test
index 613a7cf5760..fb8fd778559 100644
--- a/mysql-test/t/range_vs_index_merge.test
+++ b/mysql-test/t/range_vs_index_merge.test
@@ -675,6 +675,64 @@ SELECT Name, Country, Population FROM City WHERE
$cond;
set optimizer_switch=@save_optimizer_switch;
+
+--echo #
+--echo # Bug mdev-585: range vs index-merge with ORDER BY ... LIMIT n
+--echo # (LP bug #637962)
+--echo #
+
+DROP INDEX CountryPopulation ON City;
+DROP INDEX CountryName ON City;
+DROP INDEX CityName on City;
+
+CREATE INDEX Name ON City(Name);
+CREATE INDEX Population ON City(Population);
+
+
+--replace_column 9 #
+EXPLAIN
+SELECT * FROM City
+ WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+ AND (Population >= 100000 AND Population < 120000);
+FLUSH STATUS;
+SELECT * FROM City
+ WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+ AND (Population >= 100000 AND Population < 120000);
+SHOW STATUS LIKE 'Handler_read_%';
+
+
+--replace_column 9 #
+EXPLAIN
+SELECT * FROM City
+ WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+ AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+
+FLUSH STATUS;
+SELECT * FROM City
+ WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+ AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+SHOW STATUS LIKE 'Handler_read_%';
+
+
+set optimizer_switch='index_merge=off';
+
+--replace_column 9 #
+EXPLAIN
+SELECT * FROM City
+ WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+ AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+
+FLUSH STATUS;
+SELECT * FROM City
+ WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'H'))
+ AND (Population >= 100000 AND Population < 120000)
+ORDER BY Population LIMIT 5;
+SHOW STATUS LIKE 'Handler_read_%';
+
+set optimizer_switch=@save_optimizer_switch;
DROP DATABASE world;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 07f0084e7ab..e7cb505b19f 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -5078,6 +5078,82 @@ SELECT col_int_nokey FROM ot
DROP TABLE ot,it1,it2;
+--echo #
+--echo # MDEV-746
+--echo # Bug#13651009 WRONG RESULT FROM DERIVED TABLE IF THE SUBQUERY
+--echo # HAS AN EMPTY RESULT
+--echo #
+
+CREATE TABLE t1 (
+ pk int NOT NULL,
+ col_int_nokey int NOT NULL,
+ col_int_key int NOT NULL,
+ col_time_key time NOT NULL,
+ col_varchar_key varchar(1) NOT NULL,
+ col_varchar_nokey varchar(1) NOT NULL,
+ PRIMARY KEY (pk),
+ KEY col_int_key (col_int_key),
+ KEY col_time_key (col_time_key),
+ KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+
+CREATE TABLE t2 (
+ pk int NOT NULL AUTO_INCREMENT,
+ col_int_nokey int NOT NULL,
+ col_int_key int NOT NULL,
+ col_time_key time NOT NULL,
+ col_varchar_key varchar(1) NOT NULL,
+ col_varchar_nokey varchar(1) NOT NULL,
+ PRIMARY KEY (pk),
+ KEY col_int_key (col_int_key),
+ KEY col_time_key (col_time_key),
+ KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=MyISAM;
+
+INSERT INTO t2 VALUES (1,4,4,'00:00:00','b','b');
+
+SET @var2:=4, @var3:=8;
+
+--echo
+--echo Testcase without inner subquery
+
+let $subq=
+SELECT @var3:=12, sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key + NULL) IS NULL OR
+ sq4_alias1.col_varchar_key = @var3;
+
+eval EXPLAIN $subq;
+eval $subq;
+SELECT @var3;
+
+# Now as derived table:
+eval EXPLAIN SELECT * FROM ( $subq ) AS alias3;
+eval SELECT * FROM ( $subq ) AS alias3;
+SELECT @var3;
+
+--echo
+--echo Testcase with inner subquery; crashed WL#6095
+SET @var3=8;
+let $subq=
+SELECT sq4_alias1.*
+FROM t1 AS sq4_alias1
+WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
+ NOT IN
+ (SELECT c_sq1_alias1.col_varchar_key AS c_sq1_field1,
+ c_sq1_alias1.col_varchar_nokey AS c_sq1_field2
+ FROM t2 AS c_sq1_alias1
+ WHERE (c_sq1_alias1.col_int_nokey != @var2
+ OR c_sq1_alias1.pk != @var3));
+
+eval EXPLAIN $subq;
+eval $subq;
+# Now as derived table:
+eval EXPLAIN SELECT * FROM ( $subq ) AS alias3;
+eval SELECT * FROM ( $subq ) AS alias3;
+
+DROP TABLE t1,t2;
+
--echo End of 5.2 tests
--echo #
diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test
index 575c30431b6..1c17743e7f1 100644
--- a/mysql-test/t/type_timestamp.test
+++ b/mysql-test/t/type_timestamp.test
@@ -86,17 +86,16 @@ drop table t1;
# Test for TIMESTAMP column with default now() and on update now() clauses
#
-# These statements should fail.
---error 1293
create table t1 (t1 timestamp, t2 timestamp default now());
---error 1293
+drop table t1;
create table t1 (t1 timestamp, t2 timestamp on update now());
---error 1293
+drop table t1;
create table t1 (t1 timestamp, t2 timestamp default now() on update now());
---error 1293
+drop table t1;
create table t1 (t1 timestamp default now(), t2 timestamp on update now());
---error 1293
+drop table t1;
create table t1 (t1 timestamp on update now(), t2 timestamp default now() on update now());
+drop table t1;
# Let us test TIMESTAMP auto-update behaviour
# Also we will test behaviour of TIMESTAMP field in SHOW CREATE TABLE and
diff --git a/mysql-test/t/type_timestamp_hires.test b/mysql-test/t/type_timestamp_hires.test
index 8e1f8586956..17a2c3e1f1f 100644
--- a/mysql-test/t/type_timestamp_hires.test
+++ b/mysql-test/t/type_timestamp_hires.test
@@ -14,3 +14,18 @@ insert t1 values ();
select * from t1;
drop table t1;
+#
+# MDEV-438 Microseconds: Precision is ignored in CURRENT_TIMESTAMP(N) when it is given as a default column value
+#
+create table t1 (a timestamp(5) default current_timestamp); drop table t1;
+create table t1 (a timestamp(5) default current_timestamp()); drop table t1;
+--error ER_INVALID_DEFAULT
+create table t1 (a timestamp(5) default current_timestamp(2));
+create table t1 (a timestamp(5) default current_timestamp(5)); drop table t1;
+create table t1 (a timestamp(5) default current_timestamp(6)); drop table t1;
+create table t1 (a timestamp(5) on update current_timestamp); drop table t1;
+create table t1 (a timestamp(5) on update current_timestamp()); drop table t1;
+--error ER_INVALID_ON_UPDATE
+create table t1 (a timestamp(5) on update current_timestamp(3));
+create table t1 (a timestamp(5) on update current_timestamp(5)); drop table t1;
+create table t1 (a timestamp(5) on update current_timestamp(6)); drop table t1;
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 3e30f5cdbda..072a179e822 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -4751,6 +4751,40 @@ drop tables t1,t2;
--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 # -----------------------------------------------------------------
--echo # some subqueries in SELECT list test
create table t1 (a int, b int);
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 10382163331..2a710458670 100644
--- a/mysys/my_context.c
+++ b/mysys/my_context.c
@@ -454,7 +454,7 @@ 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
+#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
diff --git a/plugin/audit_null/audit_null.c b/plugin/audit_null/audit_null.c
index 469e5ae494c..be0c70fbd35 100644
--- a/plugin/audit_null/audit_null.c
+++ b/plugin/audit_null/audit_null.c
@@ -145,7 +145,7 @@ mysql_declare_plugin(audit_null)
{
MYSQL_AUDIT_PLUGIN, /* type */
&audit_null_descriptor, /* descriptor */
- "NULL_AUDIT", /* name */
+ "AUDIT_NULL", /* name */
"Oracle Corp", /* author */
"Simple NULL Audit", /* description */
PLUGIN_LICENSE_GPL,
diff --git a/plugin/feedback/CMakeLists.txt b/plugin/feedback/CMakeLists.txt
index 627e4d643fb..3e14ef3918b 100644
--- a/plugin/feedback/CMakeLists.txt
+++ b/plugin/feedback/CMakeLists.txt
@@ -1,9 +1,11 @@
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql ${CMAKE_SOURCE_DIR}/regex
- ${CMAKE_SOURCE_DIR}/extra/yassl/include)
+ ${SSL_INCLUDE_DIRS})
SET(FEEDBACK_SOURCES feedback.cc sender_thread.cc
url_base.cc url_http.cc utils.cc)
+ADD_DEFINITIONS(${SSL_DEFINES})
+
INCLUDE (CheckIncludeFiles)
CHECK_INCLUDE_FILES (netdb.h HAVE_NETDB_H)
IF(HAVE_NETDB_H)
@@ -11,8 +13,10 @@ IF(HAVE_NETDB_H)
ENDIF(HAVE_NETDB_H)
IF(WIN32)
- #SET(FEEDBACK_LIBS Ws2_32)
- MYSQL_ADD_PLUGIN(FEEDBACK ${FEEDBACK_SOURCES} STATIC_ONLY DEFAULT)
+ MYSQL_ADD_PLUGIN(FEEDBACK ${FEEDBACK_SOURCES}
+ LINK_LIBRARIES ${SSL_LIBRARIES}
+ STATIC_ONLY DEFAULT)
ELSE(WIN32)
- MYSQL_ADD_PLUGIN(FEEDBACK ${FEEDBACK_SOURCES})
+ MYSQL_ADD_PLUGIN(FEEDBACK ${FEEDBACK_SOURCES}
+ LINK_LIBRARIES ${SSL_LIBRARIES})
ENDIF(WIN32)
diff --git a/plugin/feedback/url_http.cc b/plugin/feedback/url_http.cc
index a9d4c5bbbaf..f214f7a6ccc 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, 0, 0)) ||
+ sslconnect(ssl_fd, vio, send_timeout, &ssl_error))
{
+ const char *err;
+ if (ssl_init_error != SSL_INITERR_NOERROR)
+ err= sslGetErrString(ssl_init_error);
+ else
+ {
+ ERR_error_string_n(ssl_error, buf, sizeof(buf));
+ buf[sizeof(buf)-1]= 0;
+ err= buf;
+ }
+
sql_print_error("feedback plugin: ssl failed for url '%s' %s",
- full_url.str, buf);
+ full_url.str, err);
if (ssl_fd)
free_vio_ssl_acceptor_fd(ssl_fd);
closesocket(fd);
@@ -256,18 +261,21 @@ int Url_http::send(const char* data, size_t data_length)
Extract the first string between <h1>...</h1> tags
and put it as a server reply into the error log.
*/
+ len= 0;
for (;;)
{
- size_t i= vio_read(vio, (uchar*)buf + len, sizeof(buf) - len - 1);
+ size_t i= sizeof(buf) - len - 1;
+ if (i)
+ i= vio_read(vio, (uchar*)buf + len, i);
if ((int)i <= 0)
break;
len+= i;
}
- if (len && len < sizeof(buf))
+ if (len)
{
char *from;
- buf[len+1]= 0; // safety
+ buf[len]= 0; // safety
if ((from= strstr(buf, "<h1>")))
{
@@ -296,7 +304,7 @@ int Url_http::send(const char* data, size_t data_length)
if (ssl)
{
SSL_CTX_free(ssl_fd->ssl_context);
- my_free(ssl_fd, MYF(0));
+ my_free(ssl_fd);
}
#endif
diff --git a/scripts/mysql_config.sh b/scripts/mysql_config.sh
index fd15d7ac746..38cd2b6b910 100644
--- a/scripts/mysql_config.sh
+++ b/scripts/mysql_config.sh
@@ -92,11 +92,7 @@ plugindir_rel=`echo $plugindir | sed -e "s;^$basedir/;;"`
fix_path plugindir $plugindir_rel lib/mysql/plugin lib/plugin
pkgincludedir='@pkgincludedir@'
-if [ -f "$basedir/include/mysql/mysql.h" ]; then
- pkgincludedir="$basedir/include/mysql"
-elif [ -f "$basedir/include/mysql.h" ]; then
- pkgincludedir="$basedir/include"
-fi
+fix_path pkgincludedir include/mysql
version='@VERSION@'
socket='@MYSQL_UNIX_ADDR@'
@@ -125,8 +121,11 @@ if [ -r "$pkglibdir/libmygcc.a" ]; then
embedded_libs="$embedded_libs -lmygcc "
fi
-cflags="-I$pkgincludedir @CFLAGS@ " #note: end space!
include="-I$pkgincludedir"
+if [ "$basedir" != "/usr" ]; then
+ include="$include -I$pkgincludedir/.."
+fi
+cflags="$include @CFLAGS@ " #note: end space!
# Remove some options that a client doesn't have to care about
# FIXME until we have a --cxxflags, we need to remove -Xa
diff --git a/scripts/mysql_secure_installation.pl.in b/scripts/mysql_secure_installation.pl.in
index de549add904..188a6bd7104 100755
--- a/scripts/mysql_secure_installation.pl.in
+++ b/scripts/mysql_secure_installation.pl.in
@@ -1,7 +1,7 @@
#!/usr/bin/perl
# -*- cperl -*-
#
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates
+# Copyright (c) 2007, 2012, Oracle and/or its affiliates.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/scripts/mysql_secure_installation.sh b/scripts/mysql_secure_installation.sh
index 28c631a46d5..9e9bce9fa87 100644
--- a/scripts/mysql_secure_installation.sh
+++ b/scripts/mysql_secure_installation.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-# Copyright (c) 2002, 2012, Oracle and/or its affiliates
+# Copyright (c) 2002, 2012, Oracle and/or its affiliates.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/sql-bench/test-table-elimination.sh b/sql-bench/test-table-elimination.sh
index 0dcfe975486..5b494688bec 100755
--- a/sql-bench/test-table-elimination.sh
+++ b/sql-bench/test-table-elimination.sh
@@ -1,4 +1,3 @@
-
#!@PERL@
# Test of table elimination feature
@@ -93,7 +92,7 @@ $dbh->do("create view elim_current_facts as $select_current_full_facts");
if ($opt_lock_tables)
{
- do_query($dbh,"LOCK TABLES elim_facts, elim_attr1, elim_attr2 WRITE");
+ do_query($dbh,"LOCK TABLES elim_current_facts WRITE, elim_facts WRITE, elim_attr1 WRITE, elim_attr2 WRITE");
}
if ($opt_fast && defined($server->{vacuum}))
@@ -200,12 +199,14 @@ if ($opt_lock_tables)
if ($opt_fast && defined($server->{vacuum}))
{
- $server->vacuum(0,\$dbh,["elim_facts", "elim_attr1", "elim_attr2"]);
+ $server->vacuum(1,\$dbh,"elim_facts");
+ $server->vacuum(1,\$dbh,"elim_attr1");
+ $server->vacuum(1,\$dbh,"elim_attr2");
}
if ($opt_lock_tables)
{
- do_query($dbh,"LOCK TABLES elim_facts, elim_attr1, elim_attr2 WRITE");
+ do_query($dbh,"LOCK TABLES elim_current_facts READ, elim_facts READ, elim_attr1 READ, elim_attr2 READ");
}
####
diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc
index 3ef1f22e2b8..6c8eae82a47 100644
--- a/sql/debug_sync.cc
+++ b/sql/debug_sync.cc
@@ -984,6 +984,7 @@ static bool debug_sync_eval_action(THD *thd, char *action_str)
DBUG_ENTER("debug_sync_eval_action");
DBUG_ASSERT(thd);
DBUG_ASSERT(action_str);
+ DBUG_PRINT("debug_sync", ("action_str='%s'", action_str));
/*
Get debug sync point name. Or a special command.
diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc
index d77c6e3a683..12d34580d3c 100644
--- a/sql/event_db_repository.cc
+++ b/sql/event_db_repository.cc
@@ -830,9 +830,6 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
(int) table->field[ET_FIELD_ON_COMPLETION]->val_int()))
goto end;
- /* Don't update create on row update. */
- table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
-
/*
mysql_event_fill_row() calls my_error() in case of error so no need to
handle it here
@@ -1134,8 +1131,6 @@ update_timing_fields_for_event(THD *thd,
goto end;
store_record(table, record[1]);
- /* Don't update create on row update. */
- table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
my_tz_OFFSET0->gmt_sec_to_TIME(&time, last_executed);
fields[ET_FIELD_LAST_EXECUTED]->set_notnull();
diff --git a/sql/field.cc b/sql/field.cc
index e0ecd6ab74f..a18c72119be 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -50,11 +50,6 @@
Instansiate templates and static variables
*****************************************************************************/
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-template class List<Create_field>;
-template class List_iterator<Create_field>;
-#endif
-
static const char *zero_timestamp="0000-00-00 00:00:00.000000";
/* number of bytes to store second_part part of the TIMESTAMP(N) */
@@ -1817,6 +1812,10 @@ Field *Field::new_field(MEM_ROOT *root, TABLE *new_table,
tmp->key_start.init(0);
tmp->part_of_key.init(0);
tmp->part_of_sortkey.init(0);
+ /*
+ TODO: it is not clear why this method needs to reset unireg_check.
+ Try not to reset it, or explain why it needs to be reset.
+ */
tmp->unireg_check= Field::NONE;
tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG |
ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG);
@@ -4369,16 +4368,10 @@ void Field_double::sql_type(String &res) const
2038-01-01 00:00:00 UTC stored as number of seconds since Unix
Epoch in UTC.
- Up to one of timestamps columns in the table can be automatically
- set on row update and/or have NOW() as default value.
- TABLE::timestamp_field points to Field object for such timestamp with
- auto-set-on-update. TABLE::time_stamp holds offset in record + 1 for this
- field, and is used by handler code which performs updates required.
-
Actually SQL-99 says that we should allow niladic functions (like NOW())
- as defaults for any field. Current limitations (only NOW() and only
- for one TIMESTAMP field) are because of restricted binary .frm format
- and should go away in the future.
+ as defaults for any field. The current limitation (only NOW() and only
+ for TIMESTAMP and DATETIME fields) are because of restricted binary .frm
+ format and should go away in the future.
Also because of this limitation of binary .frm format we use 5 different
unireg_check values with TIMESTAMP field to distinguish various cases of
@@ -4419,10 +4412,12 @@ Field_timestamp::Field_timestamp(uchar *ptr_arg, uint32 len_arg,
{
/* For 4.0 MYD and 4.0 InnoDB compatibility */
flags|= UNSIGNED_FLAG | BINARY_FLAG;
- if (unireg_check != NONE && !share->timestamp_field)
+ if (unireg_check != NONE)
{
- /* This timestamp has auto-update */
- share->timestamp_field= this;
+ /*
+ We mark the flag with TIMESTAMP_FLAG to indicate to the client that
+ this field will be automaticly updated on insert.
+ */
flags|= TIMESTAMP_FLAG;
if (unireg_check != TIMESTAMP_DN_FIELD)
flags|= ON_UPDATE_NOW_FLAG;
@@ -4430,40 +4425,6 @@ Field_timestamp::Field_timestamp(uchar *ptr_arg, uint32 len_arg,
}
-/**
- Get auto-set type for TIMESTAMP field.
-
- Returns value indicating during which operations this TIMESTAMP field
- should be auto-set to current timestamp.
-*/
-timestamp_auto_set_type Field_timestamp::get_auto_set_type() const
-{
- switch (unireg_check)
- {
- case TIMESTAMP_DN_FIELD:
- return TIMESTAMP_AUTO_SET_ON_INSERT;
- case TIMESTAMP_UN_FIELD:
- return TIMESTAMP_AUTO_SET_ON_UPDATE;
- case TIMESTAMP_OLD_FIELD:
- /*
- Although we can have several such columns in legacy tables this
- function should be called only for first of them (i.e. the one
- having auto-set property).
- */
- DBUG_ASSERT(table->timestamp_field == this);
- /* Fall-through */
- case TIMESTAMP_DNUN_FIELD:
- return TIMESTAMP_AUTO_SET_ON_BOTH;
- default:
- /*
- Normally this function should not be called for TIMESTAMPs without
- auto-set property.
- */
- DBUG_ASSERT(0);
- return TIMESTAMP_NO_AUTO_SET;
- }
-}
-
my_time_t Field_timestamp::get_timestamp(ulong *sec_part) const
{
ASSERT_COLUMN_MARKED_FOR_READ;
@@ -4713,6 +4674,34 @@ int Field_timestamp::set_time()
return 0;
}
+/**
+ Mark the field as having an explicit default value.
+
+ @param value if available, the value that the field is being set to
+
+ @note
+ Fields that have an explicit default value should not be updated
+ automatically via the DEFAULT or ON UPDATE functions. The functions
+ that deal with data change functionality (INSERT/UPDATE/LOAD),
+ determine if there is an explicit value for each field before performing
+ the data change, and call this method to mark the field.
+
+ For timestamp columns, the only case where a column is not marked
+ as been given a value are:
+ - It's explicitly assigned with DEFAULT
+ - We assign NULL to a timestamp field that is defined as NOT NULL.
+ This is how MySQL has worked since it's start.
+*/
+
+void Field_timestamp::set_explicit_default(Item *value)
+{
+ if (((value->type() == Item::DEFAULT_VALUE_ITEM &&
+ !((Item_default_value*)value)->arg) ||
+ (!maybe_null() && value->is_null())))
+ return;
+ set_has_explicit_value();
+}
+
void Field_timestamp_hires::sql_type(String &res) const
{
CHARSET_INFO *cs=res.charset();
@@ -5834,6 +5823,20 @@ void Field_datetime::sql_type(String &res) const
res.set_ascii(STRING_WITH_LEN("datetime"));
}
+
+int Field_datetime::set_time()
+{
+ THD *thd= table->in_use;
+ MYSQL_TIME now_time;
+ thd->variables.time_zone->gmt_sec_to_TIME(&now_time, thd->query_start());
+ now_time.second_part= thd->query_start_sec_part();
+ set_notnull();
+ store_TIME(&now_time);
+ thd->time_zone_used= 1;
+ return 0;
+}
+
+
void Field_datetime_hires::store_TIME(MYSQL_TIME *ltime)
{
ulonglong packed= sec_part_shift(pack_time(ltime), dec);
@@ -8855,16 +8858,37 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
{
uint sign_len, allowed_type_modifier= 0;
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
+ const bool on_update_is_function=
+ (fld_on_update_value != NULL &&
+ fld_on_update_value->type() == Item::FUNC_ITEM);
DBUG_ENTER("Create_field::init()");
field= 0;
field_name= fld_name;
- def= fld_default_value;
flags= fld_type_modifier;
option_list= create_opt;
- unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ?
- Field::NEXT_NUMBER : Field::NONE);
+
+ if (fld_default_value != NULL && fld_default_value->type() == Item::FUNC_ITEM)
+ {
+ /* There is a function default for insertions. */
+ def= NULL;
+ unireg_check= (on_update_is_function ?
+ Field::TIMESTAMP_DNUN_FIELD : // for insertions and for updates.
+ Field::TIMESTAMP_DN_FIELD); // only for insertions.
+ }
+ else
+ {
+ /* No function default for insertions. Either NULL or a constant. */
+ def= fld_default_value;
+ if (on_update_is_function)
+ unireg_check= Field::TIMESTAMP_UN_FIELD; // function default for updates
+ else
+ unireg_check= ((fld_type_modifier & AUTO_INCREMENT_FLAG) != 0 ?
+ Field::NEXT_NUMBER : // Automatic increment.
+ Field::NONE);
+ }
+
decimals= fld_decimals ? (uint)atoi(fld_decimals) : 0;
if (decimals >= NOT_FIXED_DEC)
{
@@ -9085,44 +9109,6 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
}
length+= MAX_DATETIME_WIDTH + (length ? 1 : 0);
flags|= UNSIGNED_FLAG;
-
- if (fld_default_value)
- {
- /* Grammar allows only NOW() value for ON UPDATE clause */
- if (fld_default_value->type() == Item::FUNC_ITEM &&
- ((Item_func*)fld_default_value)->functype() == Item_func::NOW_FUNC)
- {
- unireg_check= (fld_on_update_value ? Field::TIMESTAMP_DNUN_FIELD:
- Field::TIMESTAMP_DN_FIELD);
- /*
- We don't need default value any longer moreover it is dangerous.
- Everything handled by unireg_check further.
- */
- def= 0;
- }
- else
- unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD:
- Field::NONE);
- }
- else
- {
- /*
- If we have default TIMESTAMP NOT NULL column without explicit DEFAULT
- or ON UPDATE values then for the sake of compatiblity we should treat
- this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't
- have another TIMESTAMP column with auto-set option before this one)
- or DEFAULT 0 (in other cases).
- So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will
- replace this value by TIMESTAMP_DNUN_FIELD or NONE later when
- information about all TIMESTAMP fields in table will be availiable.
-
- If we have TIMESTAMP NULL column without explicit DEFAULT value
- we treat it as having DEFAULT NULL attribute.
- */
- unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD :
- (flags & NOT_NULL_FLAG ? Field::TIMESTAMP_OLD_FIELD :
- Field::NONE));
- }
break;
case MYSQL_TYPE_DATE:
/* We don't support creation of MYSQL_TYPE_DATE anymore */
@@ -9588,11 +9574,18 @@ Create_field::Create_field(Field *old_field,Field *orig_field)
def=0;
char_length= length;
- if (!(flags & (NO_DEFAULT_VALUE_FLAG | BLOB_FLAG)) &&
- old_field->ptr && orig_field &&
- (sql_type != MYSQL_TYPE_TIMESTAMP || /* set def only if */
- old_field->table->timestamp_field != old_field || /* timestamp field */
- unireg_check == Field::TIMESTAMP_UN_FIELD)) /* has default val */
+ /*
+ Copy the default value from the column object orig_field, if:
+ 1) The column has a constant default value.
+ 2) The column type is not a BLOB type.
+ 3) The original column (old_field) was properly initialized with a record
+ buffer pointer.
+ 4) The original column doesn't have a default function to auto-initialize
+ the column on INSERT
+ */
+ if (!(flags & (NO_DEFAULT_VALUE_FLAG | BLOB_FLAG)) && // 1) 2)
+ old_field->ptr && orig_field && // 3)
+ !old_field->has_insert_default_function()) // 4)
{
char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff), charset);
@@ -9776,3 +9769,29 @@ key_map Field::get_possible_keys()
return (table->pos_in_table_list->is_materialized_derived() ?
part_of_key : key_start);
}
+
+
+/**
+ Mark the field as having an explicit default value.
+
+ @param value if available, the value that the field is being set to
+
+ @note
+ Fields that have an explicit default value should not be updated
+ automatically via the DEFAULT or ON UPDATE functions. The functions
+ that deal with data change functionality (INSERT/UPDATE/LOAD),
+ determine if there is an explicit value for each field before performing
+ the data change, and call this method to mark the field.
+
+ If the 'value' parameter is NULL, then the field is marked unconditionally
+ as having an explicit value. If 'value' is not NULL, then it can be further
+ analyzed to check if it really should count as a value.
+*/
+
+void Field::set_explicit_default(Item *value)
+{
+ if (value->type() == Item::DEFAULT_VALUE_ITEM &&
+ !((Item_default_value*)value)->arg)
+ return;
+ set_has_explicit_value();
+}
diff --git a/sql/field.h b/sql/field.h
index f22bab0409d..da78a7c7674 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -329,6 +329,46 @@ public:
*null_ptr= ((*null_ptr & (uchar) ~null_bit) |
(null_ptr[l_offset] & null_bit));
}
+
+ bool has_insert_default_function() const
+ {
+ return unireg_check == TIMESTAMP_DN_FIELD ||
+ unireg_check == TIMESTAMP_DNUN_FIELD;
+ }
+
+ bool has_update_default_function() const
+ {
+ return unireg_check == TIMESTAMP_UN_FIELD ||
+ unireg_check == TIMESTAMP_DNUN_FIELD;
+ }
+
+ /*
+ Mark the field as having a value supplied by the client, thus it should
+ not be auto-updated.
+ */
+ void set_has_explicit_value()
+ {
+ flags|= HAS_EXPLICIT_VALUE;
+ }
+
+ virtual void set_explicit_default(Item *value);
+
+ /**
+ Evaluates the @c INSERT default function and stores the result in the
+ field. If no such function exists for the column, or the function is not
+ valid for the column's data type, invoking this function has no effect.
+ */
+ virtual int evaluate_insert_default_function() { return 0; }
+
+
+ /**
+ Evaluates the @c UPDATE default function, if one exists, and stores the
+ result in the record buffer. If no such function exists for the column,
+ or the function is not valid for the column's data type, invoking this
+ function has no effect.
+ */
+ virtual int evaluate_update_default_function() { return 0; }
+
virtual bool binary() const { return 1; }
virtual bool zero_pack() const { return 1; }
virtual enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
@@ -1239,12 +1279,26 @@ public:
virtual int set_time();
virtual void set_default()
{
- if (table->timestamp_field == this &&
- unireg_check != TIMESTAMP_UN_FIELD)
+ if (has_insert_default_function())
set_time();
else
Field::set_default();
}
+ virtual void set_explicit_default(Item *value);
+ virtual int evaluate_insert_default_function()
+ {
+ int res= 0;
+ if (has_insert_default_function())
+ res= set_time();
+ return res;
+ }
+ virtual int evaluate_update_default_function()
+ {
+ int res= 0;
+ if (has_update_default_function())
+ res= set_time();
+ return res;
+ }
/* Get TIMESTAMP field value as seconds since begging of Unix Epoch */
virtual my_time_t get_timestamp(ulong *sec_part) const;
virtual void store_TIME(my_time_t timestamp, ulong sec_part)
@@ -1252,7 +1306,6 @@ public:
int4store(ptr,timestamp);
}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
- timestamp_auto_set_type get_auto_set_type() const;
uchar *pack(uchar *to, const uchar *from,
uint max_length __attribute__((unused)))
{
@@ -1503,6 +1556,28 @@ public:
void sql_type(String &str) const;
bool zero_pack() const { return 1; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
+ virtual int set_time();
+ virtual void set_default()
+ {
+ if (has_insert_default_function())
+ set_time();
+ else
+ Field::set_default();
+ }
+ virtual int evaluate_insert_default_function()
+ {
+ int res= 0;
+ if (has_insert_default_function())
+ res= set_time();
+ return res;
+ }
+ virtual int evaluate_update_default_function()
+ {
+ int res= 0;
+ if (has_update_default_function())
+ res= set_time();
+ return res;
+ }
uchar *pack(uchar* to, const uchar *from,
uint max_length __attribute__((unused)))
{
diff --git a/sql/filesort.cc b/sql/filesort.cc
index ac67fb56395..c612d2c55cb 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -45,10 +45,6 @@
if (my_b_write((file),(uchar*) (from),param->ref_length)) \
DBUG_RETURN(1);
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-template class Bounded_queue<uchar, uchar>;
-#endif
-
/* functions defined in this file */
static uchar *read_buffpek_from_file(IO_CACHE *buffer_file, uint count,
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 2878f25ed14..6ba4fe46441 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -2906,8 +2906,6 @@ int ha_ndbcluster::write_row(uchar *record)
}
ha_statistic_increment(&SSV::ha_write_count);
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
- table->timestamp_field->set_time();
if (!(op= trans->getNdbOperation(m_table)))
ERR_RETURN(trans->getNdbError());
@@ -3146,11 +3144,6 @@ int ha_ndbcluster::update_row(const uchar *old_data, uchar *new_data)
}
ha_statistic_increment(&SSV::ha_update_count);
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
- {
- table->timestamp_field->set_time();
- bitmap_set_bit(table->write_set, table->timestamp_field->field_index);
- }
if (m_use_partition_function &&
(error= get_parts_for_update(old_data, new_data, table->record[0],
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 2804da8e7ae..a24d144c97b 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -298,13 +298,6 @@ void ha_partition::init_handler_variables()
}
-const char *ha_partition::table_type() const
-{
- // we can do this since we only support a single engine type
- return m_file[0]->table_type();
-}
-
-
/*
Destructor method
@@ -3446,8 +3439,8 @@ void ha_partition::try_semi_consistent_read(bool yes)
ADDITIONAL INFO:
- We have to set timestamp fields and auto_increment fields, because those
- may be used in determining which partition the row should be written to.
+ We have to set auto_increment fields, because those may be used in
+ determining which partition the row should be written to.
*/
int ha_partition::write_row(uchar * buf)
@@ -3458,7 +3451,6 @@ int ha_partition::write_row(uchar * buf)
bool have_auto_increment= table->next_number_field && buf == table->record[0];
my_bitmap_map *old_map;
THD *thd= ha_thd();
- timestamp_auto_set_type saved_timestamp_type= table->timestamp_field_type;
ulonglong saved_sql_mode= thd->variables.sql_mode;
bool saved_auto_inc_field_not_null= table->auto_increment_field_not_null;
#ifdef NOT_NEEDED
@@ -3467,11 +3459,6 @@ int ha_partition::write_row(uchar * buf)
DBUG_ENTER("ha_partition::write_row");
DBUG_ASSERT(buf == m_rec0);
- /* If we have a timestamp column, update it to the current time */
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
- table->timestamp_field->set_time();
- table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
-
/*
If we have an auto_increment column and we are writing a changed row
or a new row, then update the auto_increment value in the record.
@@ -3547,7 +3534,6 @@ int ha_partition::write_row(uchar * buf)
exit:
thd->variables.sql_mode= saved_sql_mode;
table->auto_increment_field_not_null= saved_auto_inc_field_not_null;
- table->timestamp_field_type= saved_timestamp_type;
DBUG_RETURN(error);
}
@@ -3582,18 +3568,8 @@ int ha_partition::update_row(const uchar *old_data, uchar *new_data)
uint32 new_part_id, old_part_id;
int error= 0;
longlong func_value;
- timestamp_auto_set_type orig_timestamp_type= table->timestamp_field_type;
DBUG_ENTER("ha_partition::update_row");
- /*
- We need to set timestamp field once before we calculate
- the partition. Then we disable timestamp calculations
- inside m_file[*]->update_row() methods
- */
- if (orig_timestamp_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
- table->timestamp_field->set_time();
- table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
-
if ((error= get_parts_for_update(old_data, new_data, table->record[0],
m_part_info, &old_part_id, &new_part_id,
&func_value)))
@@ -3667,7 +3643,6 @@ exit:
info(HA_STATUS_AUTO);
set_auto_increment_if_higher(table->found_next_number_field);
}
- table->timestamp_field_type= orig_timestamp_type;
DBUG_RETURN(error);
}
@@ -4680,8 +4655,8 @@ int ha_partition::common_index_read(uchar *buf, bool have_start_key)
bool reverse_order= FALSE;
DBUG_ENTER("ha_partition::common_index_read");
- DBUG_PRINT("info", ("m_ordered %u m_ordered_scan_ong %u have_start_key %u",
- m_ordered, m_ordered_scan_ongoing, have_start_key));
+ DBUG_PRINT("info", ("m_ordered: %u have_start_key: %u",
+ m_ordered, have_start_key));
if (have_start_key)
{
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index 3a0a35fdfc0..7818e1e608f 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -637,9 +637,6 @@ public:
*/
virtual const char *index_type(uint inx);
- /* The name of the table type that will be used for display purposes */
- virtual const char *table_type() const;
-
/* The name of the row type used for the underlying tables. */
virtual enum row_type get_row_type() const;
diff --git a/sql/handler.cc b/sql/handler.cc
index 271ed73ad53..bf84b1287d5 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -5363,10 +5363,6 @@ int handler::ha_write_row(uchar *buf)
DBUG_ENTER("handler::ha_write_row");
DEBUG_SYNC_C("ha_write_row_start");
- /* If we have a timestamp column, update it to the current time */
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
- table->timestamp_field->set_time();
-
MYSQL_INSERT_ROW_START(table_share->db.str, table_share->table_name.str);
mark_trx_read_write();
increment_statistics(&SSV::ha_write_count);
@@ -5397,9 +5393,6 @@ int handler::ha_update_row(const uchar *old_data, uchar *new_data)
*/
DBUG_ASSERT(new_data == table->record[0]);
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
- table->timestamp_field->set_time();
-
MYSQL_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str);
mark_trx_read_write();
increment_statistics(&SSV::ha_update_count);
diff --git a/sql/handler.h b/sql/handler.h
index f043f1b44cd..997088b1192 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -2487,7 +2487,7 @@ public:
{ return; } /* prepare InnoDB for HANDLER */
virtual void free_foreign_key_create_info(char* str) {}
/** The following can be called without an open handler */
- virtual const char *table_type() const =0;
+ const char *table_type() const { return hton_name(ht)->str; }
/**
If frm_error() is called then we will use this to find out what file
extentions exist for the storage engine. This is also used by the default
diff --git a/sql/item.cc b/sql/item.cc
index 5f4b34ea552..27e6d7052d6 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -9652,14 +9652,3 @@ const char *dbug_print_item(Item *item)
#endif /*DBUG_OFF*/
-/*****************************************************************************
-** Instantiate templates
-*****************************************************************************/
-
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-template class List<Item>;
-template class List_iterator<Item>;
-template class List_iterator_fast<Item>;
-template class List_iterator_fast<Item_field>;
-template class List<List_item>;
-#endif
diff --git a/sql/item_buff.cc b/sql/item_buff.cc
index 86e0fd32774..ce396736d6f 100644
--- a/sql/item_buff.cc
+++ b/sql/item_buff.cc
@@ -173,12 +173,3 @@ bool Cached_item_decimal::cmp()
return FALSE;
}
-
-/*****************************************************************************
-** Instansiate templates
-*****************************************************************************/
-
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-template class List<Cached_item>;
-template class List_iterator<Cached_item>;
-#endif
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_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/keycaches.cc b/sql/keycaches.cc
index 26a39808c56..84ed67d00f0 100644
--- a/sql/keycaches.cc
+++ b/sql/keycaches.cc
@@ -159,7 +159,3 @@ bool process_key_caches(process_key_cache_t func, void *param)
return res != 0;
}
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-template class I_List_iterator<NAMED_ILINK>;
-#endif
-
diff --git a/sql/log.cc b/sql/log.cc
index 69ff68d335f..1813120dd81 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -54,6 +54,7 @@
#include "rpl_handler.h"
#include "debug_sync.h"
#include "sql_show.h"
+#include "my_pthread.h"
/* max size of the log message */
#define MAX_LOG_BUFFER_SIZE 1024
@@ -107,6 +108,17 @@ static SHOW_VAR binlog_status_vars_detail[]=
{NullS, NullS, SHOW_LONG}
};
+/*
+ Variables for the binlog background thread.
+ Protected by the MYSQL_BIN_LOG::LOCK_binlog_background_thread mutex.
+ */
+static bool binlog_background_thread_started= false;
+static bool binlog_background_thread_stop= false;
+static MYSQL_BIN_LOG::xid_count_per_binlog *
+ binlog_background_thread_queue= NULL;
+
+static bool start_binlog_background_thread();
+
/**
purge logs, master and slave sides both, related error code
@@ -1288,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();
@@ -1304,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;
}
@@ -2972,12 +2982,28 @@ void MYSQL_BIN_LOG::cleanup()
my_free(b);
}
+ /* Wait for the binlog background thread to stop. */
+ if (!is_relay_log && binlog_background_thread_started)
+ {
+ mysql_mutex_lock(&LOCK_binlog_background_thread);
+ binlog_background_thread_stop= true;
+ mysql_cond_signal(&COND_binlog_background_thread);
+ while (binlog_background_thread_stop)
+ mysql_cond_wait(&COND_binlog_background_thread_end,
+ &LOCK_binlog_background_thread);
+ mysql_mutex_unlock(&LOCK_binlog_background_thread);
+ binlog_background_thread_started= false;
+ }
+
mysql_mutex_destroy(&LOCK_log);
mysql_mutex_destroy(&LOCK_index);
mysql_mutex_destroy(&LOCK_xid_list);
+ mysql_mutex_destroy(&LOCK_binlog_background_thread);
mysql_cond_destroy(&update_cond);
mysql_cond_destroy(&COND_queue_busy);
mysql_cond_destroy(&COND_xid_list);
+ mysql_cond_destroy(&COND_binlog_background_thread);
+ mysql_cond_destroy(&COND_binlog_background_thread_end);
}
DBUG_VOID_RETURN;
}
@@ -3003,6 +3029,13 @@ void MYSQL_BIN_LOG::init_pthread_objects()
mysql_cond_init(m_key_update_cond, &update_cond, 0);
mysql_cond_init(m_key_COND_queue_busy, &COND_queue_busy, 0);
mysql_cond_init(key_BINLOG_COND_xid_list, &COND_xid_list, 0);
+
+ mysql_mutex_init(key_BINLOG_LOCK_binlog_background_thread,
+ &LOCK_binlog_background_thread, MY_MUTEX_INIT_FAST);
+ mysql_cond_init(key_BINLOG_COND_binlog_background_thread,
+ &COND_binlog_background_thread, 0);
+ mysql_cond_init(key_BINLOG_COND_binlog_background_thread_end,
+ &COND_binlog_background_thread_end, 0);
}
@@ -3100,6 +3133,10 @@ bool MYSQL_BIN_LOG::open(const char *log_name,
DBUG_ENTER("MYSQL_BIN_LOG::open");
DBUG_PRINT("enter",("log_type: %d",(int) log_type_arg));
+ if (!is_relay_log && !binlog_background_thread_started &&
+ start_binlog_background_thread())
+ DBUG_RETURN(1);
+
if (init_and_set_log_file_name(log_name, new_name, log_type_arg,
io_cache_type_arg))
{
@@ -5548,18 +5585,14 @@ 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;
}
-/*
- I would like to make this function static, but this causes compiler warnings
- when it is declared as friend function in log.h.
-*/
-void
+static void
binlog_checkpoint_callback(void *cookie)
{
MYSQL_BIN_LOG::xid_count_per_binlog *entry=
@@ -7398,8 +7431,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;
@@ -7432,8 +7466,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)
@@ -7450,10 +7484,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);
@@ -7560,12 +7594,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);
}
@@ -7617,8 +7648,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
@@ -8148,9 +8179,129 @@ int TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)
void
TC_LOG_BINLOG::commit_checkpoint_notify(void *cookie)
{
- mark_xid_done(((xid_count_per_binlog *)cookie)->binlog_id, true);
+ xid_count_per_binlog *entry= static_cast<xid_count_per_binlog *>(cookie);
+ mysql_mutex_lock(&LOCK_binlog_background_thread);
+ entry->next_in_queue= binlog_background_thread_queue;
+ binlog_background_thread_queue= entry;
+ mysql_cond_signal(&COND_binlog_background_thread);
+ mysql_mutex_unlock(&LOCK_binlog_background_thread);
}
+/*
+ Binlog background thread.
+
+ This thread is used to log binlog checkpoints in the background, rather than
+ in the context of random storage engine threads that happen to call
+ commit_checkpoint_notify_ha() and may not like the delays while syncing
+ binlog to disk or may not be setup with all my_thread_init() and other
+ necessary stuff.
+
+ In the future, this thread could also be used to do log rotation in the
+ background, which could elimiate all stalls around binlog rotations.
+*/
+pthread_handler_t
+binlog_background_thread(void *arg __attribute__((unused)))
+{
+ bool stop;
+ MYSQL_BIN_LOG::xid_count_per_binlog *queue, *next;
+ THD *thd;
+
+ my_thread_init();
+ thd= new THD;
+ thd->system_thread= SYSTEM_THREAD_BINLOG_BACKGROUND;
+ thd->thread_stack= (char*) &thd; /* Set approximate stack start */
+ mysql_mutex_lock(&LOCK_thread_count);
+ thd->thread_id= thread_id++;
+ mysql_mutex_unlock(&LOCK_thread_count);
+ thd->store_globals();
+
+ for (;;)
+ {
+ /*
+ Wait until there is something in the queue to process, or we are asked
+ to shut down.
+ */
+ THD_STAGE_INFO(thd, stage_binlog_waiting_background_tasks);
+ mysql_mutex_lock(&mysql_bin_log.LOCK_binlog_background_thread);
+ for (;;)
+ {
+ stop= binlog_background_thread_stop;
+ queue= binlog_background_thread_queue;
+ if (stop || queue)
+ break;
+ mysql_cond_wait(&mysql_bin_log.COND_binlog_background_thread,
+ &mysql_bin_log.LOCK_binlog_background_thread);
+ }
+ /* Grab the queue, if any. */
+ binlog_background_thread_queue= NULL;
+ mysql_mutex_unlock(&mysql_bin_log.LOCK_binlog_background_thread);
+
+ /* Process any incoming commit_checkpoint_notify() calls. */
+ while (queue)
+ {
+ THD_STAGE_INFO(thd, stage_binlog_processing_checkpoint_notify);
+ /* Grab next pointer first, as mark_xid_done() may free the element. */
+ next= queue->next_in_queue;
+ mysql_bin_log.mark_xid_done(queue->binlog_id, true);
+ queue= next;
+
+ DBUG_EXECUTE_IF("binlog_background_checkpoint_processed",
+ DBUG_ASSERT(!debug_sync_set_action(
+ thd,
+ STRING_WITH_LEN("now SIGNAL binlog_background_checkpoint_processed")));
+ );
+ }
+
+ if (stop)
+ break;
+ }
+
+ THD_STAGE_INFO(thd, stage_binlog_stopping_background_thread);
+
+ mysql_mutex_lock(&LOCK_thread_count);
+ delete thd;
+ mysql_mutex_unlock(&LOCK_thread_count);
+
+ my_thread_end();
+
+ /* Signal that we are (almost) stopped. */
+ mysql_mutex_lock(&mysql_bin_log.LOCK_binlog_background_thread);
+ binlog_background_thread_stop= false;
+ mysql_cond_signal(&mysql_bin_log.COND_binlog_background_thread_end);
+ mysql_mutex_unlock(&mysql_bin_log.LOCK_binlog_background_thread);
+
+ return 0;
+}
+
+#ifdef HAVE_PSI_INTERFACE
+static PSI_thread_key key_thread_binlog;
+
+static PSI_thread_info all_binlog_threads[]=
+{
+ { &key_thread_binlog, "binlog_background", PSI_FLAG_GLOBAL},
+};
+#endif /* HAVE_PSI_INTERFACE */
+
+static bool
+start_binlog_background_thread()
+{
+ pthread_t th;
+
+#ifdef HAVE_PSI_INTERFACE
+ if (PSI_server)
+ PSI_server->register_thread("sql", all_binlog_threads,
+ array_elements(all_binlog_threads));
+#endif
+
+ if (mysql_thread_create(key_thread_binlog, &th, NULL,
+ binlog_background_thread, NULL))
+ return 1;
+
+ binlog_background_thread_started= true;
+ return 0;
+}
+
+
int TC_LOG_BINLOG::recover(LOG_INFO *linfo, const char *last_log_name,
IO_CACHE *first_log,
Format_description_log_event *fdle)
diff --git a/sql/log.h b/sql/log.h
index 3959411d83a..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
@@ -395,8 +395,6 @@ private:
#define BINLOG_COOKIE_IS_DUMMY(c) \
( ((ulong)(c)>>1) == BINLOG_COOKIE_DUMMY_ID )
-void binlog_checkpoint_callback(void *cookie);
-
class binlog_cache_mngr;
class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
{
@@ -451,27 +449,6 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
};
/*
- A list of struct xid_count_per_binlog is used to keep track of how many
- XIDs are in prepared, but not committed, state in each binlog. And how
- many commit_checkpoint_request()'s are pending.
-
- When count drops to zero in a binlog after rotation, it means that there
- are no more XIDs in prepared state, so that binlog is no longer needed
- for XA crash recovery, and we can log a new binlog checkpoint event.
-
- The list is protected against simultaneous access from multiple
- threads by LOCK_xid_list.
- */
- struct xid_count_per_binlog : public ilink {
- char *binlog_name;
- uint binlog_name_len;
- ulong binlog_id;
- /* Total prepared XIDs and pending checkpoint requests in this binlog. */
- long xid_count;
- xid_count_per_binlog(); /* Give link error if constructor used. */
- };
- I_List<xid_count_per_binlog> binlog_xid_count_list;
- /*
When this is set, a RESET MASTER is in progress.
Then we should not write any binlog checkpoints into the binlog (that
@@ -480,7 +457,6 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
checkpoint arrives - when all have arrived, RESET MASTER will complete.
*/
bool reset_master_pending;
- friend void binlog_checkpoint_callback(void *cookie);
/* LOCK_log and LOCK_index are inited by init_pthread_objects() */
mysql_mutex_t LOCK_index;
@@ -550,10 +526,35 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
int write_transaction_or_stmt(group_commit_entry *entry);
bool write_transaction_to_binlog_events(group_commit_entry *entry);
void trx_group_commit_leader(group_commit_entry *leader);
- void mark_xid_done(ulong cookie, bool write_checkpoint);
- void mark_xids_active(ulong cookie, uint xid_count);
public:
+ /*
+ A list of struct xid_count_per_binlog is used to keep track of how many
+ XIDs are in prepared, but not committed, state in each binlog. And how
+ many commit_checkpoint_request()'s are pending.
+
+ When count drops to zero in a binlog after rotation, it means that there
+ are no more XIDs in prepared state, so that binlog is no longer needed
+ for XA crash recovery, and we can log a new binlog checkpoint event.
+
+ The list is protected against simultaneous access from multiple
+ threads by LOCK_xid_list.
+ */
+ struct xid_count_per_binlog : public ilink {
+ char *binlog_name;
+ uint binlog_name_len;
+ ulong binlog_id;
+ /* Total prepared XIDs and pending checkpoint requests in this binlog. */
+ long xid_count;
+ /* For linking in requests to the binlog background thread. */
+ xid_count_per_binlog *next_in_queue;
+ xid_count_per_binlog(); /* Give link error if constructor used. */
+ };
+ I_List<xid_count_per_binlog> binlog_xid_count_list;
+ mysql_mutex_t LOCK_binlog_background_thread;
+ mysql_cond_t COND_binlog_background_thread;
+ mysql_cond_t COND_binlog_background_thread_end;
+
using MYSQL_LOG::generate_name;
using MYSQL_LOG::is_open;
@@ -709,6 +710,8 @@ public:
bool appendv(const char* buf,uint len,...);
bool append(Log_event* ev);
+ void mark_xids_active(ulong cookie, uint xid_count);
+ void mark_xid_done(ulong cookie, bool write_checkpoint);
void make_log_name(char* buf, const char* log_ident);
bool is_active(const char* log_file_name);
bool can_purge_log(const char *log_file_name);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 13de7523054..fb9e6b7107f 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -9881,23 +9881,6 @@ Write_rows_log_event::do_before_row_operations(const Slave_reporting_capability
*/
}
- /*
- We need TIMESTAMP_NO_AUTO_SET otherwise ha_write_row() will not use fill
- any TIMESTAMP column with data from the row but instead will use
- the event's current time.
- As we replicate from TIMESTAMP to TIMESTAMP and slave has no extra
- columns, we know that all TIMESTAMP columns on slave will receive explicit
- data from the row, so TIMESTAMP_NO_AUTO_SET is ok.
- When we allow a table without TIMESTAMP to be replicated to a table having
- more columns including a TIMESTAMP column, or when we allow a TIMESTAMP
- column to be replicated into a BIGINT column and the slave's table has a
- TIMESTAMP column, then the slave's TIMESTAMP column will take its value
- from set_time() which we called earlier (consistent with SBR). And then in
- some cases we won't want TIMESTAMP_NO_AUTO_SET (will require some code to
- analyze if explicit data is provided for slave's TIMESTAMP columns).
- */
- m_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
-
/* Honor next number column if present */
m_table->next_number_field= m_table->found_next_number_field;
/*
@@ -10986,8 +10969,6 @@ Update_rows_log_event::do_before_row_operations(const Slave_reporting_capability
if ((err= find_key()))
return err;
- m_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
-
return 0;
}
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index d7c66af769a..bd837adc9d9 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -924,22 +924,6 @@ int Write_rows_log_event_old::do_before_row_operations(TABLE *table)
from the start.
*/
table->file->ha_start_bulk_insert(0);
- /*
- We need TIMESTAMP_NO_AUTO_SET otherwise ha_write_row() will not use fill
- any TIMESTAMP column with data from the row but instead will use
- the event's current time.
- As we replicate from TIMESTAMP to TIMESTAMP and slave has no extra
- columns, we know that all TIMESTAMP columns on slave will receive explicit
- data from the row, so TIMESTAMP_NO_AUTO_SET is ok.
- When we allow a table without TIMESTAMP to be replicated to a table having
- more columns including a TIMESTAMP column, or when we allow a TIMESTAMP
- column to be replicated into a BIGINT column and the slave's table has a
- TIMESTAMP column, then the slave's TIMESTAMP column will take its value
- from set_time() which we called earlier (consistent with SBR). And then in
- some cases we won't want TIMESTAMP_NO_AUTO_SET (will require some code to
- analyze if explicit data is provided for slave's TIMESTAMP columns).
- */
- table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
return error;
}
@@ -1128,8 +1112,6 @@ int Update_rows_log_event_old::do_before_row_operations(TABLE *table)
if (!m_memory)
return HA_ERR_OUT_OF_MEM;
- table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
-
return error;
}
@@ -2589,22 +2571,6 @@ Write_rows_log_event_old::do_before_row_operations(const Slave_reporting_capabil
from the start.
*/
m_table->file->ha_start_bulk_insert(0);
- /*
- We need TIMESTAMP_NO_AUTO_SET otherwise ha_write_row() will not use fill
- any TIMESTAMP column with data from the row but instead will use
- the event's current time.
- As we replicate from TIMESTAMP to TIMESTAMP and slave has no extra
- columns, we know that all TIMESTAMP columns on slave will receive explicit
- data from the row, so TIMESTAMP_NO_AUTO_SET is ok.
- When we allow a table without TIMESTAMP to be replicated to a table having
- more columns including a TIMESTAMP column, or when we allow a TIMESTAMP
- column to be replicated into a BIGINT column and the slave's table has a
- TIMESTAMP column, then the slave's TIMESTAMP column will take its value
- from set_time() which we called earlier (consistent with SBR). And then in
- some cases we won't want TIMESTAMP_NO_AUTO_SET (will require some code to
- analyze if explicit data is provided for slave's TIMESTAMP columns).
- */
- m_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
return error;
}
@@ -2814,8 +2780,6 @@ Update_rows_log_event_old::do_before_row_operations(const Slave_reporting_capabi
return HA_ERR_OUT_OF_MEM;
}
- m_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
-
return 0;
}
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 28e2c43ca43..ea38d61cca2 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -747,6 +747,7 @@ PSI_mutex_key key_LOCK_des_key_file;
#endif /* HAVE_OPENSSL */
PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list,
+ key_BINLOG_LOCK_binlog_background_thread,
key_delayed_insert_mutex, key_hash_filo_lock, key_LOCK_active_mi,
key_LOCK_connection_count, key_LOCK_crypt, key_LOCK_delayed_create,
key_LOCK_delayed_insert, key_LOCK_delayed_status, key_LOCK_error_log,
@@ -789,6 +790,7 @@ static PSI_mutex_info all_server_mutexes[]=
{ &key_BINLOG_LOCK_index, "MYSQL_BIN_LOG::LOCK_index", 0},
{ &key_BINLOG_LOCK_xid_list, "MYSQL_BIN_LOG::LOCK_xid_list", 0},
+ { &key_BINLOG_LOCK_binlog_background_thread, "MYSQL_BIN_LOG::LOCK_binlog_background_thread", 0},
{ &key_RELAYLOG_LOCK_index, "MYSQL_RELAY_LOG::LOCK_index", 0},
{ &key_delayed_insert_mutex, "Delayed_insert::mutex", 0},
{ &key_hash_filo_lock, "hash_filo::lock", 0},
@@ -857,6 +859,8 @@ PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool;
#endif /* HAVE_MMAP */
PSI_cond_key key_BINLOG_COND_xid_list, key_BINLOG_update_cond,
+ key_BINLOG_COND_binlog_background_thread,
+ key_BINLOG_COND_binlog_background_thread_end,
key_COND_cache_status_changed, key_COND_manager,
key_COND_rpl_status, key_COND_server_started,
key_delayed_insert_cond, key_delayed_insert_cond_client,
@@ -886,6 +890,8 @@ static PSI_cond_info all_server_conds[]=
#endif /* HAVE_MMAP */
{ &key_BINLOG_COND_xid_list, "MYSQL_BIN_LOG::COND_xid_list", 0},
{ &key_BINLOG_update_cond, "MYSQL_BIN_LOG::update_cond", 0},
+ { &key_BINLOG_COND_binlog_background_thread, "MYSQL_BIN_LOG::COND_binlog_background_thread", 0},
+ { &key_BINLOG_COND_binlog_background_thread_end, "MYSQL_BIN_LOG::COND_binlog_background_thread_end", 0},
{ &key_BINLOG_COND_queue_busy, "MYSQL_BIN_LOG::COND_queue_busy", 0},
{ &key_RELAYLOG_update_cond, "MYSQL_RELAY_LOG::update_cond", 0},
{ &key_RELAYLOG_COND_queue_busy, "MYSQL_RELAY_LOG::COND_queue_busy", 0},
@@ -7259,8 +7265,8 @@ SHOW_VAR status_vars[]= {
{"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_read", (char*) offsetof(STATUS_VAR, rows_read), SHOW_LONGLONG_STATUS},
{"Rows_sent", (char*) offsetof(STATUS_VAR, rows_sent), SHOW_LONGLONG_STATUS},
+ {"Rows_read", (char*) offsetof(STATUS_VAR, rows_read), SHOW_LONGLONG_STATUS},
{"Rows_tmp_read", (char*) offsetof(STATUS_VAR, rows_tmp_read), SHOW_LONGLONG_STATUS},
#ifdef HAVE_QUERY_CACHE
{"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_NOFLUSH},
@@ -8820,6 +8826,9 @@ PSI_stage_info stage_slave_waiting_worker_to_release_partition= { 0, "Waiting fo
PSI_stage_info stage_slave_waiting_worker_to_free_events= { 0, "Waiting for Slave Workers to free pending events", 0};
PSI_stage_info stage_slave_waiting_worker_queue= { 0, "Waiting for Slave Worker queue", 0};
PSI_stage_info stage_slave_waiting_event_from_coordinator= { 0, "Waiting for an event from Coordinator", 0};
+PSI_stage_info stage_binlog_waiting_background_tasks= { 0, "Waiting for background binlog tasks", 0};
+PSI_stage_info stage_binlog_processing_checkpoint_notify= { 0, "Processing binlog checkpoint notification", 0};
+PSI_stage_info stage_binlog_stopping_background_thread= { 0, "Stopping binlog background thread", 0};
#ifdef HAVE_PSI_INTERFACE
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 7da96ca932e..a07efa9178f 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -230,6 +230,7 @@ extern PSI_mutex_key key_LOCK_des_key_file;
#endif
extern PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list,
+ key_BINLOG_LOCK_binlog_background_thread,
key_delayed_insert_mutex, key_hash_filo_lock, key_LOCK_active_mi,
key_LOCK_connection_count, key_LOCK_crypt, key_LOCK_delayed_create,
key_LOCK_delayed_insert, key_LOCK_delayed_status, key_LOCK_error_log,
@@ -261,6 +262,8 @@ extern PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool;
#endif /* HAVE_MMAP */
extern PSI_cond_key key_BINLOG_COND_xid_list, key_BINLOG_update_cond,
+ key_BINLOG_COND_binlog_background_thread,
+ key_BINLOG_COND_binlog_background_thread_end,
key_COND_cache_status_changed, key_COND_manager,
key_COND_rpl_status, key_COND_server_started,
key_delayed_insert_cond, key_delayed_insert_cond_client,
@@ -402,6 +405,9 @@ extern PSI_stage_info stage_slave_waiting_worker_to_free_events;
extern PSI_stage_info stage_slave_waiting_worker_queue;
extern PSI_stage_info stage_slave_waiting_event_from_coordinator;
extern PSI_stage_info stage_slave_waiting_workers_to_exit;
+extern PSI_stage_info stage_binlog_waiting_background_tasks;
+extern PSI_stage_info stage_binlog_processing_checkpoint_notify;
+extern PSI_stage_info stage_binlog_stopping_background_thread;
#ifdef HAVE_PSI_STATEMENT_INTERFACE
/**
Statement instrumentation keys (sql).
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 67bc1639f2d..8aeb89ed9ed 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -14137,11 +14137,3 @@ void QUICK_GROUP_MIN_MAX_SELECT::dbug_dump(int indent, bool verbose)
#endif /* !DBUG_OFF */
-/*****************************************************************************
-** Instantiate templates
-*****************************************************************************/
-
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-template class List<QUICK_RANGE>;
-template class List_iterator<QUICK_RANGE>;
-#endif
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index 8c01e979226..364dfb3bc20 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -59,6 +59,7 @@ Relay_log_info::Relay_log_info(bool is_slave_recovery)
{
DBUG_ENTER("Relay_log_info::Relay_log_info");
+ relay_log.is_relay_log= TRUE;
#ifdef HAVE_PSI_INTERFACE
relay_log.set_psi_keys(key_RELAYLOG_LOCK_index,
key_RELAYLOG_update_cond,
@@ -217,8 +218,6 @@ a file name for --relay-log-index option", opt_relaylog_index_name);
&mi->connection_name);
}
- rli->relay_log.is_relay_log= TRUE;
-
/*
note, that if open() fails, we'll still have index file open
but a destructor will take care of that
diff --git a/sql/slave.cc b/sql/slave.cc
index e1bac640e00..95818e60426 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -5693,11 +5693,6 @@ bool rpl_master_erroneous_autoinc(THD *thd)
return FALSE;
}
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-template class I_List_iterator<i_string>;
-template class I_List_iterator<i_string_pair>;
-#endif
-
/**
@} (end of group Replication)
*/
diff --git a/sql/sp.cc b/sql/sp.cc
index db180bde4b5..f6f5d640bc0 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -1350,7 +1350,6 @@ sp_update_routine(THD *thd, stored_procedure_type type, sp_name *name,
}
store_record(table,record[1]);
- table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time();
if (chistics->suid != SP_IS_DEFAULT_SUID)
table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 2ab5f96d4cb..b725f6d7fcc 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -2425,7 +2425,6 @@ sp_head::fill_field_definition(THD *thd, LEX *lex,
{
LEX_STRING cmt = { 0, 0 };
uint unused1= 0;
- int unused2= 0;
if (field_def->init(thd, (char*) "", field_type, lex->length, lex->dec,
lex->type, (Item*) 0, (Item*) 0, &cmt, 0,
@@ -2442,8 +2441,7 @@ sp_head::fill_field_definition(THD *thd, LEX *lex,
sp_prepare_create_field(thd, field_def);
- if (prepare_create_field(field_def, &unused1, &unused2, &unused2,
- HA_CAN_GEOMETRY))
+ if (prepare_create_field(field_def, &unused1, HA_CAN_GEOMETRY))
{
return TRUE;
}
@@ -3112,8 +3110,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
(the order of query cache and subst_spvars calls is irrelevant because
queries with SP vars can't be cached)
*/
- if (unlikely((thd->variables.option_bits & OPTION_LOG_OFF)==0))
- general_log_write(thd, COM_QUERY, thd->query(), thd->query_length());
+ general_log_write(thd, COM_QUERY, thd->query(), thd->query_length());
if (query_cache_send_result_to_client(thd, thd->query(),
thd->query_length()) <= 0)
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 7e8a6a93d57..723d825de17 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1634,14 +1634,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)))
{
@@ -4888,11 +4894,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);
@@ -7013,17 +7025,6 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
}
-/*****************************************************************************
- Instantiate used templates
-*****************************************************************************/
-
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-template class List_iterator<LEX_COLUMN>;
-template class List_iterator<LEX_USER>;
-template class List<LEX_COLUMN>;
-template class List<LEX_USER>;
-#endif
-
/**
Validate if a user can proxy as another user
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 db926061406..834e5ac0046 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -8852,34 +8852,33 @@ err_no_arena:
******************************************************************************/
-/*
- Fill fields with given items.
+/**
+ Fill the fields of a table with the values of an Item list
- SYNOPSIS
- fill_record()
- thd thread handler
- fields Item_fields list to be filled
- values values to fill with
- ignore_errors TRUE if we should ignore errors
+ @param thd thread handler
+ @param table_arg the table that is being modified
+ @param fields Item_fields list to be filled
+ @param values values to fill with
+ @param ignore_errors TRUE if we should ignore errors
- NOTE
+ @details
fill_record() may set table->auto_increment_field_not_null and a
caller should make sure that it is reset after their last call to this
function.
- RETURN
- FALSE OK
- TRUE error occured
+ @return Status
+ @retval true An error occured.
+ @retval false OK.
*/
static bool
-fill_record(THD * thd, List<Item> &fields, List<Item> &values,
+fill_record(THD * thd, TABLE *table_arg, List<Item> &fields, List<Item> &values,
bool ignore_errors)
{
List_iterator_fast<Item> f(fields),v(values);
Item *value, *fld;
Item_field *field;
- TABLE *table= 0, *vcol_table= 0;
+ TABLE *vcol_table= 0;
bool save_abort_on_warning= thd->abort_on_warning;
bool save_no_errors= thd->no_errors;
DBUG_ENTER("fill_record");
@@ -8901,12 +8900,13 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), fld->name);
goto err;
}
- table= field->field->table;
- table->auto_increment_field_not_null= FALSE;
+ DBUG_ASSERT(field->field->table == table_arg);
+ table_arg->auto_increment_field_not_null= FALSE;
f.rewind();
}
else if (thd->lex->unit.insert_table_with_stored_vcol)
vcol_table= thd->lex->unit.insert_table_with_stored_vcol;
+
while ((fld= f++))
{
if (!(field= fld->filed_for_view_update()))
@@ -8916,7 +8916,7 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
}
value=v++;
Field *rfield= field->field;
- table= rfield->table;
+ TABLE* table= rfield->table;
if (rfield == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
if (rfield->vcol_info &&
@@ -8934,13 +8934,16 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
goto err;
}
+ rfield->set_explicit_default(value);
DBUG_ASSERT(vcol_table == 0 || vcol_table == table);
vcol_table= table;
}
/* 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;
@@ -8948,8 +8951,8 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
err:
thd->abort_on_warning= save_abort_on_warning;
thd->no_errors= save_no_errors;
- if (table)
- table->auto_increment_field_not_null= FALSE;
+ if (fields.elements)
+ table_arg->auto_increment_field_not_null= FALSE;
DBUG_RETURN(TRUE);
}
@@ -8958,42 +8961,39 @@ err:
Fill fields in list with values from the list of items and invoke
before triggers.
- SYNOPSIS
- fill_record_n_invoke_before_triggers()
- thd thread context
- fields Item_fields list to be filled
- values values to fill with
- ignore_errors TRUE if we should ignore errors
- triggers object holding list of triggers to be invoked
- event event type for triggers to be invoked
+ @param thd thread context
+ @param table the table that is being modified
+ @param fields Item_fields list to be filled
+ @param values values to fill with
+ @param ignore_errors TRUE if we should ignore errors
+ @param event event type for triggers to be invoked
- NOTE
+ @detail
This function assumes that fields which values will be set and triggers
to be invoked belong to the same table, and that TABLE::record[0] and
record[1] buffers correspond to new and old versions of row respectively.
- RETURN
- FALSE OK
- TRUE error occured
+ @return Status
+ @retval true An error occured.
+ @retval false OK.
*/
bool
-fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
+fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, List<Item> &fields,
List<Item> &values, bool ignore_errors,
- Table_triggers_list *triggers,
enum trg_event_type event)
{
bool result;
- result= (fill_record(thd, fields, values, ignore_errors) ||
+ Table_triggers_list *triggers= table->triggers;
+ result= (fill_record(thd, table, fields, values, ignore_errors) ||
(triggers && triggers->process_triggers(thd, event,
TRG_ACTION_BEFORE, TRUE)));
/*
Re-calculate virtual fields to cater for cases when base columns are
updated by the triggers.
*/
- if (!result && triggers)
+ if (!result && triggers && table)
{
- TABLE *table= 0;
List_iterator_fast<Item> f(fields);
Item *fld;
Item_field *item_field;
@@ -9001,45 +9001,46 @@ fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
{
fld= (Item_field*)f++;
item_field= fld->filed_for_view_update();
- if (item_field && item_field->field &&
- (table= item_field->field->table) &&
- table->vfield)
- result= update_virtual_fields(thd, table, TRUE);
+ if (item_field && item_field->field && table && table->vfield)
+ {
+ DBUG_ASSERT(table == item_field->field->table);
+ result= update_virtual_fields(thd, table,
+ table->triggers ? VCOL_UPDATE_ALL :
+ VCOL_UPDATE_FOR_WRITE);
+ }
}
}
return result;
}
-/*
- Fill field buffer with values from Field list
+/**
+ Fill the field buffer of a table with the values of an Item list
- SYNOPSIS
- fill_record()
- thd thread handler
- ptr pointer on pointer to record
- values list of fields
- ignore_errors TRUE if we should ignore errors
- use_value forces usage of value of the items instead of result
+ @param thd thread handler
+ @param table_arg the table that is being modified
+ @param ptr pointer on pointer to record of fields
+ @param values values to fill with
+ @param ignore_errors TRUE if we should ignore errors
+ @param use_value forces usage of value of the items instead of result
- NOTE
+ @details
fill_record() may set table->auto_increment_field_not_null and a
caller should make sure that it is reset after their last call to this
function.
- RETURN
- FALSE OK
- TRUE error occured
+ @return Status
+ @retval true An error occured.
+ @retval false OK.
*/
bool
-fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors,
- bool use_value)
+fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values,
+ bool ignore_errors, bool use_value)
{
List_iterator_fast<Item> v(values);
List<TABLE> tbl_list;
Item *value;
- TABLE *table= 0;
Field *field;
bool abort_on_warning_saved= thd->abort_on_warning;
DBUG_ENTER("fill_record");
@@ -9054,7 +9055,7 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors,
On INSERT or UPDATE fields are checked to be from the same table,
thus we safely can take table from the first field.
*/
- table= (*ptr)->table;
+ DBUG_ASSERT((*ptr)->table == table);
/*
Reset the table->auto_increment_field_not_null as it is valid for
@@ -9085,10 +9086,14 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors,
else
if (value->save_in_field(field, 0) < 0)
goto err;
+ field->set_explicit_default(value);
}
/* 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());
@@ -9101,36 +9106,34 @@ err:
/*
- Fill fields in array with values from the list of items and invoke
+ Fill fields in an array with values from the list of items and invoke
before triggers.
- SYNOPSIS
- fill_record_n_invoke_before_triggers()
- thd thread context
- ptr NULL-ended array of fields to be filled
- values values to fill with
- ignore_errors TRUE if we should ignore errors
- triggers object holding list of triggers to be invoked
- event event type for triggers to be invoked
+ @param thd thread context
+ @param table the table that is being modified
+ @param ptr the fields to be filled
+ @param values values to fill with
+ @param ignore_errors TRUE if we should ignore errors
+ @param event event type for triggers to be invoked
- NOTE
+ @detail
This function assumes that fields which values will be set and triggers
to be invoked belong to the same table, and that TABLE::record[0] and
record[1] buffers correspond to new and old versions of row respectively.
- RETURN
- FALSE OK
- TRUE error occured
+ @return Status
+ @retval true An error occured.
+ @retval false OK.
*/
bool
-fill_record_n_invoke_before_triggers(THD *thd, Field **ptr,
+fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, Field **ptr,
List<Item> &values, bool ignore_errors,
- Table_triggers_list *triggers,
enum trg_event_type event)
{
bool result;
- result= (fill_record(thd, ptr, values, ignore_errors, FALSE) ||
+ Table_triggers_list *triggers= table->triggers;
+ result= (fill_record(thd, table, ptr, values, ignore_errors, FALSE) ||
(triggers && triggers->process_triggers(thd, event,
TRG_ACTION_BEFORE, TRUE)));
/*
@@ -9139,9 +9142,11 @@ fill_record_n_invoke_before_triggers(THD *thd, Field **ptr,
*/
if (!result && triggers && *ptr)
{
- TABLE *table= (*ptr)->table;
+ 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;
@@ -9779,11 +9784,6 @@ open_log_table(THD *thd, TABLE_LIST *one_table, Open_tables_backup *backup)
/* Make sure all columns get assigned to a default value */
table->use_all_columns();
table->no_replicate= 1;
- /*
- Don't set automatic timestamps as we may want to use time of logging,
- not from query start
- */
- table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
}
else
thd->restore_backup_open_tables_state(backup);
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 3deb97c9730..af63aefa7f9 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -170,15 +170,15 @@ TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl);
TABLE *find_temporary_table(THD *thd, const char *table_key,
uint table_key_length);
void close_thread_tables(THD *thd);
-bool fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
+bool fill_record_n_invoke_before_triggers(THD *thd, TABLE *table,
+ List<Item> &fields,
List<Item> &values,
bool ignore_errors,
- Table_triggers_list *triggers,
enum trg_event_type event);
-bool fill_record_n_invoke_before_triggers(THD *thd, Field **field,
+bool fill_record_n_invoke_before_triggers(THD *thd, TABLE *table,
+ Field **field,
List<Item> &values,
bool ignore_errors,
- Table_triggers_list *triggers,
enum trg_event_type event);
bool insert_fields(THD *thd, Name_resolution_context *context,
const char *db_name, const char *table_name,
@@ -191,7 +191,7 @@ bool setup_fields(THD *thd, Item** ref_pointer_array,
List<Item> &item, enum_mark_columns mark_used_columns,
List<Item> *sum_func_list, bool allow_sum_func);
void unfix_fields(List<Item> &items);
-bool fill_record(THD *thd, Field **field, List<Item> &values,
+bool fill_record(THD *thd, TABLE *table, Field **field, List<Item> &values,
bool ignore_errors, bool use_value);
Field *
@@ -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 fc5653750f3..cbb798d96a4 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -73,23 +73,6 @@ char empty_c_string[1]= {0}; /* used for not defined db */
const char * const THD::DEFAULT_WHERE= "field list";
-
-/*****************************************************************************
-** Instansiate templates
-*****************************************************************************/
-
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-/* Used templates */
-template class List<Key>;
-template class List_iterator<Key>;
-template class List<Key_part_spec>;
-template class List_iterator<Key_part_spec>;
-template class List<Alter_drop>;
-template class List_iterator<Alter_drop>;
-template class List<Alter_column>;
-template class List_iterator<Alter_column>;
-#endif
-
/****************************************************************************
** User variables
****************************************************************************/
@@ -5183,27 +5166,6 @@ THD::binlog_prepare_pending_rows_event(TABLE* table, uint32 serv_id,
DBUG_RETURN(pending); /* This is the current pending event */
}
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-/*
- Instantiate the versions we need, we have -fno-implicit-template as
- compiling option.
-*/
-template Rows_log_event*
-THD::binlog_prepare_pending_rows_event(TABLE*, uint32, MY_BITMAP const*,
- size_t, size_t, bool,
- Write_rows_log_event*);
-
-template Rows_log_event*
-THD::binlog_prepare_pending_rows_event(TABLE*, uint32, MY_BITMAP const*,
- size_t colcnt, size_t, bool,
- Delete_rows_log_event *);
-
-template Rows_log_event*
-THD::binlog_prepare_pending_rows_event(TABLE*, uint32, MY_BITMAP const*,
- size_t colcnt, size_t, bool,
- Update_rows_log_event *);
-#endif
-
/* Declare in unnamed namespace. */
CPP_UNNAMED_NS_START
/**
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 3dbccf9b41e..8df3a2eee36 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1272,7 +1272,8 @@ enum enum_thread_type
SYSTEM_THREAD_SLAVE_SQL= 4,
SYSTEM_THREAD_NDBCLUSTER_BINLOG= 8,
SYSTEM_THREAD_EVENT_SCHEDULER= 16,
- SYSTEM_THREAD_EVENT_WORKER= 32
+ SYSTEM_THREAD_EVENT_WORKER= 32,
+ SYSTEM_THREAD_BINLOG_BACKGROUND= 64
};
inline char const *
@@ -4365,6 +4366,16 @@ public:
*/
#define CF_FORCE_ORIGINAL_BINLOG_FORMAT (1U << 16)
+/**
+ Statement that inserts new rows (INSERT, REPLACE, LOAD, ALTER TABLE)
+*/
+#define CF_INSERTS_DATA (1U << 11)
+
+/**
+ Statement that updates existing rows (UPDATE, multi-update)
+*/
+#define CF_UPDATES_DATA (1U << 12)
+
/* Bits in server_command_flags */
/**
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 0f07f01c6fd..09ddedecc75 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->inc_examined_row_count(1);
// thd->is_error() is tested to disallow delete row on error
if (!select || select->skip_record(thd) > 0)
diff --git a/sql/sql_expression_cache.cc b/sql/sql_expression_cache.cc
index e65ec3c22b0..1193c7c27f4 100644
--- a/sql/sql_expression_cache.cc
+++ b/sql/sql_expression_cache.cc
@@ -257,7 +257,7 @@ my_bool Expression_cache_tmptable::put_value(Item *value)
}
*(items.head_ref())= value;
- fill_record(table_thd, cache_table->field, items, TRUE, TRUE);
+ fill_record(table_thd, cache_table, cache_table->field, items, TRUE, TRUE);
if (table_thd->is_error())
goto err;;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 25c696bc476..67f3955ea61 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -191,11 +191,6 @@ error:
different table maps, like on select ... insert
map Store here table map for used fields
- NOTE
- Clears TIMESTAMP_AUTO_SET_ON_INSERT from table->timestamp_field_type
- or leaves it as is, depending on if timestamp should be updated or
- not.
-
RETURN
0 OK
-1 Error
@@ -234,8 +229,6 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
if (check_grant_all_columns(thd, INSERT_ACL, &field_it))
return -1;
#endif
- clear_timestamp_auto_bits(table->timestamp_field_type,
- TIMESTAMP_AUTO_SET_ON_INSERT);
/*
No fields are provided so all fields must be provided in the values.
Thus we set all bits in the write set.
@@ -295,18 +288,8 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
my_error(ER_FIELD_SPECIFIED_TWICE, MYF(0), thd->dup_field->field_name);
return -1;
}
- if (table->timestamp_field) // Don't automaticly set timestamp if used
- {
- if (bitmap_is_set(table->write_set,
- table->timestamp_field->field_index))
- clear_timestamp_auto_bits(table->timestamp_field_type,
- TIMESTAMP_AUTO_SET_ON_INSERT);
- else
- {
- bitmap_set_bit(table->write_set,
- table->timestamp_field->field_index);
- }
- }
+ if (table->default_field)
+ table->mark_default_fields_for_write();
}
/* Mark virtual columns used in the insert statement */
if (table->vfield)
@@ -339,9 +322,6 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
update_fields The update fields.
NOTE
- If the update fields include the timestamp field,
- remove TIMESTAMP_AUTO_SET_ON_UPDATE from table->timestamp_field_type.
-
If the update fields include an autoinc field, set the
table->next_number_field_updated flag.
@@ -355,21 +335,9 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
List<Item> &update_values, table_map *map)
{
TABLE *table= insert_table_list->table;
- my_bool timestamp_mark;
my_bool autoinc_mark;
- LINT_INIT(timestamp_mark);
LINT_INIT(autoinc_mark);
- if (table->timestamp_field)
- {
- /*
- Unmark the timestamp field so that we can check if this is modified
- by update_fields
- */
- timestamp_mark= bitmap_test_and_clear(table->write_set,
- table->timestamp_field->field_index);
- }
-
table->next_number_field_updated= FALSE;
if (table->found_next_number_field)
@@ -393,17 +361,8 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
insert_table_list, map, false))
return -1;
- if (table->timestamp_field)
- {
- /* Don't set timestamp column if this is modified. */
- if (bitmap_is_set(table->write_set,
- table->timestamp_field->field_index))
- clear_timestamp_auto_bits(table->timestamp_field_type,
- TIMESTAMP_AUTO_SET_ON_UPDATE);
- if (timestamp_mark)
- bitmap_set_bit(table->write_set,
- table->timestamp_field->field_index);
- }
+ if (table->default_field)
+ table->mark_default_fields_for_write();
if (table->found_next_number_field)
{
@@ -716,7 +675,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
int error, res;
bool transactional_table, joins_freed= FALSE;
bool changed;
- bool was_insert_delayed= (table_list->lock_type == TL_WRITE_DELAYED);
+ const bool was_insert_delayed= (table_list->lock_type == TL_WRITE_DELAYED);
bool using_bulk_insert= 0;
uint value_count;
ulong counter = 1;
@@ -916,8 +875,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
if (fields.elements || !value_count)
{
restore_record(table,s->default_values); // Get empty record
- if (fill_record_n_invoke_before_triggers(thd, fields, *values, 0,
- table->triggers,
+ if (fill_record_n_invoke_before_triggers(thd, table, fields, *values, 0,
TRG_EVENT_INSERT))
{
if (values_list.elements != 1 && ! thd->is_error())
@@ -961,8 +919,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
share->default_values[share->null_bytes - 1];
}
}
- if (fill_record_n_invoke_before_triggers(thd, table->field, *values, 0,
- table->triggers,
+ if (fill_record_n_invoke_before_triggers(thd, table, table->field, *values, 0,
TRG_EVENT_INSERT))
{
if (values_list.elements != 1 && ! thd->is_error())
@@ -974,6 +931,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
break;
}
}
+ if (table->default_field && table->update_default_fields())
+ {
+ error= 1;
+ break;
+ }
if ((res= table_list->view_check_option(thd,
(values_list.elements == 1 ?
@@ -990,7 +952,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
if (lock_type == TL_WRITE_DELAYED)
{
LEX_STRING const st_query = { query, thd->query_length() };
+ DEBUG_SYNC(thd, "before_write_delayed");
error=write_delayed(thd, table, duplic, st_query, ignore, log_on);
+ DEBUG_SYNC(thd, "after_write_delayed");
query=0;
}
else
@@ -1680,9 +1644,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;
}
@@ -1699,13 +1664,32 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
restore_record(table,record[1]);
DBUG_ASSERT(info->update_fields->elements ==
info->update_values->elements);
- if (fill_record_n_invoke_before_triggers(thd, *info->update_fields,
+ if (fill_record_n_invoke_before_triggers(thd, table, *info->update_fields,
*info->update_values,
info->ignore,
- table->triggers,
TRG_EVENT_UPDATE))
goto before_trg_err;
+ bool different_records= (!records_are_comparable(table) ||
+ compare_record(table));
+ /*
+ Default fields must be updated before checking view updateability.
+ This branch of INSERT is executed only when a UNIQUE key was violated
+ with the ON DUPLICATE KEY UPDATE option. In this case the INSERT
+ operation is transformed to an UPDATE, and the default fields must
+ be updated as if this is an UPDATE.
+ */
+ if (different_records && table->default_field)
+ {
+ bool res;
+ enum_sql_command cmd= thd->lex->sql_command;
+ thd->lex->sql_command= SQLCOM_UPDATE;
+ res= table->update_default_fields();
+ thd->lex->sql_command= cmd;
+ if (res)
+ goto err;
+ }
+
/* CHECK OPTION for VIEW ... ON DUPLICATE KEY UPDATE ... */
if (info->view &&
(res= info->view->view_check_option(current_thd, info->ignore)) ==
@@ -1716,7 +1700,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
table->file->restore_auto_increment(prev_insert_id);
info->touched++;
- if (!records_are_comparable(table) || compare_record(table))
+ if (different_records)
{
if ((error=table->file->ha_update_row(table->record[1],
table->record[0])) &&
@@ -1787,8 +1771,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
*/
if (last_uniq_key(table,key_nr) &&
!table->file->referenced_by_foreign_key() &&
- (table->timestamp_field_type == TIMESTAMP_NO_AUTO_SET ||
- table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH) &&
(!table->triggers || !table->triggers->has_delete_triggers()))
{
if ((error=table->file->ha_update_row(table->record[1],
@@ -1951,7 +1933,6 @@ public:
ulonglong forced_insert_id;
ulong auto_increment_increment;
ulong auto_increment_offset;
- timestamp_auto_set_type timestamp_field_type;
LEX_STRING query;
Time_zone *time_zone;
@@ -2324,7 +2305,7 @@ end_create:
TABLE *Delayed_insert::get_local_table(THD* client_thd)
{
my_ptrdiff_t adjust_ptrs;
- Field **field,**org_field, *found_next_number_field;
+ Field **field,**org_field, *found_next_number_field, **dfield_ptr= 0;
TABLE *copy;
TABLE_SHARE *share;
uchar *bitmap;
@@ -2393,6 +2374,14 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
bitmap= (uchar*) (field + share->fields + 1);
copy->record[0]= (bitmap + share->column_bitmap_size*3);
memcpy((char*) copy->record[0], (char*) table->record[0], share->reclength);
+ if (share->default_fields)
+ {
+ copy->default_field= (Field**) client_thd->alloc((share->default_fields+1)*
+ sizeof(Field**));
+ if (!copy->default_field)
+ goto error;
+ dfield_ptr= copy->default_field;
+ }
/*
Make a copy of all fields.
The copied fields need to point into the copied record. This is done
@@ -2410,18 +2399,19 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
(*field)->move_field_offset(adjust_ptrs); // Point at copy->record[0]
if (*org_field == found_next_number_field)
(*field)->table->found_next_number_field= *field;
+ if (share->default_fields &&
+ ((*org_field)->has_insert_default_function() ||
+ (*org_field)->has_update_default_function()))
+ {
+ /* Put the newly copied field into the set of default fields. */
+ *dfield_ptr= *field;
+ (*dfield_ptr)->unireg_check= (*org_field)->unireg_check;
+ dfield_ptr++;
+ }
}
*field=0;
-
- /* Adjust timestamp */
- if (table->timestamp_field)
- {
- /* Restore offset as this may have been reset in handle_inserts */
- copy->timestamp_field=
- (Field_timestamp*) copy->field[share->timestamp_field_offset];
- copy->timestamp_field->unireg_check= table->timestamp_field->unireg_check;
- copy->timestamp_field_type= copy->timestamp_field->get_auto_set_type();
- }
+ if (share->default_fields)
+ *dfield_ptr= NULL;
/* Adjust in_use for pointing to client thread */
copy->in_use= client_thd;
@@ -2511,7 +2501,6 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic,
thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt;
row->first_successful_insert_id_in_prev_stmt=
thd->first_successful_insert_id_in_prev_stmt;
- row->timestamp_field_type= table->timestamp_field_type;
/* Add session variable timezone
Time_zone object will not be freed even the thread is ended.
@@ -3053,7 +3042,6 @@ bool Delayed_insert::handle_inserts(void)
row->first_successful_insert_id_in_prev_stmt;
thd.stmt_depends_on_first_successful_insert_id_in_prev_stmt=
row->stmt_depends_on_first_successful_insert_id_in_prev_stmt;
- table->timestamp_field_type= row->timestamp_field_type;
table->auto_increment_field_not_null= row->auto_increment_field_not_null;
/* Copy the session variables. */
@@ -3523,6 +3511,8 @@ int select_insert::send_data(List<Item> &values)
thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields
store_values(values);
+ if (table->default_field && table->update_default_fields())
+ DBUG_RETURN(1);
thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
if (thd->is_error())
{
@@ -3582,11 +3572,11 @@ int select_insert::send_data(List<Item> &values)
void select_insert::store_values(List<Item> &values)
{
if (fields->elements)
- fill_record_n_invoke_before_triggers(thd, *fields, values, 1,
- table->triggers, TRG_EVENT_INSERT);
+ fill_record_n_invoke_before_triggers(thd, table, *fields, values, 1,
+ TRG_EVENT_INSERT);
else
- fill_record_n_invoke_before_triggers(thd, table->field, values, 1,
- table->triggers, TRG_EVENT_INSERT);
+ fill_record_n_invoke_before_triggers(thd, table, table->field, values, 1,
+ TRG_EVENT_INSERT);
}
void select_insert::send_error(uint errcode,const char *err)
@@ -3804,7 +3794,6 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
DBUG_ENTER("create_table_from_items");
tmp_table.alias= 0;
- tmp_table.timestamp_field= 0;
tmp_table.s= &share;
init_tmp_table_share(thd, &share, "", 0, "", "");
@@ -3813,6 +3802,8 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
tmp_table.null_row= 0;
tmp_table.maybe_null= 0;
+ promote_first_timestamp_column(&alter_info->create_list);
+
while ((item=it++))
{
Create_field *cr_field;
@@ -4052,8 +4043,6 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
for (Field **f= field ; *f ; f++)
bitmap_set_bit(table->write_set, (*f)->field_index);
- /* Don't set timestamp if used */
- table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
table->next_number_field=table->found_next_number_field;
restore_record(table,s->default_values); // Get empty record
@@ -4126,8 +4115,8 @@ select_create::binlog_show_create_table(TABLE **tables, uint count)
void select_create::store_values(List<Item> &values)
{
- fill_record_n_invoke_before_triggers(thd, field, values, 1,
- table->triggers, TRG_EVENT_INSERT);
+ fill_record_n_invoke_before_triggers(thd, table, field, values, 1,
+ TRG_EVENT_INSERT);
}
@@ -4236,16 +4225,3 @@ void select_create::abort_result_set()
DBUG_VOID_RETURN;
}
-
-/*****************************************************************************
- Instansiate templates
-*****************************************************************************/
-
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-template class List_iterator_fast<List_item>;
-#ifndef EMBEDDED_LIBRARY
-template class I_List<Delayed_insert>;
-template class I_List_iterator<Delayed_insert>;
-template class I_List<delayed_row>;
-#endif /* EMBEDDED_LIBRARY */
-#endif /* HAVE_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 975f0c77349..2c9a55208fc 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -4445,6 +4445,3 @@ void binlog_unsafe_map_init()
}
#endif
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-template class Mem_root_array<ORDER*, true>;
-#endif
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index daa9298d52d..38853eb8b6d 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -273,7 +273,6 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
for (field=table->field; *field ; field++)
fields_vars.push_back(new Item_field(*field));
bitmap_set_all(table->write_set);
- table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
/*
Let us also prepare SET clause, altough it is probably empty
in this case.
@@ -289,21 +288,9 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
check_that_all_fields_are_given_values(thd, table, table_list))
DBUG_RETURN(TRUE);
- /*
- Check whenever TIMESTAMP field with auto-set feature specified
- explicitly.
- */
- if (table->timestamp_field)
- {
- if (bitmap_is_set(table->write_set,
- table->timestamp_field->field_index))
- table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
- else
- {
- bitmap_set_bit(table->write_set,
- table->timestamp_field->field_index);
- }
- }
+ /* Add all fields with default functions to table->write_set. */
+ if (table->default_field)
+ table->mark_default_fields_for_write();
/* Fix the expressions in SET clause */
if (setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0))
DBUG_RETURN(TRUE);
@@ -846,8 +833,12 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
ER_WARN_TOO_FEW_RECORDS,
ER(ER_WARN_TOO_FEW_RECORDS),
thd->warning_info->current_row_for_warning());
+ /*
+ Timestamp fields that are NOT NULL are autoupdated if there is no
+ corresponding value in the data file.
+ */
if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP)
- ((Field_timestamp*) field)->set_time();
+ field->set_time();
}
else
{
@@ -862,6 +853,8 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if ((pos+=length) > read_info.row_end)
pos= read_info.row_end; /* Fills rest with space */
}
+ /* Do not auto-update this field. */
+ field->set_has_explicit_value();
}
if (pos != read_info.row_end)
{
@@ -873,10 +866,10 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
}
if (thd->killed ||
- fill_record_n_invoke_before_triggers(thd, set_fields, set_values,
+ fill_record_n_invoke_before_triggers(thd, table, set_fields, set_values,
ignore_check_option_errors,
- table->triggers,
- TRG_EVENT_INSERT))
+ TRG_EVENT_INSERT) ||
+ (table->default_field && table->update_default_fields()))
DBUG_RETURN(1);
switch (table_list->view_check_option(thd,
@@ -993,12 +986,18 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
field->set_null();
if (!field->maybe_null())
{
+ /*
+ Timestamp fields that are NOT NULL are autoupdated if there is no
+ corresponding value in the data file.
+ */
if (field->type() == MYSQL_TYPE_TIMESTAMP)
- ((Field_timestamp*) field)->set_time();
+ field->set_time();
else if (field != table->next_number_field)
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_NULL_TO_NOTNULL, 1);
}
+ /* Do not auto-update this field. */
+ field->set_has_explicit_value();
}
else if (item->type() == Item::STRING_ITEM)
{
@@ -1022,6 +1021,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (field == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
field->store((char*) pos, length, read_info.read_charset);
+ field->set_has_explicit_value();
}
else if (item->type() == Item::STRING_ITEM)
{
@@ -1063,7 +1063,8 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
DBUG_RETURN(1);
}
if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP)
- ((Field_timestamp*) field)->set_time();
+ field->set_time();
+ field->set_has_explicit_value();
/*
TODO: We probably should not throw warning for each field.
But how about intention to always have the same number
@@ -1090,10 +1091,10 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
}
if (thd->killed ||
- fill_record_n_invoke_before_triggers(thd, set_fields, set_values,
+ fill_record_n_invoke_before_triggers(thd, table, set_fields, set_values,
ignore_check_option_errors,
- table->triggers,
- TRG_EVENT_INSERT))
+ TRG_EVENT_INSERT) ||
+ (table->default_field && table->update_default_fields()))
DBUG_RETURN(1);
switch (table_list->view_check_option(thd,
@@ -1203,11 +1204,13 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (!field->maybe_null())
{
if (field->type() == FIELD_TYPE_TIMESTAMP)
- ((Field_timestamp *) field)->set_time();
+ field->set_time();
else if (field != table->next_number_field)
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_NULL_TO_NOTNULL, 1);
}
+ /* Do not auto-update this field. */
+ field->set_has_explicit_value();
}
else
((Item_user_var_as_out_param *) item)->set_null_value(cs);
@@ -1222,6 +1225,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (field == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
field->store((char *) tag->value.ptr(), tag->value.length(), cs);
+ field->set_has_explicit_value();
}
else
((Item_user_var_as_out_param *) item)->set_value(
@@ -1266,10 +1270,10 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
}
if (thd->killed ||
- fill_record_n_invoke_before_triggers(thd, set_fields, set_values,
+ fill_record_n_invoke_before_triggers(thd, table, set_fields, set_values,
ignore_check_option_errors,
- table->triggers,
- TRG_EVENT_INSERT))
+ TRG_EVENT_INSERT) ||
+ (table->default_field && table->update_default_fields()))
DBUG_RETURN(1);
switch (table_list->view_check_option(thd,
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 36447a1836d..14601f99138 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -270,12 +270,14 @@ void init_update_queries(void)
CF_CAN_GENERATE_ROW_EVENTS;
sql_command_flags[SQLCOM_CREATE_INDEX]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
- CF_AUTO_COMMIT_TRANS | CF_REPORT_PROGRESS ;
+ CF_AUTO_COMMIT_TRANS | CF_REPORT_PROGRESS |
+ CF_INSERTS_DATA;
sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_LOAD]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
- CF_CAN_GENERATE_ROW_EVENTS | CF_REPORT_PROGRESS;
+ CF_CAN_GENERATE_ROW_EVENTS | CF_REPORT_PROGRESS |
+ CF_INSERTS_DATA;
sql_command_flags[SQLCOM_CREATE_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_DROP_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_ALTER_DB_UPGRADE]= CF_AUTO_COMMIT_TRANS;
@@ -294,19 +296,23 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_UPDATE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE |
- CF_CAN_BE_EXPLAINED;
+ CF_CAN_BE_EXPLAINED |
+ CF_UPDATES_DATA;
sql_command_flags[SQLCOM_UPDATE_MULTI]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE |
- CF_CAN_BE_EXPLAINED;
+ CF_CAN_BE_EXPLAINED |
+ CF_UPDATES_DATA;
sql_command_flags[SQLCOM_INSERT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE |
- CF_CAN_BE_EXPLAINED;
+ CF_CAN_BE_EXPLAINED |
+ CF_INSERTS_DATA;
sql_command_flags[SQLCOM_INSERT_SELECT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE |
- CF_CAN_BE_EXPLAINED;
+ CF_CAN_BE_EXPLAINED |
+ CF_INSERTS_DATA;
sql_command_flags[SQLCOM_DELETE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE |
@@ -318,11 +324,13 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE |
- CF_CAN_BE_EXPLAINED;;
+ CF_CAN_BE_EXPLAINED |
+ CF_INSERTS_DATA;;
sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE |
- CF_CAN_BE_EXPLAINED;
+ CF_CAN_BE_EXPLAINED |
+ CF_INSERTS_DATA;
sql_command_flags[SQLCOM_SELECT]= CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE |
@@ -6175,6 +6183,7 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
{
register Create_field *new_field;
LEX *lex= thd->lex;
+ uint8 datetime_precision= length ? atoi(length) : 0;
DBUG_ENTER("add_field_to_list");
if (check_string_char_length(field_name, "", NAME_CHAR_LEN,
@@ -6211,11 +6220,13 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
no need fix_fields()
We allow only one function as part of default value -
- NOW() as default for TIMESTAMP type.
+ NOW() as default for TIMESTAMP and DATETIME type.
*/
if (default_value->type() == Item::FUNC_ITEM &&
- !(((Item_func*)default_value)->functype() == Item_func::NOW_FUNC &&
- type == MYSQL_TYPE_TIMESTAMP))
+ (static_cast<Item_func*>(default_value)->functype() !=
+ Item_func::NOW_FUNC ||
+ (mysql_type_to_time_type(type) != MYSQL_TIMESTAMP_DATETIME) ||
+ default_value->decimals < datetime_precision))
{
my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str);
DBUG_RETURN(1);
@@ -6237,7 +6248,9 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
}
}
- if (on_update_value && type != MYSQL_TYPE_TIMESTAMP)
+ if (on_update_value &&
+ (mysql_type_to_time_type(type) != MYSQL_TIMESTAMP_DATETIME ||
+ on_update_value->decimals < datetime_precision))
{
my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name->str);
DBUG_RETURN(1);
@@ -7097,8 +7110,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_partition.cc b/sql/sql_partition.cc
index 2bec12e4f66..f042f028450 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -6526,9 +6526,6 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
lpt->pack_frm_data= NULL;
lpt->pack_frm_len= 0;
- /* Never update timestamp columns when alter */
- lpt->table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
-
if (table->file->alter_table_flags(alter_info->flags) &
HA_PARTITION_ONE_PHASE)
{
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 969e6ee4574..24dde140a8a 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2508,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_select.cc b/sql/sql_select.cc
index 8f565cb3d32..90302897a49 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1291,11 +1291,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;
@@ -2143,6 +2141,7 @@ JOIN::reinit()
ULL(0));
first_record= 0;
+ cleaned= false;
if (exec_tmp_table1)
{
@@ -5513,7 +5512,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;
@@ -8111,18 +8111,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)
{
@@ -9283,7 +9288,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;
@@ -9571,7 +9576,7 @@ end_sj_materialize(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
if (item->is_null())
DBUG_RETURN(NESTED_LOOP_OK);
}
- fill_record(thd, table->field, sjm->sjm_table_cols, TRUE, FALSE);
+ fill_record(thd, table, table->field, sjm->sjm_table_cols, TRUE, FALSE);
if (thd->is_error())
DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
if ((error= table->file->ha_write_tmp_row(table->record[0])))
@@ -10774,6 +10779,7 @@ void JOIN::cleanup(bool full)
{
tab->cleanup();
}
+ cleaned= true;
}
else
{
@@ -11247,14 +11253,6 @@ public:
COND_CMP(Item *a,Item_func *b) :and_level(a),cmp_func(b) {}
};
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-template class I_List<COND_CMP>;
-template class I_List_iterator<COND_CMP>;
-template class List<Item_func_match>;
-template class List_iterator<Item_func_match>;
-#endif
-
-
/**
Find the multiple equality predicate containing a field.
@@ -16622,6 +16620,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)
{
@@ -16740,6 +16749,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)
{
@@ -16772,12 +16791,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
@@ -18638,15 +18654,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.
@@ -19170,49 +19189,7 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
*(join->pre_sort_join_tab)= *tab;
- /*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->type=JT_ALL; // Read with normal read_record
@@ -19236,34 +19213,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
@@ -20744,40 +20700,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)
{
@@ -20789,20 +20771,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);
}
@@ -22613,6 +22595,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 "));
@@ -23080,6 +23073,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
@@ -23104,7 +23098,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)
@@ -23211,7 +23206,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 */
@@ -23293,7 +23288,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 8420a223fb6..54aca3c4829 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -896,6 +896,14 @@ protected:
public:
JOIN_TAB *join_tab, **best_ref;
+ /*
+ Saved join_tab for pre_sorting. create_sort_index() will save here..
+ */
+ JOIN_TAB *pre_sort_join_tab;
+ uint pre_sort_index;
+ Item *pre_sort_idx_pushed_cond;
+ void clean_pre_sort_join_tab();
+
/*
For "Using temporary+Using filesort" queries, JOIN::join_tab can point to
either:
@@ -908,15 +916,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
@@ -1140,6 +1139,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
@@ -1274,6 +1275,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 73d441a2d9d..4d251aa1c81 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1386,8 +1386,35 @@ static void append_directory(THD *thd, String *packet, const char *dir_type,
#define LIST_PROCESS_HOST_LEN 64
-static bool get_field_default_value(THD *thd, Field *timestamp_field,
- Field *field, String *def_value,
+
+/**
+ Print "ON UPDATE" clause of a field into a string.
+
+ @param timestamp_field Pointer to timestamp field of a table.
+ @param field The field to generate ON UPDATE clause for.
+ @bool lcase Whether to print in lower case.
+ @return false on success, true on error.
+*/
+static bool print_on_update_clause(Field *field, String *val, bool lcase)
+{
+ DBUG_ASSERT(val->charset()->mbminlen == 1);
+ val->length(0);
+ if (field->has_update_default_function())
+ {
+ if (lcase)
+ val->append(STRING_WITH_LEN("on update "));
+ else
+ val->append(STRING_WITH_LEN("ON UPDATE "));
+ val->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
+ if (field->decimals() > 0)
+ val->append_parenthesized(field->decimals());
+ return true;
+ }
+ return false;
+}
+
+
+static bool get_field_default_value(THD *thd, Field *field, String *def_value,
bool quoted)
{
bool has_default;
@@ -1398,8 +1425,7 @@ static bool get_field_default_value(THD *thd, Field *timestamp_field,
We are using CURRENT_TIMESTAMP instead of NOW because it is
more standard
*/
- has_now_default= (timestamp_field == field &&
- field->unireg_check != Field::TIMESTAMP_UN_FIELD);
+ has_now_default= field->has_insert_default_function();
has_default= (field_type != FIELD_TYPE_BLOB &&
!(field->flags & NO_DEFAULT_VALUE_FLAG) &&
@@ -1411,7 +1437,11 @@ static bool get_field_default_value(THD *thd, Field *timestamp_field,
if (has_default)
{
if (has_now_default)
+ {
def_value->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
+ if (field->decimals() > 0)
+ def_value->append_parenthesized(field->decimals());
+ }
else if (!field->is_null())
{ // Not null by default
char tmp[MAX_FIELD_WIDTH];
@@ -1643,16 +1673,18 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
}
if (!field->vcol_info &&
- get_field_default_value(thd, table->timestamp_field,
- field, &def_value, 1))
+ get_field_default_value(thd, field, &def_value, 1))
{
packet->append(STRING_WITH_LEN(" DEFAULT "));
packet->append(def_value.ptr(), def_value.length(), system_charset_info);
}
- if (!limited_mysql_mode && table->timestamp_field == field &&
- field->unireg_check != Field::TIMESTAMP_DN_FIELD)
- packet->append(STRING_WITH_LEN(" ON UPDATE CURRENT_TIMESTAMP"));
+ if (!limited_mysql_mode && print_on_update_clause(field, &def_value, false))
+ {
+ packet->append(STRING_WITH_LEN(" "));
+ packet->append(def_value);
+ }
+
if (field->unireg_check == Field::NEXT_NUMBER &&
!(thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS))
@@ -2116,10 +2148,6 @@ public:
double progress;
};
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-template class I_List<thread_info>;
-#endif
-
static const char *thread_state_info(THD *tmp)
{
#ifndef EMBEDDED_LIBRARY
@@ -2320,7 +2348,7 @@ void Show_explain_request::call_in_target_thread()
int select_result_explain_buffer::send_data(List<Item> &items)
{
- fill_record(thd, dst_table->field, items, TRUE, FALSE);
+ fill_record(thd, dst_table, dst_table->field, items, TRUE, FALSE);
if ((dst_table->file->ha_write_tmp_row(dst_table->record[0])))
return 1;
return 0;
@@ -4056,8 +4084,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
@@ -5212,7 +5241,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
const char *wild= lex->wild ? lex->wild->ptr() : NullS;
CHARSET_INFO *cs= system_charset_info;
TABLE *show_table;
- Field **ptr, *field, *timestamp_field;
+ Field **ptr, *field;
int count;
DBUG_ENTER("get_schema_column_record");
@@ -5236,7 +5265,6 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
show_table= tables->table;
count= 0;
ptr= show_table->field;
- timestamp_field= show_table->timestamp_field;
show_table->use_all_columns(); // Required for default
restore_record(show_table, s->default_values);
@@ -5284,7 +5312,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
cs);
table->field[4]->store((longlong) count, TRUE);
- if (get_field_default_value(thd, timestamp_field, field, &type, 0))
+ if (get_field_default_value(thd, field, &type, 0))
{
table->field[5]->store(type.ptr(), type.length(), cs);
table->field[5]->set_notnull();
@@ -5301,10 +5329,8 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
if (field->unireg_check == Field::NEXT_NUMBER)
table->field[17]->store(STRING_WITH_LEN("auto_increment"), cs);
- if (timestamp_field == field &&
- field->unireg_check != Field::TIMESTAMP_DN_FIELD)
- table->field[17]->store(STRING_WITH_LEN("on update CURRENT_TIMESTAMP"),
- cs);
+ if (print_on_update_clause(field, &type, true))
+ table->field[17]->store(type.ptr(), type.length(), cs);
if (field->vcol_info)
{
if (field->stored_in_db)
@@ -8905,11 +8931,6 @@ ST_SCHEMA_TABLE schema_tables[]=
};
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-template class List_iterator_fast<char>;
-template class List<char>;
-#endif
-
int initialize_schema_table(st_plugin_int *plugin)
{
ST_SCHEMA_TABLE *schema_table;
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 75029a03790..89536b93feb 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -502,6 +502,24 @@ bool String::append(IO_CACHE* file, uint32 arg_length)
return FALSE;
}
+
+/**
+ Append a parenthesized number to String.
+ Used in various pieces of SHOW related code.
+
+ @param nr Number
+ @param radix Radix, optional parameter, 10 by default.
+*/
+bool String::append_parenthesized(long nr, int radix)
+{
+ char buff[64], *end;
+ buff[0]= '(';
+ end= int10_to_str(nr, buff + 1, radix);
+ *end++ = ')';
+ return append(buff, (uint) (end - buff));
+}
+
+
bool String::append_with_prefill(const char *s,uint32 arg_length,
uint32 full_length, char fill_char)
{
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 8b09d449c2b..2966fc2a920 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -346,6 +346,7 @@ public:
bool append(IO_CACHE* file, uint32 arg_length);
bool append_with_prefill(const char *s, uint32 arg_length,
uint32 full_length, char fill_char);
+ bool append_parenthesized(long nr, int radix= 10);
int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
bool replace(uint32 offset,uint32 arg_length,const char *to,uint32 length);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 66e3b0b2544..6e99ebb0d37 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2610,7 +2610,6 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
prepare_create_field()
sql_field field to prepare for packing
blob_columns count for BLOBs
- timestamps count for timestamps
table_flags table flags
DESCRIPTION
@@ -2624,7 +2623,6 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
int prepare_create_field(Create_field *sql_field,
uint *blob_columns,
- int *timestamps, int *timestamps_with_niladic,
longlong table_flags)
{
unsigned int dup_val_count;
@@ -2746,21 +2744,6 @@ int prepare_create_field(Create_field *sql_field,
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
break;
case MYSQL_TYPE_TIMESTAMP:
- /* We should replace old TIMESTAMP fields with their newer analogs */
- if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
- {
- if (!*timestamps)
- {
- sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
- (*timestamps_with_niladic)++;
- }
- else
- sql_field->unireg_check= Field::NONE;
- }
- else if (sql_field->unireg_check != Field::NONE)
- (*timestamps_with_niladic)++;
-
- (*timestamps)++;
/* fall-through */
default:
sql_field->pack_flag=(FIELDFLAG_NUMBER |
@@ -2832,6 +2815,40 @@ bool check_duplicate_warning(THD *thd, char *msg, ulong length)
}
+/**
+ Modifies the first column definition whose SQL type is TIMESTAMP
+ by adding the features DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP.
+
+ @param column_definitions The list of column definitions, in the physical
+ order in which they appear in the table.
+ */
+void promote_first_timestamp_column(List<Create_field> *column_definitions)
+{
+ List_iterator<Create_field> it(*column_definitions);
+ Create_field *column_definition;
+
+ while ((column_definition= it++) != NULL)
+ {
+ if (column_definition->sql_type == MYSQL_TYPE_TIMESTAMP || // TIMESTAMP
+ column_definition->unireg_check == Field::TIMESTAMP_OLD_FIELD) // Legacy
+ {
+ if ((column_definition->flags & NOT_NULL_FLAG) != 0 && // NOT NULL,
+ column_definition->def == NULL && // no constant default,
+ column_definition->unireg_check == Field::NONE) // no function default
+ {
+ DBUG_PRINT("info", ("First TIMESTAMP column '%s' was promoted to "
+ "DEFAULT CURRENT_TIMESTAMP ON UPDATE "
+ "CURRENT_TIMESTAMP",
+ column_definition->field_name
+ ));
+ column_definition->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
+ }
+ return;
+ }
+ }
+}
+
+
/*
Preparation for table creation
@@ -2872,7 +2889,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
ulong record_offset= 0;
KEY *key_info;
KEY_PART_INFO *key_part_info;
- int timestamps= 0, timestamps_with_niladic= 0;
int field_no,dup_no;
int select_field_pos,auto_increment=0;
List_iterator<Create_field> it(alter_info->create_list);
@@ -3156,7 +3172,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_ASSERT(sql_field->charset != 0);
if (prepare_create_field(sql_field, &blob_columns,
- &timestamps, &timestamps_with_niladic,
file->ha_table_flags()))
DBUG_RETURN(TRUE);
if (sql_field->sql_type == MYSQL_TYPE_VARCHAR)
@@ -3187,12 +3202,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
record_offset+= sql_field->pack_length;
}
}
- if (timestamps_with_niladic > 1)
- {
- my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,
- ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0));
- DBUG_RETURN(TRUE);
- }
if (auto_increment > 1)
{
my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
@@ -4559,6 +4568,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
/* Got lock. */
DEBUG_SYNC(thd, "locked_table_name");
+ promote_first_timestamp_column(&alter_info->create_list);
result= mysql_create_table_no_lock(thd, create_table->db,
create_table->table_name, create_info,
alter_info, FALSE, 0, &is_trans);
@@ -6386,6 +6396,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
need_copy_table= alter_info->change_level;
set_table_default_charset(thd, create_info, db);
+ promote_first_timestamp_column(&alter_info->create_list);
if (thd->variables.old_alter_table
|| (table->s->db_type() != create_info->db_type)
@@ -6753,8 +6764,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
*/
if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
{
- /* We don't want update TIMESTAMP fields during ALTER TABLE. */
- new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
new_table->next_number_field=new_table->found_next_number_field;
DBUG_EXECUTE_IF("abort_copy_table", {
my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
@@ -7331,6 +7340,7 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to,
ulonglong prev_insert_id, time_to_report_progress;
List_iterator<Create_field> it(create);
Create_field *def;
+ Field **dfield_ptr= to->default_field;
DBUG_ENTER("copy_data_between_tables");
/* Two or 3 stages; Sorting, copying data and update indexes */
@@ -7358,6 +7368,7 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to,
errpos= 3;
copy_end=copy;
+ to->s->default_fields= 0;
for (Field **ptr=to->field ; *ptr ; ptr++)
{
def=it++;
@@ -7377,8 +7388,23 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to,
}
(copy_end++)->set(*ptr,def->field,0);
}
-
+ else
+ {
+ /*
+ Update the set of auto-update fields to contain only the new fields
+ added to the table. Only these fields should be updated automatically.
+ Old fields keep their current values, and therefore should not be
+ present in the set of autoupdate fields.
+ */
+ if ((*ptr)->has_insert_default_function())
+ {
+ *(dfield_ptr++)= *ptr;
+ ++to->s->default_fields;
+ }
+ }
}
+ if (dfield_ptr)
+ *dfield_ptr= NULL;
if (order)
{
@@ -7468,7 +7494,12 @@ 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;
+ break;
+ }
if (thd->is_error())
{
error= 1;
diff --git a/sql/sql_table.h b/sql/sql_table.h
index 00de6ed1b8d..9d5e768a5a3 100644
--- a/sql/sql_table.h
+++ b/sql/sql_table.h
@@ -187,7 +187,6 @@ void close_cached_table(THD *thd, TABLE *table);
void sp_prepare_create_field(THD *thd, Create_field *sql_field);
int prepare_create_field(Create_field *sql_field,
uint *blob_columns,
- int *timestamps, int *timestamps_with_niladic,
longlong table_flags);
CHARSET_INFO* get_sql_field_charset(Create_field *sql_field,
HA_CREATE_INFO *create_info);
@@ -208,6 +207,9 @@ void execute_ddl_log_recovery();
bool execute_ddl_log_entry(THD *thd, uint first_entry);
bool check_duplicate_warning(THD *thd, char *msg, ulong length);
+template<typename T> class List;
+void promote_first_timestamp_column(List<Create_field> *column_definitions);
+
/*
These prototypes where under INNODB_COMPATIBILITY_HOOKS.
*/
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 7fab29a7d64..bda9b919663 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -63,7 +63,7 @@ int select_union::send_data(List<Item> &values)
return 0;
if (table->no_rows_with_nulls)
table->null_catch_flags= CHECK_ROW_FOR_NULLS_TO_REJECT;
- fill_record(thd, table->field, values, TRUE, FALSE);
+ fill_record(thd, table, table->field, values, TRUE, FALSE);
if (thd->is_error())
return 1;
if (table->no_rows_with_nulls)
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 42e2eb6cbfd..4ed67c86eb1 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -342,19 +342,8 @@ int mysql_update(THD *thd,
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE");
DBUG_RETURN(1);
}
- if (table->timestamp_field)
- {
- // Don't set timestamp column if this is modified
- if (bitmap_is_set(table->write_set,
- table->timestamp_field->field_index))
- table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
- else
- {
- if (((uint) table->timestamp_field_type) & TIMESTAMP_AUTO_SET_ON_UPDATE)
- bitmap_set_bit(table->write_set,
- table->timestamp_field->field_index);
- }
- }
+ if (table->default_field)
+ table->mark_default_fields_for_write();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Check values */
@@ -389,7 +378,7 @@ int mysql_update(THD *thd,
to compare records and detect data change.
*/
if ((table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) &&
- (((uint) table->timestamp_field_type) & TIMESTAMP_AUTO_SET_ON_UPDATE))
+ table->default_field && table->has_default_function(true))
bitmap_union(table->read_set, table->write_set);
// Don't count on usage of 'only index' when calculating which key to use
table->covering_keys.clear_all();
@@ -563,7 +552,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->inc_examined_row_count(1);
if (!select || (error= select->skip_record(thd)) > 0)
{
@@ -676,7 +667,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->inc_examined_row_count(1);
if (!select || select->skip_record(thd) > 0)
{
@@ -684,8 +677,7 @@ int mysql_update(THD *thd,
continue; /* repeat the read of the same row if it still exists */
store_record(table,record[1]);
- if (fill_record_n_invoke_before_triggers(thd, fields, values, 0,
- table->triggers,
+ if (fill_record_n_invoke_before_triggers(thd, table, fields, values, 0,
TRG_EVENT_UPDATE))
break; /* purecov: inspected */
@@ -693,6 +685,11 @@ int mysql_update(THD *thd,
if (!can_compare_record || compare_record(table))
{
+ if (table->default_field && table->update_default_fields())
+ {
+ error= 1;
+ break;
+ }
if ((res= table_list->view_check_option(thd, ignore)) !=
VIEW_CHECK_OK)
{
@@ -1239,11 +1236,6 @@ int mysql_multi_update_prepare(THD *thd)
while ((tl= ti++))
{
TABLE *table= tl->table;
- /* Only set timestamp column if this is not modified */
- if (table->timestamp_field &&
- bitmap_is_set(table->write_set,
- table->timestamp_field->field_index))
- table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
/* if table will be updated then check that it is unique */
if (table->map & tables_for_update)
@@ -1491,8 +1483,7 @@ int multi_update::prepare(List<Item> &not_used_values,
to compare records and detect data change.
*/
if ((table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) &&
- (((uint) table->timestamp_field_type) &
- TIMESTAMP_AUTO_SET_ON_UPDATE))
+ table->default_field && table->has_default_function(true))
bitmap_union(table->read_set, table->write_set);
}
}
@@ -1871,10 +1862,10 @@ int multi_update::send_data(List<Item> &not_used_values)
table->status|= STATUS_UPDATED;
store_record(table,record[1]);
- if (fill_record_n_invoke_before_triggers(thd, *fields_for_table[offset],
+ if (fill_record_n_invoke_before_triggers(thd, table, *fields_for_table[offset],
*values_for_table[offset], 0,
- table->triggers,
- TRG_EVENT_UPDATE))
+ TRG_EVENT_UPDATE) ||
+ (table->default_field && table->update_default_fields()))
DBUG_RETURN(1);
/*
@@ -1975,7 +1966,7 @@ int multi_update::send_data(List<Item> &not_used_values)
} while ((tbl= tbl_it++));
/* Store regular updated fields in the row. */
- fill_record(thd,
+ fill_record(thd, tmp_table,
tmp_table->field + 1 + unupdated_check_opt_tables.elements,
*values_for_table[offset], TRUE, FALSE);
@@ -2165,7 +2156,10 @@ int multi_update::do_updates()
for (copy_field_ptr=copy_field;
copy_field_ptr != copy_field_end;
copy_field_ptr++)
+ {
(*copy_field_ptr->do_copy)(copy_field_ptr);
+ copy_field_ptr->to_field->set_has_explicit_value();
+ }
if (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
@@ -2175,6 +2169,8 @@ int multi_update::do_updates()
if (!can_compare_record || compare_record(table))
{
int error;
+ if (table->default_field && (error= table->update_default_fields()))
+ goto err2;
if ((error= cur_table->view_check_option(thd, ignore)) !=
VIEW_CHECK_OK)
{
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index b14757f7581..e9df67a7a05 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1595,6 +1595,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt
optional_flush_tables_arguments opt_dyncol_type dyncol_type
opt_time_precision kill_type kill_option int_num
+ opt_default_time_precision
/*
Bit field of MYSQL_START_TRANS_OPT_* flags.
@@ -6025,9 +6026,9 @@ attribute:
NULL_SYM { Lex->type&= ~ NOT_NULL_FLAG; }
| not NULL_SYM { Lex->type|= NOT_NULL_FLAG; }
| DEFAULT now_or_signed_literal { Lex->default_value=$2; }
- | ON UPDATE_SYM NOW_SYM optional_braces
+ | ON UPDATE_SYM NOW_SYM opt_default_time_precision
{
- Item *item= new (YYTHD->mem_root) Item_func_now_local(6);
+ Item *item= new (YYTHD->mem_root) Item_func_now_local($4);
if (item == NULL)
MYSQL_YYABORT;
Lex->on_update_value= item;
@@ -6119,9 +6120,9 @@ type_with_opt_collate:
now_or_signed_literal:
- NOW_SYM optional_braces
+ NOW_SYM opt_default_time_precision
{
- $$= new (YYTHD->mem_root) Item_func_now_local(6);
+ $$= new (YYTHD->mem_root) Item_func_now_local($2);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -7945,6 +7946,12 @@ select_alias:
| TEXT_STRING_sys { $$=$1; }
;
+opt_default_time_precision:
+ /* empty */ { $$= NOT_FIXED_DEC; }
+ | '(' ')' { $$= NOT_FIXED_DEC; }
+ | '(' real_ulong_num ')' { $$= $2; };
+ ;
+
opt_time_precision:
/* empty */ { $$= 0; }
| '(' ')' { $$= 0; }
diff --git a/sql/sys_vars.h b/sql/sys_vars.h
index 98a2b4c17fb..98c71e1df13 100644
--- a/sql/sys_vars.h
+++ b/sql/sys_vars.h
@@ -2047,18 +2047,3 @@ public:
}
};
-
-/****************************************************************************
- Used templates
-****************************************************************************/
-
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-template class List<set_var_base>;
-template class List_iterator_fast<set_var_base>;
-template class Sys_var_integer<int, GET_INT, SHOW_SINT>;
-template class Sys_var_integer<uint, GET_UINT, SHOW_INT>;
-template class Sys_var_integer<ulong, GET_ULONG, SHOW_LONG>;
-template class Sys_var_integer<ha_rows, GET_HA_ROWS, SHOW_HA_ROWS>;
-template class Sys_var_integer<ulonglong, GET_ULL, SHOW_LONGLONG>;
-#endif
-
diff --git a/sql/table.cc b/sql/table.cc
index 18aaed6d81f..9954d91cab4 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;
}
@@ -1250,6 +1251,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
com_length= uint2korr(forminfo+284);
vcol_screen_length= uint2korr(forminfo+286);
share->vfields= 0;
+ share->default_fields= 0;
share->stored_fields= share->fields;
if (forminfo[46] != (uchar)255)
{
@@ -1581,8 +1583,6 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
if (reg_field->unireg_check == Field::NEXT_NUMBER)
share->found_next_number_field= field_ptr;
- if (share->timestamp_field == reg_field)
- share->timestamp_field_offset= i;
if (use_hash)
{
@@ -1604,6 +1604,9 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
if (share->stored_rec_length>=recpos)
share->stored_rec_length= recpos-1;
}
+ if (reg_field->has_insert_default_function() ||
+ reg_field->has_update_default_function())
+ ++share->default_fields;
}
*field_ptr=0; // End marker
/* Sanity checks: */
@@ -2315,7 +2318,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
uint records, i, bitmap_size;
bool error_reported= FALSE;
uchar *record, *bitmaps;
- Field **field_ptr, **vfield_ptr;
+ Field **field_ptr, **vfield_ptr, **dfield_ptr;
uint8 save_context_analysis_only= thd->lex->context_analysis_only;
DBUG_ENTER("open_table_from_share");
DBUG_PRINT("enter",("name: '%s.%s' form: 0x%lx", share->db.str,
@@ -2419,9 +2422,6 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
if (share->found_next_number_field)
outparam->found_next_number_field=
outparam->field[(uint) (share->found_next_number_field - share->field)];
- if (share->timestamp_field)
- outparam->timestamp_field= (Field_timestamp*) outparam->field[share->timestamp_field_offset];
-
/* Fix key->name and key_part->field */
if (share->key_parts)
@@ -2472,11 +2472,9 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
}
/*
- Process virtual columns, if any.
+ Process virtual and default columns, if any.
*/
- if (!share->vfields)
- outparam->vfield= NULL;
- else
+ if (share->vfields)
{
if (!(vfield_ptr = (Field **) alloc_root(&outparam->mem_root,
(uint) ((share->vfields+1)*
@@ -2484,10 +2482,24 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
goto err;
outparam->vfield= vfield_ptr;
+ }
+
+ if (share->default_fields)
+ {
+ if (!(dfield_ptr = (Field **) alloc_root(&outparam->mem_root,
+ (uint) ((share->default_fields+1)*
+ sizeof(Field*)))))
+ goto err;
+ outparam->default_field= dfield_ptr;
+ }
+
+ if (share->vfields || share->default_fields)
+ {
+ /* Reuse the same loop both for virtual and default fields. */
for (field_ptr= outparam->field; *field_ptr; field_ptr++)
{
- if ((*field_ptr)->vcol_info)
+ if (share->vfields && (*field_ptr)->vcol_info)
{
if (unpack_vcol_info_from_frm(thd,
outparam,
@@ -2500,8 +2512,15 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
}
*(vfield_ptr++)= *field_ptr;
}
+ if (share->default_fields &&
+ ((*field_ptr)->has_insert_default_function() ||
+ (*field_ptr)->has_update_default_function()))
+ *(dfield_ptr++)= *field_ptr;
}
- *vfield_ptr= 0; // End marker
+ if (share->vfields)
+ *vfield_ptr= 0; // End marker
+ if (share->default_fields)
+ *dfield_ptr= 0; // End marker
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
@@ -3927,9 +3946,6 @@ void TABLE::init(THD *thd, TABLE_LIST *tl)
DBUG_ASSERT(!auto_increment_field_not_null);
auto_increment_field_not_null= FALSE;
- if (timestamp_field)
- timestamp_field_type= timestamp_field->get_auto_set_type();
-
pos_in_table_list= tl;
clear_column_bitmaps();
@@ -5856,6 +5872,51 @@ void TABLE::mark_virtual_columns_for_write(bool insert_fl)
/**
+ Check if a table has a default function either for INSERT or UPDATE-like
+ operation
+ @retval true there is a default function
+ @retval false there is no default function
+*/
+
+bool TABLE::has_default_function(bool is_update)
+{
+ Field **dfield_ptr, *dfield;
+ bool res= false;
+ for (dfield_ptr= default_field; *dfield_ptr; dfield_ptr++)
+ {
+ dfield= (*dfield_ptr);
+ if (is_update)
+ res= dfield->has_update_default_function();
+ else
+ res= dfield->has_insert_default_function();
+ if (res)
+ return res;
+ }
+ return res;
+}
+
+
+/**
+ Add all fields that have a default function to the table write set.
+*/
+
+void TABLE::mark_default_fields_for_write()
+{
+ Field **dfield_ptr, *dfield;
+ enum_sql_command cmd= in_use->lex->sql_command;
+ for (dfield_ptr= default_field; *dfield_ptr; dfield_ptr++)
+ {
+ dfield= (*dfield_ptr);
+ if (((sql_command_flags[cmd] & CF_INSERTS_DATA) &&
+ dfield->has_insert_default_function()) ||
+ ((sql_command_flags[cmd] & CF_UPDATES_DATA) &&
+ dfield->has_update_default_function()))
+ bitmap_set_bit(write_set, dfield->field_index);
+ }
+}
+
+
+/**
@brief
Allocate space for keys
@@ -6416,22 +6477,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;
@@ -6444,9 +6508,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);
@@ -6461,6 +6525,56 @@ int update_virtual_fields(THD *thd, TABLE *table, bool for_write)
DBUG_RETURN(0);
}
+
+/**
+ Update all DEFAULT and/or ON INSERT fields.
+
+ @details
+ Compute and set the default value of all fields with a default function.
+ There are two kinds of default functions - one is used for INSERT-like
+ operations, the other for UPDATE-like operations. Depending on the field
+ definition and the current operation one or the other kind of update
+ function is evaluated.
+
+ @retval
+ 0 Success
+ @retval
+ >0 Error occurred when storing a virtual field value
+*/
+
+int TABLE::update_default_fields()
+{
+ DBUG_ENTER("update_default_fields");
+ Field **dfield_ptr, *dfield;
+ int res= 0;
+ enum_sql_command cmd= in_use->lex->sql_command;
+
+ DBUG_ASSERT(default_field);
+
+ /* Iterate over virtual fields in the table */
+ for (dfield_ptr= default_field; *dfield_ptr; dfield_ptr++)
+ {
+ dfield= (*dfield_ptr);
+ /*
+ If an explicit default value for a filed overrides the default,
+ do not update the field with its automatic default value.
+ */
+ if (!(dfield->flags & HAS_EXPLICIT_VALUE))
+ {
+ if (sql_command_flags[cmd] & CF_INSERTS_DATA)
+ res= dfield->evaluate_insert_default_function();
+ if (sql_command_flags[cmd] & CF_UPDATES_DATA)
+ res= dfield->evaluate_update_default_function();
+ if (res)
+ DBUG_RETURN(res);
+ }
+ /* Unset the explicit default flag for the next record. */
+ dfield->flags&= ~HAS_EXPLICIT_VALUE;
+ }
+ DBUG_RETURN(res);
+}
+
+
/*
@brief Reset const_table flag
@@ -6767,12 +6881,3 @@ uint TABLE_SHARE::actual_n_key_parts(THD *thd)
ext_key_parts : key_parts;
}
-
-/*****************************************************************************
-** Instansiate templates
-*****************************************************************************/
-
-#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-template class List<String>;
-template class List_iterator<String>;
-#endif
diff --git a/sql/table.h b/sql/table.h
index 1f546693fb3..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
{
@@ -350,25 +356,6 @@ public:
};
-/*
- Values in this enum are used to indicate how a tables TIMESTAMP field
- should be treated. It can be set to the current timestamp on insert or
- update or both.
- WARNING: The values are used for bit operations. If you change the
- enum, you must keep the bitwise relation of the values. For example:
- (int) TIMESTAMP_AUTO_SET_ON_BOTH must be equal to
- (int) TIMESTAMP_AUTO_SET_ON_INSERT | (int) TIMESTAMP_AUTO_SET_ON_UPDATE.
- We use an enum here so that the debugger can display the value names.
-*/
-enum timestamp_auto_set_type
-{
- TIMESTAMP_NO_AUTO_SET= 0, TIMESTAMP_AUTO_SET_ON_INSERT= 1,
- TIMESTAMP_AUTO_SET_ON_UPDATE= 2, TIMESTAMP_AUTO_SET_ON_BOTH= 3
-};
-#define clear_timestamp_auto_bits(_target_, _bits_) \
- (_target_)= (enum timestamp_auto_set_type)((int)(_target_) & ~(int)(_bits_))
-
-class Field_timestamp;
class Field_blob;
class Table_triggers_list;
@@ -608,7 +595,6 @@ struct TABLE_SHARE
/* The following is copied to each TABLE on OPEN */
Field **field;
Field **found_next_number_field;
- Field *timestamp_field; /* Used only during open */
KEY *key_info; /* data of keys in database */
uint *blob_field; /* Index to blobs in Field arrray*/
@@ -680,7 +666,6 @@ struct TABLE_SHARE
uint uniques; /* Number of UNIQUE index */
uint null_fields; /* number of null fields */
uint blob_fields; /* number of blob fields */
- uint timestamp_field_offset; /* Field number for timestamp field */
uint varchar_fields; /* number of varchar fields */
uint db_create_options; /* Create options from database */
uint db_options_in_use; /* Options in use */
@@ -695,6 +680,7 @@ struct TABLE_SHARE
uint column_bitmap_size;
uchar frm_version;
uint vfields; /* Number of computed (virtual) fields */
+ uint default_fields; /* Number of default fields */
bool use_ext_keys; /* Extended keys can be used */
bool null_field_first;
bool system; /* Set if system table (one record) */
@@ -1007,8 +993,9 @@ public:
Field *next_number_field; /* Set if next_number is activated */
Field *found_next_number_field; /* Set on open */
- Field_timestamp *timestamp_field;
Field **vfield; /* Pointer to virtual fields*/
+ /* Fields that are updated automatically on INSERT or UPDATE. */
+ Field **default_field;
/* Table's triggers, 0 if there are no of them */
Table_triggers_list *triggers;
@@ -1064,19 +1051,6 @@ public:
*/
ha_rows quick_condition_rows;
- /*
- If this table has TIMESTAMP field with auto-set property (pointed by
- timestamp_field member) then this variable indicates during which
- operations (insert only/on update/in both cases) we should set this
- field to current timestamp. If there are no such field in this table
- or we should not automatically set its value during execution of current
- statement then the variable contains TIMESTAMP_NO_AUTO_SET (i.e. 0).
-
- Value of this variable is set for each statement in open_table() and
- if needed cleared later in statement processing code (see mysql_update()
- as example).
- */
- timestamp_auto_set_type timestamp_field_type;
table_map map; /* ID bit of table (1,2,4,8,16...) */
uint lock_position; /* Position in MYSQL_LOCK.table */
@@ -1212,6 +1186,8 @@ public:
void mark_columns_needed_for_insert(void);
bool mark_virtual_col(Field *field);
void mark_virtual_columns_for_write(bool insert_fl);
+ void mark_default_fields_for_write();
+ bool has_default_function(bool is_update);
inline void column_bitmaps_set(MY_BITMAP *read_set_arg,
MY_BITMAP *write_set_arg)
{
@@ -1298,6 +1274,7 @@ public:
bool update_const_key_parts(COND *conds);
uint actual_n_key_parts(KEY *keyinfo);
ulong actual_key_flags(KEY *keyinfo);
+ int update_default_fields();
};
diff --git a/storage/archive/ha_archive.h b/storage/archive/ha_archive.h
index 165c7443070..d1c4bfbc7fb 100644
--- a/storage/archive/ha_archive.h
+++ b/storage/archive/ha_archive.h
@@ -82,7 +82,6 @@ public:
~ha_archive()
{
}
- const char *table_type() const { return "ARCHIVE"; }
const char *index_type(uint inx) { return "NONE"; }
const char **bas_ext() const;
ulonglong table_flags() const
diff --git a/storage/blackhole/ha_blackhole.h b/storage/blackhole/ha_blackhole.h
index a7efd261ddb..51857f3bb2a 100644
--- a/storage/blackhole/ha_blackhole.h
+++ b/storage/blackhole/ha_blackhole.h
@@ -46,8 +46,6 @@ public:
~ha_blackhole()
{
}
- /* The name that will be used for display purposes */
- const char *table_type() const { return "BLACKHOLE"; }
/*
The name of the index type that will be used for display
don't implement this method unless you really have indexes
diff --git a/storage/csv/ha_tina.h b/storage/csv/ha_tina.h
index 88af2c9652c..26404b3a9e7 100644
--- a/storage/csv/ha_tina.h
+++ b/storage/csv/ha_tina.h
@@ -102,7 +102,6 @@ public:
delete file_buff;
free_root(&blobroot, MYF(0));
}
- const char *table_type() const { return "CSV"; }
const char *index_type(uint inx) { return "NONE"; }
const char **bas_ext() const;
ulonglong table_flags() const
diff --git a/storage/example/ha_example.h b/storage/example/ha_example.h
index ca8ca5ff293..9be370edfe3 100644
--- a/storage/example/ha_example.h
+++ b/storage/example/ha_example.h
@@ -67,11 +67,6 @@ public:
}
/** @brief
- The name that will be used for display purposes.
- */
- const char *table_type() const { return "EXAMPLE"; }
-
- /** @brief
The name of the index type that will be used for display.
Don't implement this method unless you really have indexes.
*/
diff --git a/storage/federated/ha_federated.h b/storage/federated/ha_federated.h
index 98b0efdbe2b..6583d438c4d 100644
--- a/storage/federated/ha_federated.h
+++ b/storage/federated/ha_federated.h
@@ -124,8 +124,6 @@ private:
public:
ha_federated(handlerton *hton, TABLE_SHARE *table_arg);
~ha_federated() {}
- /* The name that will be used for display purposes */
- const char *table_type() const { return "FEDERATED"; }
/*
Next pointer used in transaction
*/
diff --git a/storage/federatedx/ha_federatedx.h b/storage/federatedx/ha_federatedx.h
index dc7733806ad..3af05387cb2 100644
--- a/storage/federatedx/ha_federatedx.h
+++ b/storage/federatedx/ha_federatedx.h
@@ -311,8 +311,6 @@ private:
public:
ha_federatedx(handlerton *hton, TABLE_SHARE *table_arg);
~ha_federatedx() {}
- /* The name that will be used for display purposes */
- const char *table_type() const { return "FEDERATED"; }
/*
The name of the index type that will be used for display
don't implement this method unless you really have indexes
diff --git a/storage/heap/ha_heap.h b/storage/heap/ha_heap.h
index c5b8a09b216..30ad06e2c06 100644
--- a/storage/heap/ha_heap.h
+++ b/storage/heap/ha_heap.h
@@ -38,11 +38,6 @@ public:
ha_heap(handlerton *hton, TABLE_SHARE *table);
~ha_heap() {}
handler *clone(const char *name, MEM_ROOT *mem_root);
- const char *table_type() const
- {
- return (table->in_use->variables.sql_mode & MODE_MYSQL323) ?
- "HEAP" : "MEMORY";
- }
const char *index_type(uint inx)
{
return ((table_share->key_info[inx].algorithm == HA_KEY_ALG_BTREE) ?
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/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 5b3aa15a9a2..b1215e6bdef 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -98,6 +98,7 @@ static ulong commit_threads = 0;
static mysql_mutex_t commit_threads_m;
static mysql_cond_t commit_cond;
static mysql_mutex_t commit_cond_m;
+static mysql_mutex_t pending_checkpoint_mutex;
static bool innodb_inited = 0;
#define INSIDE_HA_INNOBASE_CC
@@ -256,11 +257,13 @@ static mysql_pfs_key_t innobase_share_mutex_key;
static mysql_pfs_key_t commit_threads_m_key;
static mysql_pfs_key_t commit_cond_mutex_key;
static mysql_pfs_key_t commit_cond_key;
+static mysql_pfs_key_t pending_checkpoint_mutex_key;
static PSI_mutex_info all_pthread_mutexes[] = {
{&commit_threads_m_key, "commit_threads_m", 0},
{&commit_cond_mutex_key, "commit_cond_mutex", 0},
- {&innobase_share_mutex_key, "innobase_share_mutex", 0}
+ {&innobase_share_mutex_key, "innobase_share_mutex", 0},
+ {&pending_checkpoint_mutex_key, "pending_checkpoint_mutex", 0}
};
static PSI_cond_info all_innodb_conds[] = {
@@ -3066,6 +3069,9 @@ innobase_change_buffering_inited_ok:
mysql_mutex_init(commit_cond_mutex_key,
&commit_cond_m, MY_MUTEX_INIT_FAST);
mysql_cond_init(commit_cond_key, &commit_cond, NULL);
+ mysql_mutex_init(pending_checkpoint_mutex_key,
+ &pending_checkpoint_mutex,
+ MY_MUTEX_INIT_FAST);
innodb_inited= 1;
#ifdef MYSQL_DYNAMIC_PLUGIN
if (innobase_hton != p) {
@@ -3130,6 +3136,7 @@ innobase_end(
mysql_mutex_destroy(&commit_threads_m);
mysql_mutex_destroy(&commit_cond_m);
mysql_cond_destroy(&commit_cond);
+ mysql_mutex_destroy(&pending_checkpoint_mutex);
}
DBUG_RETURN(err);
@@ -3513,17 +3520,144 @@ innobase_rollback_trx(
DBUG_RETURN(convert_error_code_to_mysql(error, 0, NULL));
}
+
+struct pending_checkpoint {
+ struct pending_checkpoint *next;
+ handlerton *hton;
+ void *cookie;
+ ib_uint64_t lsn;
+};
+static struct pending_checkpoint *pending_checkpoint_list;
+static struct pending_checkpoint *pending_checkpoint_list_end;
+
/*****************************************************************//**
Handle a commit checkpoint request from server layer.
-We simply flush the redo log immediately and do the notify call.*/
+We put the request in a queue, so that we can notify upper layer about
+checkpoint complete when we have flushed the redo log.
+If we have already flushed all relevant redo log, we notify immediately.*/
static
void
innobase_checkpoint_request(
handlerton *hton,
void *cookie)
{
- log_buffer_flush_to_disk();
- commit_checkpoint_notify_ha(hton, cookie);
+ ib_uint64_t lsn;
+ ib_uint64_t flush_lsn;
+ struct pending_checkpoint * entry;
+
+ /* Do the allocation outside of lock to reduce contention. The normal
+ case is that not everything is flushed, so we will need to enqueue. */
+ entry = static_cast<struct pending_checkpoint *>
+ (my_malloc(sizeof(*entry), MYF(MY_WME)));
+ if (!entry) {
+ sql_print_error("Failed to allocate %u bytes."
+ " Commit checkpoint will be skipped.",
+ static_cast<unsigned>(sizeof(*entry)));
+ return;
+ }
+
+ entry->next = NULL;
+ entry->hton = hton;
+ entry->cookie = cookie;
+
+ mysql_mutex_lock(&pending_checkpoint_mutex);
+ lsn = log_get_lsn();
+ flush_lsn = log_get_flush_lsn();
+ if (lsn > flush_lsn) {
+ /* Put the request in queue.
+ When the log gets flushed past the lsn, we will remove the
+ entry from the queue and notify the upper layer. */
+ entry->lsn = lsn;
+ if (pending_checkpoint_list_end) {
+ pending_checkpoint_list_end->next = entry;
+ /* There is no need to order the entries in the list
+ by lsn. The upper layer can accept notifications in
+ any order, and short delays in notifications do not
+ significantly impact performance. */
+ } else {
+ pending_checkpoint_list = entry;
+ }
+ pending_checkpoint_list_end = entry;
+ entry = NULL;
+ }
+ mysql_mutex_unlock(&pending_checkpoint_mutex);
+
+ if (entry) {
+ /* We are already flushed. Notify the checkpoint immediately. */
+ commit_checkpoint_notify_ha(entry->hton, entry->cookie);
+ my_free(entry);
+ }
+}
+
+/*****************************************************************//**
+Log code calls this whenever log has been written and/or flushed up
+to a new position. We use this to notify upper layer of a new commit
+checkpoint when necessary.*/
+void
+innobase_mysql_log_notify(
+/*===============*/
+ ib_uint64_t write_lsn, /*!< in: LSN written to log file */
+ ib_uint64_t flush_lsn) /*!< in: LSN flushed to disk */
+{
+ struct pending_checkpoint * pending;
+ struct pending_checkpoint * entry;
+ struct pending_checkpoint * last_ready;
+
+ /* It is safe to do a quick check for NULL first without lock.
+ Even if we should race, we will at most skip one checkpoint and
+ take the next one, which is harmless. */
+ if (!pending_checkpoint_list)
+ return;
+
+ mysql_mutex_lock(&pending_checkpoint_mutex);
+ pending = pending_checkpoint_list;
+ if (!pending)
+ {
+ mysql_mutex_unlock(&pending_checkpoint_mutex);
+ return;
+ }
+
+ last_ready = NULL;
+ for (entry = pending; entry != NULL; entry = entry -> next)
+ {
+ /* Notify checkpoints up until the first entry that has not
+ been fully flushed to the redo log. Since we do not maintain
+ the list ordered, in principle there could be more entries
+ later than were also flushed. But there is no harm in
+ delaying notifications for those a bit. And in practise, the
+ list is unlikely to have more than one element anyway, as we
+ flush the redo log at least once every second. */
+ if (entry->lsn > flush_lsn)
+ break;
+ last_ready = entry;
+ }
+
+ if (last_ready)
+ {
+ /* We found some pending checkpoints that are now flushed to
+ disk. So remove them from the list. */
+ pending_checkpoint_list = entry;
+ if (!entry)
+ pending_checkpoint_list_end = NULL;
+ }
+
+ mysql_mutex_unlock(&pending_checkpoint_mutex);
+
+ if (!last_ready)
+ return;
+
+ /* Now that we have released the lock, notify upper layer about all
+ commit checkpoints that have now completed. */
+ for (;;) {
+ entry = pending;
+ pending = pending->next;
+
+ commit_checkpoint_notify_ha(entry->hton, entry->cookie);
+
+ my_free(entry);
+ if (entry == last_ready)
+ break;
+ }
}
/*****************************************************************//**
diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h
index f2317054c7f..5512bf7c62f 100644
--- a/storage/innobase/include/ha_prototypes.h
+++ b/storage/innobase/include/ha_prototypes.h
@@ -145,6 +145,17 @@ innobase_mysql_print_thd(
uint max_query_len); /*!< in: max query length to print, or 0 to
use the default max length */
+/*****************************************************************//**
+Log code calls this whenever log has been written and/or flushed up
+to a new position. We use this to notify upper layer of a new commit
+checkpoint when necessary.*/
+UNIV_INTERN
+void
+innobase_mysql_log_notify(
+/*===============*/
+ ib_uint64_t write_lsn, /*!< in: LSN written to log file */
+ ib_uint64_t flush_lsn); /*!< in: LSN flushed to disk */
+
/*************************************************************//**
InnoDB uses this function to compare two data fields for which the data type
is such that we must use MySQL code to compare them.
diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h
index 6d27d9d4f10..5d72c7a96da 100644
--- a/storage/innobase/include/log0log.h
+++ b/storage/innobase/include/log0log.h
@@ -146,6 +146,13 @@ UNIV_INLINE
lsn_t
log_get_lsn(void);
/*=============*/
+/************************************************************//**
+Gets the last lsn that is fully flushed to disk.
+@return last flushed lsn */
+UNIV_INLINE
+ib_uint64_t
+log_get_flush_lsn(void);
+/*=============*/
/****************************************************************
Gets the log group capacity. It is OK to read the value without
holding log_sys->mutex because it is constant.
diff --git a/storage/innobase/include/log0log.ic b/storage/innobase/include/log0log.ic
index 5ecd7b85a26..ad7b7e790a2 100644
--- a/storage/innobase/include/log0log.ic
+++ b/storage/innobase/include/log0log.ic
@@ -415,6 +415,25 @@ log_get_lsn(void)
return(lsn);
}
+/************************************************************//**
+Gets the last lsn that is fully flushed to disk.
+@return last flushed lsn */
+UNIV_INLINE
+ib_uint64_t
+log_get_flush_lsn(void)
+/*=============*/
+{
+ ib_uint64_t lsn;
+
+ mutex_enter(&(log_sys->mutex));
+
+ lsn = log_sys->flushed_to_disk_lsn;
+
+ mutex_exit(&(log_sys->mutex));
+
+ return(lsn);
+}
+
/****************************************************************
Gets the log group capacity. It is OK to read the value without
holding log_sys->mutex because it is constant.
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index ecbc6c59da1..74f6566d588 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -1341,6 +1341,8 @@ log_write_up_to(
ulint loop_count = 0;
#endif /* UNIV_DEBUG */
ulint unlock;
+ ib_uint64_t write_lsn;
+ ib_uint64_t flush_lsn;
if (recv_no_ibuf_operations) {
/* Recovery is running and no operations on the log files are
@@ -1520,8 +1522,13 @@ loop:
log_flush_do_unlocks(unlock);
+ write_lsn = log_sys->write_lsn;
+ flush_lsn = log_sys->flushed_to_disk_lsn;
+
mutex_exit(&(log_sys->mutex));
+ innobase_mysql_log_notify(write_lsn, flush_lsn);
+
return;
do_waits:
diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc
index f6124fdd9ff..f4706363cd6 100644
--- a/storage/maria/ha_maria.cc
+++ b/storage/maria/ha_maria.cc
@@ -2482,9 +2482,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/ha_maria.h b/storage/maria/ha_maria.h
index 2cba48c04aa..3ca3a592963 100644
--- a/storage/maria/ha_maria.h
+++ b/storage/maria/ha_maria.h
@@ -59,8 +59,6 @@ public:
ha_maria(handlerton *hton, TABLE_SHARE * table_arg);
~ha_maria() {}
handler *clone(const char *name, MEM_ROOT *mem_root);
- const char *table_type() const
- { return "Aria"; }
const char *index_type(uint key_number);
const char **bas_ext() const;
ulonglong table_flags() const
diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c
index 8e0407c9d7a..71faa11fd2b 100644
--- a/storage/maria/ma_blockrec.c
+++ b/storage/maria/ma_blockrec.c
@@ -4669,7 +4669,7 @@ int _ma_read_block_record2(MARIA_HA *info, uchar *record,
uchar *data, uchar *end_of_data)
{
MARIA_SHARE *share= info->s;
- uchar *UNINIT_VAR(field_length_data), *blob_buffer, *start_of_data;
+ uchar *UNINIT_VAR(field_length_data), *UNINIT_VAR(blob_buffer), *start_of_data;
uint flag, null_bytes, cur_null_bytes, row_extents, field_lengths;
my_bool found_blob= 0;
MARIA_EXTENT_CURSOR extent;
@@ -4677,8 +4677,6 @@ int _ma_read_block_record2(MARIA_HA *info, uchar *record,
MARIA_ROW *cur_row= &info->cur_row;
DBUG_ENTER("_ma_read_block_record2");
- LINT_INIT(blob_buffer);
-
start_of_data= data;
flag= (uint) (uchar) data[0];
cur_null_bytes= share->base.original_null_bytes;
@@ -5106,6 +5104,7 @@ int _ma_read_block_record(MARIA_HA *info, uchar *record,
uchar *data, *end_of_data, *buff;
uint offset;
uint block_size= share->block_size;
+ int ret;
DBUG_ENTER("_ma_read_block_record");
DBUG_PRINT("enter", ("rowid: %lu page: %lu rownr: %u",
(ulong) record_pos,
@@ -5127,7 +5126,8 @@ int _ma_read_block_record(MARIA_HA *info, uchar *record,
my_errno= HA_ERR_RECORD_DELETED; /* File crashed */
DBUG_RETURN(HA_ERR_RECORD_DELETED);
}
- DBUG_RETURN(_ma_read_block_record2(info, record, data, end_of_data));
+ ret= _ma_read_block_record2(info, record, data, end_of_data);
+ DBUG_RETURN(ret);
}
diff --git a/storage/maria/ma_rrnd.c b/storage/maria/ma_rrnd.c
index 24c4bfdd467..8c35c71c95e 100644
--- a/storage/maria/ma_rrnd.c
+++ b/storage/maria/ma_rrnd.c
@@ -30,6 +30,7 @@
int maria_rrnd(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS filepos)
{
+ int ret;
DBUG_ENTER("maria_rrnd");
DBUG_ASSERT(filepos != HA_OFFSET_ERROR);
@@ -40,5 +41,6 @@ int maria_rrnd(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS filepos)
DBUG_RETURN(my_errno);
info->cur_row.lastpos= filepos; /* Remember for update */
- DBUG_RETURN((*info->s->read_record)(info, buf, filepos));
+ ret= (*info->s->read_record)(info, buf, filepos);
+ DBUG_RETURN(ret);
}
diff --git a/storage/maria/ma_test2.c b/storage/maria/ma_test2.c
index 5d0882f3fcb..ea1978b4ee5 100644
--- a/storage/maria/ma_test2.c
+++ b/storage/maria/ma_test2.c
@@ -50,7 +50,7 @@ static ulong pagecache_size=8192*32;
static enum data_file_type record_type= DYNAMIC_RECORD;
static uint keys=MARIA_KEYS,recant=1000;
-static uint16 key1[1001],key3[5000];
+static uint16 key1[1001],key3[5001];
static uchar record[300],record2[300],key[100],key2[100];
static uchar read_record[300],read_record2[300],read_record3[300];
static HA_KEYSEG glob_keyseg[MARIA_KEYS][MAX_PARTS];
@@ -222,7 +222,7 @@ int main(int argc, char *argv[])
blob_buffer=0;
for (i=1000 ; i>0 ; i--) key1[i]=0;
- for (i=4999 ; i>0 ; i--) key3[i]=0;
+ for (i=5000 ; i>0 ; i--) key3[i]=0;
if (!silent)
printf("- Creating maria-file\n");
@@ -280,7 +280,7 @@ int main(int argc, char *argv[])
if (key3[n3] == 1 && first_key <3 && first_key+keys >= 3)
{
printf("Error: Didn't get error when writing second key: '%8d'\n",n3);
- goto err;
+ goto err2;
}
write_count++; key1[n1]++; key3[n3]=1;
}
@@ -341,7 +341,7 @@ int main(int argc, char *argv[])
key, keyinfo[0].seg[0].length))
{
printf("Found wrong record when searching for key: \"%s\"\n",key);
- goto err;
+ goto err2;
}
if (opt_delete == (uint) remove_count) /* While testing */
goto end;
@@ -394,7 +394,7 @@ int main(int argc, char *argv[])
printf("Found wrong record when searching for key: \"%s\"; Found \"%.*s\"\n",
key, keyinfo[0].seg[0].length,
read_record+keyinfo[0].seg[0].start);
- goto err;
+ goto err2;
}
if (use_blob)
{
@@ -455,7 +455,7 @@ int main(int argc, char *argv[])
if (memcmp(read_record,read_record2,reclength) != 0)
{
printf("maria_rsame didn't find same record\n");
- goto err;
+ goto err2;
}
info.recpos=maria_position(file);
if (maria_rfirst(file,read_record2,0) ||
@@ -463,7 +463,7 @@ int main(int argc, char *argv[])
memcmp(read_record,read_record2,reclength) != 0)
{
printf("maria_rsame_with_pos didn't find same record\n");
- goto err;
+ goto err2;
}
{
int skr;
@@ -484,7 +484,7 @@ int main(int argc, char *argv[])
if (ant != dupp_keys)
{
printf("next: Found: %d keys of %d\n",ant,dupp_keys);
- goto err;
+ goto err2;
}
ant=0;
while (maria_rprev(file,read_record3,0) == 0 &&
@@ -492,7 +492,7 @@ int main(int argc, char *argv[])
if (ant != dupp_keys)
{
printf("prev: Found: %d records of %d\n",ant,dupp_keys);
- goto err;
+ goto err2;
}
/* Check of maria_rnext_same */
@@ -504,7 +504,7 @@ int main(int argc, char *argv[])
if (ant != dupp_keys || my_errno != HA_ERR_END_OF_FILE)
{
printf("maria_rnext_same: Found: %d records of %d\n",ant,dupp_keys);
- goto err;
+ goto err2;
}
}
@@ -531,7 +531,7 @@ int main(int argc, char *argv[])
printf("Can't find last record\n");
DBUG_DUMP("record2", read_record2, reclength);
DBUG_DUMP("record3", read_record3, reclength);
- goto err;
+ goto err2;
}
ant=1;
while (maria_rprev(file,read_record3,0) == 0 && ant < write_count+10)
@@ -539,12 +539,12 @@ int main(int argc, char *argv[])
if (ant != write_count - opt_delete)
{
printf("prev: I found: %d records of %d\n",ant,write_count);
- goto err;
+ goto err2;
}
if (bcmp(read_record,read_record3,reclength))
{
printf("Can't find first record\n");
- goto err;
+ goto err2;
}
if (!silent)
@@ -585,7 +585,7 @@ int main(int argc, char *argv[])
if (bcmp(read_record+start,key,(uint) i))
{
puts("Didn't find right record");
- goto err;
+ goto err2;
}
}
#endif
@@ -605,7 +605,7 @@ int main(int argc, char *argv[])
if (ant != dupp_keys-1)
{
printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-1);
- goto err;
+ goto err2;
}
}
if (dupp_keys>4)
@@ -623,7 +623,7 @@ int main(int argc, char *argv[])
if (ant != dupp_keys-2)
{
printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-2);
- goto err;
+ goto err2;
}
}
if (dupp_keys > 6)
@@ -643,7 +643,7 @@ int main(int argc, char *argv[])
if (ant != dupp_keys-3)
{
printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-3);
- goto err;
+ goto err2;
}
if (!silent)
@@ -658,7 +658,7 @@ int main(int argc, char *argv[])
if (ant != dupp_keys-4)
{
printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-4);
- goto err;
+ goto err2;
}
}
@@ -687,7 +687,7 @@ int main(int argc, char *argv[])
if (i != write_count && i != write_count - opt_delete)
{
printf("Found wrong number of rows while scanning table\n");
- goto err;
+ goto err2;
}
if (maria_rsame_with_pos(file,read_record,0,info.recpos))
@@ -695,7 +695,7 @@ int main(int argc, char *argv[])
if (bcmp(read_record,read_record2,reclength) != 0)
{
printf("maria_rsame_with_pos didn't find same record\n");
- goto err;
+ goto err2;
}
for (i=min(2,keys) ; i-- > 0 ;)
@@ -704,7 +704,7 @@ int main(int argc, char *argv[])
if (bcmp(read_record,read_record2,reclength) != 0)
{
printf("maria_rsame didn't find same record\n");
- goto err;
+ goto err2;
}
}
if (!silent)
@@ -731,7 +731,7 @@ int main(int argc, char *argv[])
{
printf("maria_records_range returned %ld; Should be about %ld\n",
(long) range_records,(long) info.records);
- goto err;
+ goto err2;
}
if (verbose)
{
@@ -768,7 +768,7 @@ int main(int argc, char *argv[])
{
printf("maria_records_range for key: %d returned %lu; Should be about %lu\n",
i, (ulong) range_records, (ulong) records);
- goto err;
+ goto err2;
}
if (verbose && records)
{
@@ -783,13 +783,13 @@ int main(int argc, char *argv[])
if (!silent)
printf("- maria_info\n");
maria_status(file,&info,HA_STATUS_VARIABLE | HA_STATUS_CONST);
- if (info.records != write_count-opt_delete || info.deleted > opt_delete + update
- || info.keys != keys)
+ if (info.records != write_count-opt_delete ||
+ info.deleted > opt_delete + update || info.keys != keys)
{
puts("Wrong info from maria_info");
printf("Got: records: %lu delete: %lu i_keys: %d\n",
(ulong) info.records, (ulong) info.deleted, info.keys);
- goto err;
+ goto err2;
}
if (verbose)
{
@@ -828,7 +828,7 @@ int main(int argc, char *argv[])
printf("scan with cache: I can only find: %d records of %d\n",
ant,write_count-opt_delete);
maria_scan_end(file);
- goto err;
+ goto err2;
}
if (maria_extra(file,HA_EXTRA_NO_CACHE,0))
{
@@ -848,7 +848,7 @@ int main(int argc, char *argv[])
printf("scan with cache: I can only find: %d records of %d\n",
ant,write_count-opt_delete);
maria_scan_end(file);
- goto err;
+ goto err2;
}
maria_scan_end(file);
@@ -872,7 +872,7 @@ int main(int argc, char *argv[])
{
printf("maria_rrnd didn't advance filepointer; old: %ld, new: %ld\n",
(long) lastpos, (long) info.recpos);
- goto err;
+ goto err2;
}
lastpos=info.recpos;
if (error == 0)
@@ -897,7 +897,7 @@ int main(int argc, char *argv[])
printf("Found blob with wrong info at %ld\n",(long) lastpos);
maria_scan_end(file);
my_errno= 0;
- goto err;
+ goto err2;
}
}
}
@@ -920,7 +920,7 @@ int main(int argc, char *argv[])
printf("Deleted only %d of %d records (%d parts)\n",opt_delete,write_count,
found_parts);
maria_scan_end(file);
- goto err;
+ goto err2;
}
if (testflag == 6)
goto end;
@@ -1021,10 +1021,11 @@ reads: %10lu\n",
return(0);
err:
printf("got error: %d when using MARIA-database\n",my_errno);
+err2:
if (file)
{
if (maria_commit(file))
- goto err;
+ printf("got error: %d when using MARIA-database\n",my_errno);
maria_close(file);
}
maria_end();
diff --git a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h
index 42b4f7f1653..fbb0bc6156e 100644
--- a/storage/myisam/ha_myisam.h
+++ b/storage/myisam/ha_myisam.h
@@ -56,7 +56,6 @@ class ha_myisam: public handler
ha_myisam(handlerton *hton, TABLE_SHARE *table_arg);
~ha_myisam() {}
handler *clone(const char *name, MEM_ROOT *mem_root);
- const char *table_type() const { return "MyISAM"; }
const char *index_type(uint key_number);
const char **bas_ext() const;
ulonglong table_flags() const { return int_table_flags; }
diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc
index 093a2a6dcef..1b0eea13418 100644
--- a/storage/myisammrg/ha_myisammrg.cc
+++ b/storage/myisammrg/ha_myisammrg.cc
@@ -1704,28 +1704,11 @@ static int myisammrg_init(void *p)
struct st_mysql_storage_engine myisammrg_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
-mysql_declare_plugin(myisammrg)
-{
- MYSQL_STORAGE_ENGINE_PLUGIN,
- &myisammrg_storage_engine,
- "MRG_MYISAM",
- "MySQL AB",
- "Collection of identical MyISAM tables",
- PLUGIN_LICENSE_GPL,
- myisammrg_init, /* 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(myisammrg)
{
MYSQL_STORAGE_ENGINE_PLUGIN,
&myisammrg_storage_engine,
- "MRG_MYISAM",
+ "MRG_MyISAM",
"MySQL AB",
"Collection of identical MyISAM tables",
PLUGIN_LICENSE_GPL,
diff --git a/storage/myisammrg/ha_myisammrg.h b/storage/myisammrg/ha_myisammrg.h
index f5ba2ffef38..8007e7d04e8 100644
--- a/storage/myisammrg/ha_myisammrg.h
+++ b/storage/myisammrg/ha_myisammrg.h
@@ -82,7 +82,6 @@ public:
ha_myisammrg(handlerton *hton, TABLE_SHARE *table_arg);
~ha_myisammrg();
- const char *table_type() const { return "MRG_MyISAM"; }
const char **bas_ext() const;
const char *index_type(uint key_number);
ulonglong table_flags() const
diff --git a/storage/oqgraph/ha_oqgraph.h b/storage/oqgraph/ha_oqgraph.h
index 97f8cb54081..ee88e38c526 100644
--- a/storage/oqgraph/ha_oqgraph.h
+++ b/storage/oqgraph/ha_oqgraph.h
@@ -62,10 +62,6 @@ public:
Table_flags table_flags() const;
#endif
~ha_oqgraph() {}
- const char *table_type() const
- {
- return "OQGRAPH";
- }
const char *index_type(uint inx)
{
return "HASH";
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/ha_perfschema.h b/storage/perfschema/ha_perfschema.h
index 91ca83c443e..dc465da3758 100644
--- a/storage/perfschema/ha_perfschema.h
+++ b/storage/perfschema/ha_perfschema.h
@@ -44,8 +44,6 @@ public:
~ha_perfschema();
- const char *table_type(void) const { return pfs_engine_name; }
-
const char *index_type(uint) { return ""; }
const char **bas_ext(void) const;
diff --git a/storage/xtradb/btr/btr0btr.c b/storage/xtradb/btr/btr0btr.c
index 3f11684cb34..ed97fc5bd58 100644
--- a/storage/xtradb/btr/btr0btr.c
+++ b/storage/xtradb/btr/btr0btr.c
@@ -1891,6 +1891,7 @@ btr_root_raise_and_insert(
root = btr_cur_get_page(cursor);
root_block = btr_cur_get_block(cursor);
root_page_zip = buf_block_get_page_zip(root_block);
+ ut_ad(page_get_n_recs(root) > 0);
#ifdef UNIV_ZIP_DEBUG
ut_a(!root_page_zip || page_zip_validate(root_page_zip, root));
#endif /* UNIV_ZIP_DEBUG */
@@ -2371,12 +2372,20 @@ btr_insert_on_non_leaf_level_func(
BTR_CONT_MODIFY_TREE,
&cursor, 0, file, line, mtr);
- err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG
- | BTR_KEEP_SYS_FLAG
- | BTR_NO_UNDO_LOG_FLAG,
- &cursor, tuple, &rec,
- &dummy_big_rec, 0, NULL, mtr);
- ut_a(err == DB_SUCCESS);
+ ut_ad(cursor.flag == BTR_CUR_BINARY);
+
+ err = btr_cur_optimistic_insert(
+ BTR_NO_LOCKING_FLAG | BTR_KEEP_SYS_FLAG
+ | BTR_NO_UNDO_LOG_FLAG, &cursor, tuple, &rec,
+ &dummy_big_rec, 0, NULL, mtr);
+
+ if (err == DB_FAIL) {
+ err = btr_cur_pessimistic_insert(
+ BTR_NO_LOCKING_FLAG | BTR_KEEP_SYS_FLAG
+ | BTR_NO_UNDO_LOG_FLAG,
+ &cursor, tuple, &rec, &dummy_big_rec, 0, NULL, mtr);
+ ut_a(err == DB_SUCCESS);
+ }
}
/**************************************************************//**
diff --git a/storage/xtradb/btr/btr0cur.c b/storage/xtradb/btr/btr0cur.c
index 26db7329b7e..61c07ac792e 100644
--- a/storage/xtradb/btr/btr0cur.c
+++ b/storage/xtradb/btr/btr0cur.c
@@ -1412,7 +1412,12 @@ fail_err:
if (UNIV_UNLIKELY(reorg)) {
ut_a(zip_size);
- ut_a(*rec);
+ /* It's possible for rec to be NULL if the
+ page is compressed. This is because a
+ reorganized page may become incompressible. */
+ if (!*rec) {
+ goto fail;
+ }
}
}
@@ -1548,20 +1553,9 @@ btr_cur_pessimistic_insert(
ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, btr_cur_get_block(cursor),
MTR_MEMO_PAGE_X_FIX));
- /* Try first an optimistic insert; reset the cursor flag: we do not
- assume anything of how it was positioned */
-
cursor->flag = BTR_CUR_BINARY;
- err = btr_cur_optimistic_insert(flags, cursor, entry, rec,
- big_rec, n_ext, thr, mtr);
- if (err != DB_FAIL) {
-
- return(err);
- }
-
- /* Retry with a pessimistic insert. Check locks and write to undo log,
- if specified */
+ /* Check locks and write to undo log, if specified */
err = btr_cur_ins_lock_and_undo(flags, cursor, entry,
thr, mtr, &dummy_inh);
@@ -2188,8 +2182,12 @@ any_extern:
goto err_exit;
}
- max_size = old_rec_size
- + page_get_max_insert_size_after_reorganize(page, 1);
+ /* We do not attempt to reorganize if the page is compressed.
+ This is because the page may fail to compress after reorganization. */
+ max_size = page_zip
+ ? page_get_max_insert_size(page, 1)
+ : (old_rec_size
+ + page_get_max_insert_size_after_reorganize(page, 1));
if (!(((max_size >= BTR_CUR_PAGE_REORGANIZE_LIMIT)
&& (max_size >= new_rec_size))
@@ -2559,7 +2557,12 @@ make_external:
err = DB_SUCCESS;
goto return_after_reservations;
} else {
- ut_a(optim_err != DB_UNDERFLOW);
+ /* If the page is compressed and it initially
+ compresses very well, and there is a subsequent insert
+ of a badly-compressing record, it is possible for
+ btr_cur_optimistic_update() to return DB_UNDERFLOW and
+ btr_cur_insert_if_possible() to return FALSE. */
+ ut_a(page_zip || optim_err != DB_UNDERFLOW);
/* Out of space: reset the free bits. */
if (!dict_index_is_clust(index)
@@ -2588,7 +2591,9 @@ make_external:
was_first = page_cur_is_before_first(page_cursor);
/* Lock checks and undo logging were already performed by
- btr_cur_upd_lock_and_undo(). */
+ btr_cur_upd_lock_and_undo(). We do not try
+ btr_cur_optimistic_insert() because
+ btr_cur_insert_if_possible() already failed above. */
err = btr_cur_pessimistic_insert(BTR_NO_UNDO_LOG_FLAG
| BTR_NO_LOCKING_FLAG
diff --git a/storage/xtradb/btr/btr0pcur.c b/storage/xtradb/btr/btr0pcur.c
index 0de7b63f92d..b335e2c8aee 100644
--- a/storage/xtradb/btr/btr0pcur.c
+++ b/storage/xtradb/btr/btr0pcur.c
@@ -354,44 +354,39 @@ btr_pcur_restore_position_func(
/* Restore the old search mode */
cursor->search_mode = old_mode;
- if (btr_pcur_is_on_user_rec(cursor)) {
- switch (cursor->rel_pos) {
- case BTR_PCUR_ON:
- if (!cmp_dtuple_rec(
- tuple, btr_pcur_get_rec(cursor),
- rec_get_offsets(btr_pcur_get_rec(cursor),
- index, NULL,
- ULINT_UNDEFINED, &heap))) {
-
- /* We have to store the NEW value for
- the modify clock, since the cursor can
- now be on a different page! But we can
- retain the value of old_rec */
-
- cursor->block_when_stored =
- btr_pcur_get_block(cursor);
- cursor->modify_clock =
- buf_block_get_modify_clock(
- cursor->block_when_stored);
- cursor->old_stored = BTR_PCUR_OLD_STORED;
-
- mem_heap_free(heap);
-
- return(TRUE);
- }
-
- break;
- case BTR_PCUR_BEFORE:
- page_cur_move_to_next(btr_pcur_get_page_cur(cursor));
- break;
- case BTR_PCUR_AFTER:
- page_cur_move_to_prev(btr_pcur_get_page_cur(cursor));
- break;
+ switch (cursor->rel_pos) {
+ case BTR_PCUR_ON:
+ if (btr_pcur_is_on_user_rec(cursor)
+ && !cmp_dtuple_rec(
+ tuple, btr_pcur_get_rec(cursor),
+ rec_get_offsets(btr_pcur_get_rec(cursor),
+ index, NULL,
+ ULINT_UNDEFINED, &heap))) {
+
+ /* We have to store the NEW value for
+ the modify clock, since the cursor can
+ now be on a different page! But we can
+ retain the value of old_rec */
+
+ cursor->block_when_stored =
+ btr_pcur_get_block(cursor);
+ cursor->modify_clock =
+ buf_block_get_modify_clock(
+ cursor->block_when_stored);
+ cursor->old_stored = BTR_PCUR_OLD_STORED;
+
+ mem_heap_free(heap);
+
+ return(TRUE);
+ }
#ifdef UNIV_DEBUG
- default:
- ut_error;
+ /* fall through */
+ case BTR_PCUR_BEFORE:
+ case BTR_PCUR_AFTER:
+ break;
+ default:
+ ut_error;
#endif /* UNIV_DEBUG */
- }
}
mem_heap_free(heap);
diff --git a/storage/xtradb/buf/buf0buf.c b/storage/xtradb/buf/buf0buf.c
index 6ce77372dac..bbc1042ca78 100644
--- a/storage/xtradb/buf/buf0buf.c
+++ b/storage/xtradb/buf/buf0buf.c
@@ -336,15 +336,6 @@ be effective only if PFS_GROUP_BUFFER_SYNC is defined. */
# endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
#endif /* UNIV_PFS_MUTEX || UNIV_PFS_RWLOCK */
-/** A chunk of buffers. The buffer pool is allocated in chunks. (moved to buf0buf.h)*/
-//struct buf_chunk_struct{
-// ulint mem_size; /*!< allocated size of the chunk */
-// ulint size; /*!< size of frames[] and blocks[] */
-// void* mem; /*!< pointer to the memory area which
-// was allocated for the frames */
-// buf_block_t* blocks; /*!< array of buffer control blocks */
-//};
-
/********************************************************************//**
Gets the smallest oldest_modification lsn for any page in the pool. Returns
zero if all modified pages have been flushed to disk.
@@ -1028,7 +1019,8 @@ buf_chunk_init(
/*===========*/
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
buf_chunk_t* chunk, /*!< out: chunk of buffers */
- ulint mem_size) /*!< in: requested size in bytes */
+ ulint mem_size, /*!< in: requested size in bytes */
+ ibool populate) /*!< in: virtual page preallocation */
{
buf_block_t* block;
byte* frame;
@@ -1044,7 +1036,7 @@ buf_chunk_init(
+ (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
chunk->mem_size = mem_size;
- chunk->mem = os_mem_alloc_large(&chunk->mem_size);
+ chunk->mem = os_mem_alloc_large(&chunk->mem_size, populate);
if (UNIV_UNLIKELY(chunk->mem == NULL)) {
@@ -1254,6 +1246,7 @@ buf_pool_init_instance(
/*===================*/
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
ulint buf_pool_size, /*!< in: size in bytes */
+ ibool populate, /*!< in: virtual page preallocation */
ulint instance_no) /*!< in: id of the instance */
{
ulint i;
@@ -1286,7 +1279,7 @@ buf_pool_init_instance(
UT_LIST_INIT(buf_pool->free);
- if (!buf_chunk_init(buf_pool, chunk, buf_pool_size)) {
+ if (!buf_chunk_init(buf_pool, chunk, buf_pool_size, populate)) {
mem_free(chunk);
mem_free(buf_pool);
@@ -1381,6 +1374,7 @@ ulint
buf_pool_init(
/*==========*/
ulint total_size, /*!< in: size of the total pool in bytes */
+ ibool populate, /*!< in: virtual page preallocation */
ulint n_instances) /*!< in: number of instances */
{
ulint i;
@@ -1398,7 +1392,7 @@ buf_pool_init(
for (i = 0; i < n_instances; i++) {
buf_pool_t* ptr = &buf_pool_ptr[i];
- if (buf_pool_init_instance(ptr, size, i) != DB_SUCCESS) {
+ if (buf_pool_init_instance(ptr, size, populate, i) != DB_SUCCESS) {
/* Free all the instances created so far. */
buf_pool_free(i);
@@ -4973,7 +4967,7 @@ buf_stats_aggregate_pool_info(
Collect buffer pool stats information for a buffer pool. Also
record aggregated stats if there are more than one buffer pool
in the server */
-static
+UNIV_INTERN
void
buf_stats_get_pool_info(
/*====================*/
diff --git a/storage/xtradb/buf/buf0lru.c b/storage/xtradb/buf/buf0lru.c
index e8300107f3d..a6a1f8dcf9c 100644
--- a/storage/xtradb/buf/buf0lru.c
+++ b/storage/xtradb/buf/buf0lru.c
@@ -2384,7 +2384,7 @@ buf_LRU_free_one_page(
#endif
mutex_t* block_mutex = buf_page_get_mutex(bpage);
- ut_ad(buf_pool_mutex_own(buf_pool));
+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
ut_ad(mutex_own(block_mutex));
if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
diff --git a/storage/xtradb/buf/buf0rea.c b/storage/xtradb/buf/buf0rea.c
index c29dcbf0444..67379d614a0 100644
--- a/storage/xtradb/buf/buf0rea.c
+++ b/storage/xtradb/buf/buf0rea.c
@@ -64,7 +64,7 @@ buf_read_page_handle_error(
== BUF_BLOCK_FILE_PAGE);
/* First unfix and release lock on the bpage */
- buf_pool_mutex_enter(buf_pool);
+ mutex_enter(&buf_pool->LRU_list_mutex);
mutex_enter(buf_page_get_mutex(bpage));
ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ);
ut_ad(bpage->buf_fix_count == 0);
@@ -85,7 +85,7 @@ buf_read_page_handle_error(
buf_pool->n_pend_reads--;
mutex_exit(buf_page_get_mutex(bpage));
- buf_pool_mutex_exit(buf_pool);
+ mutex_exit(&buf_pool->LRU_list_mutex);
}
/********************************************************************//**
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index 36b7daaa682..f3a321c58e2 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -121,6 +121,7 @@ static ulong commit_threads = 0;
static mysql_mutex_t commit_threads_m;
static mysql_cond_t commit_cond;
static mysql_mutex_t commit_cond_m;
+static mysql_mutex_t pending_checkpoint_mutex;
static bool innodb_inited = 0;
@@ -254,11 +255,13 @@ static mysql_pfs_key_t innobase_share_mutex_key;
static mysql_pfs_key_t commit_threads_m_key;
static mysql_pfs_key_t commit_cond_mutex_key;
static mysql_pfs_key_t commit_cond_key;
+static mysql_pfs_key_t pending_checkpoint_mutex_key;
static PSI_mutex_info all_pthread_mutexes[] = {
{&commit_threads_m_key, "commit_threads_m", 0},
{&commit_cond_mutex_key, "commit_cond_mutex", 0},
- {&innobase_share_mutex_key, "innobase_share_mutex", 0}
+ {&innobase_share_mutex_key, "innobase_share_mutex", 0},
+ {&pending_checkpoint_mutex_key, "pending_checkpoint_mutex", 0}
};
static PSI_cond_info all_innodb_conds[] = {
@@ -882,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));
}
@@ -2473,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 */
@@ -2607,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) {
@@ -2621,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))) {
@@ -2638,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;
@@ -2656,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;
@@ -2670,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, master_log_fname,
+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+ trx_sys_mysql_master_log_pos = (ib_int64_t) master_log_pos;
- strncpy(trx_sys_mysql_master_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
- trx_sys_mysql_master_log_pos = (ib_int64_t) pos;
+ strncpy(original_master_log_fname, master_log_fname,
+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+ original_master_log_pos = master_log_pos;
end_io_cache(&info_file);
if (info_fd >= 0)
@@ -3008,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);
@@ -3090,6 +3158,9 @@ skip_overwrite:
mysql_mutex_init(commit_cond_mutex_key,
&commit_cond_m, MY_MUTEX_INIT_FAST);
mysql_cond_init(commit_cond_key, &commit_cond, NULL);
+ mysql_mutex_init(pending_checkpoint_mutex_key,
+ &pending_checkpoint_mutex,
+ MY_MUTEX_INIT_FAST);
innodb_inited= 1;
#ifdef MYSQL_DYNAMIC_PLUGIN
if (innobase_hton != p) {
@@ -3137,6 +3208,7 @@ innobase_end(
mysql_mutex_destroy(&commit_threads_m);
mysql_mutex_destroy(&commit_cond_m);
mysql_cond_destroy(&commit_cond);
+ mysql_mutex_destroy(&pending_checkpoint_mutex);
}
DBUG_RETURN(err);
@@ -3179,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
@@ -3212,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);
}
}
@@ -3410,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);
@@ -3532,17 +3639,145 @@ innobase_rollback_trx(
DBUG_RETURN(convert_error_code_to_mysql(error, 0, NULL));
}
+
+struct pending_checkpoint {
+ struct pending_checkpoint *next;
+ handlerton *hton;
+ void *cookie;
+ ib_uint64_t lsn;
+};
+static struct pending_checkpoint *pending_checkpoint_list;
+static struct pending_checkpoint *pending_checkpoint_list_end;
+
/*****************************************************************//**
Handle a commit checkpoint request from server layer.
-We simply flush the redo log immediately and do the notify call.*/
+We put the request in a queue, so that we can notify upper layer about
+checkpoint complete when we have flushed the redo log.
+If we have already flushed all relevant redo log, we notify immediately.*/
static
void
innobase_checkpoint_request(
handlerton *hton,
void *cookie)
{
- log_buffer_flush_to_disk();
- commit_checkpoint_notify_ha(hton, cookie);
+ ib_uint64_t lsn;
+ ib_uint64_t flush_lsn;
+ struct pending_checkpoint * entry;
+
+ /* Do the allocation outside of lock to reduce contention. The normal
+ case is that not everything is flushed, so we will need to enqueue. */
+ entry = static_cast<struct pending_checkpoint *>
+ (my_malloc(sizeof(*entry), MYF(MY_WME)));
+ if (!entry) {
+ sql_print_error("Failed to allocate %u bytes."
+ " Commit checkpoint will be skipped.",
+ static_cast<unsigned>(sizeof(*entry)));
+ return;
+ }
+
+ entry->next = NULL;
+ entry->hton = hton;
+ entry->cookie = cookie;
+
+ mysql_mutex_lock(&pending_checkpoint_mutex);
+ lsn = log_get_lsn();
+ flush_lsn = log_get_flush_lsn();
+ if (lsn > flush_lsn) {
+ /* Put the request in queue.
+ When the log gets flushed past the lsn, we will remove the
+ entry from the queue and notify the upper layer. */
+ entry->lsn = lsn;
+ if (pending_checkpoint_list_end) {
+ pending_checkpoint_list_end->next = entry;
+ /* There is no need to order the entries in the list
+ by lsn. The upper layer can accept notifications in
+ any order, and short delays in notifications do not
+ significantly impact performance. */
+ } else {
+ pending_checkpoint_list = entry;
+ }
+ pending_checkpoint_list_end = entry;
+ entry = NULL;
+ }
+ mysql_mutex_unlock(&pending_checkpoint_mutex);
+
+ if (entry) {
+ /* We are already flushed. Notify the checkpoint immediately. */
+ commit_checkpoint_notify_ha(entry->hton, entry->cookie);
+ my_free(entry);
+ }
+}
+
+/*****************************************************************//**
+Log code calls this whenever log has been written and/or flushed up
+to a new position. We use this to notify upper layer of a new commit
+checkpoint when necessary.*/
+extern "C" UNIV_INTERN
+void
+innobase_mysql_log_notify(
+/*===============*/
+ ib_uint64_t write_lsn, /*!< in: LSN written to log file */
+ ib_uint64_t flush_lsn) /*!< in: LSN flushed to disk */
+{
+ struct pending_checkpoint * pending;
+ struct pending_checkpoint * entry;
+ struct pending_checkpoint * last_ready;
+
+ /* It is safe to do a quick check for NULL first without lock.
+ Even if we should race, we will at most skip one checkpoint and
+ take the next one, which is harmless. */
+ if (!pending_checkpoint_list)
+ return;
+
+ mysql_mutex_lock(&pending_checkpoint_mutex);
+ pending = pending_checkpoint_list;
+ if (!pending)
+ {
+ mysql_mutex_unlock(&pending_checkpoint_mutex);
+ return;
+ }
+
+ last_ready = NULL;
+ for (entry = pending; entry != NULL; entry = entry -> next)
+ {
+ /* Notify checkpoints up until the first entry that has not
+ been fully flushed to the redo log. Since we do not maintain
+ the list ordered, in principle there could be more entries
+ later than were also flushed. But there is no harm in
+ delaying notifications for those a bit. And in practise, the
+ list is unlikely to have more than one element anyway, as we
+ flush the redo log at least once every second. */
+ if (entry->lsn > flush_lsn)
+ break;
+ last_ready = entry;
+ }
+
+ if (last_ready)
+ {
+ /* We found some pending checkpoints that are now flushed to
+ disk. So remove them from the list. */
+ pending_checkpoint_list = entry;
+ if (!entry)
+ pending_checkpoint_list_end = NULL;
+ }
+
+ mysql_mutex_unlock(&pending_checkpoint_mutex);
+
+ if (!last_ready)
+ return;
+
+ /* Now that we have released the lock, notify upper layer about all
+ commit checkpoints that have now completed. */
+ for (;;) {
+ entry = pending;
+ pending = pending->next;
+
+ commit_checkpoint_notify_ha(entry->hton, entry->cookie);
+
+ my_free(entry);
+ if (entry == last_ready)
+ break;
+ }
}
/*****************************************************************//**
@@ -3770,17 +4005,6 @@ static const char* ha_innobase_exts[] = {
};
/****************************************************************//**
-Returns the table type (storage engine name).
-@return table type */
-UNIV_INTERN
-const char*
-ha_innobase::table_type() const
-/*===========================*/
-{
- return(innobase_hton_name);
-}
-
-/****************************************************************//**
Returns the index type. */
UNIV_INTERN
const char*
@@ -5935,9 +6159,6 @@ ha_innobase::write_row(
DBUG_RETURN(HA_ERR_CRASHED);
}
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
- table->timestamp_field->set_time();
-
sql_command = thd_sql_command(user_thd);
if ((sql_command == SQLCOM_ALTER_TABLE
@@ -6359,9 +6580,6 @@ ha_innobase::update_row(
DBUG_RETURN(HA_ERR_CRASHED);
}
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
- table->timestamp_field->set_time();
-
if (prebuilt->upd_node) {
uvect = prebuilt->upd_node->update;
} else {
@@ -11564,7 +11782,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 */
@@ -11657,6 +11895,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);
@@ -12675,6 +12929,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",
@@ -13054,6 +13314,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),
@@ -13199,7 +13460,10 @@ i_s_innodb_buffer_pool_pages,
i_s_innodb_buffer_pool_pages_index,
i_s_innodb_buffer_pool_pages_blob,
i_s_innodb_admin_command,
-i_s_innodb_changed_pages
+i_s_innodb_changed_pages,
+i_s_innodb_buffer_page,
+i_s_innodb_buffer_page_lru,
+i_s_innodb_buffer_stats
maria_declare_plugin_end;
/** @brief Initialize the default value of innodb_commit_concurrency.
diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h
index 933d75cf0d2..4d9c0a1ab35 100644
--- a/storage/xtradb/handler/ha_innodb.h
+++ b/storage/xtradb/handler/ha_innodb.h
@@ -123,7 +123,6 @@ class ha_innobase: public handler
*/
enum row_type get_row_type() const;
- const char* table_type() const;
const char* index_type(uint key_number);
const char** bas_ext() const;
Table_flags table_flags() const;
diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc
index 57a091ea80d..29a80594344 100644
--- a/storage/xtradb/handler/i_s.cc
+++ b/storage/xtradb/handler/i_s.cc
@@ -64,8 +64,93 @@ extern "C" {
#include "buf0lru.h" /* for XTRA_LRU_[DUMP/RESTORE] */
#include "btr0btr.h" /* for btr_page_get_index_id */
#include "log0online.h"
+#include "btr0btr.h"
+#include "page0zip.h"
+#include "log0log.h"
}
+/** structure associates a name string with a file page type and/or buffer
+page state. */
+struct buffer_page_desc_str_struct{
+ const char* type_str; /*!< String explain the page
+ type/state */
+ ulint type_value; /*!< Page type or page state */
+};
+
+typedef struct buffer_page_desc_str_struct buf_page_desc_str_t;
+
+/** Any states greater than FIL_PAGE_TYPE_LAST would be treated as unknown. */
+#define I_S_PAGE_TYPE_UNKNOWN (FIL_PAGE_TYPE_LAST + 1)
+
+/** We also define I_S_PAGE_TYPE_INDEX as the Index Page's position
+in i_s_page_type[] array */
+#define I_S_PAGE_TYPE_INDEX 1
+
+/** Name string for File Page Types */
+static buf_page_desc_str_t i_s_page_type[] = {
+ {"ALLOCATED", FIL_PAGE_TYPE_ALLOCATED},
+ {"INDEX", FIL_PAGE_INDEX},
+ {"UNDO_LOG", FIL_PAGE_UNDO_LOG},
+ {"INODE", FIL_PAGE_INODE},
+ {"IBUF_FREE_LIST", FIL_PAGE_IBUF_FREE_LIST},
+ {"IBUF_BITMAP", FIL_PAGE_IBUF_BITMAP},
+ {"SYSTEM", FIL_PAGE_TYPE_SYS},
+ {"TRX_SYSTEM", FIL_PAGE_TYPE_TRX_SYS},
+ {"FILE_SPACE_HEADER", FIL_PAGE_TYPE_FSP_HDR},
+ {"EXTENT_DESCRIPTOR", FIL_PAGE_TYPE_XDES},
+ {"BLOB", FIL_PAGE_TYPE_BLOB},
+ {"COMPRESSED_BLOB", FIL_PAGE_TYPE_ZBLOB},
+ {"COMPRESSED_BLOB2", FIL_PAGE_TYPE_ZBLOB2},
+ {"UNKNOWN", I_S_PAGE_TYPE_UNKNOWN}
+};
+
+/* Check if we can hold all page type in a 4 bit value */
+#if I_S_PAGE_TYPE_UNKNOWN > 1<<4
+# error "i_s_page_type[] is too large"
+#endif
+
+/** This structure defines information we will fetch from pages
+currently cached in the buffer pool. It will be used to populate
+table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE */
+struct buffer_page_info_struct{
+ ulint block_id; /*!< Buffer Pool block ID */
+ unsigned space_id:32; /*!< Tablespace ID */
+ unsigned page_num:32; /*!< Page number/offset */
+ unsigned access_time:32; /*!< Time of first access */
+ unsigned pool_id:MAX_BUFFER_POOLS_BITS;
+ /*!< Buffer Pool ID. Must be less than
+ MAX_BUFFER_POOLS */
+ unsigned flush_type:2; /*!< Flush type */
+ unsigned io_fix:2; /*!< type of pending I/O operation */
+ unsigned fix_count:19; /*!< Count of how manyfold this block
+ is bufferfixed */
+ unsigned hashed:1; /*!< Whether hash index has been
+ built on this page */
+ unsigned is_old:1; /*!< TRUE if the block is in the old
+ blocks in buf_pool->LRU_old */
+ unsigned freed_page_clock:31; /*!< the value of
+ buf_pool->freed_page_clock */
+ unsigned zip_ssize:PAGE_ZIP_SSIZE_BITS;
+ /*!< Compressed page size */
+ unsigned page_state:BUF_PAGE_STATE_BITS; /*!< Page state */
+ unsigned page_type:4; /*!< Page type */
+ unsigned num_recs;
+ /*!< Number of records on Page */
+ unsigned data_size;
+ /*!< Sum of the sizes of the records */
+ lsn_t newest_mod; /*!< Log sequence number of
+ the youngest modification */
+ lsn_t oldest_mod; /*!< Log sequence number of
+ the oldest modification */
+ index_id_t index_id; /*!< Index ID if a index page */
+};
+
+typedef struct buffer_page_info_struct buf_page_info_t;
+
+/** maximum number of buffer page info we would cache. */
+#define MAX_BUF_INFO_CACHED 10000
+
+
#define OK(expr) \
if ((expr) != 0) { \
DBUG_RETURN(1); \
@@ -1570,7 +1655,6 @@ i_s_cmpmem_fill_low(
buf_pool = buf_pool_from_array(i);
- //buf_pool_mutex_enter(buf_pool);
mutex_enter(&buf_pool->zip_free_mutex);
for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) {
@@ -1601,7 +1685,6 @@ i_s_cmpmem_fill_low(
}
}
- //buf_pool_mutex_exit(buf_pool);
mutex_exit(&buf_pool->zip_free_mutex);
if (status) {
@@ -1771,6 +1854,1755 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset =
INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
};
+/* Fields of the dynamic table INNODB_BUFFER_POOL_STATS. */
+static ST_FIELD_INFO i_s_innodb_buffer_stats_fields_info[] =
+{
+#define IDX_BUF_STATS_POOL_ID 0
+ {STRUCT_FLD(field_name, "POOL_ID"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_POOL_SIZE 1
+ {STRUCT_FLD(field_name, "POOL_SIZE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_FREE_BUFFERS 2
+ {STRUCT_FLD(field_name, "FREE_BUFFERS"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_LRU_LEN 3
+ {STRUCT_FLD(field_name, "DATABASE_PAGES"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_OLD_LRU_LEN 4
+ {STRUCT_FLD(field_name, "OLD_DATABASE_PAGES"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_FLUSH_LIST_LEN 5
+ {STRUCT_FLD(field_name, "MODIFIED_DATABASE_PAGES"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PENDING_ZIP 6
+ {STRUCT_FLD(field_name, "PENDING_DECOMPRESS"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PENDING_READ 7
+ {STRUCT_FLD(field_name, "PENDING_READS"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_FLUSH_LRU 8
+ {STRUCT_FLD(field_name, "PENDING_FLUSH_LRU"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_FLUSH_LIST 9
+ {STRUCT_FLD(field_name, "PENDING_FLUSH_LIST"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_YOUNG 10
+ {STRUCT_FLD(field_name, "PAGES_MADE_YOUNG"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_NOT_YOUNG 11
+ {STRUCT_FLD(field_name, "PAGES_NOT_MADE_YOUNG"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_YOUNG_RATE 12
+ {STRUCT_FLD(field_name, "PAGES_MADE_YOUNG_RATE"),
+ STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE 13
+ {STRUCT_FLD(field_name, "PAGES_MADE_NOT_YOUNG_RATE"),
+ STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_READ 14
+ {STRUCT_FLD(field_name, "NUMBER_PAGES_READ"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_CREATED 15
+ {STRUCT_FLD(field_name, "NUMBER_PAGES_CREATED"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_WRITTEN 16
+ {STRUCT_FLD(field_name, "NUMBER_PAGES_WRITTEN"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_READ_RATE 17
+ {STRUCT_FLD(field_name, "PAGES_READ_RATE"),
+ STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_CREATE_RATE 18
+ {STRUCT_FLD(field_name, "PAGES_CREATE_RATE"),
+ STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_PAGE_WRITTEN_RATE 19
+ {STRUCT_FLD(field_name, "PAGES_WRITTEN_RATE"),
+ STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_GET 20
+ {STRUCT_FLD(field_name, "NUMBER_PAGES_GET"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_HIT_RATE 21
+ {STRUCT_FLD(field_name, "HIT_RATE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_MADE_YOUNG_PCT 22
+ {STRUCT_FLD(field_name, "YOUNG_MAKE_PER_THOUSAND_GETS"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_NOT_MADE_YOUNG_PCT 23
+ {STRUCT_FLD(field_name, "NOT_YOUNG_MAKE_PER_THOUSAND_GETS"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_READ_AHREAD 24
+ {STRUCT_FLD(field_name, "NUMBER_PAGES_READ_AHEAD"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_READ_AHEAD_EVICTED 25
+ {STRUCT_FLD(field_name, "NUMBER_READ_AHEAD_EVICTED"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_READ_AHEAD_RATE 26
+ {STRUCT_FLD(field_name, "READ_AHEAD_RATE"),
+ STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_READ_AHEAD_EVICT_RATE 27
+ {STRUCT_FLD(field_name, "READ_AHEAD_EVICTED_RATE"),
+ STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_LRU_IO_SUM 28
+ {STRUCT_FLD(field_name, "LRU_IO_TOTAL"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_LRU_IO_CUR 29
+ {STRUCT_FLD(field_name, "LRU_IO_CURRENT"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_UNZIP_SUM 30
+ {STRUCT_FLD(field_name, "UNCOMPRESS_TOTAL"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_STATS_UNZIP_CUR 31
+ {STRUCT_FLD(field_name, "UNCOMPRESS_CURRENT"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ END_OF_ST_FIELD_INFO
+};
+
+/*******************************************************************//**
+Fill Information Schema table INNODB_BUFFER_POOL_STATS for a particular
+buffer pool
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_stats_fill(
+/*==================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ const buf_pool_info_t* info) /*!< in: buffer pool
+ information */
+{
+ TABLE* table;
+ Field** fields;
+
+ DBUG_ENTER("i_s_innodb_stats_fill");
+
+ table = tables->table;
+
+ fields = table->field;
+
+ OK(fields[IDX_BUF_STATS_POOL_ID]->store(info->pool_unique_id));
+
+ OK(fields[IDX_BUF_STATS_POOL_SIZE]->store(info->pool_size));
+
+ OK(fields[IDX_BUF_STATS_LRU_LEN]->store(info->lru_len));
+
+ OK(fields[IDX_BUF_STATS_OLD_LRU_LEN]->store(info->old_lru_len));
+
+ OK(fields[IDX_BUF_STATS_FREE_BUFFERS]->store(info->free_list_len));
+
+ OK(fields[IDX_BUF_STATS_FLUSH_LIST_LEN]->store(
+ info->flush_list_len));
+
+ OK(fields[IDX_BUF_STATS_PENDING_ZIP]->store(info->n_pend_unzip));
+
+ OK(fields[IDX_BUF_STATS_PENDING_READ]->store(info->n_pend_reads));
+
+ OK(fields[IDX_BUF_STATS_FLUSH_LRU]->store(info->n_pending_flush_lru));
+
+ OK(fields[IDX_BUF_STATS_FLUSH_LIST]->store(info->n_pending_flush_list));
+
+ OK(fields[IDX_BUF_STATS_PAGE_YOUNG]->store(info->n_pages_made_young));
+
+ OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG]->store(
+ info->n_pages_not_made_young));
+
+ OK(fields[IDX_BUF_STATS_PAGE_YOUNG_RATE]->store(
+ info->page_made_young_rate));
+
+ OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE]->store(
+ info->page_not_made_young_rate));
+
+ OK(fields[IDX_BUF_STATS_PAGE_READ]->store(info->n_pages_read));
+
+ OK(fields[IDX_BUF_STATS_PAGE_CREATED]->store(info->n_pages_created));
+
+ OK(fields[IDX_BUF_STATS_PAGE_WRITTEN]->store(info->n_pages_written));
+
+ OK(fields[IDX_BUF_STATS_GET]->store(info->n_page_gets));
+
+ OK(fields[IDX_BUF_STATS_PAGE_READ_RATE]->store(info->pages_read_rate));
+
+ OK(fields[IDX_BUF_STATS_PAGE_CREATE_RATE]->store(info->pages_created_rate));
+
+ OK(fields[IDX_BUF_STATS_PAGE_WRITTEN_RATE]->store(info->pages_written_rate));
+
+ if (info->n_page_get_delta) {
+ OK(fields[IDX_BUF_STATS_HIT_RATE]->store(
+ 1000 - (1000 * info->page_read_delta
+ / info->n_page_get_delta)));
+
+ OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(
+ 1000 * info->young_making_delta
+ / info->n_page_get_delta));
+
+ OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(
+ 1000 * info->not_young_making_delta
+ / info->n_page_get_delta));
+ } else {
+ OK(fields[IDX_BUF_STATS_HIT_RATE]->store(0));
+ OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(0));
+ OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(0));
+ }
+
+ OK(fields[IDX_BUF_STATS_READ_AHREAD]->store(info->n_ra_pages_read));
+
+ OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICTED]->store(
+ info->n_ra_pages_evicted));
+
+ OK(fields[IDX_BUF_STATS_READ_AHEAD_RATE]->store(
+ info->pages_readahead_rate));
+
+ OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICT_RATE]->store(
+ info->pages_evicted_rate));
+
+ OK(fields[IDX_BUF_STATS_LRU_IO_SUM]->store(info->io_sum));
+
+ OK(fields[IDX_BUF_STATS_LRU_IO_CUR]->store(info->io_cur));
+
+ OK(fields[IDX_BUF_STATS_UNZIP_SUM]->store(info->unzip_sum));
+
+ OK(fields[IDX_BUF_STATS_UNZIP_CUR]->store( info->unzip_cur));
+
+ DBUG_RETURN(schema_table_store_record(thd, table));
+}
+
+/*******************************************************************//**
+This is the function that loops through each buffer pool and fetch buffer
+pool stats to information schema table: I_S_INNODB_BUFFER_POOL_STATS
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_buffer_stats_fill_table(
+/*===============================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ Item* ) /*!< in: condition (ignored) */
+{
+ int status = 0;
+ buf_pool_info_t* pool_info;
+
+ DBUG_ENTER("i_s_innodb_buffer_fill_general");
+
+ /* Only allow the PROCESS privilege holder to access the stats */
+ if (check_global_access(thd, PROCESS_ACL)) {
+ DBUG_RETURN(0);
+ }
+
+ pool_info = (buf_pool_info_t*) mem_zalloc(
+ srv_buf_pool_instances * sizeof *pool_info);
+
+ /* Walk through each buffer pool */
+ for (ulint i = 0; i < srv_buf_pool_instances; i++) {
+ buf_pool_t* buf_pool;
+
+ buf_pool = buf_pool_from_array(i);
+
+ /* Fetch individual buffer pool info */
+ buf_stats_get_pool_info(buf_pool, i, pool_info);
+
+ status = i_s_innodb_stats_fill(thd, tables, &pool_info[i]);
+
+ /* If something goes wrong, break and return */
+ if (status) {
+ break;
+ }
+ }
+
+ mem_free(pool_info);
+
+ DBUG_RETURN(status);
+}
+
+/*******************************************************************//**
+Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS.
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_buffer_pool_stats_init(
+/*==============================*/
+ void* p) /*!< in/out: table schema object */
+{
+ ST_SCHEMA_TABLE* schema;
+
+ DBUG_ENTER("i_s_innodb_buffer_pool_stats_init");
+
+ schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
+
+ schema->fields_info = i_s_innodb_buffer_stats_fields_info;
+ schema->fill_table = i_s_innodb_buffer_stats_fill_table;
+
+ DBUG_RETURN(0);
+}
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_stats =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_STATS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB Buffer Pool Statistics Information "),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_pool_stats_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
+};
+
+/* Fields of the dynamic table INNODB_BUFFER_POOL_PAGE. */
+static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] =
+{
+#define IDX_BUFFER_POOL_ID 0
+ {STRUCT_FLD(field_name, "POOL_ID"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_BLOCK_ID 1
+ {STRUCT_FLD(field_name, "BLOCK_ID"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_SPACE 2
+ {STRUCT_FLD(field_name, "SPACE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_NUM 3
+ {STRUCT_FLD(field_name, "PAGE_NUMBER"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_TYPE 4
+ {STRUCT_FLD(field_name, "PAGE_TYPE"),
+ STRUCT_FLD(field_length, 64),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_FLUSH_TYPE 5
+ {STRUCT_FLD(field_name, "FLUSH_TYPE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_FIX_COUNT 6
+ {STRUCT_FLD(field_name, "FIX_COUNT"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_HASHED 7
+ {STRUCT_FLD(field_name, "IS_HASHED"),
+ STRUCT_FLD(field_length, 3),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_NEWEST_MOD 8
+ {STRUCT_FLD(field_name, "NEWEST_MODIFICATION"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_OLDEST_MOD 9
+ {STRUCT_FLD(field_name, "OLDEST_MODIFICATION"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_ACCESS_TIME 10
+ {STRUCT_FLD(field_name, "ACCESS_TIME"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_TABLE_NAME 11
+ {STRUCT_FLD(field_name, "TABLE_NAME"),
+ STRUCT_FLD(field_length, 1024),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_INDEX_NAME 12
+ {STRUCT_FLD(field_name, "INDEX_NAME"),
+ STRUCT_FLD(field_length, 1024),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_NUM_RECS 13
+ {STRUCT_FLD(field_name, "NUMBER_RECORDS"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_DATA_SIZE 14
+ {STRUCT_FLD(field_name, "DATA_SIZE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_ZIP_SIZE 15
+ {STRUCT_FLD(field_name, "COMPRESSED_SIZE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_STATE 16
+ {STRUCT_FLD(field_name, "PAGE_STATE"),
+ STRUCT_FLD(field_length, 64),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_IO_FIX 17
+ {STRUCT_FLD(field_name, "IO_FIX"),
+ STRUCT_FLD(field_length, 64),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_IS_OLD 18
+ {STRUCT_FLD(field_name, "IS_OLD"),
+ STRUCT_FLD(field_length, 3),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUFFER_PAGE_FREE_CLOCK 19
+ {STRUCT_FLD(field_name, "FREE_PAGE_CLOCK"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ END_OF_ST_FIELD_INFO
+};
+
+/*******************************************************************//**
+Fill Information Schema table INNODB_BUFFER_PAGE with information
+cached in the buf_page_info_t array
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_buffer_page_fill(
+/*========================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ const buf_page_info_t* info_array, /*!< in: array cached page
+ info */
+ ulint num_page, /*!< in: number of page info
+ cached */
+ mem_heap_t* heap) /*!< in: temp heap memory */
+{
+ TABLE* table;
+ Field** fields;
+
+ DBUG_ENTER("i_s_innodb_buffer_page_fill");
+
+ table = tables->table;
+
+ fields = table->field;
+
+ /* Iterate through the cached array and fill the I_S table rows */
+ for (ulint i = 0; i < num_page; i++) {
+ const buf_page_info_t* page_info;
+ const char* table_name;
+ const char* index_name;
+ const char* state_str;
+ enum buf_page_state state;
+
+ page_info = info_array + i;
+
+ table_name = NULL;
+ index_name = NULL;
+ state_str = NULL;
+
+ OK(fields[IDX_BUFFER_POOL_ID]->store(page_info->pool_id));
+
+ OK(fields[IDX_BUFFER_BLOCK_ID]->store(page_info->block_id));
+
+ OK(fields[IDX_BUFFER_PAGE_SPACE]->store(page_info->space_id));
+
+ OK(fields[IDX_BUFFER_PAGE_NUM]->store(page_info->page_num));
+
+ OK(field_store_string(
+ fields[IDX_BUFFER_PAGE_TYPE],
+ i_s_page_type[page_info->page_type].type_str));
+
+ OK(fields[IDX_BUFFER_PAGE_FLUSH_TYPE]->store(
+ page_info->flush_type));
+
+ OK(fields[IDX_BUFFER_PAGE_FIX_COUNT]->store(
+ page_info->fix_count));
+
+ if (page_info->hashed) {
+ OK(field_store_string(
+ fields[IDX_BUFFER_PAGE_HASHED], "YES"));
+ } else {
+ OK(field_store_string(
+ fields[IDX_BUFFER_PAGE_HASHED], "NO"));
+ }
+
+ OK(fields[IDX_BUFFER_PAGE_NEWEST_MOD]->store(
+ (longlong) page_info->newest_mod, true));
+
+ OK(fields[IDX_BUFFER_PAGE_OLDEST_MOD]->store(
+ (longlong) page_info->oldest_mod, true));
+
+ OK(fields[IDX_BUFFER_PAGE_ACCESS_TIME]->store(
+ page_info->access_time));
+
+ /* If this is an index page, fetch the index name
+ and table name */
+ if (page_info->page_type == I_S_PAGE_TYPE_INDEX) {
+ const dict_index_t* index;
+
+ mutex_enter(&dict_sys->mutex);
+ index = dict_index_get_if_in_cache_low(
+ page_info->index_id);
+
+ /* Copy the index/table name under mutex. We
+ do not want to hold the InnoDB mutex while
+ filling the IS table */
+ if (index) {
+ const char* name_ptr = index->name;
+
+ if (name_ptr[0] == TEMP_INDEX_PREFIX) {
+ name_ptr++;
+ }
+
+ index_name = mem_heap_strdup(heap, name_ptr);
+
+ table_name = mem_heap_strdup(heap,
+ index->table_name);
+
+ }
+
+ mutex_exit(&dict_sys->mutex);
+ }
+
+ OK(field_store_string(
+ fields[IDX_BUFFER_PAGE_TABLE_NAME], table_name));
+
+ OK(field_store_string(
+ fields[IDX_BUFFER_PAGE_INDEX_NAME], index_name));
+
+ OK(fields[IDX_BUFFER_PAGE_NUM_RECS]->store(
+ page_info->num_recs));
+
+ OK(fields[IDX_BUFFER_PAGE_DATA_SIZE]->store(
+ page_info->data_size));
+
+ OK(fields[IDX_BUFFER_PAGE_ZIP_SIZE]->store(
+ page_info->zip_ssize
+ ? (PAGE_ZIP_MIN_SIZE >> 1) << page_info->zip_ssize
+ : 0));
+
+#if BUF_PAGE_STATE_BITS > 3
+# error "BUF_PAGE_STATE_BITS > 3, please ensure that all 1<<BUF_PAGE_STATE_BITS values are checked for"
+#endif
+ state = static_cast<enum buf_page_state>(page_info->page_state);
+
+ switch (state) {
+ /* First three states are for compression pages and
+ are not states we would get as we scan pages through
+ buffer blocks */
+ case BUF_BLOCK_ZIP_FREE:
+ case BUF_BLOCK_ZIP_PAGE:
+ case BUF_BLOCK_ZIP_DIRTY:
+ state_str = NULL;
+ break;
+ case BUF_BLOCK_NOT_USED:
+ state_str = "NOT_USED";
+ break;
+ case BUF_BLOCK_READY_FOR_USE:
+ state_str = "READY_FOR_USE";
+ break;
+ case BUF_BLOCK_FILE_PAGE:
+ state_str = "FILE_PAGE";
+ break;
+ case BUF_BLOCK_MEMORY:
+ state_str = "MEMORY";
+ break;
+ case BUF_BLOCK_REMOVE_HASH:
+ state_str = "REMOVE_HASH";
+ break;
+ };
+
+ OK(field_store_string(fields[IDX_BUFFER_PAGE_STATE],
+ state_str));
+
+ switch (page_info->io_fix) {
+ case BUF_IO_NONE:
+ OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
+ "IO_NONE"));
+ break;
+ case BUF_IO_READ:
+ OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
+ "IO_READ"));
+ break;
+ case BUF_IO_WRITE:
+ OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
+ "IO_WRITE"));
+ break;
+ case BUF_IO_PIN:
+ OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
+ "IO_PIN"));
+ break;
+ }
+
+ OK(field_store_string(fields[IDX_BUFFER_PAGE_IS_OLD],
+ (page_info->is_old) ? "YES" : "NO"));
+
+ OK(fields[IDX_BUFFER_PAGE_FREE_CLOCK]->store(
+ page_info->freed_page_clock));
+
+ if (schema_table_store_record(thd, table)) {
+ DBUG_RETURN(1);
+ }
+ }
+
+ DBUG_RETURN(0);
+}
+
+/*******************************************************************//**
+Set appropriate page type to a buf_page_info_t structure */
+static
+void
+i_s_innodb_set_page_type(
+/*=====================*/
+ buf_page_info_t*page_info, /*!< in/out: structure to fill with
+ scanned info */
+ ulint page_type, /*!< in: page type */
+ const byte* frame) /*!< in: buffer frame */
+{
+ if (page_type == FIL_PAGE_INDEX) {
+ const page_t* page = (const page_t*) frame;
+
+ /* FIL_PAGE_INDEX is a bit special, its value
+ is defined as 17855, so we cannot use FIL_PAGE_INDEX
+ to index into i_s_page_type[] array, its array index
+ in the i_s_page_type[] array is I_S_PAGE_TYPE_INDEX
+ (1) */
+ page_info->page_type = I_S_PAGE_TYPE_INDEX;
+
+ page_info->index_id = btr_page_get_index_id(page);
+
+ page_info->data_size = (ulint)(page_header_get_field(
+ page, PAGE_HEAP_TOP) - (page_is_comp(page)
+ ? PAGE_NEW_SUPREMUM_END
+ : PAGE_OLD_SUPREMUM_END)
+ - page_header_get_field(page, PAGE_GARBAGE));
+
+ page_info->num_recs = page_get_n_recs(page);
+ } else if (page_type >= I_S_PAGE_TYPE_UNKNOWN) {
+ /* Encountered an unknown page type */
+ page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
+ } else {
+ /* Make sure we get the right index into the
+ i_s_page_type[] array */
+ ut_a(page_type == i_s_page_type[page_type].type_value);
+
+ page_info->page_type = page_type;
+ }
+
+ if (page_info->page_type == FIL_PAGE_TYPE_ZBLOB
+ || page_info->page_type == FIL_PAGE_TYPE_ZBLOB2) {
+ page_info->page_num = mach_read_from_4(
+ frame + FIL_PAGE_OFFSET);
+ page_info->space_id = mach_read_from_4(
+ frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
+ }
+}
+/*******************************************************************//**
+Scans pages in the buffer cache, and collect their general information
+into the buf_page_info_t array which is zero-filled. So any fields
+that are not initialized in the function will default to 0 */
+static
+void
+i_s_innodb_buffer_page_get_info(
+/*============================*/
+ const buf_page_t*bpage, /*!< in: buffer pool page to scan */
+ ulint pool_id, /*!< in: buffer pool id */
+ ulint pos, /*!< in: buffer block position in
+ buffer pool or in the LRU list */
+ buf_page_info_t*page_info) /*!< in: zero filled info structure;
+ out: structure filled with scanned
+ info */
+{
+ ut_ad(pool_id < MAX_BUFFER_POOLS);
+
+ page_info->pool_id = pool_id;
+
+ page_info->block_id = pos;
+
+ page_info->page_state = buf_page_get_state(bpage);
+
+ /* Only fetch information for buffers that map to a tablespace,
+ that is, buffer page with state BUF_BLOCK_ZIP_PAGE,
+ BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_FILE_PAGE */
+ if (buf_page_in_file(bpage)) {
+ const byte* frame;
+ ulint page_type;
+
+ page_info->space_id = buf_page_get_space(bpage);
+
+ page_info->page_num = buf_page_get_page_no(bpage);
+
+ page_info->flush_type = bpage->flush_type;
+
+ page_info->fix_count = bpage->buf_fix_count;
+
+ page_info->newest_mod = bpage->newest_modification;
+
+ page_info->oldest_mod = bpage->oldest_modification;
+
+ page_info->access_time = bpage->access_time;
+
+ page_info->zip_ssize = bpage->zip.ssize;
+
+ page_info->io_fix = bpage->io_fix;
+
+ page_info->is_old = bpage->old;
+
+ page_info->freed_page_clock = bpage->freed_page_clock;
+
+ if (page_info->page_state == BUF_BLOCK_FILE_PAGE) {
+ const buf_block_t*block;
+
+ block = reinterpret_cast<const buf_block_t*>(bpage);
+ frame = block->frame;
+ page_info->hashed = (block->index != NULL);
+ } else {
+ ut_ad(page_info->zip_ssize);
+ frame = bpage->zip.data;
+ }
+
+ page_type = fil_page_get_type(frame);
+
+ i_s_innodb_set_page_type(page_info, page_type, frame);
+ } else {
+ page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
+ }
+}
+
+/*******************************************************************//**
+This is the function that goes through each block of the buffer pool
+and fetch information to information schema tables: INNODB_BUFFER_PAGE.
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_fill_buffer_pool(
+/*========================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ buf_pool_t* buf_pool, /*!< in: buffer pool to scan */
+ const ulint pool_id) /*!< in: buffer pool id */
+{
+ int status = 0;
+ mem_heap_t* heap;
+
+ DBUG_ENTER("i_s_innodb_fill_buffer_pool");
+
+ heap = mem_heap_create(10000);
+
+ /* Go through each chunk of buffer pool. Currently, we only
+ have one single chunk for each buffer pool */
+ for (ulint n = 0; n < buf_pool->n_chunks; n++) {
+ const buf_block_t* block;
+ ulint n_blocks;
+ buf_page_info_t* info_buffer;
+ ulint num_page;
+ ulint mem_size;
+ ulint chunk_size;
+ ulint num_to_process = 0;
+ ulint block_id = 0;
+ mutex_t* block_mutex;
+
+ /* Get buffer block of the nth chunk */
+ block = buf_get_nth_chunk_block(buf_pool, n, &chunk_size);
+ num_page = 0;
+
+ while (chunk_size > 0) {
+ /* we cache maximum MAX_BUF_INFO_CACHED number of
+ buffer page info */
+ num_to_process = ut_min(chunk_size,
+ MAX_BUF_INFO_CACHED);
+
+ mem_size = num_to_process * sizeof(buf_page_info_t);
+
+ /* For each chunk, we'll pre-allocate information
+ structures to cache the page information read from
+ the buffer pool. Doing so before obtain any mutex */
+ info_buffer = (buf_page_info_t*) mem_heap_zalloc(
+ heap, mem_size);
+
+ /* GO through each block in the chunk */
+ for (n_blocks = num_to_process; n_blocks--; block++) {
+ block_mutex = buf_page_get_mutex_enter(&block->page);
+ i_s_innodb_buffer_page_get_info(
+ &block->page, pool_id, block_id,
+ info_buffer + num_page);
+ mutex_exit(block_mutex);
+ block_id++;
+ num_page++;
+ }
+
+
+ /* Fill in information schema table with information
+ just collected from the buffer chunk scan */
+ status = i_s_innodb_buffer_page_fill(
+ thd, tables, info_buffer,
+ num_page, heap);
+
+ /* If something goes wrong, break and return */
+ if (status) {
+ break;
+ }
+
+ mem_heap_empty(heap);
+ chunk_size -= num_to_process;
+ num_page = 0;
+ }
+ }
+
+ mem_heap_free(heap);
+
+ DBUG_RETURN(status);
+}
+
+/*******************************************************************//**
+Fill page information for pages in InnoDB buffer pool to the
+dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_buffer_page_fill_table(
+/*==============================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ Item* ) /*!< in: condition (ignored) */
+{
+ int status = 0;
+
+ DBUG_ENTER("i_s_innodb_buffer_page_fill_table");
+
+ /* deny access to user without PROCESS privilege */
+ if (check_global_access(thd, PROCESS_ACL)) {
+ DBUG_RETURN(0);
+ }
+
+ /* Walk through each buffer pool */
+ for (ulint i = 0; i < srv_buf_pool_instances; i++) {
+ buf_pool_t* buf_pool;
+
+ buf_pool = buf_pool_from_array(i);
+
+ /* Fetch information from pages in this buffer pool,
+ and fill the corresponding I_S table */
+ status = i_s_innodb_fill_buffer_pool(thd, tables, buf_pool, i);
+
+ /* If something wrong, break and return */
+ if (status) {
+ break;
+ }
+ }
+
+ DBUG_RETURN(status);
+}
+
+/*******************************************************************//**
+Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE.
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_buffer_page_init(
+/*========================*/
+ void* p) /*!< in/out: table schema object */
+{
+ ST_SCHEMA_TABLE* schema;
+
+ DBUG_ENTER("i_s_innodb_buffer_page_init");
+
+ schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
+
+ schema->fields_info = i_s_innodb_buffer_page_fields_info;
+ schema->fill_table = i_s_innodb_buffer_page_fill_table;
+
+ DBUG_RETURN(0);
+}
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_page =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_PAGE"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB Buffer Page Information"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_page_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
+};
+
+static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] =
+{
+#define IDX_BUF_LRU_POOL_ID 0
+ {STRUCT_FLD(field_name, "POOL_ID"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_POS 1
+ {STRUCT_FLD(field_name, "LRU_POSITION"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_SPACE 2
+ {STRUCT_FLD(field_name, "SPACE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_NUM 3
+ {STRUCT_FLD(field_name, "PAGE_NUMBER"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_TYPE 4
+ {STRUCT_FLD(field_name, "PAGE_TYPE"),
+ STRUCT_FLD(field_length, 64),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_FLUSH_TYPE 5
+ {STRUCT_FLD(field_name, "FLUSH_TYPE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_FIX_COUNT 6
+ {STRUCT_FLD(field_name, "FIX_COUNT"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_HASHED 7
+ {STRUCT_FLD(field_name, "IS_HASHED"),
+ STRUCT_FLD(field_length, 3),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_NEWEST_MOD 8
+ {STRUCT_FLD(field_name, "NEWEST_MODIFICATION"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_OLDEST_MOD 9
+ {STRUCT_FLD(field_name, "OLDEST_MODIFICATION"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_ACCESS_TIME 10
+ {STRUCT_FLD(field_name, "ACCESS_TIME"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_TABLE_NAME 11
+ {STRUCT_FLD(field_name, "TABLE_NAME"),
+ STRUCT_FLD(field_length, 1024),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_INDEX_NAME 12
+ {STRUCT_FLD(field_name, "INDEX_NAME"),
+ STRUCT_FLD(field_length, 1024),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_NUM_RECS 13
+ {STRUCT_FLD(field_name, "NUMBER_RECORDS"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_DATA_SIZE 14
+ {STRUCT_FLD(field_name, "DATA_SIZE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_ZIP_SIZE 15
+ {STRUCT_FLD(field_name, "COMPRESSED_SIZE"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_STATE 16
+ {STRUCT_FLD(field_name, "COMPRESSED"),
+ STRUCT_FLD(field_length, 3),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_IO_FIX 17
+ {STRUCT_FLD(field_name, "IO_FIX"),
+ STRUCT_FLD(field_length, 64),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_IS_OLD 18
+ {STRUCT_FLD(field_name, "IS_OLD"),
+ STRUCT_FLD(field_length, 3),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+#define IDX_BUF_LRU_PAGE_FREE_CLOCK 19
+ {STRUCT_FLD(field_name, "FREE_PAGE_CLOCK"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ END_OF_ST_FIELD_INFO
+};
+
+/*******************************************************************//**
+Fill Information Schema table INNODB_BUFFER_PAGE_LRU with information
+cached in the buf_page_info_t array
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_buf_page_lru_fill(
+/*=========================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ const buf_page_info_t* info_array, /*!< in: array cached page
+ info */
+ ulint num_page) /*!< in: number of page info
+ cached */
+{
+ TABLE* table;
+ Field** fields;
+ mem_heap_t* heap;
+
+ DBUG_ENTER("i_s_innodb_buf_page_lru_fill");
+
+ table = tables->table;
+
+ fields = table->field;
+
+ heap = mem_heap_create(1000);
+
+ /* Iterate through the cached array and fill the I_S table rows */
+ for (ulint i = 0; i < num_page; i++) {
+ const buf_page_info_t* page_info;
+ const char* table_name;
+ const char* index_name;
+ const char* state_str;
+ enum buf_page_state state;
+
+ table_name = NULL;
+ index_name = NULL;
+ state_str = NULL;
+
+ page_info = info_array + i;
+
+ OK(fields[IDX_BUF_LRU_POOL_ID]->store(page_info->pool_id));
+
+ OK(fields[IDX_BUF_LRU_POS]->store(page_info->block_id));
+
+ OK(fields[IDX_BUF_LRU_PAGE_SPACE]->store(page_info->space_id));
+
+ OK(fields[IDX_BUF_LRU_PAGE_NUM]->store(page_info->page_num));
+
+ OK(field_store_string(
+ fields[IDX_BUF_LRU_PAGE_TYPE],
+ i_s_page_type[page_info->page_type].type_str));
+
+ OK(fields[IDX_BUF_LRU_PAGE_FLUSH_TYPE]->store(
+ page_info->flush_type));
+
+ OK(fields[IDX_BUF_LRU_PAGE_FIX_COUNT]->store(
+ page_info->fix_count));
+
+ if (page_info->hashed) {
+ OK(field_store_string(
+ fields[IDX_BUF_LRU_PAGE_HASHED], "YES"));
+ } else {
+ OK(field_store_string(
+ fields[IDX_BUF_LRU_PAGE_HASHED], "NO"));
+ }
+
+ OK(fields[IDX_BUF_LRU_PAGE_NEWEST_MOD]->store(
+ page_info->newest_mod, true));
+
+ OK(fields[IDX_BUF_LRU_PAGE_OLDEST_MOD]->store(
+ page_info->oldest_mod, true));
+
+ OK(fields[IDX_BUF_LRU_PAGE_ACCESS_TIME]->store(
+ page_info->access_time));
+
+ /* If this is an index page, fetch the index name
+ and table name */
+ if (page_info->page_type == I_S_PAGE_TYPE_INDEX) {
+ const dict_index_t* index;
+
+ mutex_enter(&dict_sys->mutex);
+ index = dict_index_get_if_in_cache_low(
+ page_info->index_id);
+
+ /* Copy the index/table name under mutex. We
+ do not want to hold the InnoDB mutex while
+ filling the IS table */
+ if (index) {
+ const char* name_ptr = index->name;
+
+ if (name_ptr[0] == TEMP_INDEX_PREFIX) {
+ name_ptr++;
+ }
+
+ index_name = mem_heap_strdup(heap, name_ptr);
+
+ table_name = mem_heap_strdup(heap,
+ index->table_name);
+ }
+
+ mutex_exit(&dict_sys->mutex);
+ }
+
+ OK(field_store_string(
+ fields[IDX_BUF_LRU_PAGE_TABLE_NAME], table_name));
+
+ OK(field_store_string(
+ fields[IDX_BUF_LRU_PAGE_INDEX_NAME], index_name));
+ OK(fields[IDX_BUF_LRU_PAGE_NUM_RECS]->store(
+ page_info->num_recs));
+
+ OK(fields[IDX_BUF_LRU_PAGE_DATA_SIZE]->store(
+ page_info->data_size));
+
+ OK(fields[IDX_BUF_LRU_PAGE_ZIP_SIZE]->store(
+ page_info->zip_ssize ?
+ 512 << page_info->zip_ssize : 0));
+
+ state = static_cast<enum buf_page_state>(page_info->page_state);
+
+ switch (state) {
+ /* Compressed page */
+ case BUF_BLOCK_ZIP_PAGE:
+ case BUF_BLOCK_ZIP_DIRTY:
+ state_str = "YES";
+ break;
+ /* Uncompressed page */
+ case BUF_BLOCK_FILE_PAGE:
+ state_str = "NO";
+ break;
+ /* We should not see following states */
+ case BUF_BLOCK_ZIP_FREE:
+ case BUF_BLOCK_READY_FOR_USE:
+ case BUF_BLOCK_NOT_USED:
+ case BUF_BLOCK_MEMORY:
+ case BUF_BLOCK_REMOVE_HASH:
+ state_str = NULL;
+ break;
+ };
+
+ OK(field_store_string(fields[IDX_BUF_LRU_PAGE_STATE],
+ state_str));
+
+ switch (page_info->io_fix) {
+ case BUF_IO_NONE:
+ OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
+ "IO_NONE"));
+ break;
+ case BUF_IO_READ:
+ OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
+ "IO_READ"));
+ break;
+ case BUF_IO_WRITE:
+ OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
+ "IO_WRITE"));
+ break;
+ }
+
+ OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IS_OLD],
+ (page_info->is_old) ? "YES" : "NO"));
+
+ OK(fields[IDX_BUF_LRU_PAGE_FREE_CLOCK]->store(
+ page_info->freed_page_clock));
+
+ if (schema_table_store_record(thd, table)) {
+ mem_heap_free(heap);
+ DBUG_RETURN(1);
+ }
+
+ mem_heap_empty(heap);
+ }
+
+ mem_heap_free(heap);
+
+ DBUG_RETURN(0);
+}
+
+/*******************************************************************//**
+This is the function that goes through buffer pool's LRU list
+and fetch information to INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU.
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_fill_buffer_lru(
+/*=======================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ buf_pool_t* buf_pool, /*!< in: buffer pool to scan */
+ const ulint pool_id) /*!< in: buffer pool id */
+{
+ int status = 0;
+ buf_page_info_t* info_buffer;
+ ulint lru_pos = 0;
+ const buf_page_t* bpage;
+ ulint lru_len;
+ mutex_t* block_mutex;
+
+ DBUG_ENTER("i_s_innodb_fill_buffer_lru");
+
+ RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
+
+ /* Obtain buf_pool mutex before allocate info_buffer, since
+ UT_LIST_GET_LEN(buf_pool->LRU) could change */
+ mutex_enter(&buf_pool->LRU_list_mutex);
+
+ lru_len = UT_LIST_GET_LEN(buf_pool->LRU);
+
+ /* Print error message if malloc fail */
+ info_buffer = (buf_page_info_t*) my_malloc(
+ lru_len * sizeof *info_buffer, MYF(MY_WME));
+
+ if (!info_buffer) {
+ status = 1;
+ goto exit;
+ }
+
+ memset(info_buffer, 0, lru_len * sizeof *info_buffer);
+
+ /* Walk through Pool's LRU list and print the buffer page
+ information */
+ bpage = UT_LIST_GET_LAST(buf_pool->LRU);
+
+ while (bpage != NULL) {
+ block_mutex = buf_page_get_mutex_enter(bpage);
+ /* Use the same function that collect buffer info for
+ INNODB_BUFFER_PAGE to get buffer page info */
+ i_s_innodb_buffer_page_get_info(bpage, pool_id, lru_pos,
+ (info_buffer + lru_pos));
+
+ bpage = UT_LIST_GET_PREV(LRU, bpage);
+ mutex_exit(block_mutex);
+
+ lru_pos++;
+ }
+
+ ut_ad(lru_pos == lru_len);
+ ut_ad(lru_pos == UT_LIST_GET_LEN(buf_pool->LRU));
+
+exit:
+ mutex_exit(&buf_pool->LRU_list_mutex);
+
+ if (info_buffer) {
+ status = i_s_innodb_buf_page_lru_fill(
+ thd, tables, info_buffer, lru_len);
+
+ my_free(info_buffer);
+ }
+
+ DBUG_RETURN(status);
+}
+
+/*******************************************************************//**
+Fill page information for pages in InnoDB buffer pool to the
+dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_buf_page_lru_fill_table(
+/*===============================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ Item* ) /*!< in: condition (ignored) */
+{
+ int status = 0;
+
+ DBUG_ENTER("i_s_innodb_buf_page_lru_fill_table");
+
+ /* deny access to any users that do not hold PROCESS_ACL */
+ if (check_global_access(thd, PROCESS_ACL)) {
+ DBUG_RETURN(0);
+ }
+
+ /* Walk through each buffer pool */
+ for (ulint i = 0; i < srv_buf_pool_instances; i++) {
+ buf_pool_t* buf_pool;
+
+ buf_pool = buf_pool_from_array(i);
+
+ /* Fetch information from pages in this buffer pool's LRU list,
+ and fill the corresponding I_S table */
+ status = i_s_innodb_fill_buffer_lru(thd, tables, buf_pool, i);
+
+ /* If something wrong, break and return */
+ if (status) {
+ break;
+ }
+ }
+
+ DBUG_RETURN(status);
+}
+
+/*******************************************************************//**
+Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU.
+@return 0 on success, 1 on failure */
+static
+int
+i_s_innodb_buffer_page_lru_init(
+/*============================*/
+ void* p) /*!< in/out: table schema object */
+{
+ ST_SCHEMA_TABLE* schema;
+
+ DBUG_ENTER("i_s_innodb_buffer_page_lru_init");
+
+ schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
+
+ schema->fields_info = i_s_innodb_buf_page_lru_fields_info;
+ schema->fill_table = i_s_innodb_buf_page_lru_fill_table;
+
+ DBUG_RETURN(0);
+}
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_page_lru =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_PAGE_LRU"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB Buffer Page in LRU"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_page_lru_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
+};
+
/*******************************************************************//**
Unbind a dynamic INFORMATION_SCHEMA table.
@return 0 on success */
diff --git a/storage/xtradb/handler/i_s.h b/storage/xtradb/handler/i_s.h
index a8964356747..620309bebfe 100644
--- a/storage/xtradb/handler/i_s.h
+++ b/storage/xtradb/handler/i_s.h
@@ -52,5 +52,8 @@ extern struct st_maria_plugin i_s_innodb_buffer_pool_pages;
extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_index;
extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_blob;
extern struct st_maria_plugin i_s_innodb_changed_pages;
+extern struct st_maria_plugin i_s_innodb_buffer_page;
+extern struct st_maria_plugin i_s_innodb_buffer_page_lru;
+extern struct st_maria_plugin i_s_innodb_buffer_stats;
#endif /* i_s_h */
diff --git a/storage/xtradb/ibuf/ibuf0ibuf.c b/storage/xtradb/ibuf/ibuf0ibuf.c
index 562f207268a..78cb6e20176 100644
--- a/storage/xtradb/ibuf/ibuf0ibuf.c
+++ b/storage/xtradb/ibuf/ibuf0ibuf.c
@@ -3650,11 +3650,18 @@ bitmap_fail:
root = ibuf_tree_root_get(&mtr);
- err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG
- | BTR_NO_UNDO_LOG_FLAG,
- cursor,
- ibuf_entry, &ins_rec,
- &dummy_big_rec, 0, thr, &mtr);
+ err = btr_cur_optimistic_insert(
+ BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG,
+ cursor, ibuf_entry, &ins_rec,
+ &dummy_big_rec, 0, thr, &mtr);
+
+ if (err == DB_FAIL) {
+ err = btr_cur_pessimistic_insert(
+ BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG,
+ cursor, ibuf_entry, &ins_rec,
+ &dummy_big_rec, 0, thr, &mtr);
+ }
+
mutex_exit(&ibuf_pessimistic_insert_mutex);
ibuf_size_update(root, &mtr);
mutex_exit(&ibuf_mutex);
diff --git a/storage/xtradb/include/buf0buf.h b/storage/xtradb/include/buf0buf.h
index 1a4990be69f..d48c7f0212f 100644
--- a/storage/xtradb/include/buf0buf.h
+++ b/storage/xtradb/include/buf0buf.h
@@ -68,7 +68,10 @@ Created 11/5/1995 Heikki Tuuri
position of the block. */
/* @} */
-#define MAX_BUFFER_POOLS 64 /*!< The maximum number of buffer
+#define MAX_BUFFER_POOLS_BITS 6 /*!< Number of bits to representing
+ a buffer pool ID */
+#define MAX_BUFFER_POOLS (1 << MAX_BUFFER_POOLS_BITS)
+ /*!< The maximum number of buffer
pools that can be defined */
#define BUF_POOL_WATCH_SIZE 1 /*!< Maximum number of concurrent
@@ -233,6 +236,7 @@ ulint
buf_pool_init(
/*=========*/
ulint size, /*!< in: Size of the total pool in bytes */
+ ibool populate, /*!< in: Force virtual page preallocation */
ulint n_instances); /*!< in: Number of instances */
/********************************************************************//**
Frees the buffer pool at shutdown. This must not be invoked before
@@ -778,6 +782,18 @@ void
buf_print_io(
/*=========*/
FILE* file); /*!< in: file where to print */
+/*******************************************************************//**
+Collect buffer pool stats information for a buffer pool. Also
+record aggregated stats if there are more than one buffer pool
+in the server */
+UNIV_INTERN
+void
+buf_stats_get_pool_info(
+/*====================*/
+ buf_pool_t* buf_pool, /*!< in: buffer pool */
+ ulint pool_id, /*!< in: buffer pool ID */
+ buf_pool_info_t* all_pool_info); /*!< in/out: buffer pool info
+ to fill */
/*********************************************************************//**
Returns the ratio in percents of modified pages in the buffer pool /
database pages in the buffer pool.
@@ -1364,12 +1380,25 @@ void
buf_get_total_stat(
/*===============*/
buf_pool_stat_t*tot_stat); /*!< out: buffer pool stats */
+/*********************************************************************//**
+Get the nth chunk's buffer block in the specified buffer pool.
+@return the nth chunk's buffer block. */
+UNIV_INLINE
+buf_block_t*
+buf_get_nth_chunk_block(
+/*====================*/
+ const buf_pool_t* buf_pool, /*!< in: buffer pool instance */
+ ulint n, /*!< in: nth chunk in the buffer pool */
+ ulint* chunk_size); /*!< in: chunk size */
#endif /* !UNIV_HOTBACKUP */
/** The common buffer control block structure
for compressed and uncompressed frames */
+/** Number of bits used for buffer page states. */
+#define BUF_PAGE_STATE_BITS 3
+
struct buf_page_struct{
/** @name General fields
None of these bit-fields must be modified without holding
@@ -1384,7 +1413,8 @@ struct buf_page_struct{
unsigned offset:32; /*!< page number; also protected
by buf_pool->mutex. */
- unsigned state:3; /*!< state of the control block; also
+ unsigned state:BUF_PAGE_STATE_BITS;
+ /*!< state of the control block; also
protected by buf_pool->mutex.
State transitions from
BUF_BLOCK_READY_FOR_USE to
diff --git a/storage/xtradb/include/buf0buf.ic b/storage/xtradb/include/buf0buf.ic
index 6595e86a8fe..221f86d9d62 100644
--- a/storage/xtradb/include/buf0buf.ic
+++ b/storage/xtradb/include/buf0buf.ic
@@ -36,6 +36,8 @@ Created 11/5/1995 Heikki Tuuri
#include "buf0lru.h"
#include "buf0rea.h"
#include "srv0srv.h"
+#include "buf0types.h"
+
/*********************************************************************//**
Gets the current size of buffer buf_pool in bytes.
@return size in bytes */
@@ -1354,4 +1356,21 @@ buf_pool_page_hash_x_unlock_all(void)
rw_lock_x_unlock(&buf_pool->page_hash_latch);
}
}
+/*********************************************************************//**
+Get the nth chunk's buffer block in the specified buffer pool.
+@return the nth chunk's buffer block. */
+UNIV_INLINE
+buf_block_t*
+buf_get_nth_chunk_block(
+/*====================*/
+ const buf_pool_t* buf_pool, /*!< in: buffer pool instance */
+ ulint n, /*!< in: nth chunk in the buffer pool */
+ ulint* chunk_size) /*!< in: chunk size */
+{
+ const buf_chunk_t* chunk;
+
+ chunk = buf_pool->chunks + n;
+ *chunk_size = chunk->size;
+ return(chunk->blocks);
+}
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h
index 19bf5960ae4..7da62e68e56 100644
--- a/storage/xtradb/include/fil0fil.h
+++ b/storage/xtradb/include/fil0fil.h
@@ -144,6 +144,8 @@ extern fil_addr_t fil_addr_null;
#define FIL_PAGE_TYPE_BLOB 10 /*!< Uncompressed BLOB page */
#define FIL_PAGE_TYPE_ZBLOB 11 /*!< First compressed BLOB page */
#define FIL_PAGE_TYPE_ZBLOB2 12 /*!< Subsequent compressed BLOB page */
+#define FIL_PAGE_TYPE_LAST FIL_PAGE_TYPE_ZBLOB2
+ /*!< Last page type */
/* @} */
/** Space types @{ */
diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h
index 2907365a32a..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
@@ -136,6 +136,17 @@ innobase_mysql_print_thd(
uint max_query_len); /*!< in: max query length to print, or 0 to
use the default max length */
+/*****************************************************************//**
+Log code calls this whenever log has been written and/or flushed up
+to a new position. We use this to notify upper layer of a new commit
+checkpoint when necessary.*/
+UNIV_INTERN
+void
+innobase_mysql_log_notify(
+/*===============*/
+ ib_uint64_t write_lsn, /*!< in: LSN written to log file */
+ ib_uint64_t flush_lsn); /*!< in: LSN flushed to disk */
+
/**************************************************************//**
Converts a MySQL type to an InnoDB type. Note that this function returns
the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
diff --git a/storage/xtradb/include/log0log.h b/storage/xtradb/include/log0log.h
index 96c4b81695a..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 */
@@ -151,6 +154,13 @@ UNIV_INLINE
ib_uint64_t
log_get_lsn(void);
/*=============*/
+/************************************************************//**
+Gets the last lsn that is fully flushed to disk.
+@return last flushed lsn */
+UNIV_INLINE
+ib_uint64_t
+log_get_flush_lsn(void);
+/*=============*/
/****************************************************************
Gets the log group capacity. It is OK to read the value without
holding log_sys->mutex because it is constant.
diff --git a/storage/xtradb/include/log0log.ic b/storage/xtradb/include/log0log.ic
index 67db6695cab..b54697637b0 100644
--- a/storage/xtradb/include/log0log.ic
+++ b/storage/xtradb/include/log0log.ic
@@ -411,6 +411,25 @@ log_get_lsn(void)
return(lsn);
}
+/************************************************************//**
+Gets the last lsn that is fully flushed to disk.
+@return last flushed lsn */
+UNIV_INLINE
+ib_uint64_t
+log_get_flush_lsn(void)
+/*=============*/
+{
+ ib_uint64_t lsn;
+
+ mutex_enter(&(log_sys->mutex));
+
+ lsn = log_sys->flushed_to_disk_lsn;
+
+ mutex_exit(&(log_sys->mutex));
+
+ return(lsn);
+}
+
/****************************************************************
Gets the log group capacity. It is OK to read the value without
holding log_sys->mutex because it is constant.
diff --git a/storage/xtradb/include/os0proc.h b/storage/xtradb/include/os0proc.h
index fd46bd7db87..a78b1c2a250 100644
--- a/storage/xtradb/include/os0proc.h
+++ b/storage/xtradb/include/os0proc.h
@@ -58,7 +58,8 @@ UNIV_INTERN
void*
os_mem_alloc_large(
/*===============*/
- ulint* n); /*!< in/out: number of bytes */
+ ulint* n, /*!< in/out: number of bytes */
+ ibool populate); /*!< in: virtual page preallocation */
/****************************************************************//**
Frees large pages memory. */
UNIV_INTERN
diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h
index b8820f1b7c9..a95eb8a1d58 100644
--- a/storage/xtradb/include/srv0srv.h
+++ b/storage/xtradb/include/srv0srv.h
@@ -182,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 */
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 9aee2a0c7f9..5d2cd2d0313 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -54,7 +54,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_BUGFIX 8
#ifndef PERCONA_INNODB_VERSION
-#define PERCONA_INNODB_VERSION 29.0
+#define PERCONA_INNODB_VERSION 29.1
#endif
/* The following is the InnoDB version as shown in
diff --git a/storage/xtradb/log/log0log.c b/storage/xtradb/log/log0log.c
index e3e023c0c5a..f2066b49662 100644
--- a/storage/xtradb/log/log0log.c
+++ b/storage/xtradb/log/log0log.c
@@ -1466,6 +1466,8 @@ log_write_up_to(
ulint loop_count = 0;
#endif /* UNIV_DEBUG */
ulint unlock;
+ ib_uint64_t write_lsn;
+ ib_uint64_t flush_lsn;
if (recv_no_ibuf_operations) {
/* Recovery is running and no operations on the log files are
@@ -1644,8 +1646,13 @@ loop:
log_flush_do_unlocks(unlock);
+ write_lsn = log_sys->write_lsn;
+ flush_lsn = log_sys->flushed_to_disk_lsn;
+
mutex_exit(&(log_sys->mutex));
+ innobase_mysql_log_notify(write_lsn, flush_lsn);
+
return;
do_waits:
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 dff9fc07a7f..9d479ac6c87 100644
--- a/storage/xtradb/srv/srv0srv.c
+++ b/storage/xtradb/srv/srv0srv.c
@@ -232,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 */
diff --git a/storage/xtradb/srv/srv0start.c b/storage/xtradb/srv/srv0start.c
index 7c98f74909e..65a775b56da 100644
--- a/storage/xtradb/srv/srv0start.c
+++ b/storage/xtradb/srv/srv0start.c
@@ -1543,7 +1543,8 @@ innobase_start_or_create_for_mysql(void)
((double) srv_buf_pool_size) / (1024 * 1024));
}
- err = buf_pool_init(srv_buf_pool_size, srv_buf_pool_instances);
+ err = buf_pool_init(srv_buf_pool_size, (ibool) srv_buf_pool_populate,
+ srv_buf_pool_instances);
ut_print_timestamp(stderr);
fprintf(stderr,
diff --git a/storage/xtradb/trx/trx0sys.c b/storage/xtradb/trx/trx0sys.c
index 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/strings/decimal.c b/strings/decimal.c
index 51c4457d934..f318a234d3f 100644
--- a/strings/decimal.c
+++ b/strings/decimal.c
@@ -1170,7 +1170,7 @@ int decimal2longlong(const decimal_t *from, longlong *to)
And for -1234567890.1234 it would be
- 7E F2 04 37 2D FB 2D
+ 7E F2 04 C7 2D FB 2D
*/
int decimal2bin(const decimal_t *from, uchar *to, int precision, int frac)
{
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index 10db62781ee..b45a4ade400 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -18554,6 +18554,22 @@ static void test_progress_reporting()
mysql_close(conn);
}
+/**
+ MDEV-3885 - connection suicide via mysql_kill() causes assertion in server
+*/
+
+static void test_mdev3885()
+{
+ int rc;
+ MYSQL *conn;
+
+ myheader("test_mdev3885");
+ conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
+ rc= mysql_kill(conn, mysql_thread_id(conn));
+ DIE_UNLESS(rc);
+ mysql_close(conn);
+}
+
/**
Bug#57058 SERVER_QUERY_WAS_SLOW not wired up.
@@ -19056,6 +19072,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug58036", test_bug58036 },
{ "test_bug57058", test_bug57058 },
{ "test_bug56976", test_bug56976 },
+ { "test_mdev3855", test_mdev3885 },
{ "test_bug11766854", test_bug11766854 },
{ "test_bug12337762", test_bug12337762 },
{ "test_progress_reporting", test_progress_reporting },
diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c
index 0ed315c7d97..c492770cc97 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"