summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2019-02-12 23:19:43 -0800
committerIgor Babaev <igor@askmonty.org>2019-02-12 23:19:43 -0800
commit953ca199fb62bcd190d2af4d6177f986564ec1ad (patch)
tree0ee967694db2fe959eed2f4091ab18bf722436b7
parent27c3abde3071ad2010cbcda5b07435ad15364a70 (diff)
parentbe8709eb7bdf2a68a1c04fd8ab368113f5f39b63 (diff)
downloadmariadb-git-953ca199fb62bcd190d2af4d6177f986564ec1ad.tar.gz
Merge branch '10.4' into bb-10.4-mdev17096
-rw-r--r--cmake/build_configurations/mysql_release.cmake3
-rw-r--r--cmake/wsrep.cmake20
-rw-r--r--extra/innochecksum.cc138
-rw-r--r--extra/mariabackup/fil_cur.cc32
-rw-r--r--extra/mariabackup/fil_cur.h7
-rw-r--r--extra/mariabackup/read_filt.cc2
-rw-r--r--extra/mariabackup/read_filt.h2
-rw-r--r--extra/mariabackup/write_filt.cc12
-rw-r--r--extra/mariabackup/xtrabackup.cc37
-rw-r--r--extra/mariabackup/xtrabackup.h9
-rw-r--r--libmysqld/CMakeLists.txt1
-rw-r--r--mysql-test/main/failed_auth_unixsocket.result2
-rw-r--r--mysql-test/main/failed_auth_unixsocket.test2
-rw-r--r--mysql-test/main/information_schema.result3
-rw-r--r--mysql-test/main/information_schema_all_engines.result8
-rw-r--r--mysql-test/main/mysql_upgrade-6984.result2
-rw-r--r--mysql-test/main/mysql_upgrade-6984.test2
-rw-r--r--mysql-test/main/mysqld--help.result8
-rw-r--r--mysql-test/main/opt_trace.result3499
-rw-r--r--mysql-test/main/opt_trace.test335
-rw-r--r--mysql-test/main/opt_trace_index_merge.result249
-rw-r--r--mysql-test/main/opt_trace_index_merge.test21
-rw-r--r--mysql-test/main/opt_trace_index_merge_innodb.result242
-rw-r--r--mysql-test/main/opt_trace_index_merge_innodb.test31
-rw-r--r--mysql-test/main/opt_trace_security.result396
-rw-r--r--mysql-test/main/opt_trace_security.test197
-rw-r--r--mysql-test/main/type_timestamp.result9
-rw-r--r--mysql-test/main/type_timestamp.test8
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_is.result8
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_is_embedded.result8
-rw-r--r--mysql-test/suite/funcs_1/r/is_tables_is.result50
-rw-r--r--mysql-test/suite/funcs_1/r/is_tables_is_embedded.result50
-rw-r--r--mysql-test/suite/galera/disabled.def1
-rw-r--r--mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result2
-rw-r--r--mysql-test/suite/galera/r/galera_sst_rsync2.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_load_data_splitting.result4
-rw-r--r--mysql-test/suite/galera/t/galera_sst_mysqldump.cnf2
-rw-r--r--mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result1
-rw-r--r--mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test2
-rw-r--r--mysql-test/suite/innodb/r/alter_varchar_change.result18
-rw-r--r--mysql-test/suite/innodb/r/instant_alter_bugs.result47
-rw-r--r--mysql-test/suite/innodb/r/instant_alter_import.result72
-rw-r--r--mysql-test/suite/innodb/t/alter_varchar_change.test18
-rw-r--r--mysql-test/suite/innodb/t/instant_alter_bugs.test49
-rw-r--r--mysql-test/suite/innodb/t/instant_alter_import.test84
-rw-r--r--mysql-test/suite/roles/i_s_applicable_roles_is_default.result2
-rw-r--r--mysql-test/suite/roles/i_s_applicable_roles_is_default.test2
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff319
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_server_embedded.result28
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff339
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result28
-rw-r--r--mysys/my_fopen.c5
-rw-r--r--plugin/user_variables/mysql-test/user_variables/basic.result2
-rw-r--r--plugin/user_variables/user_variables.cc2
-rw-r--r--scripts/mysql_install_db.sh29
-rw-r--r--scripts/mysql_secure_installation.sh59
-rw-r--r--scripts/mysql_system_tables_data.sql9
-rw-r--r--scripts/wsrep_sst_mariabackup.sh4
-rw-r--r--scripts/wsrep_sst_rsync.sh23
-rw-r--r--sql/CMakeLists.txt1
-rw-r--r--sql/ha_sequence.cc2
-rw-r--r--sql/handler.h1
-rw-r--r--sql/my_json_writer.cc75
-rw-r--r--sql/my_json_writer.h425
-rw-r--r--sql/mysqld.cc9
-rw-r--r--sql/mysqld.h3
-rw-r--r--sql/opt_range.cc845
-rw-r--r--sql/opt_range.h2
-rw-r--r--sql/opt_subselect.cc66
-rw-r--r--sql/opt_table_elimination.cc30
-rw-r--r--sql/opt_trace.cc722
-rw-r--r--sql/opt_trace.h201
-rw-r--r--sql/opt_trace_context.h92
-rw-r--r--sql/set_var.h9
-rw-r--r--sql/sp_head.cc13
-rw-r--r--sql/sp_head.h1
-rw-r--r--sql/sql_class.cc14
-rw-r--r--sql/sql_class.h15
-rw-r--r--sql/sql_derived.cc49
-rw-r--r--sql/sql_explain.cc2
-rw-r--r--sql/sql_parse.cc13
-rw-r--r--sql/sql_parse.h2
-rw-r--r--sql/sql_prepare.cc12
-rw-r--r--sql/sql_select.cc632
-rw-r--r--sql/sql_show.cc7
-rw-r--r--sql/sql_test.cc27
-rw-r--r--sql/sql_test.h2
-rw-r--r--sql/sql_type.h8
-rw-r--r--sql/sql_view.cc10
-rw-r--r--sql/sys_vars.cc18
-rw-r--r--sql/table.cc2
-rw-r--r--sql/wsrep_mysqld.cc15
-rw-r--r--sql/wsrep_server_state.cc1
-rw-r--r--sql/wsrep_sst.cc17
-rw-r--r--storage/innobase/btr/btr0btr.cc115
-rw-r--r--storage/innobase/btr/btr0bulk.cc13
-rw-r--r--storage/innobase/btr/btr0cur.cc179
-rw-r--r--storage/innobase/btr/btr0defragment.cc18
-rw-r--r--storage/innobase/btr/btr0pcur.cc2
-rw-r--r--storage/innobase/btr/btr0scrub.cc22
-rw-r--r--storage/innobase/btr/btr0sea.cc2
-rw-r--r--storage/innobase/buf/buf0buf.cc166
-rw-r--r--storage/innobase/buf/buf0dblwr.cc82
-rw-r--r--storage/innobase/buf/buf0dump.cc8
-rw-r--r--storage/innobase/buf/buf0flu.cc11
-rw-r--r--storage/innobase/buf/buf0lru.cc68
-rw-r--r--storage/innobase/buf/buf0rea.cc99
-rw-r--r--storage/innobase/data/data0data.cc8
-rw-r--r--storage/innobase/dict/dict0boot.cc2
-rw-r--r--storage/innobase/dict/dict0crea.cc24
-rw-r--r--storage/innobase/dict/dict0dict.cc56
-rw-r--r--storage/innobase/dict/dict0stats.cc4
-rw-r--r--storage/innobase/fil/fil0crypt.cc103
-rw-r--r--storage/innobase/fil/fil0fil.cc140
-rw-r--r--storage/innobase/fil/fil0pagecompress.cc3
-rw-r--r--storage/innobase/fsp/fsp0file.cc43
-rw-r--r--storage/innobase/fsp/fsp0fsp.cc441
-rw-r--r--storage/innobase/fts/fts0fts.cc4
-rw-r--r--storage/innobase/fts/fts0que.cc8
-rw-r--r--storage/innobase/fut/fut0lst.cc64
-rw-r--r--storage/innobase/gis/gis0rtree.cc8
-rw-r--r--storage/innobase/gis/gis0sea.cc11
-rw-r--r--storage/innobase/handler/ha_innodb.cc81
-rw-r--r--storage/innobase/handler/handler0alter.cc41
-rw-r--r--storage/innobase/handler/i_s.cc13
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc346
-rw-r--r--storage/innobase/include/btr0btr.h57
-rw-r--r--storage/innobase/include/btr0btr.ic14
-rw-r--r--storage/innobase/include/btr0cur.h16
-rw-r--r--storage/innobase/include/btr0types.h10
-rw-r--r--storage/innobase/include/buf0buf.h56
-rw-r--r--storage/innobase/include/buf0rea.h37
-rw-r--r--storage/innobase/include/dict0dict.h34
-rw-r--r--storage/innobase/include/dict0dict.ic22
-rw-r--r--storage/innobase/include/fil0crypt.h41
-rw-r--r--storage/innobase/include/fil0fil.h59
-rw-r--r--storage/innobase/include/fsp0fsp.h106
-rw-r--r--storage/innobase/include/fsp0fsp.ic69
-rw-r--r--storage/innobase/include/fut0fut.h28
-rw-r--r--storage/innobase/include/fut0fut.ic68
-rw-r--r--storage/innobase/include/ibuf0ibuf.h75
-rw-r--r--storage/innobase/include/ibuf0ibuf.ic49
-rw-r--r--storage/innobase/include/mem0mem.ic4
-rw-r--r--storage/innobase/include/mtr0types.h9
-rw-r--r--storage/innobase/include/os0file.h2
-rw-r--r--storage/innobase/include/page0size.h197
-rw-r--r--storage/innobase/include/page0zip.h15
-rw-r--r--storage/innobase/include/page0zip.ic21
-rw-r--r--storage/innobase/include/row0ext.h9
-rw-r--r--storage/innobase/include/trx0rseg.ic5
-rw-r--r--storage/innobase/include/trx0sys.h2
-rw-r--r--storage/innobase/include/trx0undo.ic8
-rw-r--r--storage/innobase/lock/lock0lock.cc2
-rw-r--r--storage/innobase/log/log0log.cc8
-rw-r--r--storage/innobase/log/log0recv.cc32
-rw-r--r--storage/innobase/mtr/mtr0mtr.cc2
-rw-r--r--storage/innobase/os/os0file.cc2
-rw-r--r--storage/innobase/page/page0zip.cc17
-rw-r--r--storage/innobase/rem/rem0rec.cc8
-rw-r--r--storage/innobase/row/row0ext.cc32
-rw-r--r--storage/innobase/row/row0ftsort.cc4
-rw-r--r--storage/innobase/row/row0import.cc119
-rw-r--r--storage/innobase/row/row0log.cc18
-rw-r--r--storage/innobase/row/row0merge.cc17
-rw-r--r--storage/innobase/row/row0mysql.cc12
-rw-r--r--storage/innobase/row/row0purge.cc2
-rw-r--r--storage/innobase/row/row0row.cc4
-rw-r--r--storage/innobase/row/row0sel.cc16
-rw-r--r--storage/innobase/row/row0upd.cc39
-rw-r--r--storage/innobase/srv/srv0srv.cc2
-rw-r--r--storage/innobase/srv/srv0start.cc13
-rw-r--r--storage/innobase/trx/trx0rec.cc34
-rw-r--r--storage/innobase/trx/trx0rseg.cc20
-rw-r--r--storage/innobase/trx/trx0undo.cc8
m---------wsrep-lib0
175 files changed, 10543 insertions, 2955 deletions
diff --git a/cmake/build_configurations/mysql_release.cmake b/cmake/build_configurations/mysql_release.cmake
index 105855a0bd1..4b399a131f5 100644
--- a/cmake/build_configurations/mysql_release.cmake
+++ b/cmake/build_configurations/mysql_release.cmake
@@ -98,17 +98,20 @@ ELSEIF(RPM)
SET(CHECKMODULE /usr/bin/checkmodule CACHE STRING "")
SET(SEMODULE_PACKAGE /usr/bin/semodule_package CACHE STRING "")
SET(WITH_LIBARCHIVE ON CACHE STRING "")
+ SET(PLUGIN_AUTH_SOCKET YES)
ELSEIF(DEB)
SET(WITH_SSL system CACHE STRING "")
SET(WITH_ZLIB system CACHE STRING "")
SET(WITH_LIBWRAP ON)
SET(HAVE_EMBEDDED_PRIVILEGE_CONTROL ON)
SET(WITH_LIBARCHIVE ON CACHE STRING "")
+ SET(PLUGIN_AUTH_SOCKET YES)
ELSE()
SET(WITH_SSL bundled CACHE STRING "")
SET(WITH_ZLIB bundled CACHE STRING "")
SET(WITH_JEMALLOC static CACHE STRING "")
SET(WITH_LIBARCHIVE STATIC CACHE STRING "")
+ SET(PLUGIN_AUTH_SOCKET STATIC)
ENDIF()
IF(NOT COMPILATION_COMMENT)
diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake
index 44e00649993..37ed0c78cf5 100644
--- a/cmake/wsrep.cmake
+++ b/cmake/wsrep.cmake
@@ -28,20 +28,20 @@ OPTION(WITH_WSREP_ALL
"Build all components of WSREP (unit tests, sample programs)"
OFF)
-# Set the patch version
-SET(WSREP_PATCH_VERSION "22")
+IF(WITH_WSREP)
+ # Set the patch version
+ SET(WSREP_PATCH_VERSION "22")
-# Obtain wsrep API version
-FILE(STRINGS "${CMAKE_SOURCE_DIR}/wsrep-lib/wsrep-API/v26/wsrep_api.h" WSREP_API_VERSION
- LIMIT_COUNT 1 REGEX "WSREP_INTERFACE_VERSION")
-STRING(REGEX MATCH "([0-9]+)" WSREP_API_VERSION "${WSREP_API_VERSION}")
+ # Obtain wsrep API version
+ FILE(STRINGS "${CMAKE_SOURCE_DIR}/wsrep-lib/wsrep-API/v26/wsrep_api.h" WSREP_API_VERSION
+ LIMIT_COUNT 1 REGEX "WSREP_INTERFACE_VERSION")
+ STRING(REGEX MATCH "([0-9]+)" WSREP_API_VERSION "${WSREP_API_VERSION}")
-SET(WSREP_VERSION "${WSREP_API_VERSION}.${WSREP_PATCH_VERSION}"
- CACHE INTERNAL "WSREP version")
+ SET(WSREP_VERSION "${WSREP_API_VERSION}.${WSREP_PATCH_VERSION}"
+ CACHE INTERNAL "WSREP version")
-SET(WSREP_PROC_INFO ${WITH_WSREP})
+ SET(WSREP_PROC_INFO ${WITH_WSREP})
-IF(WITH_WSREP)
SET(WSREP_PATCH_VERSION "wsrep_${WSREP_VERSION}")
if (NOT WITH_WSREP_ALL)
SET(WSREP_LIB_WITH_UNIT_TESTS OFF CACHE BOOL
diff --git a/extra/innochecksum.cc b/extra/innochecksum.cc
index de640a17765..31826981ba3 100644
--- a/extra/innochecksum.cc
+++ b/extra/innochecksum.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
- Copyright (c) 2014, 2018, MariaDB Corporation.
+ Copyright (c) 2014, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -71,10 +71,8 @@ static my_bool per_page_details;
static ulint n_merge;
extern ulong srv_checksum_algorithm;
static ulint physical_page_size; /* Page size in bytes on disk. */
-static ulint logical_page_size; /* Page size when uncompressed. */
ulong srv_page_size;
ulong srv_page_size_shift;
-page_size_t univ_page_size(0, 0, false);
/* Current page number (0 based). */
unsigned long long cur_page_num;
/* Skip the checksum verification. */
@@ -276,13 +274,11 @@ void print_leaf_stats(
}
}
-/** Get the page size of the filespace from the filespace header.
+/** Get the ROW_FORMAT=COMPRESSED size from the filespace header.
@param[in] buf buffer used to read the page.
-@return page size */
-static
-const page_size_t
-get_page_size(
- byte* buf)
+@return ROW_FORMAT_COMPRESSED page size
+@retval 0 if not ROW_FORMAT=COMPRESSED */
+static ulint get_zip_size(const byte* buf)
{
const unsigned flags = mach_read_from_4(buf + FIL_PAGE_DATA
+ FSP_SPACE_FLAGS);
@@ -294,11 +290,14 @@ get_page_size(
: UNIV_PAGE_SIZE_SHIFT_ORIG;
srv_page_size = 1U << srv_page_size_shift;
-
- univ_page_size.copy_from(
- page_size_t(srv_page_size, srv_page_size, false));
-
- return(page_size_t(flags));
+ ulint zip_size = FSP_FLAGS_GET_ZIP_SSIZE(flags);
+ if (zip_size) {
+ zip_size = (UNIV_ZIP_SIZE_MIN >> 1) << zip_size;
+ physical_page_size = zip_size;
+ } else {
+ physical_page_size = srv_page_size;
+ }
+ return zip_size;
}
#ifdef _WIN32
@@ -430,7 +429,7 @@ ulint read_file(
/** Check if page is corrupted or not.
@param[in] buf page frame
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] is_encrypted true if page0 contained cryp_data
with crypt_scheme encrypted
@param[in] is_compressed true if page0 fsp_flags contained
@@ -440,7 +439,7 @@ static
bool
is_page_corrupted(
byte* buf,
- const page_size_t& page_size,
+ ulint zip_size,
bool is_encrypted,
bool is_compressed)
{
@@ -465,12 +464,12 @@ is_page_corrupted(
return (false);
}
- if (page_size.is_compressed()) {
+ if (!zip_size) {
/* check the stored log sequence numbers
for uncompressed tablespace. */
logseq = mach_read_from_4(buf + FIL_PAGE_LSN + 4);
logseqfield = mach_read_from_4(
- buf + page_size.logical() -
+ buf + srv_page_size -
FIL_PAGE_END_LSN_OLD_CHKSUM + 4);
if (is_log_enabled) {
@@ -499,8 +498,7 @@ is_page_corrupted(
so if crypt checksum does not match we verify checksum using
normal method. */
if (is_encrypted && key_version != 0) {
- is_corrupted = !fil_space_verify_crypt_checksum(buf,
- page_size);
+ is_corrupted = !fil_space_verify_crypt_checksum(buf, zip_size);
if (is_corrupted && log_file) {
fprintf(log_file,
"Page " ULINTPF ":%llu may be corrupted;"
@@ -516,7 +514,7 @@ is_page_corrupted(
if (is_corrupted) {
is_corrupted = buf_page_is_corrupted(
- true, buf, page_size, NULL);
+ true, buf, zip_size, NULL);
}
return(is_corrupted);
@@ -568,7 +566,6 @@ is_page_empty(
/********************************************************************//**
Rewrite the checksum for the page.
@param [in/out] page page buffer
-@param [in] physical_page_size page size in bytes on disk.
@param [in] iscompressed Is compressed/Uncompressed Page.
@retval true : do rewrite
@@ -579,7 +576,6 @@ Rewrite the checksum for the page.
bool
update_checksum(
byte* page,
- ulong physical_page_size,
bool iscompressed)
{
ib_uint32_t checksum = 0;
@@ -696,7 +692,6 @@ func_exit:
@param[in] compressed Enabled if tablespace is
compressed.
@param[in,out] pos current file position.
-@param[in] page_size page size in bytes on disk.
@retval true if successfully written
@retval false if a non-recoverable error occurred
@@ -708,12 +703,11 @@ write_file(
FILE* file,
byte* buf,
bool compressed,
- fpos_t* pos,
- ulong page_size)
+ fpos_t* pos)
{
bool do_update;
- do_update = update_checksum(buf, page_size, compressed);
+ do_update = update_checksum(buf, compressed);
if (file != stdin) {
if (do_update) {
@@ -733,8 +727,9 @@ write_file(
}
}
- if (page_size
- != fwrite(buf, 1, page_size, file == stdin ? stdout : file)) {
+ if (physical_page_size
+ != fwrite(buf, 1, physical_page_size,
+ file == stdin ? stdout : file)) {
fprintf(stderr, "Failed to write page::%llu to %s: %s\n",
cur_page_num, filename, strerror(errno));
@@ -757,7 +752,6 @@ Parse the page and collect/dump the information about page type
@param [in] page buffer page
@param [out] xdes extend descriptor page
@param [in] file file for diagnosis.
-@param [in] page_size page_size
@param [in] is_encrypted tablespace is encrypted
*/
void
@@ -765,7 +759,6 @@ parse_page(
const byte* page,
byte* xdes,
FILE* file,
- const page_size_t& page_size,
bool is_encrypted)
{
unsigned long long id;
@@ -824,8 +817,7 @@ parse_page(
}
size_range_id = (data_bytes * SIZE_RANGES_FOR_PAGE
- + page_size.logical() - 1) /
- page_size.logical();
+ + srv_page_size - 1) / srv_page_size;
if (size_range_id > SIZE_RANGES_FOR_PAGE + 1) {
/* data_bytes is bigger than logical_page_size */
@@ -844,7 +836,7 @@ parse_page(
it = index_ids.find(id);
per_index_stats &index = (it->second);
const byte* des = xdes + XDES_ARR_OFFSET
- + XDES_SIZE * ((page_no & (page_size.physical() - 1))
+ + XDES_SIZE * ((page_no & (physical_page_size - 1))
/ FSP_EXTENT_SIZE);
if (xdes_get_bit(des, XDES_FREE_BIT,
page_no % FSP_EXTENT_SIZE)) {
@@ -1007,7 +999,7 @@ parse_page(
case FIL_PAGE_TYPE_FSP_HDR:
page_type.n_fil_page_type_fsp_hdr++;
- memcpy(xdes, page, page_size.physical());
+ memcpy(xdes, page, physical_page_size);
if (page_type_dump) {
fprintf(file, "#::%llu\t\t|\t\tFile Space "
"Header\t\t|\t%s\n", cur_page_num, str);
@@ -1016,7 +1008,7 @@ parse_page(
case FIL_PAGE_TYPE_XDES:
page_type.n_fil_page_type_xdes++;
- memcpy(xdes, page, page_size.physical());
+ memcpy(xdes, page, physical_page_size);
if (page_type_dump) {
fprintf(file, "#::%llu\t\t|\t\tExtent descriptor "
"page\t\t|\t%s\n", cur_page_num, str);
@@ -1384,18 +1376,13 @@ get_options(
/** Check from page 0 if table is encrypted.
@param[in] filename Filename
-@param[in] page_size page size
@param[in] page Page 0
@retval true if tablespace is encrypted, false if not
*/
-static
-bool check_encryption(
- const char* filename,
- const page_size_t& page_size,
- byte * page)
+static bool check_encryption(const char* filename, const byte* page)
{
- ulint offset = (FSP_HEADER_OFFSET + (XDES_ARR_OFFSET + XDES_SIZE *
- (page_size.physical()) / FSP_EXTENT_SIZE));
+ ulint offset = FSP_HEADER_OFFSET + XDES_ARR_OFFSET + XDES_SIZE *
+ physical_page_size / FSP_EXTENT_SIZE;
if (memcmp(page + offset, CRYPT_MAGIC, MAGIC_SZ) != 0) {
return false;
@@ -1431,7 +1418,7 @@ bool check_encryption(
/**
Verify page checksum.
@param[in] buf page to verify
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] is_encrypted true if tablespace is encrypted
@param[in] is_compressed true if tablespace is page compressed
@param[in,out] mismatch_count Number of pages failed in checksum verify
@@ -1440,7 +1427,7 @@ Verify page checksum.
static
int verify_checksum(
byte* buf,
- const page_size_t& page_size,
+ ulint zip_size,
bool is_encrypted,
bool is_compressed,
unsigned long long* mismatch_count)
@@ -1449,7 +1436,7 @@ int verify_checksum(
bool is_corrupted = false;
is_corrupted = is_page_corrupted(
- buf, page_size, is_encrypted, is_compressed);
+ buf, zip_size, is_encrypted, is_compressed);
if (is_corrupted) {
fprintf(stderr, "Fail: page::%llu invalid\n",
@@ -1477,7 +1464,7 @@ int verify_checksum(
@param[in] filename File name
@param[in] fil_in File pointer
@param[in] buf page
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] pos File position
@param[in] is_encrypted true if tablespace is encrypted
@param[in] is_compressed true if tablespace is page compressed
@@ -1488,7 +1475,7 @@ rewrite_checksum(
const char* filename,
FILE* fil_in,
byte* buf,
- const page_size_t& page_size,
+ ulint zip_size,
fpos_t* pos,
bool is_encrypted,
bool is_compressed)
@@ -1500,8 +1487,7 @@ rewrite_checksum(
!is_encrypted &&
!is_compressed
&& !write_file(filename, fil_in, buf,
- page_size.is_compressed(), pos,
- static_cast<ulong>(page_size.physical()))) {
+ zip_size, pos)) {
exit_status = 1;
}
@@ -1682,22 +1668,19 @@ int main(
/* Determine page size, zip_size and page compression
from fsp_flags and encryption metadata from page 0 */
- const page_size_t& page_size = get_page_size(buf);
+ ulint zip_size = get_zip_size(buf);
ulint flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + buf);
- ulint zip_size = page_size.is_compressed() ? page_size.logical() : 0;
- logical_page_size = page_size.is_compressed() ? zip_size : 0;
- physical_page_size = page_size.physical();
bool is_compressed = FSP_FLAGS_HAS_PAGE_COMPRESSION(flags);
- if (page_size.physical() > UNIV_ZIP_SIZE_MIN) {
+ if (physical_page_size > UNIV_ZIP_SIZE_MIN) {
/* Read rest of the page 0 to determine crypt_data */
- bytes = read_file(buf, partial_page_read, page_size.physical(), fil_in);
- if (bytes != page_size.physical()) {
+ bytes = read_file(buf, partial_page_read, physical_page_size, fil_in);
+ if (bytes != physical_page_size) {
fprintf(stderr, "Error: Was not able to read the "
"rest of the page ");
fprintf(stderr, "of " ULINTPF " bytes. Bytes read was " ULINTPF "\n",
- page_size.physical() - UNIV_ZIP_SIZE_MIN, bytes);
+ physical_page_size - UNIV_ZIP_SIZE_MIN, bytes);
exit_status = 1;
goto my_exit;
@@ -1706,7 +1689,7 @@ int main(
}
/* Now that we have full page 0 in buffer, check encryption */
- bool is_encrypted = check_encryption(filename, page_size, buf);
+ bool is_encrypted = check_encryption(filename, buf);
/* Verify page 0 contents. Note that we can't allow
checksum mismatch on page 0, because that would mean we
@@ -1715,7 +1698,7 @@ int main(
unsigned long long tmp_allow_mismatches = allow_mismatches;
allow_mismatches = 0;
- exit_status = verify_checksum(buf, page_size, is_encrypted, is_compressed, &mismatch_count);
+ exit_status = verify_checksum(buf, zip_size, is_encrypted, is_compressed, &mismatch_count);
if (exit_status) {
fprintf(stderr, "Error: Page 0 checksum mismatch, can't continue. \n");
@@ -1725,7 +1708,7 @@ int main(
}
if ((exit_status = rewrite_checksum(filename, fil_in, buf,
- page_size, &pos, is_encrypted, is_compressed))) {
+ zip_size, &pos, is_encrypted, is_compressed))) {
goto my_exit;
}
@@ -1748,10 +1731,10 @@ int main(
}
if (page_type_summary || page_type_dump) {
- parse_page(buf, xdes, fil_page_type, page_size, is_encrypted);
+ parse_page(buf, xdes, fil_page_type, is_encrypted);
}
- pages = (ulint) (size / page_size.physical());
+ pages = (ulint) (size / physical_page_size);
if (just_count) {
if (read_from_stdin) {
@@ -1788,12 +1771,9 @@ int main(
partial_page_read = false;
offset = (off_t) start_page
- * (off_t) page_size.physical();
-#ifdef _WIN32
- if (_fseeki64(fil_in, offset, SEEK_SET)) {
-#else
- if (fseeko(fil_in, offset, SEEK_SET)) {
-#endif /* _WIN32 */
+ * (off_t) physical_page_size;
+ if (IF_WIN(_fseeki64,fseeko)(fil_in, offset,
+ SEEK_SET)) {
perror("Error: Unable to seek to "
"necessary offset");
@@ -1825,8 +1805,7 @@ int main(
if partial_page_read is enable. */
bytes = read_file(buf,
partial_page_read,
- static_cast<ulong>(
- page_size.physical()),
+ physical_page_size,
fil_in);
partial_page_read = false;
@@ -1851,8 +1830,7 @@ int main(
while (!feof(fil_in)) {
bytes = read_file(buf, partial_page_read,
- static_cast<ulong>(
- page_size.physical()), fil_in);
+ physical_page_size, fil_in);
partial_page_read = false;
if (!bytes && feof(fil_in)) {
@@ -1861,17 +1839,17 @@ int main(
if (ferror(fil_in)) {
fprintf(stderr, "Error reading " ULINTPF " bytes",
- page_size.physical());
+ physical_page_size);
perror(" ");
exit_status = 1;
goto my_exit;
}
- if (bytes != page_size.physical()) {
+ if (bytes != physical_page_size) {
fprintf(stderr, "Error: bytes read (" ULINTPF ") "
"doesn't match page size (" ULINTPF ")\n",
- bytes, page_size.physical());
+ bytes, physical_page_size);
exit_status = 1;
goto my_exit;
}
@@ -1896,13 +1874,13 @@ int main(
checksum verification.*/
if (!no_check
&& !skip_page
- && (exit_status = verify_checksum(buf, page_size,
+ && (exit_status = verify_checksum(buf, zip_size,
is_encrypted, is_compressed, &mismatch_count))) {
goto my_exit;
}
if ((exit_status = rewrite_checksum(filename, fil_in, buf,
- page_size, &pos, is_encrypted, is_compressed))) {
+ zip_size, &pos, is_encrypted, is_compressed))) {
goto my_exit;
}
@@ -1916,7 +1894,7 @@ int main(
}
if (page_type_summary || page_type_dump) {
- parse_page(buf, xdes, fil_page_type, page_size, is_encrypted);
+ parse_page(buf, xdes, fil_page_type, is_encrypted);
}
/* do counter increase and progress printing */
diff --git a/extra/mariabackup/fil_cur.cc b/extra/mariabackup/fil_cur.cc
index f40304c07d7..04bf2b1f64d 100644
--- a/extra/mariabackup/fil_cur.cc
+++ b/extra/mariabackup/fil_cur.cc
@@ -231,11 +231,11 @@ xb_fil_cur_open(
posix_fadvise(cursor->file, 0, 0, POSIX_FADV_SEQUENTIAL);
- const page_size_t page_size(node->space->flags);
- cursor->page_size = page_size;
+ cursor->page_size = node->space->physical_size();
+ cursor->zip_size = node->space->zip_size();
/* Allocate read buffer */
- cursor->buf_size = XB_FIL_CUR_PAGES * page_size.physical();
+ cursor->buf_size = XB_FIL_CUR_PAGES * cursor->page_size;
cursor->orig_buf = static_cast<byte *>
(malloc(cursor->buf_size + srv_page_size));
cursor->buf = static_cast<byte *>
@@ -250,18 +250,17 @@ xb_fil_cur_open(
if (!node->space->crypt_data
&& os_file_read(IORequestRead,
node->handle, cursor->buf, 0,
- page_size.physical())) {
+ cursor->page_size)) {
mutex_enter(&fil_system.mutex);
if (!node->space->crypt_data) {
- node->space->crypt_data
- = fil_space_read_crypt_data(page_size,
- cursor->buf);
+ node->space->crypt_data = fil_space_read_crypt_data(
+ node->space->zip_size(), cursor->buf);
}
mutex_exit(&fil_system.mutex);
}
cursor->space_size = (ulint)(cursor->statinfo.st_size
- / page_size.physical());
+ / cursor->page_size);
cursor->read_filter = read_filter;
cursor->read_filter->init(&cursor->read_filter_ctxt, cursor,
@@ -276,7 +275,7 @@ static bool page_is_corrupted(const byte *page, ulint page_no,
{
byte tmp_frame[UNIV_PAGE_SIZE_MAX];
byte tmp_page[UNIV_PAGE_SIZE_MAX];
- const ulint page_size = cursor->page_size.physical();
+ const ulint page_size = cursor->page_size;
ulint page_type = mach_read_from_2(page + FIL_PAGE_TYPE);
/* We ignore the doublewrite buffer pages.*/
@@ -325,7 +324,7 @@ static bool page_is_corrupted(const byte *page, ulint page_no,
|| (space->crypt_data
&& space->crypt_data->type != CRYPT_SCHEME_UNENCRYPTED))) {
- if (!fil_space_verify_crypt_checksum(page, cursor->page_size))
+ if (!fil_space_verify_crypt_checksum(page, space->zip_size()))
return true;
/* Compressed encrypted need to be decrypted
@@ -345,8 +344,7 @@ static bool page_is_corrupted(const byte *page, ulint page_no,
}
if (page_type != FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED) {
- return buf_page_is_corrupted(true, tmp_page,
- cursor->page_size, space);
+ return buf_page_is_corrupted(true, tmp_page, 0, space);
}
}
@@ -361,14 +359,14 @@ static bool page_is_corrupted(const byte *page, ulint page_no,
return (!decomp
|| (decomp != srv_page_size
- && cursor->page_size.is_compressed())
+ && cursor->zip_size)
|| page_type == FIL_PAGE_PAGE_COMPRESSED
|| page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED
|| buf_page_is_corrupted(true, tmp_page,
- cursor->page_size, space));
+ space->zip_size(), space));
}
- return buf_page_is_corrupted(true, page, cursor->page_size, space);
+ return buf_page_is_corrupted(true, page, space->zip_size(), space);
}
/************************************************************************
@@ -389,7 +387,7 @@ xb_fil_cur_read(
xb_fil_cur_result_t ret;
ib_int64_t offset;
ib_int64_t to_read;
- const ulint page_size = cursor->page_size.physical();
+ const ulint page_size = cursor->page_size;
xb_ad(!cursor->is_system() || page_size == srv_page_size);
cursor->read_filter->get_next_batch(&cursor->read_filter_ctxt,
@@ -459,7 +457,7 @@ read_retry:
"10 retries. File %s seems to be "
"corrupted.", cursor->abs_path);
ret = XB_FIL_CUR_ERROR;
- buf_page_print(page, cursor->page_size);
+ ut_print_buf(stderr, page, page_size);
break;
}
msg(cursor->thread_n, "Database page corruption detected at page "
diff --git a/extra/mariabackup/fil_cur.h b/extra/mariabackup/fil_cur.h
index ad023d93208..193c51d6c43 100644
--- a/extra/mariabackup/fil_cur.h
+++ b/extra/mariabackup/fil_cur.h
@@ -38,7 +38,9 @@ struct xb_fil_cur_t {
char abs_path[FN_REFLEN];
/*!< absolute file path */
MY_STAT statinfo; /*!< information about the file */
- page_size_t page_size; /*!< page size */
+ ulint zip_size; /*!< compressed page size in bytes or 0
+ for uncompressed pages */
+ ulint page_size; /*!< physical page size */
xb_read_filt_t* read_filter; /*!< read filter */
xb_read_filt_ctxt_t read_filter_ctxt;
/*!< read filter context */
@@ -57,9 +59,6 @@ struct xb_fil_cur_t {
ulint space_id; /*!< ID of tablespace */
ulint space_size; /*!< space size in pages */
- /** TODO: remove this default constructor */
- xb_fil_cur_t() : page_size(0), read_filter(0), read_filter_ctxt() {}
-
/** @return whether this is not a file-per-table tablespace */
bool is_system() const
{
diff --git a/extra/mariabackup/read_filt.cc b/extra/mariabackup/read_filt.cc
index a48591abf29..055056245ba 100644
--- a/extra/mariabackup/read_filt.cc
+++ b/extra/mariabackup/read_filt.cc
@@ -127,7 +127,7 @@ rf_bitmap_get_next_batch(
of pages */
{
ulint start_page_id;
- const ulint page_size = ctxt->page_size.physical();
+ const ulint page_size = ctxt->page_size;
start_page_id = (ulint)(ctxt->offset / page_size);
diff --git a/extra/mariabackup/read_filt.h b/extra/mariabackup/read_filt.h
index cebc714eed8..585662c7f9c 100644
--- a/extra/mariabackup/read_filt.h
+++ b/extra/mariabackup/read_filt.h
@@ -41,7 +41,7 @@ struct xb_read_filt_ctxt_t {
/* Move these to union if any other filters are added in future */
xb_page_bitmap_range *bitmap_range; /*!< changed page bitmap range
iterator for space_id */
- page_size_t page_size; /*!< page size */
+ ulint page_size; /*!< page size */
ulint filter_batch_end;/*!< the ending page id of the
current changed page block in
the bitmap */
diff --git a/extra/mariabackup/write_filt.cc b/extra/mariabackup/write_filt.cc
index 63b11850bfb..3332159f99b 100644
--- a/extra/mariabackup/write_filt.cc
+++ b/extra/mariabackup/write_filt.cc
@@ -75,8 +75,7 @@ wf_incremental_init(xb_write_filt_ctxt_t *ctxt, char *dst_name,
ctxt->cursor = cursor;
/* allocate buffer for incremental backup (4096 pages) */
- cp->delta_buf_size = (cursor->page_size.physical() / 4)
- * cursor->page_size.physical();
+ cp->delta_buf_size = (cursor->page_size / 4) * cursor->page_size;
cp->delta_buf = (unsigned char *)os_mem_alloc_large(&cp->delta_buf_size);
if (!cp->delta_buf) {
@@ -88,7 +87,8 @@ wf_incremental_init(xb_write_filt_ctxt_t *ctxt, char *dst_name,
/* write delta meta info */
snprintf(meta_name, sizeof(meta_name), "%s%s", dst_name,
XB_DELTA_INFO_SUFFIX);
- const xb_delta_info_t info(cursor->page_size, cursor->space_id);
+ const xb_delta_info_t info(cursor->page_size, cursor->zip_size,
+ cursor->space_id);
if (!xb_write_delta_metadata(meta_name, &info)) {
msg(cursor->thread_n,"Error: "
"failed to write meta info for %s",
@@ -116,8 +116,7 @@ wf_incremental_process(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile)
ulint i;
xb_fil_cur_t *cursor = ctxt->cursor;
byte *page;
- const ulint page_size
- = cursor->page_size.physical();
+ const ulint page_size = cursor->page_size;
xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt);
for (i = 0, page = cursor->buf; i < cursor->buf_npages;
@@ -162,8 +161,7 @@ static my_bool
wf_incremental_finalize(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile)
{
xb_fil_cur_t *cursor = ctxt->cursor;
- const ulint page_size
- = cursor->page_size.physical();
+ const ulint page_size = cursor->page_size;
xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt);
if (cp->npages != page_size / 4) {
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc
index 009a4891d93..8a107a408eb 100644
--- a/extra/mariabackup/xtrabackup.cc
+++ b/extra/mariabackup/xtrabackup.cc
@@ -1861,11 +1861,6 @@ static bool innodb_init_param()
msg("innodb_data_file_path = %s",
innobase_data_file_path);
- /* This is the first time univ_page_size is used.
- It was initialized to 16k pages before srv_page_size was set */
- univ_page_size.copy_from(
- page_size_t(srv_page_size, srv_page_size, false));
-
srv_sys_space.set_space_id(TRX_SYS_SPACE);
srv_sys_space.set_name("innodb_system");
srv_sys_space.set_path(srv_data_home);
@@ -2173,8 +2168,7 @@ xb_read_delta_metadata(const char *filepath, xb_delta_info_t *info)
msg("page_size is required in %s", filepath);
r = FALSE;
} else {
- info->page_size = page_size_t(zip_size ? zip_size : page_size,
- page_size, zip_size != 0);
+ info->page_size = zip_size ? zip_size : page_size;
}
if (info->space_id == ULINT_UNDEFINED) {
@@ -2202,9 +2196,8 @@ xb_write_delta_metadata(const char *filename, const xb_delta_info_t *info)
"page_size = " ULINTPF "\n"
"zip_size = " ULINTPF " \n"
"space_id = " ULINTPF "\n",
- info->page_size.logical(),
- info->page_size.is_compressed()
- ? info->page_size.physical() : 0,
+ info->page_size,
+ info->zip_size,
info->space_id);
len = strlen(buf);
@@ -3107,7 +3100,7 @@ xb_load_single_table_tablespace(
ut_a(node_size != (os_offset_t) -1);
- n_pages = node_size / page_size_t(file->flags()).physical();
+ n_pages = node_size / fil_space_t::physical_size(file->flags());
space = fil_space_create(
name, file->space_id(), file->flags(),
@@ -3312,7 +3305,7 @@ retry:
}
/* TRX_SYS page can't be compressed or encrypted. */
- if (buf_page_is_corrupted(false, page, univ_page_size)) {
+ if (buf_page_is_corrupted(false, page, 0)) {
if (n_retries--) {
os_thread_sleep(1000);
goto retry;
@@ -4590,16 +4583,15 @@ xb_space_create_file(
fsp_header_init_fields(page, space_id, flags);
mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id);
- const page_size_t page_size(flags);
+ const ulint zip_size = fil_space_t::zip_size(flags);
- if (!page_size.is_compressed()) {
+ if (!zip_size) {
buf_flush_init_for_writing(NULL, page, NULL, 0);
ret = os_file_write(IORequestWrite, path, *file, page, 0,
srv_page_size);
} else {
page_zip_des_t page_zip;
- ulint zip_size = page_size.physical();
page_zip_set_size(&page_zip, zip_size);
page_zip.data = page + srv_page_size;
fprintf(stderr, "zip_size = " ULINTPF "\n", zip_size);
@@ -4776,19 +4768,20 @@ exit:
}
/* No matching space found. create the new one. */
- const ulint flags = info.page_size.is_compressed()
- ? get_bit_shift(info.page_size.physical()
+ const ulint flags = info.zip_size
+ ? get_bit_shift(info.page_size
>> (UNIV_ZIP_SIZE_SHIFT_MIN - 1))
<< FSP_FLAGS_POS_ZIP_SSIZE
| FSP_FLAGS_MASK_POST_ANTELOPE
| FSP_FLAGS_MASK_ATOMIC_BLOBS
- | (info.page_size.logical() == UNIV_PAGE_SIZE_ORIG
+ | (srv_page_size == UNIV_PAGE_SIZE_ORIG
? 0
- : get_bit_shift(info.page_size.logical()
+ : get_bit_shift(srv_page_size
>> (UNIV_ZIP_SIZE_SHIFT_MIN - 1))
<< FSP_FLAGS_POS_PAGE_SSIZE)
: FSP_FLAGS_PAGE_SSIZE();
- ut_ad(page_size_t(flags).equals_to(info.page_size));
+ ut_ad(fil_space_t::zip_size(flags) == info.zip_size);
+ ut_ad(fil_space_t::physical_size(flags) == info.page_size);
if (fil_space_create(dest_space_name, info.space_id, flags,
FIL_TYPE_TABLESPACE, 0)) {
@@ -4825,7 +4818,7 @@ xtrabackup_apply_delta(
ulint page_in_buffer;
ulint incremental_buffers = 0;
- xb_delta_info_t info(univ_page_size, SRV_TMP_SPACE_ID);
+ xb_delta_info_t info(srv_page_size, 0, SRV_TMP_SPACE_ID);
ulint page_size;
ulint page_size_shift;
byte* incremental_buffer_base = NULL;
@@ -4863,7 +4856,7 @@ xtrabackup_apply_delta(
goto error;
}
- page_size = info.page_size.physical();
+ page_size = info.page_size;
page_size_shift = get_bit_shift(page_size);
msg("page size for %s is %zu bytes",
src_path, page_size);
diff --git a/extra/mariabackup/xtrabackup.h b/extra/mariabackup/xtrabackup.h
index 90f5e28e2c7..767efe14b50 100644
--- a/extra/mariabackup/xtrabackup.h
+++ b/extra/mariabackup/xtrabackup.h
@@ -28,11 +28,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
struct xb_delta_info_t
{
- xb_delta_info_t(page_size_t page_size, ulint space_id)
- : page_size(page_size), space_id(space_id) {}
+ xb_delta_info_t(ulint page_size, ulint zip_size, ulint space_id)
+ : page_size(page_size), zip_size(zip_size), space_id(space_id) {}
- page_size_t page_size;
- ulint space_id;
+ ulint page_size;
+ ulint zip_size;
+ ulint space_id;
};
/* value of the --incremental option */
diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt
index 782d28afb70..3146529b6fc 100644
--- a/libmysqld/CMakeLists.txt
+++ b/libmysqld/CMakeLists.txt
@@ -123,6 +123,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/sql_tvc.cc ../sql/sql_tvc.h
../sql/opt_split.cc
../sql/item_vers.cc
+ ../sql/opt_trace.cc
${GEN_SOURCES}
${MYSYS_LIBWRAP_SOURCE}
)
diff --git a/mysql-test/main/failed_auth_unixsocket.result b/mysql-test/main/failed_auth_unixsocket.result
index 690476cd753..eb02479431b 100644
--- a/mysql-test/main/failed_auth_unixsocket.result
+++ b/mysql-test/main/failed_auth_unixsocket.result
@@ -8,6 +8,6 @@ flush privileges;
connect(localhost,USER,,test,MASTER_PORT,MASTER_SOCKET);
ERROR 28000: Access denied for user 'USER'@'localhost'
ERROR 28000: Access denied for user 'USER'@'localhost'
-update mysql.global_priv set priv=json_remove(priv, '$.plugin');
+update mysql.global_priv set priv=json_compact(json_remove(priv, '$.plugin'));
flush privileges;
uninstall plugin unix_socket;
diff --git a/mysql-test/main/failed_auth_unixsocket.test b/mysql-test/main/failed_auth_unixsocket.test
index a7ae7d64a6b..01fb09e1c46 100644
--- a/mysql-test/main/failed_auth_unixsocket.test
+++ b/mysql-test/main/failed_auth_unixsocket.test
@@ -36,7 +36,7 @@ connect (fail,localhost,$USER);
--error ER_ACCESS_DENIED_NO_PASSWORD_ERROR
change_user $USER;
-update mysql.global_priv set priv=json_remove(priv, '$.plugin');
+update mysql.global_priv set priv=json_compact(json_remove(priv, '$.plugin'));
flush privileges;
uninstall plugin unix_socket;
diff --git a/mysql-test/main/information_schema.result b/mysql-test/main/information_schema.result
index b76d9f64a9f..dd093aae5e9 100644
--- a/mysql-test/main/information_schema.result
+++ b/mysql-test/main/information_schema.result
@@ -67,6 +67,7 @@ GLOBAL_VARIABLES
INDEX_STATISTICS
KEY_CACHES
KEY_COLUMN_USAGE
+OPTIMIZER_TRACE
PARAMETERS
PARTITIONS
PLUGINS
@@ -864,6 +865,8 @@ information_schema COLUMNS COLUMN_DEFAULT
information_schema COLUMNS COLUMN_TYPE
information_schema COLUMNS GENERATION_EXPRESSION
information_schema EVENTS EVENT_DEFINITION
+information_schema OPTIMIZER_TRACE QUERY
+information_schema OPTIMIZER_TRACE TRACE
information_schema PARAMETERS DTD_IDENTIFIER
information_schema PARTITIONS PARTITION_EXPRESSION
information_schema PARTITIONS SUBPARTITION_EXPRESSION
diff --git a/mysql-test/main/information_schema_all_engines.result b/mysql-test/main/information_schema_all_engines.result
index 2916858b5a6..9ba4d20c76d 100644
--- a/mysql-test/main/information_schema_all_engines.result
+++ b/mysql-test/main/information_schema_all_engines.result
@@ -43,6 +43,7 @@ INNODB_TABLESPACES_SCRUBBING
INNODB_TRX
KEY_CACHES
KEY_COLUMN_USAGE
+OPTIMIZER_TRACE
PARAMETERS
PARTITIONS
PLUGINS
@@ -123,6 +124,7 @@ INNODB_TABLESPACES_SCRUBBING SPACE
INNODB_TRX trx_id
KEY_CACHES KEY_CACHE_NAME
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
+OPTIMIZER_TRACE QUERY
PARAMETERS SPECIFIC_SCHEMA
PARTITIONS TABLE_SCHEMA
PLUGINS PLUGIN_NAME
@@ -203,6 +205,7 @@ INNODB_TABLESPACES_SCRUBBING SPACE
INNODB_TRX trx_id
KEY_CACHES KEY_CACHE_NAME
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
+OPTIMIZER_TRACE QUERY
PARAMETERS SPECIFIC_SCHEMA
PARTITIONS TABLE_SCHEMA
PLUGINS PLUGIN_NAME
@@ -288,6 +291,7 @@ INNODB_TABLESPACES_SCRUBBING information_schema.INNODB_TABLESPACES_SCRUBBING 1
INNODB_TRX information_schema.INNODB_TRX 1
KEY_CACHES information_schema.KEY_CACHES 1
KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1
+OPTIMIZER_TRACE information_schema.OPTIMIZER_TRACE 1
PARAMETERS information_schema.PARAMETERS 1
PARTITIONS information_schema.PARTITIONS 1
PLUGINS information_schema.PLUGINS 1
@@ -358,6 +362,7 @@ Database: information_schema
| INNODB_TRX |
| KEY_CACHES |
| KEY_COLUMN_USAGE |
+| OPTIMIZER_TRACE |
| PARAMETERS |
| PARTITIONS |
| PLUGINS |
@@ -428,6 +433,7 @@ Database: INFORMATION_SCHEMA
| INNODB_TRX |
| KEY_CACHES |
| KEY_COLUMN_USAGE |
+| OPTIMIZER_TRACE |
| PARAMETERS |
| PARTITIONS |
| PLUGINS |
@@ -459,5 +465,5 @@ Wildcard: inf_rmation_schema
| information_schema |
SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') GROUP BY TABLE_SCHEMA;
table_schema count(*)
-information_schema 65
+information_schema 66
mysql 31
diff --git a/mysql-test/main/mysql_upgrade-6984.result b/mysql-test/main/mysql_upgrade-6984.result
index 87f3c1a5359..ad48004a2a3 100644
--- a/mysql-test/main/mysql_upgrade-6984.result
+++ b/mysql-test/main/mysql_upgrade-6984.result
@@ -63,6 +63,6 @@ test
Phase 7/7: Running 'FLUSH PRIVILEGES'
OK
connect con1,localhost,root,foo,,,;
-update mysql.global_priv set priv=json_remove(priv, '$.plugin', '$.authentication_string');
+update mysql.global_priv set priv=json_compact(json_remove(priv, '$.plugin', '$.authentication_string'));
flush privileges;
set global event_scheduler=OFF;
diff --git a/mysql-test/main/mysql_upgrade-6984.test b/mysql-test/main/mysql_upgrade-6984.test
index a036b7a08a0..ad2b95314b0 100644
--- a/mysql-test/main/mysql_upgrade-6984.test
+++ b/mysql-test/main/mysql_upgrade-6984.test
@@ -17,7 +17,7 @@ update mysql.global_priv set priv=json_set(priv, '$.plugin', 'mysql_native_passw
connect(con1,localhost,root,foo,,,);
-update mysql.global_priv set priv=json_remove(priv, '$.plugin', '$.authentication_string');
+update mysql.global_priv set priv=json_compact(json_remove(priv, '$.plugin', '$.authentication_string'));
flush privileges;
# Load event table
set global event_scheduler=OFF;
diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result
index d621c5c8cae..47ebfa7a8ab 100644
--- a/mysql-test/main/mysqld--help.result
+++ b/mysql-test/main/mysqld--help.result
@@ -693,6 +693,12 @@ The following specify which files/extra groups are read (specified before remain
extended_keys, exists_to_in, orderby_uses_equalities,
condition_pushdown_for_derived, split_materialized,
condition_pushdown_for_subquery
+ --optimizer-trace=name
+ Controls tracing of the Optimizer:
+ optimizer_trace=option=val[,option=val...], where option
+ is one of {enabled} and val is one of {on, off, default}
+ --optimizer-trace-max-mem-size=#
+ Maximum allowed size of an optimizer trace
--optimizer-use-condition-selectivity=#
Controls selectivity of which conditions the optimizer
takes into account to calculate cardinality of a partial
@@ -1563,6 +1569,8 @@ optimizer-prune-level 1
optimizer-search-depth 62
optimizer-selectivity-sampling-limit 100
optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
+optimizer-trace
+optimizer-trace-max-mem-size 1048576
optimizer-use-condition-selectivity 4
performance-schema FALSE
performance-schema-accounts-size -1
diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result
new file mode 100644
index 00000000000..22cde925b5e
--- /dev/null
+++ b/mysql-test/main/opt_trace.result
@@ -0,0 +1,3499 @@
+SELECT table_name, column_name FROM information_schema.columns where table_name="OPTIMIZER_TRACE";
+table_name column_name
+OPTIMIZER_TRACE QUERY
+OPTIMIZER_TRACE TRACE
+OPTIMIZER_TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE
+OPTIMIZER_TRACE INSUFFICIENT_PRIVILEGES
+show variables like 'optimizer_trace';
+Variable_name Value
+optimizer_trace enabled=off
+set optimizer_trace="enabled=on";
+show variables like 'optimizer_trace';
+Variable_name Value
+optimizer_trace enabled=on
+set optimizer_trace="enabled=off";
+create table t1 (a int, b int);
+insert into t1 values (1,2),(2,3);
+create table t2 (b int);
+insert into t2 values (1),(2);
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+analyze table t2;
+Table Op Msg_type Msg_text
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status OK
+create function f1 (a int) returns INT
+return 1;
+create view v1 as select * from t1 where t1.a=1;
+create view v2 as select * from t1 where t1.a=1 group by t1.b;
+set optimizer_trace="enabled=on";
+# Mergeable views/derived tables
+select * from v1;
+a b
+1 2
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+select * from v1 {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "view": {
+ "table": "v1",
+ "select_id": 2,
+ "merged": true
+ }
+ },
+ {
+ "join_preparation": {
+ "select_id": 2,
+ "steps": [
+ {
+ "expanded_query": "/* select#2 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` where `t1`.`a` = 1"
+ }
+ ]
+ }
+ },
+ {
+ "expanded_query": "/* select#1 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `v1`"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "condition_processing": {
+ "condition": "WHERE",
+ "original_condition": "t1.a = 1",
+ "steps": [
+ {
+ "transformation": "equality_propagation",
+ "resulting_condition": "multiple equal(1, t1.a)"
+ },
+ {
+ "transformation": "constant_propagation",
+ "resulting_condition": "multiple equal(1, t1.a)"
+ },
+ {
+ "transformation": "trivial_condition_removal",
+ "resulting_condition": "multiple equal(1, t1.a)"
+ }
+ ]
+ }
+ },
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": []
+ },
+ {
+ "rows_estimation": [
+ {
+ "selectivity_for_indexes": [],
+ "selectivity_for_columns": [
+ {
+ "column_name": "a",
+ "selectivity_from_histograms": 0.5
+ }
+ ]
+ },
+ {
+ "table": "t1",
+ "table_scan": {
+ "rows": 2,
+ "cost": 2.0044
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 1,
+ "cost": 2.2044,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "t1.a = 1",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": "t1.a = 1"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+select * from (select * from t1 where t1.a=1)q;
+a b
+1 2
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+select * from (select * from t1 where t1.a=1)q {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "derived": {
+ "table": "q",
+ "select_id": 2,
+ "merged": true
+ }
+ },
+ {
+ "join_preparation": {
+ "select_id": 2,
+ "steps": [
+ {
+ "expanded_query": "/* select#2 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` where `t1`.`a` = 1"
+ }
+ ]
+ }
+ },
+ {
+ "expanded_query": "/* select#1 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from (/* select#2 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` where `t1`.`a` = 1) `q`"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "condition_processing": {
+ "condition": "WHERE",
+ "original_condition": "t1.a = 1",
+ "steps": [
+ {
+ "transformation": "equality_propagation",
+ "resulting_condition": "multiple equal(1, t1.a)"
+ },
+ {
+ "transformation": "constant_propagation",
+ "resulting_condition": "multiple equal(1, t1.a)"
+ },
+ {
+ "transformation": "trivial_condition_removal",
+ "resulting_condition": "multiple equal(1, t1.a)"
+ }
+ ]
+ }
+ },
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": []
+ },
+ {
+ "rows_estimation": [
+ {
+ "selectivity_for_indexes": [],
+ "selectivity_for_columns": [
+ {
+ "column_name": "a",
+ "selectivity_from_histograms": 0.5
+ }
+ ]
+ },
+ {
+ "table": "t1",
+ "table_scan": {
+ "rows": 2,
+ "cost": 2.0044
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 1,
+ "cost": 2.2044,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "t1.a = 1",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": "t1.a = 1"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+# Non-Mergeable views
+select * from v2;
+a b
+1 2
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+select * from v2 {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "view": {
+ "table": "v2",
+ "select_id": 2,
+ "materialized": true
+ }
+ },
+ {
+ "join_preparation": {
+ "select_id": 2,
+ "steps": [
+ {
+ "expanded_query": "/* select#2 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` where `t1`.`a` = 1 group by `t1`.`b`"
+ }
+ ]
+ }
+ },
+ {
+ "expanded_query": "/* select#1 */ select `v2`.`a` AS `a`,`v2`.`b` AS `b` from `v2`"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "join_optimization": {
+ "select_id": 2,
+ "steps": [
+ {
+ "condition_processing": {
+ "condition": "WHERE",
+ "original_condition": "t1.a = 1",
+ "steps": [
+ {
+ "transformation": "equality_propagation",
+ "resulting_condition": "multiple equal(1, t1.a)"
+ },
+ {
+ "transformation": "constant_propagation",
+ "resulting_condition": "multiple equal(1, t1.a)"
+ },
+ {
+ "transformation": "trivial_condition_removal",
+ "resulting_condition": "multiple equal(1, t1.a)"
+ }
+ ]
+ }
+ },
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": []
+ },
+ {
+ "rows_estimation": [
+ {
+ "selectivity_for_indexes": [],
+ "selectivity_for_columns": [
+ {
+ "column_name": "a",
+ "selectivity_from_histograms": 0.5
+ }
+ ]
+ },
+ {
+ "table": "t1",
+ "table_scan": {
+ "rows": 2,
+ "cost": 2.0044
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 1,
+ "cost": 2.2044,
+ "chosen": true,
+ "use_tmp_table": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "t1.a = 1",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": "t1.a = 1"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "table_dependencies": [
+ {
+ "table": "<derived2>",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "<derived2>",
+ "table_scan": {
+ "rows": 2,
+ "cost": 2
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "<derived2>",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 2,
+ "cost": 2,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": null,
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "<derived2>",
+ "attached": null
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": [
+ {
+ "join_execution": {
+ "select_id": 2,
+ "steps": []
+ }
+ }
+ ]
+ }
+ }
+ ]
+} 0 0
+drop table t1,t2;
+drop view v1,v2;
+drop function f1;
+create table t1(a int, b int);
+insert into t1 values (0,0),(1,1),(2,1),(3,2),(4,3),
+(5,3),(6,3),(7,3),(8,3),(9,3);
+create table t2(a int, b int);
+insert into t2 values (0,0),(1,1),(2,1),(3,2),(4,3),
+(5,3),(6,3),(7,3),(8,3),(9,3);
+ANALYZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+ANALYZE TABLE t2;
+Table Op Msg_type Msg_text
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status OK
+create view v1 as select a from t1 group by b;
+create view v2 as select a from t2;
+# Mergeable view
+explain select * from v2 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 10
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+explain select * from v2 {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "view": {
+ "table": "v2",
+ "select_id": 2,
+ "merged": true
+ }
+ },
+ {
+ "join_preparation": {
+ "select_id": 2,
+ "steps": [
+ {
+ "expanded_query": "/* select#2 */ select `t2`.`a` AS `a` from `t2`"
+ }
+ ]
+ }
+ },
+ {
+ "expanded_query": "/* select#1 */ select `t2`.`a` AS `a` from `v2`"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "table_dependencies": [
+ {
+ "table": "t2",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t2",
+ "table_scan": {
+ "rows": 10,
+ "cost": 2.022
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 10,
+ "cost": 2.022,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": null,
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t2",
+ "attached": null
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+# Non-Mergeable view
+explain select * from v1 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 10
+2 DERIVED t1 ALL NULL NULL NULL NULL 10 Using temporary; Using filesort
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+explain select * from v1 {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "view": {
+ "table": "v1",
+ "select_id": 2,
+ "materialized": true
+ }
+ },
+ {
+ "join_preparation": {
+ "select_id": 2,
+ "steps": [
+ {
+ "expanded_query": "/* select#2 */ select `t1`.`a` AS `a` from `t1` group by `t1`.`b`"
+ }
+ ]
+ }
+ },
+ {
+ "expanded_query": "/* select#1 */ select `v1`.`a` AS `a` from `v1`"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "join_optimization": {
+ "select_id": 2,
+ "steps": [
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "table_scan": {
+ "rows": 10,
+ "cost": 2.022
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 10,
+ "cost": 2.022,
+ "chosen": true,
+ "use_tmp_table": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": null,
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": null
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "table_dependencies": [
+ {
+ "table": "<derived2>",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "<derived2>",
+ "table_scan": {
+ "rows": 10,
+ "cost": 10
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "<derived2>",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 10,
+ "cost": 10,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": null,
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "<derived2>",
+ "attached": null
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": [
+ {
+ "join_execution": {
+ "select_id": 2,
+ "steps": []
+ }
+ }
+ ]
+ }
+ }
+ ]
+} 0 0
+drop table t1,t2;
+drop view v1,v2;
+#
+# print ref-keyues array
+#
+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, c int, key(a));
+insert into t1 select A.a*10 + B.a, A.a*10 + B.a, A.a*10 + B.a from t0 A, t0 B;
+create table t2(a int, b int, c int , key(a));
+insert into t2 select A.a*10 + B.a, A.a*10 + B.a, A.a*10 + B.a from t0 A, t0 B;
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status Table is already up to date
+analyze table t2;
+Table Op Msg_type Msg_text
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status Table is already up to date
+explain select * from t1,t2 where t1.a=t2.b+2 and t2.a= t1.b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL a NULL NULL NULL 100 Using where
+1 SIMPLE t2 ref a a 5 test.t1.b 1 Using where
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+explain select * from t1,t2 where t1.a=t2.b+2 and t2.a= t1.b {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "expanded_query": "select `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c`,`t2`.`a` AS `a`,`t2`.`b` AS `b`,`t2`.`c` AS `c` from `t1` join `t2` where `t1`.`a` = `t2`.`b` + 2 and `t2`.`a` = `t1`.`b`"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "condition_processing": {
+ "condition": "WHERE",
+ "original_condition": "t1.a = t2.b + 2 and t2.a = t1.b",
+ "steps": [
+ {
+ "transformation": "equality_propagation",
+ "resulting_condition": "t1.a = t2.b + 2 and multiple equal(t2.a, t1.b)"
+ },
+ {
+ "transformation": "constant_propagation",
+ "resulting_condition": "t1.a = t2.b + 2 and multiple equal(t2.a, t1.b)"
+ },
+ {
+ "transformation": "trivial_condition_removal",
+ "resulting_condition": "t1.a = t2.b + 2 and multiple equal(t2.a, t1.b)"
+ }
+ ]
+ }
+ },
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ },
+ {
+ "table": "t2",
+ "row_may_be_null": false,
+ "map_bit": 1,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": [
+ {
+ "table": "t1",
+ "field": "a",
+ "equals": "t2.b + 2",
+ "null_rejecting": false
+ },
+ {
+ "table": "t2",
+ "field": "a",
+ "equals": "t1.b",
+ "null_rejecting": true
+ }
+ ]
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "table_scan": {
+ "rows": 100,
+ "cost": 2.3174
+ }
+ },
+ {
+ "table": "t2",
+ "table_scan": {
+ "rows": 100,
+ "cost": 2.3174
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 100,
+ "cost": 2.3174,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t1"],
+ "table": "t2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "ref",
+ "index": "a",
+ "used_range_estimates": false,
+ "cause": "not available",
+ "rows": 1,
+ "cost": 200,
+ "chosen": true
+ },
+ {
+ "access_type": "scan",
+ "resulting_rows": 100,
+ "cost": 2.3174,
+ "chosen": false
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "plan_prefix": [],
+ "table": "t2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 100,
+ "cost": 2.3174,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t2"],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "ref",
+ "index": "a",
+ "used_range_estimates": false,
+ "cause": "not available",
+ "rows": 1,
+ "cost": 200,
+ "chosen": true
+ },
+ {
+ "access_type": "scan",
+ "resulting_rows": 100,
+ "cost": 2.3174,
+ "chosen": false
+ }
+ ]
+ },
+ "pruned_by_cost": true
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "t2.a = t1.b and t1.a = t2.b + 2",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": "t1.b is not null"
+ },
+ {
+ "table": "t2",
+ "attached": "t1.a = t2.b + 2"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+drop table t1,t2,t0;
+#
+# group_by min max optimization
+#
+CREATE TABLE t1 (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, a INT NOT NULL, KEY(a));
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+EXPLAIN SELECT DISTINCT a FROM t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL a 4 NULL 5 Using index for group-by
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+EXPLAIN SELECT DISTINCT a FROM t1 {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "expanded_query": "select distinct `t1`.`a` AS `a` from `t1`"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "range_analysis": {
+ "table_scan": {
+ "rows": 65536,
+ "cost": 13255
+ },
+ "potential_range_indexes": [
+ {
+ "index": "PRIMARY",
+ "usable": false,
+ "cause": "not applicable"
+ },
+ {
+ "index": "a",
+ "usable": true,
+ "key_parts": ["a"]
+ }
+ ],
+ "best_covering_index_scan": {
+ "index": "a",
+ "cost": 14627,
+ "chosen": false,
+ "cause": "cost"
+ },
+ "group_index_range": {
+ "distinct_query": true,
+ "potential_group_range_indexes": [
+ {
+ "index": "a",
+ "covering": true,
+ "rows": 5,
+ "cost": 7.5
+ }
+ ]
+ },
+ "best_group_range_summary": {
+ "type": "index_group",
+ "index": "a",
+ "group_attribute": null,
+ "min_aggregate": false,
+ "max_aggregate": false,
+ "distinct_aggregate": false,
+ "rows": 5,
+ "cost": 7.5,
+ "key_parts_used_for_access": ["a"],
+ "ranges": [],
+ "chosen": true
+ },
+ "chosen_range_access_summary": {
+ "range_access_plan": {
+ "type": "index_group",
+ "index": "a",
+ "group_attribute": null,
+ "min_aggregate": false,
+ "max_aggregate": false,
+ "distinct_aggregate": false,
+ "rows": 5,
+ "cost": 7.5,
+ "key_parts_used_for_access": ["a"],
+ "ranges": []
+ },
+ "rows_for_plan": 5,
+ "cost_for_plan": 7.5,
+ "chosen": true
+ }
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "range",
+ "resulting_rows": 5,
+ "cost": 7.5,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": null,
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": null
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+drop table t1;
+#
+# With group by , where clause and MIN/MAX function
+#
+CREATE TABLE t1 (a INT, b INT, c int, d int, KEY(a,b,c,d));
+INSERT INTO t1 VALUES (1,1,1,1), (2,2,2,2), (3,3,3,3), (4,4,4,4), (1,0,1,1), (3,2,3,3), (4,5,4,4);
+ANALYZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+EXPLAIN SELECT MIN(d) FROM t1 where b=2 and c=3 group by a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 20 NULL 7 Using where; Using index
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+EXPLAIN SELECT MIN(d) FROM t1 where b=2 and c=3 group by a {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "expanded_query": "select min(`t1`.`d`) AS `MIN(d)` from `t1` where `t1`.`b` = 2 and `t1`.`c` = 3 group by `t1`.`a`"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "condition_processing": {
+ "condition": "WHERE",
+ "original_condition": "t1.b = 2 and t1.c = 3",
+ "steps": [
+ {
+ "transformation": "equality_propagation",
+ "resulting_condition": "multiple equal(2, t1.b) and multiple equal(3, t1.c)"
+ },
+ {
+ "transformation": "constant_propagation",
+ "resulting_condition": "multiple equal(2, t1.b) and multiple equal(3, t1.c)"
+ },
+ {
+ "transformation": "trivial_condition_removal",
+ "resulting_condition": "multiple equal(2, t1.b) and multiple equal(3, t1.c)"
+ }
+ ]
+ }
+ },
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": []
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "range_analysis": {
+ "table_scan": {
+ "rows": 7,
+ "cost": 5.5291
+ },
+ "potential_range_indexes": [
+ {
+ "index": "a",
+ "usable": true,
+ "key_parts": ["a", "b", "c", "d"]
+ }
+ ],
+ "best_covering_index_scan": {
+ "index": "a",
+ "cost": 2.7006,
+ "chosen": true
+ },
+ "setup_range_conditions": [],
+ "group_index_range": {
+ "potential_group_range_indexes": [
+ {
+ "index": "a",
+ "covering": true,
+ "ranges": ["2 <= b <= 2 AND 3 <= c <= 3"],
+ "rows": 8,
+ "cost": 3.4
+ }
+ ]
+ },
+ "best_group_range_summary": {
+ "type": "index_group",
+ "index": "a",
+ "group_attribute": "d",
+ "min_aggregate": true,
+ "max_aggregate": false,
+ "distinct_aggregate": false,
+ "rows": 8,
+ "cost": 3.4,
+ "key_parts_used_for_access": ["a", "b", "c"],
+ "ranges": ["2 <= b <= 2 AND 3 <= c <= 3"],
+ "chosen": false,
+ "cause": "cost"
+ },
+ "analyzing_range_alternatives": {
+ "range_scan_alternatives": [],
+ "analyzing_roworder_intersect": {
+ "cause": "too few roworder scans"
+ },
+ "analyzing_index_merge_union": []
+ }
+ }
+ },
+ {
+ "selectivity_for_indexes": [],
+ "selectivity_for_columns": [
+ {
+ "column_name": "b",
+ "selectivity_from_histograms": 0.1667
+ },
+ {
+ "column_name": "c",
+ "selectivity_from_histograms": 0.25
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 0.2917,
+ "cost": 3.3707,
+ "chosen": true,
+ "use_tmp_table": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "t1.b = 2 and t1.c = 3",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": "t1.b = 2 and t1.c = 3"
+ }
+ ]
+ }
+ },
+ {
+ "reconsidering_access_paths_for_index_ordering": {
+ "clause": "GROUP BY",
+ "fanout": 1,
+ "read_time": 3.3717,
+ "table": "t1",
+ "rows_estimation": 7,
+ "possible_keys": [
+ {
+ "index": "a",
+ "can_resolve_order": true,
+ "updated_limit": 7,
+ "index_scan_time": 7,
+ "records": 7,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+DROP TABLE t1;
+CREATE TABLE t1 (id INT NOT NULL, a DATE, KEY(id,a));
+INSERT INTO t1 values (1,'2001-01-01'),(1,'2001-01-02'),
+(1,'2001-01-03'),(1,'2001-01-04'),
+(2,'2001-01-01'),(2,'2001-01-02'),
+(2,'2001-01-03'),(2,'2001-01-04'),
+(3,'2001-01-01'),(3,'2001-01-02'),
+(3,'2001-01-03'),(3,'2001-01-04'),
+(4,'2001-01-01'),(4,'2001-01-02'),
+(4,'2001-01-03'),(4,'2001-01-04');
+set optimizer_trace='enabled=on';
+EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL id 8 NULL 9 Using where; Using index for group-by
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "expanded_query": "select `t1`.`id` AS `id`,min(`t1`.`a`) AS `MIN(a)`,max(`t1`.`a`) AS `MAX(a)` from `t1` where `t1`.`a` >= 20010104e0 group by `t1`.`id`"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "condition_processing": {
+ "condition": "WHERE",
+ "original_condition": "t1.a >= 20010104e0",
+ "steps": [
+ {
+ "transformation": "equality_propagation",
+ "resulting_condition": "t1.a >= 20010104e0"
+ },
+ {
+ "transformation": "constant_propagation",
+ "resulting_condition": "t1.a >= 20010104e0"
+ },
+ {
+ "transformation": "trivial_condition_removal",
+ "resulting_condition": "t1.a >= 20010104e0"
+ }
+ ]
+ }
+ },
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": []
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "range_analysis": {
+ "table_scan": {
+ "rows": 16,
+ "cost": 7.3313
+ },
+ "potential_range_indexes": [
+ {
+ "index": "id",
+ "usable": true,
+ "key_parts": ["id", "a"]
+ }
+ ],
+ "best_covering_index_scan": {
+ "index": "id",
+ "cost": 4.6269,
+ "chosen": true
+ },
+ "setup_range_conditions": [],
+ "group_index_range": {
+ "potential_group_range_indexes": [
+ {
+ "index": "id",
+ "covering": true,
+ "ranges": ["0x24a20f <= a"],
+ "rows": 9,
+ "cost": 3.7
+ }
+ ]
+ },
+ "best_group_range_summary": {
+ "type": "index_group",
+ "index": "id",
+ "group_attribute": "a",
+ "min_aggregate": true,
+ "max_aggregate": true,
+ "distinct_aggregate": false,
+ "rows": 9,
+ "cost": 3.7,
+ "key_parts_used_for_access": ["id"],
+ "ranges": ["0x24a20f <= a"],
+ "chosen": true
+ },
+ "analyzing_range_alternatives": {
+ "range_scan_alternatives": [],
+ "analyzing_roworder_intersect": {
+ "cause": "too few roworder scans"
+ },
+ "analyzing_index_merge_union": []
+ },
+ "chosen_range_access_summary": {
+ "range_access_plan": {
+ "type": "index_group",
+ "index": "id",
+ "group_attribute": "a",
+ "min_aggregate": true,
+ "max_aggregate": true,
+ "distinct_aggregate": false,
+ "rows": 9,
+ "cost": 3.7,
+ "key_parts_used_for_access": ["id"],
+ "ranges": ["0x24a20f <= a"]
+ },
+ "rows_for_plan": 9,
+ "cost_for_plan": 3.7,
+ "chosen": true
+ }
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "range",
+ "resulting_rows": 9,
+ "cost": 3.7,
+ "chosen": true,
+ "use_tmp_table": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "t1.a >= 20010104e0",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": "t1.a >= 20010104e0"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL id 8 NULL 9 Using where; Using index for group-by
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "expanded_query": "select `t1`.`id` AS `id`,`t1`.`a` AS `a` from `t1` where `t1`.`a` = 20010104e0 group by `t1`.`id`"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "condition_processing": {
+ "condition": "WHERE",
+ "original_condition": "t1.a = 20010104e0",
+ "steps": [
+ {
+ "transformation": "equality_propagation",
+ "resulting_condition": "t1.a = 20010104e0"
+ },
+ {
+ "transformation": "constant_propagation",
+ "resulting_condition": "t1.a = 20010104e0"
+ },
+ {
+ "transformation": "trivial_condition_removal",
+ "resulting_condition": "t1.a = 20010104e0"
+ }
+ ]
+ }
+ },
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": []
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "range_analysis": {
+ "table_scan": {
+ "rows": 16,
+ "cost": 7.3313
+ },
+ "potential_range_indexes": [
+ {
+ "index": "id",
+ "usable": true,
+ "key_parts": ["id", "a"]
+ }
+ ],
+ "best_covering_index_scan": {
+ "index": "id",
+ "cost": 4.6269,
+ "chosen": true
+ },
+ "setup_range_conditions": [],
+ "group_index_range": {
+ "potential_group_range_indexes": [
+ {
+ "index": "id",
+ "covering": true,
+ "ranges": ["0x24a20f <= a <= 0x24a20f"],
+ "rows": 9,
+ "cost": 3.7
+ }
+ ]
+ },
+ "best_group_range_summary": {
+ "type": "index_group",
+ "index": "id",
+ "group_attribute": null,
+ "min_aggregate": false,
+ "max_aggregate": false,
+ "distinct_aggregate": false,
+ "rows": 9,
+ "cost": 3.7,
+ "key_parts_used_for_access": ["id", "a"],
+ "ranges": ["0x24a20f <= a <= 0x24a20f"],
+ "chosen": true
+ },
+ "analyzing_range_alternatives": {
+ "range_scan_alternatives": [],
+ "analyzing_roworder_intersect": {
+ "cause": "too few roworder scans"
+ },
+ "analyzing_index_merge_union": []
+ },
+ "chosen_range_access_summary": {
+ "range_access_plan": {
+ "type": "index_group",
+ "index": "id",
+ "group_attribute": null,
+ "min_aggregate": false,
+ "max_aggregate": false,
+ "distinct_aggregate": false,
+ "rows": 9,
+ "cost": 3.7,
+ "key_parts_used_for_access": ["id", "a"],
+ "ranges": ["0x24a20f <= a <= 0x24a20f"]
+ },
+ "rows_for_plan": 9,
+ "cost_for_plan": 3.7,
+ "chosen": true
+ }
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "range",
+ "resulting_rows": 9,
+ "cost": 3.7,
+ "chosen": true,
+ "use_tmp_table": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "t1.a = 20010104e0",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": "t1.a = 20010104e0"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+drop table t1;
+#
+# Late ORDER BY optimization
+#
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table one_k(a int primary key);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+create table t1 (
+pk int not null,
+a int,
+b int,
+c int,
+filler char(100),
+KEY a_a(c),
+KEY a_c(a,c),
+KEY a_b(a,b)
+);
+insert into t1
+select a, a,a,a, 'filler-dataaa' from test.one_k;
+update t1 set a=1 where pk between 0 and 180;
+update t1 set b=2 where pk between 0 and 20;
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+set optimizer_trace='enabled=on';
+explain select * from t1 where a=1 and b=2 order by c limit 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a_c,a_b a_c 5 NULL 180 Using where
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+explain select * from t1 where a=1 and b=2 order by c limit 1 {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "expanded_query": "select `t1`.`pk` AS `pk`,`t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c`,`t1`.`filler` AS `filler` from `t1` where `t1`.`a` = 1 and `t1`.`b` = 2 order by `t1`.`c` limit 1"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "condition_processing": {
+ "condition": "WHERE",
+ "original_condition": "t1.a = 1 and t1.b = 2",
+ "steps": [
+ {
+ "transformation": "equality_propagation",
+ "resulting_condition": "multiple equal(1, t1.a) and multiple equal(2, t1.b)"
+ },
+ {
+ "transformation": "constant_propagation",
+ "resulting_condition": "multiple equal(1, t1.a) and multiple equal(2, t1.b)"
+ },
+ {
+ "transformation": "trivial_condition_removal",
+ "resulting_condition": "multiple equal(1, t1.a) and multiple equal(2, t1.b)"
+ }
+ ]
+ }
+ },
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": [
+ {
+ "table": "t1",
+ "field": "a",
+ "equals": "1",
+ "null_rejecting": false
+ },
+ {
+ "table": "t1",
+ "field": "a",
+ "equals": "1",
+ "null_rejecting": false
+ },
+ {
+ "table": "t1",
+ "field": "b",
+ "equals": "2",
+ "null_rejecting": false
+ }
+ ]
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "range_analysis": {
+ "table_scan": {
+ "rows": 1000,
+ "cost": 232.66
+ },
+ "potential_range_indexes": [
+ {
+ "index": "a_a",
+ "usable": false,
+ "cause": "not applicable"
+ },
+ {
+ "index": "a_c",
+ "usable": true,
+ "key_parts": ["a", "c"]
+ },
+ {
+ "index": "a_b",
+ "usable": true,
+ "key_parts": ["a", "b"]
+ }
+ ],
+ "setup_range_conditions": [],
+ "group_index_range": {
+ "chosen": false,
+ "cause": "no group by or distinct"
+ },
+ "analyzing_range_alternatives": {
+ "range_scan_alternatives": [
+ {
+ "index": "a_c",
+ "ranges": ["1 <= a <= 1"],
+ "rowid_ordered": false,
+ "using_mrr": false,
+ "index_only": false,
+ "rows": 180,
+ "cost": 217.01,
+ "chosen": true
+ },
+ {
+ "index": "a_b",
+ "ranges": ["1 <= a <= 1 AND 2 <= b <= 2"],
+ "rowid_ordered": true,
+ "using_mrr": false,
+ "index_only": false,
+ "rows": 21,
+ "cost": 26.21,
+ "chosen": true
+ }
+ ],
+ "analyzing_roworder_intersect": {
+ "cause": "too few roworder scans"
+ },
+ "analyzing_index_merge_union": []
+ },
+ "chosen_range_access_summary": {
+ "range_access_plan": {
+ "type": "range_scan",
+ "index": "a_b",
+ "rows": 21,
+ "ranges": ["1 <= a <= 1 AND 2 <= b <= 2"]
+ },
+ "rows_for_plan": 21,
+ "cost_for_plan": 26.21,
+ "chosen": true
+ }
+ }
+ },
+ {
+ "selectivity_for_indexes": [
+ {
+ "index_name": "a_b",
+ "selectivity_from_index": 0.021
+ }
+ ],
+ "selectivity_for_columns": [
+ {
+ "column_name": "a",
+ "selectivity_from_histograms": 0.0012
+ },
+ {
+ "column_name": "b",
+ "selectivity_from_histograms": 0.001
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "ref",
+ "index": "a_c",
+ "used_range_estimates": true,
+ "rows": 180,
+ "cost": 92,
+ "chosen": true
+ },
+ {
+ "access_type": "ref",
+ "index": "a_b",
+ "used_range_estimates": true,
+ "rows": 21,
+ "cost": 22,
+ "chosen": true
+ },
+ {
+ "type": "scan",
+ "chosen": false,
+ "cause": "cost"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "t1.a = 1 and t1.b = 2",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": null
+ }
+ ]
+ }
+ },
+ {
+ "reconsidering_access_paths_for_index_ordering": {
+ "clause": "ORDER BY",
+ "fanout": 1,
+ "read_time": 22.001,
+ "table": "t1",
+ "rows_estimation": 21,
+ "possible_keys": [
+ {
+ "index": "a_a",
+ "can_resolve_order": true,
+ "updated_limit": 47,
+ "index_scan_time": 47,
+ "usable": false,
+ "cause": "cost"
+ },
+ {
+ "index": "a_c",
+ "can_resolve_order": true,
+ "updated_limit": 47,
+ "range_scan_time": 4.324,
+ "index_scan_time": 4.324,
+ "records": 180,
+ "chosen": true
+ },
+ {
+ "index": "a_b",
+ "can_resolve_order": false,
+ "cause": "not usable index for the query"
+ }
+ ]
+ }
+ },
+ {
+ "table": "t1",
+ "range_analysis": {
+ "table_scan": {
+ "rows": 1000,
+ "cost": 1202
+ },
+ "potential_range_indexes": [
+ {
+ "index": "a_a",
+ "usable": false,
+ "cause": "not applicable"
+ },
+ {
+ "index": "a_c",
+ "usable": true,
+ "key_parts": ["a", "c"]
+ },
+ {
+ "index": "a_b",
+ "usable": false,
+ "cause": "not applicable"
+ }
+ ],
+ "setup_range_conditions": [],
+ "group_index_range": {
+ "chosen": false,
+ "cause": "no group by or distinct"
+ },
+ "analyzing_range_alternatives": {
+ "range_scan_alternatives": [
+ {
+ "index": "a_c",
+ "ranges": ["1 <= a <= 1"],
+ "rowid_ordered": false,
+ "using_mrr": false,
+ "index_only": false,
+ "rows": 180,
+ "cost": 217.01,
+ "chosen": true
+ }
+ ],
+ "analyzing_roworder_intersect": {
+ "cause": "too few roworder scans"
+ },
+ "analyzing_index_merge_union": []
+ },
+ "chosen_range_access_summary": {
+ "range_access_plan": {
+ "type": "range_scan",
+ "index": "a_c",
+ "rows": 180,
+ "ranges": ["1 <= a <= 1"]
+ },
+ "rows_for_plan": 180,
+ "cost_for_plan": 217.01,
+ "chosen": true
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+drop table t1,ten,one_k;
+#
+# TABLE ELIMINATION
+#
+create table t1 (a int);
+insert into t1 values (0),(1),(2),(3);
+create table t0 as select * from t1;
+create table t2 (a int primary key, b int)
+as select a, a as b from t1 where a in (1,2);
+create table t3 (a int primary key, b int)
+as select a, a as b from t1 where a in (1,3);
+set optimizer_trace='enabled=on';
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+analyze table t2;
+Table Op Msg_type Msg_text
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status OK
+analyze table t3;
+Table Op Msg_type Msg_text
+test.t3 analyze status Engine-independent statistics collected
+test.t3 analyze status OK
+# table t2 should be eliminated
+explain
+select t1.a from t1 left join t2 on t1.a=t2.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+explain
+select t1.a from t1 left join t2 on t1.a=t2.a {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "expanded_query": "select `t1`.`a` AS `a` from (`t1` left join `t2` on(`t1`.`a` = `t2`.`a`))"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ },
+ {
+ "table": "t2",
+ "row_may_be_null": true,
+ "map_bit": 1,
+ "depends_on_map_bits": ["0"]
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": [
+ {
+ "table": "t2",
+ "field": "a",
+ "equals": "t1.a",
+ "null_rejecting": true
+ }
+ ]
+ },
+ {
+ "eliminated_tables": ["t2"]
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "table_scan": {
+ "rows": 4,
+ "cost": 2.0068
+ }
+ },
+ {
+ "table": "t2",
+ "rows": 1,
+ "cost": 1,
+ "table_type": "const"
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": ["t2"],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 4,
+ "cost": 2.0068,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "condition_on_constant_tables": "1"
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "1",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": null
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+# no tables should be eliminated
+explain select * from t1 left join t2 on t2.a=t1.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4
+1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 Using where
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+explain select * from t1 left join t2 on t2.a=t1.a {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "expanded_query": "select `t1`.`a` AS `a`,`t2`.`a` AS `a`,`t2`.`b` AS `b` from (`t1` left join `t2` on(`t2`.`a` = `t1`.`a`))"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ },
+ {
+ "table": "t2",
+ "row_may_be_null": true,
+ "map_bit": 1,
+ "depends_on_map_bits": ["0"]
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": [
+ {
+ "table": "t2",
+ "field": "a",
+ "equals": "t1.a",
+ "null_rejecting": true
+ }
+ ]
+ },
+ {
+ "eliminated_tables": []
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "table_scan": {
+ "rows": 4,
+ "cost": 2.0068
+ }
+ },
+ {
+ "table": "t2",
+ "table_scan": {
+ "rows": 2,
+ "cost": 2.0044
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 4,
+ "cost": 2.0068,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t1"],
+ "table": "t2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "eq_ref",
+ "index": "PRIMARY",
+ "rows": 1,
+ "cost": 4,
+ "chosen": true
+ },
+ {
+ "access_type": "scan",
+ "resulting_rows": 2,
+ "cost": 8.0176,
+ "chosen": false
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "condition_on_constant_tables": "1"
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "1",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": null
+ },
+ {
+ "table": "t2",
+ "attached": "trigcond(trigcond(t1.a is not null))"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+# multiple tables are eliminated
+explain select t1.a from t1 left join (t2 join t3 on t2.b=t3.b) on t2.a=t1.a and t3.a=t1.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+explain select t1.a from t1 left join (t2 join t3 on t2.b=t3.b) on t2.a=t1.a and t3.a=t1.a {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "expanded_query": "select `t1`.`a` AS `a` from (`t1` left join (`t2` join `t3` on(`t2`.`b` = `t3`.`b`)) on(`t2`.`a` = `t1`.`a` and `t3`.`a` = `t1`.`a`))"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ },
+ {
+ "table": "t2",
+ "row_may_be_null": true,
+ "map_bit": 1,
+ "depends_on_map_bits": ["0"]
+ },
+ {
+ "table": "t3",
+ "row_may_be_null": true,
+ "map_bit": 2,
+ "depends_on_map_bits": ["0"]
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": [
+ {
+ "table": "t2",
+ "field": "a",
+ "equals": "t1.a",
+ "null_rejecting": true
+ },
+ {
+ "table": "t2",
+ "field": "a",
+ "equals": "t3.a",
+ "null_rejecting": true
+ },
+ {
+ "table": "t3",
+ "field": "a",
+ "equals": "t2.a",
+ "null_rejecting": true
+ },
+ {
+ "table": "t3",
+ "field": "a",
+ "equals": "t1.a",
+ "null_rejecting": true
+ }
+ ]
+ },
+ {
+ "eliminated_tables": ["t3", "t2"]
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "table_scan": {
+ "rows": 4,
+ "cost": 2.0068
+ }
+ },
+ {
+ "table": "t2",
+ "rows": 1,
+ "cost": 1,
+ "table_type": "const"
+ },
+ {
+ "table": "t3",
+ "rows": 1,
+ "cost": 1,
+ "table_type": "const"
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": ["t3", "t2"],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 4,
+ "cost": 2.0068,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "condition_on_constant_tables": "1"
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "1",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": null
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+drop table t0, t1, t2, t3;
+#
+# IN subquery to sem-join is traced
+#
+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);
+insert into t1 values (0,0),(1,1),(2,2);
+create table t2 as select * from t1;
+create table t11(a int, b int);
+create table t10 (pk int, a int);
+insert into t10 select a,a from t0;
+create table t12 like t10;
+insert into t12 select * from t10;
+analyze table t1,t10;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+test.t10 analyze status Engine-independent statistics collected
+test.t10 analyze status OK
+set optimizer_trace='enabled=on';
+explain extended select * from t1 where a in (select pk from t10);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
+2 MATERIALIZED t10 ALL NULL NULL NULL NULL 10 100.00
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join (`test`.`t10`) where 1
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+explain extended select * from t1 where a in (select pk from t10) {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 2,
+ "steps": [
+ {
+ "transformation": {
+ "select_id": 2,
+ "from": "IN (SELECT)",
+ "to": "materialization",
+ "sjm_scan_allowed": true,
+ "possible": true
+ }
+ },
+ {
+ "transformation": {
+ "select_id": 2,
+ "from": "IN (SELECT)",
+ "to": "semijoin",
+ "chosen": true
+ }
+ },
+ {
+ "expanded_query": "/* select#2 */ select `t10`.`pk` from `t10`"
+ }
+ ]
+ }
+ },
+ {
+ "expanded_query": "/* select#1 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` where `t1`.`a` in (/* select#2 */ select `t10`.`pk` from `t10`)"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "transformation": {
+ "select_id": 2,
+ "from": "IN (SELECT)",
+ "to": "semijoin",
+ "converted_to_semi_join": true
+ }
+ },
+ {
+ "condition_processing": {
+ "condition": "WHERE",
+ "original_condition": "1 and t1.a = t10.pk",
+ "steps": [
+ {
+ "transformation": "equality_propagation",
+ "resulting_condition": "1 and multiple equal(t1.a, t10.pk)"
+ },
+ {
+ "transformation": "constant_propagation",
+ "resulting_condition": "1 and multiple equal(t1.a, t10.pk)"
+ },
+ {
+ "transformation": "trivial_condition_removal",
+ "resulting_condition": "multiple equal(t1.a, t10.pk)"
+ }
+ ]
+ }
+ },
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ },
+ {
+ "table": "t10",
+ "row_may_be_null": false,
+ "map_bit": 1,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": []
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "table_scan": {
+ "rows": 3,
+ "cost": 2.0066
+ }
+ },
+ {
+ "table": "t10",
+ "table_scan": {
+ "rows": 10,
+ "cost": 2.022
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": [
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t10",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 10,
+ "cost": 2.022,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0066,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t1"],
+ "table": "t10",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 10,
+ "cost": 2.022,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "plan_prefix": [],
+ "table": "t10",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 10,
+ "cost": 2.022,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+ },
+ {
+ "condition_on_constant_tables": "1"
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "1",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": null
+ },
+ {
+ "table": "t10",
+ "attached": null
+ },
+ {
+ "table": "<subquery2>",
+ "attached": null
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+drop table t0,t1,t11,t10,t12,t2;
+#
+# Selectivities for columns and indexes.
+#
+create table t0 (a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 (
+pk int,
+a int,
+b int,
+key pk(pk),
+key pk_a(pk,a),
+key pk_a_b(pk,a,b));
+insert into t1 select a,a,a from t0;
+ANALYZE TABLE t1 PERSISTENT FOR COLUMNS (a,b) INDEXES ();
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status Table is already up to date
+set @save_optimizer_use_condition_selectivity=@@optimizer_use_condition_selectivity;
+set @save_use_stat_tables= @@use_stat_tables;
+set @@optimizer_use_condition_selectivity=4;
+set @@use_stat_tables= PREFERABLY;
+set optimizer_trace='enabled=on';
+explain select * from t1 where pk = 2 and a=5 and b=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref pk,pk_a,pk_a_b pk_a_b 15 const,const,const 1 Using index
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+explain select * from t1 where pk = 2 and a=5 and b=1 {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "expanded_query": "select `t1`.`pk` AS `pk`,`t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` where `t1`.`pk` = 2 and `t1`.`a` = 5 and `t1`.`b` = 1"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "condition_processing": {
+ "condition": "WHERE",
+ "original_condition": "t1.pk = 2 and t1.a = 5 and t1.b = 1",
+ "steps": [
+ {
+ "transformation": "equality_propagation",
+ "resulting_condition": "multiple equal(2, t1.pk) and multiple equal(5, t1.a) and multiple equal(1, t1.b)"
+ },
+ {
+ "transformation": "constant_propagation",
+ "resulting_condition": "multiple equal(2, t1.pk) and multiple equal(5, t1.a) and multiple equal(1, t1.b)"
+ },
+ {
+ "transformation": "trivial_condition_removal",
+ "resulting_condition": "multiple equal(2, t1.pk) and multiple equal(5, t1.a) and multiple equal(1, t1.b)"
+ }
+ ]
+ }
+ },
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": [
+ {
+ "table": "t1",
+ "field": "pk",
+ "equals": "2",
+ "null_rejecting": false
+ },
+ {
+ "table": "t1",
+ "field": "pk",
+ "equals": "2",
+ "null_rejecting": false
+ },
+ {
+ "table": "t1",
+ "field": "a",
+ "equals": "5",
+ "null_rejecting": false
+ },
+ {
+ "table": "t1",
+ "field": "pk",
+ "equals": "2",
+ "null_rejecting": false
+ },
+ {
+ "table": "t1",
+ "field": "a",
+ "equals": "5",
+ "null_rejecting": false
+ },
+ {
+ "table": "t1",
+ "field": "b",
+ "equals": "1",
+ "null_rejecting": false
+ }
+ ]
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "range_analysis": {
+ "table_scan": {
+ "rows": 10,
+ "cost": 6.1317
+ },
+ "potential_range_indexes": [
+ {
+ "index": "pk",
+ "usable": true,
+ "key_parts": ["pk"]
+ },
+ {
+ "index": "pk_a",
+ "usable": true,
+ "key_parts": ["pk", "a"]
+ },
+ {
+ "index": "pk_a_b",
+ "usable": true,
+ "key_parts": ["pk", "a", "b"]
+ }
+ ],
+ "best_covering_index_scan": {
+ "index": "pk_a_b",
+ "cost": 3.3708,
+ "chosen": true
+ },
+ "setup_range_conditions": [],
+ "group_index_range": {
+ "chosen": false,
+ "cause": "no group by or distinct"
+ },
+ "analyzing_range_alternatives": {
+ "range_scan_alternatives": [
+ {
+ "index": "pk",
+ "ranges": ["2 <= pk <= 2"],
+ "rowid_ordered": true,
+ "using_mrr": false,
+ "index_only": false,
+ "rows": 1,
+ "cost": 2.21,
+ "chosen": true
+ },
+ {
+ "index": "pk_a",
+ "ranges": ["2 <= pk <= 2 AND 5 <= a <= 5"],
+ "rowid_ordered": true,
+ "using_mrr": false,
+ "index_only": false,
+ "rows": 1,
+ "cost": 2.21,
+ "chosen": false,
+ "cause": "cost"
+ },
+ {
+ "index": "pk_a_b",
+ "ranges": ["2 <= pk <= 2 AND 5 <= a <= 5 AND 1 <= b <= 1"],
+ "rowid_ordered": true,
+ "using_mrr": false,
+ "index_only": true,
+ "rows": 1,
+ "cost": 2.21,
+ "chosen": false,
+ "cause": "cost"
+ }
+ ],
+ "analyzing_roworder_intersect": {
+ "intersecting_indexes": [
+ {
+ "index": "pk",
+ "index_scan_cost": 1,
+ "cumulateed_index_scan_cost": 1,
+ "disk_sweep_cost": 0.9008,
+ "cumulative_total_cost": 1.9008,
+ "usable": true,
+ "matching_rows_now": 1,
+ "intersect_covering_with_this_index": false,
+ "chosen": true
+ },
+ {
+ "index": "pk_a",
+ "usable": false,
+ "cause": "does not reduce cost of intersect"
+ },
+ {
+ "index": "pk_a_b",
+ "usable": false,
+ "cause": "does not reduce cost of intersect"
+ }
+ ],
+ "clustered_pk": {
+ "clustered_pk_added_to_intersect": false,
+ "cause": "no clustered pk index"
+ },
+ "chosen": false,
+ "cause": "too few indexes to merge"
+ },
+ "analyzing_index_merge_union": []
+ },
+ "chosen_range_access_summary": {
+ "range_access_plan": {
+ "type": "range_scan",
+ "index": "pk",
+ "rows": 1,
+ "ranges": ["2 <= pk <= 2"]
+ },
+ "rows_for_plan": 1,
+ "cost_for_plan": 2.21,
+ "chosen": true
+ }
+ }
+ },
+ {
+ "selectivity_for_indexes": [
+ {
+ "index_name": "pk_a_b",
+ "selectivity_from_index": 0.1
+ }
+ ],
+ "selectivity_for_columns": [
+ {
+ "column_name": "a",
+ "selectivity_from_histograms": 0.1
+ },
+ {
+ "column_name": "b",
+ "selectivity_from_histograms": 0.1
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "ref",
+ "index": "pk",
+ "used_range_estimates": true,
+ "rows": 1,
+ "cost": 2,
+ "chosen": true
+ },
+ {
+ "access_type": "ref",
+ "index": "pk_a",
+ "used_range_estimates": true,
+ "rows": 1,
+ "cost": 2,
+ "chosen": false,
+ "cause": "cost"
+ },
+ {
+ "access_type": "ref",
+ "index": "pk_a_b",
+ "used_range_estimates": true,
+ "rows": 1,
+ "cost": 1,
+ "chosen": true
+ },
+ {
+ "access_type": "range",
+ "resulting_rows": 1,
+ "cost": 2.21,
+ "chosen": false
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "t1.pk = 2 and t1.a = 5 and t1.b = 1",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": null
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
+set @@use_stat_tables= @save_use_stat_tables;
+drop table t0,t1;
+set optimizer_trace="enabled=off";
+#
+# Tests added to show that sub-statements are not traced
+#
+create table t1(a int);
+insert into t1 values (1),(2),(3),(4);
+create table t2(a int);
+insert into t2 values (1),(2),(3),(4);
+create function f1(a int) returns int
+begin
+declare a int default 0;
+set a= a+ (select count(*) from t2);
+return a;
+end|
+create function f2(a int) returns int
+begin
+declare a int default 0;
+select count(*) from t2 into a;
+return a;
+end|
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
+set optimizer_trace='enabled=on';
+select f1(a) from t1;
+f1(a)
+4
+4
+4
+4
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+select f1(a) from t1 {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "expanded_query": "select `f1`(`t1`.`a`) AS `f1(a)` from `t1`"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "table_scan": {
+ "rows": 4,
+ "cost": 2.0068
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 4,
+ "cost": 2.0068,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": null,
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": null
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+select f2(a) from t1;
+f2(a)
+4
+4
+4
+4
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+select f2(a) from t1 {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "expanded_query": "select `f2`(`t1`.`a`) AS `f2(a)` from `t1`"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "table_scan": {
+ "rows": 4,
+ "cost": 2.0068
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 4,
+ "cost": 2.0068,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": null,
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": null
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+drop table t1,t2;
+drop function f1;
+drop function f2;
+set optimizer_trace='enabled=off';
+#
+# MDEV-18489: Limit the memory used by the optimizer trace
+#
+create table t1 (a int);
+insert into t1 values (1),(2);
+set optimizer_trace='enabled=on';
+set @save_optimizer_trace_max_mem_size= @@optimizer_trace_max_mem_size;
+select * from t1;
+a
+1
+2
+select length(trace) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+length(trace)
+1889
+set optimizer_trace_max_mem_size=100;
+select * from t1;
+a
+1
+2
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+select * from t1 {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ 1789 0
+set optimizer_trace_max_mem_size=0;
+select * from t1;
+a
+1
+2
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+select * from t1 1889 0
+drop table t1;
+set optimizer_trace='enabled=off';
+set @@optimizer_trace_max_mem_size= @save_optimizer_trace_max_mem_size;
+#
+# MDEV-18527: Optimizer trace for DELETE query shows table:null
+#
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t0 (a int, b int);
+insert into t0 select a,a from ten;
+alter table t0 add key(a);
+set optimizer_trace=1;
+explain delete from t0 where t0.a<3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 range a a 5 NULL 3 Using where
+select * from information_schema.optimizer_trace;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+explain delete from t0 where t0.a<3 {
+ "steps": [
+ {
+ "table": "t0",
+ "range_analysis": {
+ "table_scan": {
+ "rows": 10,
+ "cost": 6.122
+ },
+ "potential_range_indexes": [
+ {
+ "index": "a",
+ "usable": true,
+ "key_parts": ["a"]
+ }
+ ],
+ "setup_range_conditions": [],
+ "group_index_range": {
+ "chosen": false,
+ "cause": "no join"
+ },
+ "analyzing_range_alternatives": {
+ "range_scan_alternatives": [
+ {
+ "index": "a",
+ "ranges": ["NULL < a < 3"],
+ "rowid_ordered": false,
+ "using_mrr": false,
+ "index_only": false,
+ "rows": 3,
+ "cost": 4.61,
+ "chosen": true
+ }
+ ],
+ "analyzing_index_merge_union": []
+ },
+ "chosen_range_access_summary": {
+ "range_access_plan": {
+ "type": "range_scan",
+ "index": "a",
+ "rows": 3,
+ "ranges": ["NULL < a < 3"]
+ },
+ "rows_for_plan": 3,
+ "cost_for_plan": 4.61,
+ "chosen": true
+ }
+ }
+ }
+ ]
+} 0 0
+drop table ten,t0;
+set optimizer_trace='enabled=off';
+#
+# MDEV-18528: Optimizer trace support for multi-table UPDATE and DELETE
+#
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t0 (a int, b int);
+insert into t0 select a,a from ten;
+alter table t0 add key(a);
+create table t1 like t0;
+insert into t1 select * from t0;
+explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 range a a 5 NULL 3 Using where
+1 SIMPLE t1 ref a a 5 test.t0.a 1
+select * from information_schema.optimizer_trace;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+explain delete from t0 where t0.a<3 {
+ "steps": [
+ {
+ "table": "t0",
+ "range_analysis": {
+ "table_scan": {
+ "rows": 10,
+ "cost": 6.122
+ },
+ "potential_range_indexes": [
+ {
+ "index": "a",
+ "usable": true,
+ "key_parts": ["a"]
+ }
+ ],
+ "setup_range_conditions": [],
+ "group_index_range": {
+ "chosen": false,
+ "cause": "no join"
+ },
+ "analyzing_range_alternatives": {
+ "range_scan_alternatives": [
+ {
+ "index": "a",
+ "ranges": ["NULL < a < 3"],
+ "rowid_ordered": false,
+ "using_mrr": false,
+ "index_only": false,
+ "rows": 3,
+ "cost": 4.61,
+ "chosen": true
+ }
+ ],
+ "analyzing_index_merge_union": []
+ },
+ "chosen_range_access_summary": {
+ "range_access_plan": {
+ "type": "range_scan",
+ "index": "a",
+ "rows": 3,
+ "ranges": ["NULL < a < 3"]
+ },
+ "rows_for_plan": 3,
+ "cost_for_plan": 4.61,
+ "chosen": true
+ }
+ }
+ }
+ ]
+} 0 0
+drop table ten,t0,t1;
diff --git a/mysql-test/main/opt_trace.test b/mysql-test/main/opt_trace.test
new file mode 100644
index 00000000000..f55cf57b82a
--- /dev/null
+++ b/mysql-test/main/opt_trace.test
@@ -0,0 +1,335 @@
+--source include/not_embedded.inc
+SELECT table_name, column_name FROM information_schema.columns where table_name="OPTIMIZER_TRACE";
+show variables like 'optimizer_trace';
+set optimizer_trace="enabled=on";
+show variables like 'optimizer_trace';
+set optimizer_trace="enabled=off";
+create table t1 (a int, b int);
+insert into t1 values (1,2),(2,3);
+
+create table t2 (b int);
+insert into t2 values (1),(2);
+
+analyze table t1;
+analyze table t2;
+create function f1 (a int) returns INT
+return 1;
+
+create view v1 as select * from t1 where t1.a=1;
+create view v2 as select * from t1 where t1.a=1 group by t1.b;
+set optimizer_trace="enabled=on";
+
+--echo # Mergeable views/derived tables
+select * from v1;
+select * from information_schema.OPTIMIZER_TRACE;
+select * from (select * from t1 where t1.a=1)q;
+select * from information_schema.OPTIMIZER_TRACE;
+
+--echo # Non-Mergeable views
+select * from v2;
+select * from information_schema.OPTIMIZER_TRACE;
+
+drop table t1,t2;
+drop view v1,v2;
+drop function f1;
+
+create table t1(a int, b int);
+insert into t1 values (0,0),(1,1),(2,1),(3,2),(4,3),
+(5,3),(6,3),(7,3),(8,3),(9,3);
+create table t2(a int, b int);
+insert into t2 values (0,0),(1,1),(2,1),(3,2),(4,3),
+(5,3),(6,3),(7,3),(8,3),(9,3);
+
+ANALYZE TABLE t1;
+ANALYZE TABLE t2;
+
+create view v1 as select a from t1 group by b;
+create view v2 as select a from t2;
+
+--echo # Mergeable view
+explain select * from v2 ;
+select * from information_schema.OPTIMIZER_TRACE;
+
+--echo # Non-Mergeable view
+explain select * from v1 ;
+select * from information_schema.OPTIMIZER_TRACE;
+drop table t1,t2;
+drop view v1,v2;
+
+--echo #
+--echo # print ref-keyues array
+--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, c int, key(a));
+insert into t1 select A.a*10 + B.a, A.a*10 + B.a, A.a*10 + B.a from t0 A, t0 B;
+
+create table t2(a int, b int, c int , key(a));
+insert into t2 select A.a*10 + B.a, A.a*10 + B.a, A.a*10 + B.a from t0 A, t0 B;
+
+analyze table t1;
+analyze table t2;
+
+explain select * from t1,t2 where t1.a=t2.b+2 and t2.a= t1.b;
+select * from information_schema.OPTIMIZER_TRACE;
+drop table t1,t2,t0;
+
+--echo #
+--echo # group_by min max optimization
+--echo #
+CREATE TABLE t1 (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, a INT NOT NULL, KEY(a));
+--disable_query_log
+INSERT INTO t1(a) VALUES (1), (2), (3), (4);
+INSERT INTO t1(a) SELECT a FROM t1;
+INSERT INTO t1(a) SELECT a FROM t1;
+INSERT INTO t1(a) SELECT a FROM t1;
+INSERT INTO t1(a) SELECT a FROM t1;
+INSERT INTO t1(a) SELECT a FROM t1;
+INSERT INTO t1(a) SELECT a FROM t1;
+INSERT INTO t1(a) SELECT a FROM t1;
+INSERT INTO t1(a) SELECT a FROM t1;
+INSERT INTO t1(a) SELECT a FROM t1;
+INSERT INTO t1(a) SELECT a FROM t1;
+INSERT INTO t1(a) SELECT a FROM t1;
+INSERT INTO t1(a) SELECT a FROM t1;
+INSERT INTO t1(a) SELECT a FROM t1;
+INSERT INTO t1(a) SELECT a FROM t1;
+--enable_query_log
+
+analyze table t1;
+EXPLAIN SELECT DISTINCT a FROM t1;
+select * from information_schema.OPTIMIZER_TRACE;
+drop table t1;
+
+--echo #
+--echo # With group by , where clause and MIN/MAX function
+--echo #
+CREATE TABLE t1 (a INT, b INT, c int, d int, KEY(a,b,c,d));
+INSERT INTO t1 VALUES (1,1,1,1), (2,2,2,2), (3,3,3,3), (4,4,4,4), (1,0,1,1), (3,2,3,3), (4,5,4,4);
+ANALYZE TABLE t1;
+EXPLAIN SELECT MIN(d) FROM t1 where b=2 and c=3 group by a;
+select * from information_schema.OPTIMIZER_TRACE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (id INT NOT NULL, a DATE, KEY(id,a));
+INSERT INTO t1 values (1,'2001-01-01'),(1,'2001-01-02'),
+ (1,'2001-01-03'),(1,'2001-01-04'),
+ (2,'2001-01-01'),(2,'2001-01-02'),
+ (2,'2001-01-03'),(2,'2001-01-04'),
+ (3,'2001-01-01'),(3,'2001-01-02'),
+ (3,'2001-01-03'),(3,'2001-01-04'),
+ (4,'2001-01-01'),(4,'2001-01-02'),
+ (4,'2001-01-03'),(4,'2001-01-04');
+set optimizer_trace='enabled=on';
+EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id;
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id;
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+drop table t1;
+
+--echo #
+--echo # Late ORDER BY optimization
+--echo #
+
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table one_k(a int primary key);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+create table t1 (
+ pk int not null,
+ a int,
+ b int,
+ c int,
+ filler char(100),
+ KEY a_a(c),
+ KEY a_c(a,c),
+ KEY a_b(a,b)
+);
+
+insert into t1
+select a, a,a,a, 'filler-dataaa' from test.one_k;
+update t1 set a=1 where pk between 0 and 180;
+update t1 set b=2 where pk between 0 and 20;
+analyze table t1;
+set optimizer_trace='enabled=on';
+explain select * from t1 where a=1 and b=2 order by c limit 1;
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+drop table t1,ten,one_k;
+
+--echo #
+--echo # TABLE ELIMINATION
+--echo #
+
+create table t1 (a int);
+insert into t1 values (0),(1),(2),(3);
+create table t0 as select * from t1;
+
+create table t2 (a int primary key, b int)
+ as select a, a as b from t1 where a in (1,2);
+
+create table t3 (a int primary key, b int)
+ as select a, a as b from t1 where a in (1,3);
+
+set optimizer_trace='enabled=on';
+
+analyze table t1;
+analyze table t2;
+analyze table t3;
+
+--echo # table t2 should be eliminated
+explain
+select t1.a from t1 left join t2 on t1.a=t2.a;
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+
+--echo # no tables should be eliminated
+explain select * from t1 left join t2 on t2.a=t1.a;
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+
+--echo # multiple tables are eliminated
+explain select t1.a from t1 left join (t2 join t3 on t2.b=t3.b) on t2.a=t1.a and t3.a=t1.a;
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+drop table t0, t1, t2, t3;
+
+--echo #
+--echo # IN subquery to sem-join is traced
+--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);
+insert into t1 values (0,0),(1,1),(2,2);
+create table t2 as select * from t1;
+
+create table t11(a int, b int);
+
+create table t10 (pk int, a int);
+insert into t10 select a,a from t0;
+create table t12 like t10;
+insert into t12 select * from t10;
+
+analyze table t1,t10;
+
+set optimizer_trace='enabled=on';
+explain extended select * from t1 where a in (select pk from t10);
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+drop table t0,t1,t11,t10,t12,t2;
+
+--echo #
+--echo # Selectivities for columns and indexes.
+--echo #
+
+create table t0 (a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+create table t1 (
+pk int,
+a int,
+b int,
+key pk(pk),
+key pk_a(pk,a),
+key pk_a_b(pk,a,b));
+insert into t1 select a,a,a from t0;
+
+ANALYZE TABLE t1 PERSISTENT FOR COLUMNS (a,b) INDEXES ();
+set @save_optimizer_use_condition_selectivity=@@optimizer_use_condition_selectivity;
+set @save_use_stat_tables= @@use_stat_tables;
+set @@optimizer_use_condition_selectivity=4;
+set @@use_stat_tables= PREFERABLY;
+set optimizer_trace='enabled=on';
+explain select * from t1 where pk = 2 and a=5 and b=1;
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
+set @@use_stat_tables= @save_use_stat_tables;
+drop table t0,t1;
+set optimizer_trace="enabled=off";
+
+--echo #
+--echo # Tests added to show that sub-statements are not traced
+--echo #
+
+create table t1(a int);
+insert into t1 values (1),(2),(3),(4);
+create table t2(a int);
+insert into t2 values (1),(2),(3),(4);
+delimiter |;
+create function f1(a int) returns int
+begin
+ declare a int default 0;
+ set a= a+ (select count(*) from t2);
+ return a;
+end|
+
+create function f2(a int) returns int
+begin
+ declare a int default 0;
+ select count(*) from t2 into a;
+ return a;
+end|
+
+delimiter ;|
+set optimizer_trace='enabled=on';
+select f1(a) from t1;
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+select f2(a) from t1;
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+drop table t1,t2;
+drop function f1;
+drop function f2;
+set optimizer_trace='enabled=off';
+
+--echo #
+--echo # MDEV-18489: Limit the memory used by the optimizer trace
+--echo #
+
+create table t1 (a int);
+insert into t1 values (1),(2);
+
+set optimizer_trace='enabled=on';
+set @save_optimizer_trace_max_mem_size= @@optimizer_trace_max_mem_size;
+select * from t1;
+select length(trace) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+
+set optimizer_trace_max_mem_size=100;
+select * from t1;
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+
+set optimizer_trace_max_mem_size=0;
+select * from t1;
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+drop table t1;
+set optimizer_trace='enabled=off';
+set @@optimizer_trace_max_mem_size= @save_optimizer_trace_max_mem_size;
+
+--echo #
+--echo # MDEV-18527: Optimizer trace for DELETE query shows table:null
+--echo #
+
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t0 (a int, b int);
+insert into t0 select a,a from ten;
+alter table t0 add key(a);
+
+set optimizer_trace=1;
+explain delete from t0 where t0.a<3;
+select * from information_schema.optimizer_trace;
+drop table ten,t0;
+set optimizer_trace='enabled=off';
+
+--echo #
+--echo # MDEV-18528: Optimizer trace support for multi-table UPDATE and DELETE
+--echo #
+
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t0 (a int, b int);
+insert into t0 select a,a from ten;
+alter table t0 add key(a);
+create table t1 like t0;
+insert into t1 select * from t0;
+explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3;
+select * from information_schema.optimizer_trace;
+drop table ten,t0,t1;
diff --git a/mysql-test/main/opt_trace_index_merge.result b/mysql-test/main/opt_trace_index_merge.result
new file mode 100644
index 00000000000..4c75465f958
--- /dev/null
+++ b/mysql-test/main/opt_trace_index_merge.result
@@ -0,0 +1,249 @@
+set @tmp_opt_switch= @@optimizer_switch;
+set optimizer_switch='index_merge_sort_intersection=on';
+set optimizer_trace='enabled=on';
+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, c int, filler char(100),
+key(a), key(b), key(c));
+insert into t1 select
+A.a * B.a*10 + C.a*100,
+A.a * B.a*10 + C.a*100,
+A.a,
+'filler'
+from t0 A, t0 B, t0 C;
+This should use union:
+explain select * from t1 where a=1 or b=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 2 Using union(a,b); Using where
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+explain select * from t1 where a=1 or b=1 {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "expanded_query": "select `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c`,`t1`.`filler` AS `filler` from `t1` where `t1`.`a` = 1 or `t1`.`b` = 1"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "condition_processing": {
+ "condition": "WHERE",
+ "original_condition": "t1.a = 1 or t1.b = 1",
+ "steps": [
+ {
+ "transformation": "equality_propagation",
+ "resulting_condition": "multiple equal(1, t1.a) or multiple equal(1, t1.b)"
+ },
+ {
+ "transformation": "constant_propagation",
+ "resulting_condition": "multiple equal(1, t1.a) or multiple equal(1, t1.b)"
+ },
+ {
+ "transformation": "trivial_condition_removal",
+ "resulting_condition": "multiple equal(1, t1.a) or multiple equal(1, t1.b)"
+ }
+ ]
+ }
+ },
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": []
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "range_analysis": {
+ "table_scan": {
+ "rows": 1000,
+ "cost": 231.69
+ },
+ "potential_range_indexes": [
+ {
+ "index": "a",
+ "usable": true,
+ "key_parts": ["a"]
+ },
+ {
+ "index": "b",
+ "usable": true,
+ "key_parts": ["b"]
+ },
+ {
+ "index": "c",
+ "usable": false,
+ "cause": "not applicable"
+ }
+ ],
+ "setup_range_conditions": [],
+ "group_index_range": {
+ "chosen": false,
+ "cause": "no group by or distinct"
+ },
+ "analyzing_range_alternatives": {
+ "range_scan_alternatives": [],
+ "analyzing_roworder_intersect": {
+ "cause": "too few roworder scans"
+ },
+ "analyzing_sort_intersect": {},
+ "analyzing_index_merge_union": [
+ {
+ "indexes_to_merge": [
+ {
+ "range_scan_alternatives": [
+ {
+ "index": "a",
+ "ranges": ["1 <= a <= 1"],
+ "rowid_ordered": true,
+ "using_mrr": false,
+ "index_only": true,
+ "rows": 1,
+ "cost": 2.21,
+ "chosen": true
+ }
+ ],
+ "index_to_merge": "a",
+ "cumulated_cost": 2.21
+ },
+ {
+ "range_scan_alternatives": [
+ {
+ "index": "b",
+ "ranges": ["1 <= b <= 1"],
+ "rowid_ordered": true,
+ "using_mrr": false,
+ "index_only": true,
+ "rows": 1,
+ "cost": 2.21,
+ "chosen": true
+ }
+ ],
+ "index_to_merge": "b",
+ "cumulated_cost": 4.42
+ }
+ ],
+ "cost_of_reading_ranges": 4.42,
+ "use_roworder_union": true,
+ "cause": "always cheaper than non roworder retrieval",
+ "analyzing_roworder_scans": [
+ {
+ "type": "range_scan",
+ "index": "a",
+ "rows": 1,
+ "ranges": ["1 <= a <= 1"],
+ "analyzing_roworder_intersect": {
+ "cause": "too few roworder scans"
+ }
+ },
+ {
+ "type": "range_scan",
+ "index": "b",
+ "rows": 1,
+ "ranges": ["1 <= b <= 1"],
+ "analyzing_roworder_intersect": {
+ "cause": "too few roworder scans"
+ }
+ }
+ ],
+ "index_roworder_union_cost": 6.2137,
+ "members": 2,
+ "chosen": true
+ }
+ ]
+ },
+ "chosen_range_access_summary": {
+ "range_access_plan": {
+ "type": "index_roworder_union",
+ "union_of": [
+ {
+ "type": "range_scan",
+ "index": "a",
+ "rows": 1,
+ "ranges": ["1 <= a <= 1"]
+ },
+ {
+ "type": "range_scan",
+ "index": "b",
+ "rows": 1,
+ "ranges": ["1 <= b <= 1"]
+ }
+ ]
+ },
+ "rows_for_plan": 2,
+ "cost_for_plan": 6.2137,
+ "chosen": true
+ }
+ }
+ },
+ {
+ "selectivity_for_indexes": [],
+ "selectivity_for_columns": []
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "range",
+ "resulting_rows": 2,
+ "cost": 6.2137,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "t1.a = 1 or t1.b = 1",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": "t1.a = 1 or t1.b = 1"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+drop table t0,t1;
+set optimizer_trace="enabled=off";
+set @@optimizer_switch= @tmp_opt_switch;
diff --git a/mysql-test/main/opt_trace_index_merge.test b/mysql-test/main/opt_trace_index_merge.test
new file mode 100644
index 00000000000..d5efaf81db5
--- /dev/null
+++ b/mysql-test/main/opt_trace_index_merge.test
@@ -0,0 +1,21 @@
+--source include/not_embedded.inc
+set @tmp_opt_switch= @@optimizer_switch;
+set optimizer_switch='index_merge_sort_intersection=on';
+set optimizer_trace='enabled=on';
+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, c int, filler char(100),
+ key(a), key(b), key(c));
+insert into t1 select
+ A.a * B.a*10 + C.a*100,
+ A.a * B.a*10 + C.a*100,
+ A.a,
+ 'filler'
+from t0 A, t0 B, t0 C;
+
+--echo This should use union:
+explain select * from t1 where a=1 or b=1;
+select * from information_schema.OPTIMIZER_TRACE;
+drop table t0,t1;
+set optimizer_trace="enabled=off";
+set @@optimizer_switch= @tmp_opt_switch;
diff --git a/mysql-test/main/opt_trace_index_merge_innodb.result b/mysql-test/main/opt_trace_index_merge_innodb.result
new file mode 100644
index 00000000000..a0f03e326a3
--- /dev/null
+++ b/mysql-test/main/opt_trace_index_merge_innodb.result
@@ -0,0 +1,242 @@
+create table t1
+(
+pk1 int not null,
+pk2 int not null,
+key1 int not null,
+key2 int not null,
+key (key1),
+key (key2),
+primary key (pk1, pk2)
+)engine=Innodb;
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+set optimizer_trace="enabled=on";
+set @tmp_index_merge_ror_cpk=@@optimizer_switch;
+set optimizer_switch='extended_keys=off';
+explain select * from t1 where pk1 != 0 and key1 = 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref PRIMARY,key1 key1 4 const 1 Using index condition
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+explain select * from t1 where pk1 != 0 and key1 = 1 {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "expanded_query": "select `t1`.`pk1` AS `pk1`,`t1`.`pk2` AS `pk2`,`t1`.`key1` AS `key1`,`t1`.`key2` AS `key2` from `t1` where `t1`.`pk1` <> 0 and `t1`.`key1` = 1"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "condition_processing": {
+ "condition": "WHERE",
+ "original_condition": "t1.pk1 <> 0 and t1.key1 = 1",
+ "steps": [
+ {
+ "transformation": "equality_propagation",
+ "resulting_condition": "t1.pk1 <> 0 and multiple equal(1, t1.key1)"
+ },
+ {
+ "transformation": "constant_propagation",
+ "resulting_condition": "t1.pk1 <> 0 and multiple equal(1, t1.key1)"
+ },
+ {
+ "transformation": "trivial_condition_removal",
+ "resulting_condition": "t1.pk1 <> 0 and multiple equal(1, t1.key1)"
+ }
+ ]
+ }
+ },
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": [
+ {
+ "table": "t1",
+ "field": "key1",
+ "equals": "1",
+ "null_rejecting": false
+ }
+ ]
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "range_analysis": {
+ "table_scan": {
+ "rows": 1000,
+ "cost": 206.1
+ },
+ "potential_range_indexes": [
+ {
+ "index": "PRIMARY",
+ "usable": true,
+ "key_parts": ["pk1", "pk2"]
+ },
+ {
+ "index": "key1",
+ "usable": true,
+ "key_parts": ["key1"]
+ },
+ {
+ "index": "key2",
+ "usable": false,
+ "cause": "not applicable"
+ }
+ ],
+ "setup_range_conditions": [],
+ "group_index_range": {
+ "chosen": false,
+ "cause": "no group by or distinct"
+ },
+ "analyzing_range_alternatives": {
+ "range_scan_alternatives": [
+ {
+ "index": "PRIMARY",
+ "ranges": ["pk1 < 0", "0 < pk1"],
+ "rowid_ordered": true,
+ "using_mrr": false,
+ "index_only": false,
+ "rows": 1001,
+ "cost": 203.59,
+ "chosen": true
+ },
+ {
+ "index": "key1",
+ "ranges": ["1 <= key1 <= 1"],
+ "rowid_ordered": true,
+ "using_mrr": false,
+ "index_only": false,
+ "rows": 1,
+ "cost": 2.21,
+ "chosen": true
+ }
+ ],
+ "analyzing_roworder_intersect": {
+ "intersecting_indexes": [
+ {
+ "index": "key1",
+ "index_scan_cost": 1,
+ "cumulateed_index_scan_cost": 1,
+ "disk_sweep_cost": 1.0014,
+ "cumulative_total_cost": 2.0014,
+ "usable": true,
+ "matching_rows_now": 1,
+ "intersect_covering_with_this_index": false,
+ "chosen": true
+ }
+ ],
+ "clustered_pk": {
+ "index_scan_cost": 0.002,
+ "cumulateed_index_scan_cost": 1.002,
+ "disk_sweep_cost": 1.0014,
+ "clustered_pk_added_to_intersect": false,
+ "cause": "cost"
+ },
+ "chosen": false,
+ "cause": "too few indexes to merge"
+ },
+ "analyzing_index_merge_union": []
+ },
+ "chosen_range_access_summary": {
+ "range_access_plan": {
+ "type": "range_scan",
+ "index": "key1",
+ "rows": 1,
+ "ranges": ["1 <= key1 <= 1"]
+ },
+ "rows_for_plan": 1,
+ "cost_for_plan": 2.21,
+ "chosen": true
+ }
+ }
+ },
+ {
+ "selectivity_for_indexes": [
+ {
+ "index_name": "PRIMARY",
+ "selectivity_from_index": 1.001
+ },
+ {
+ "index_name": "key1",
+ "selectivity_from_index": 0.001
+ }
+ ],
+ "selectivity_for_columns": []
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "ref",
+ "index": "key1",
+ "used_range_estimates": true,
+ "rows": 1,
+ "cost": 2,
+ "chosen": true
+ },
+ {
+ "type": "scan",
+ "chosen": false,
+ "cause": "cost"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "t1.key1 = 1 and t1.pk1 <> 0",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": "t1.pk1 <> 0"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+drop table t1;
+set @@optimizer_switch= @tmp_index_merge_ror_cpk;
+set optimizer_trace="enabled=off";
diff --git a/mysql-test/main/opt_trace_index_merge_innodb.test b/mysql-test/main/opt_trace_index_merge_innodb.test
new file mode 100644
index 00000000000..5e18185bf7f
--- /dev/null
+++ b/mysql-test/main/opt_trace_index_merge_innodb.test
@@ -0,0 +1,31 @@
+--source include/not_embedded.inc
+--source include/have_innodb.inc
+create table t1
+(
+ pk1 int not null,
+ pk2 int not null,
+ key1 int not null,
+ key2 int not null,
+ key (key1),
+ key (key2),
+ primary key (pk1, pk2)
+)engine=Innodb;
+
+--disable_query_log
+let $1=1000;
+while ($1)
+{
+ eval insert into t1 values (1+$1/10,$1 mod 100,$1,$1/100);
+ dec $1;
+}
+--enable_query_log
+analyze table t1;
+
+set optimizer_trace="enabled=on";
+set @tmp_index_merge_ror_cpk=@@optimizer_switch;
+set optimizer_switch='extended_keys=off';
+explain select * from t1 where pk1 != 0 and key1 = 1;
+select * from information_schema.OPTIMIZER_TRACE;
+drop table t1;
+set @@optimizer_switch= @tmp_index_merge_ror_cpk;
+set optimizer_trace="enabled=off";
diff --git a/mysql-test/main/opt_trace_security.result b/mysql-test/main/opt_trace_security.result
new file mode 100644
index 00000000000..2d66a0a9576
--- /dev/null
+++ b/mysql-test/main/opt_trace_security.result
@@ -0,0 +1,396 @@
+create database db1;
+use db1;
+create table t1(a int);
+insert into t1 values (1),(2),(3);
+create table t2(a int);
+CREATE USER 'foo'@'%';
+CREATE USER 'bar'@'%';
+create definer=foo SQL SECURITY definer view db1.v1 as select * from db1.t1;
+create definer=foo function f1 (a int) returns INT SQL SECURITY DEFINER
+BEGIN
+insert into t2 select * from t1;
+return a+1;
+END|
+set optimizer_trace="enabled=on";
+select * from db1.t1;
+ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't1'
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+ 0 1
+set optimizer_trace="enabled=off";
+grant select(a) on db1.t1 to 'foo'@'%';
+set optimizer_trace="enabled=on";
+select * from db1.t1;
+a
+1
+2
+3
+# INSUFFICIENT PRIVILEGES should be set to 1
+# Trace and Query should be empty
+# We need SELECT privilege on the table db1.t1;
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+ 0 1
+set optimizer_trace="enabled=off";
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+grant select on db1.t1 to 'foo'@'%';
+grant select on db1.t2 to 'foo'@'%';
+set optimizer_trace="enabled=on";
+#
+# SELECT privilege on the table db1.t1
+# The trace would be present.
+#
+select * from db1.t1;
+a
+1
+2
+3
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+select * from db1.t1 {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "expanded_query": "select `db1`.`t1`.`a` AS `a` from `t1`"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "table_scan": {
+ "rows": 3,
+ "cost": 2.0051
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": null,
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": null
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+set optimizer_trace="enabled=off";
+grant select on db1.v1 to 'foo'@'%';
+grant show view on db1.v1 to 'foo'@'%';
+grant select on db1.v1 to 'bar'@'%';
+grant show view on db1.v1 to 'bar'@'%';
+select current_user();
+current_user()
+foo@%
+set optimizer_trace="enabled=on";
+select * from db1.v1;
+a
+1
+2
+3
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+select * from db1.v1 {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "view": {
+ "table": "v1",
+ "select_id": 2,
+ "merged": true
+ }
+ },
+ {
+ "join_preparation": {
+ "select_id": 2,
+ "steps": [
+ {
+ "expanded_query": "/* select#2 */ select `db1`.`t1`.`a` AS `a` from `t1`"
+ }
+ ]
+ }
+ },
+ {
+ "expanded_query": "/* select#1 */ select `db1`.`t1`.`a` AS `a` from `v1`"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "table_scan": {
+ "rows": 3,
+ "cost": 2.0051
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": null,
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": null
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+set optimizer_trace="enabled=off";
+select current_user();
+current_user()
+bar@%
+set optimizer_trace="enabled=on";
+select * from db1.v1;
+a
+1
+2
+3
+#
+# INSUFFICIENT PRIVILEGES should be set to 1
+# Trace and Query should be empty
+# Privileges for the underlying tables of the
+# view should also be present for the current user
+#
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+ 0 1
+set optimizer_trace="enabled=off";
+grant execute on function db1.f1 to 'foo'@'%';
+grant execute on function db1.f1 to 'bar'@'%';
+grant select on db1.t1 to 'bar'@'%';
+grant insert on db1.t2 to 'foo'@'%';
+select current_user();
+current_user()
+foo@%
+set optimizer_trace="enabled=on";
+select db1.f1(a) from db1.t1;
+db1.f1(a)
+2
+3
+4
+select INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
+INSUFFICIENT_PRIVILEGES
+0
+set optimizer_trace="enabled=off";
+select current_user();
+current_user()
+bar@%
+set optimizer_trace="enabled=on";
+#
+# The trace should be empty, because the current user
+# does not have INSERT privilege for table t2 which is
+# used in the function f1
+#
+select db1.f1(a) from db1.t1;
+db1.f1(a)
+2
+3
+4
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+ 0 1
+set optimizer_trace="enabled=off";
+select current_user();
+current_user()
+root@localhost
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM foo;
+drop user if exists foo;
+drop user if exists bar;
+drop table db1.t1, db1.t2;
+drop database db1;
+#
+# Privilege checking for optimizer trace across connections
+#
+connection default;
+create database db1;
+use db1;
+create table t1(a int);
+insert into t1 values (1),(2),(3);
+create table t2(a int);
+CREATE USER 'foo'@'localhost';
+CREATE USER 'bar'@'localhost';
+grant all on *.* to foo@localhost with grant option;
+grant all on *.* to bar@localhost with grant option;
+connect con_foo,localhost, foo,, db1;
+connection default;
+connect con_bar,localhost, bar,, db1;
+connection default;
+create definer=foo@localhost SQL SECURITY definer view db1.v1 as select * from db1.t1;
+create function f1 (a int) returns INT SQL SECURITY DEFINER
+BEGIN
+insert into t2 select * from t1;
+return a+1;
+END|
+grant execute on function f1 to bar@localhost;
+connection con_foo;
+set optimizer_trace='enabled=on';
+select * from db1.t1;
+a
+1
+2
+3
+#
+# Test that security context changes are allowed when, and only
+# when, invoker has all global privileges.
+#
+select query, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
+query INSUFFICIENT_PRIVILEGES
+select * from db1.t1 0
+set optimizer_trace='enabled=off';
+connection con_bar;
+set optimizer_trace='enabled=on';
+select f1(a) from db1.t1;
+f1(a)
+2
+3
+4
+select query, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
+query INSUFFICIENT_PRIVILEGES
+select f1(a) from db1.t1 0
+set optimizer_trace='enabled=off';
+connection default;
+revoke shutdown on *.* from foo@localhost;
+disconnect con_foo;
+connect con_foo, localhost, foo,, db1;
+connection con_foo;
+set optimizer_trace='enabled=on';
+select f1(a) from db1.t1;
+f1(a)
+2
+3
+4
+#
+# Test to check if invoker has all global privileges or not, only then
+# the security context changes are allowed. The user has been revoked
+# shutdown privilege so INSUFFICIENT PRIVILEGES should be set to 1.
+#
+select query, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
+query INSUFFICIENT_PRIVILEGES
+ 1
+set optimizer_trace='enabled=off';
+connection default;
+select current_user();
+current_user()
+root@localhost
+select * from db1.v1;
+a
+1
+2
+3
+drop user foo@localhost, bar@localhost;
+drop view db1.v1;
+drop table db1.t1;
+drop database db1;
+set optimizer_trace="enabled=off";
diff --git a/mysql-test/main/opt_trace_security.test b/mysql-test/main/opt_trace_security.test
new file mode 100644
index 00000000000..9fa49190990
--- /dev/null
+++ b/mysql-test/main/opt_trace_security.test
@@ -0,0 +1,197 @@
+--source include/not_embedded.inc
+create database db1;
+use db1;
+create table t1(a int);
+insert into t1 values (1),(2),(3);
+create table t2(a int);
+
+CREATE USER 'foo'@'%';
+CREATE USER 'bar'@'%';
+
+create definer=foo SQL SECURITY definer view db1.v1 as select * from db1.t1;
+
+delimiter |;
+create definer=foo function f1 (a int) returns INT SQL SECURITY DEFINER
+BEGIN
+ insert into t2 select * from t1;
+ return a+1;
+END|
+delimiter ;|
+
+--change_user foo
+set optimizer_trace="enabled=on";
+--error 1142
+select * from db1.t1;
+select * from information_schema.OPTIMIZER_TRACE;
+set optimizer_trace="enabled=off";
+
+--change_user root
+grant select(a) on db1.t1 to 'foo'@'%';
+
+--change_user foo
+set optimizer_trace="enabled=on";
+select * from db1.t1;
+
+--echo # INSUFFICIENT PRIVILEGES should be set to 1
+--echo # Trace and Query should be empty
+--echo # We need SELECT privilege on the table db1.t1;
+
+select * from information_schema.OPTIMIZER_TRACE;
+set optimizer_trace="enabled=off";
+
+--change_user root
+select * from information_schema.OPTIMIZER_TRACE;
+grant select on db1.t1 to 'foo'@'%';
+grant select on db1.t2 to 'foo'@'%';
+
+--change_user foo
+set optimizer_trace="enabled=on";
+
+--echo #
+--echo # SELECT privilege on the table db1.t1
+--echo # The trace would be present.
+--echo #
+select * from db1.t1;
+select * from information_schema.OPTIMIZER_TRACE;
+set optimizer_trace="enabled=off";
+
+--change_user root
+
+grant select on db1.v1 to 'foo'@'%';
+grant show view on db1.v1 to 'foo'@'%';
+
+grant select on db1.v1 to 'bar'@'%';
+grant show view on db1.v1 to 'bar'@'%';
+
+--change_user foo
+select current_user();
+set optimizer_trace="enabled=on";
+select * from db1.v1;
+select * from information_schema.OPTIMIZER_TRACE;
+set optimizer_trace="enabled=off";
+
+--change_user bar
+select current_user();
+set optimizer_trace="enabled=on";
+select * from db1.v1;
+--echo #
+--echo # INSUFFICIENT PRIVILEGES should be set to 1
+--echo # Trace and Query should be empty
+--echo # Privileges for the underlying tables of the
+--echo # view should also be present for the current user
+--echo #
+select * from information_schema.OPTIMIZER_TRACE;
+set optimizer_trace="enabled=off";
+
+--change_user root
+grant execute on function db1.f1 to 'foo'@'%';
+grant execute on function db1.f1 to 'bar'@'%';
+
+grant select on db1.t1 to 'bar'@'%';
+grant insert on db1.t2 to 'foo'@'%';
+
+--change_user foo
+select current_user();
+set optimizer_trace="enabled=on";
+
+select db1.f1(a) from db1.t1;
+select INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
+set optimizer_trace="enabled=off";
+
+--change_user bar
+select current_user();
+set optimizer_trace="enabled=on";
+--echo #
+--echo # The trace should be empty, because the current user
+--echo # does not have INSERT privilege for table t2 which is
+--echo # used in the function f1
+--echo #
+select db1.f1(a) from db1.t1;
+select * from information_schema.OPTIMIZER_TRACE;
+set optimizer_trace="enabled=off";
+
+--change_user root
+select current_user();
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM foo;
+
+--change_user root
+drop user if exists foo;
+drop user if exists bar;
+drop table db1.t1, db1.t2;
+drop database db1;
+
+
+--echo #
+--echo # Privilege checking for optimizer trace across connections
+--echo #
+
+connection default;
+create database db1;
+use db1;
+create table t1(a int);
+insert into t1 values (1),(2),(3);
+create table t2(a int);
+
+CREATE USER 'foo'@'localhost';
+CREATE USER 'bar'@'localhost';
+grant all on *.* to foo@localhost with grant option;
+grant all on *.* to bar@localhost with grant option;
+#grant select on db1.t1 to bar@localhost;
+#grant insert on db1.t2 to bar@localhost;
+
+connect (con_foo,localhost, foo,, db1);
+connection default;
+connect (con_bar,localhost, bar,, db1);
+connection default;
+create definer=foo@localhost SQL SECURITY definer view db1.v1 as select * from db1.t1;
+
+delimiter |;
+create function f1 (a int) returns INT SQL SECURITY DEFINER
+BEGIN
+ insert into t2 select * from t1;
+ return a+1;
+END|
+delimiter ;|
+
+grant execute on function f1 to bar@localhost;
+
+connection con_foo;
+set optimizer_trace='enabled=on';
+select * from db1.t1;
+--echo #
+--echo # Test that security context changes are allowed when, and only
+--echo # when, invoker has all global privileges.
+--echo #
+select query, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
+set optimizer_trace='enabled=off';
+
+connection con_bar;
+set optimizer_trace='enabled=on';
+select f1(a) from db1.t1;
+select query, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
+set optimizer_trace='enabled=off';
+
+connection default;
+revoke shutdown on *.* from foo@localhost;
+disconnect con_foo;
+connect (con_foo, localhost, foo,, db1);
+
+connection con_foo;
+set optimizer_trace='enabled=on';
+select f1(a) from db1.t1;
+--echo #
+--echo # Test to check if invoker has all global privileges or not, only then
+--echo # the security context changes are allowed. The user has been revoked
+--echo # shutdown privilege so INSUFFICIENT PRIVILEGES should be set to 1.
+--echo #
+select query, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
+set optimizer_trace='enabled=off';
+
+connection default;
+select current_user();
+select * from db1.v1;
+drop user foo@localhost, bar@localhost;
+drop view db1.v1;
+drop table db1.t1;
+drop database db1;
+set optimizer_trace="enabled=off";
diff --git a/mysql-test/main/type_timestamp.result b/mysql-test/main/type_timestamp.result
index c2af8952f4f..a8e2cbb36c6 100644
--- a/mysql-test/main/type_timestamp.result
+++ b/mysql-test/main/type_timestamp.result
@@ -1164,5 +1164,14 @@ NULL
NULL
DROP TABLE t1, t2, t3;
#
+# MDEV-18447 Assertion `!is_zero_datetime()' failed in Timestamp_or_zero_datetime::tv
+#
+CREATE TABLE t1 (a TIMESTAMP DEFAULT 0, b TIMESTAMP DEFAULT 0, c TIME DEFAULT 0);
+INSERT INTO t1 VALUES (0,0,0);
+SELECT c IN (GREATEST(a,b)) FROM t1;
+c IN (GREATEST(a,b))
+0
+DROP TABLE t1;
+#
# End of 10.4 tests
#
diff --git a/mysql-test/main/type_timestamp.test b/mysql-test/main/type_timestamp.test
index 8b64fe0bfc3..08ca173ca02 100644
--- a/mysql-test/main/type_timestamp.test
+++ b/mysql-test/main/type_timestamp.test
@@ -760,6 +760,14 @@ CREATE TABLE t3 (pk INT PRIMARY KEY, b TIMESTAMP) ENGINE=MyISAM;
SELECT ( SELECT b FROM t1 LIMIT 1 ) AS sq FROM t2 LEFT JOIN t3 USING (pk);
DROP TABLE t1, t2, t3;
+--echo #
+--echo # MDEV-18447 Assertion `!is_zero_datetime()' failed in Timestamp_or_zero_datetime::tv
+--echo #
+
+CREATE TABLE t1 (a TIMESTAMP DEFAULT 0, b TIMESTAMP DEFAULT 0, c TIME DEFAULT 0);
+INSERT INTO t1 VALUES (0,0,0);
+SELECT c IN (GREATEST(a,b)) FROM t1;
+DROP TABLE t1;
--echo #
--echo # End of 10.4 tests
diff --git a/mysql-test/suite/funcs_1/r/is_columns_is.result b/mysql-test/suite/funcs_1/r/is_columns_is.result
index dfaa5d75137..386b0f07f98 100644
--- a/mysql-test/suite/funcs_1/r/is_columns_is.result
+++ b/mysql-test/suite/funcs_1/r/is_columns_is.result
@@ -205,6 +205,10 @@ def information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_SCHEMA 10 NULL YES varc
def information_schema KEY_COLUMN_USAGE TABLE_CATALOG 4 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL
def information_schema KEY_COLUMN_USAGE TABLE_NAME 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL
def information_schema KEY_COLUMN_USAGE TABLE_SCHEMA 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL
+def information_schema OPTIMIZER_TRACE INSUFFICIENT_PRIVILEGES 4 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(1) select NEVER NULL
+def information_schema OPTIMIZER_TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE 3 0 NO int NULL NULL 10 0 NULL NULL NULL int(20) select NEVER NULL
+def information_schema OPTIMIZER_TRACE QUERY 1 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL
+def information_schema OPTIMIZER_TRACE TRACE 2 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL
def information_schema PARAMETERS CHARACTER_MAXIMUM_LENGTH 8 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL
def information_schema PARAMETERS CHARACTER_OCTET_LENGTH 9 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL
def information_schema PARAMETERS CHARACTER_SET_NAME 13 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL
@@ -743,6 +747,10 @@ NULL information_schema KEY_COLUMN_USAGE POSITION_IN_UNIQUE_CONSTRAINT bigint NU
3.0000 information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema KEY_COLUMN_USAGE REFERENCED_COLUMN_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
+1.0000 information_schema OPTIMIZER_TRACE QUERY longtext 4294967295 4294967295 utf8 utf8_general_ci longtext
+1.0000 information_schema OPTIMIZER_TRACE TRACE longtext 4294967295 4294967295 utf8 utf8_general_ci longtext
+NULL information_schema OPTIMIZER_TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE int NULL NULL NULL NULL int(20)
+NULL information_schema OPTIMIZER_TRACE INSUFFICIENT_PRIVILEGES tinyint NULL NULL NULL NULL tinyint(1)
3.0000 information_schema PARAMETERS SPECIFIC_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512)
3.0000 information_schema PARAMETERS SPECIFIC_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema PARAMETERS SPECIFIC_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
diff --git a/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result b/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result
index 96fb1e286c0..97346c4648d 100644
--- a/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result
+++ b/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result
@@ -205,6 +205,10 @@ def information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_SCHEMA 10 NULL YES varc
def information_schema KEY_COLUMN_USAGE TABLE_CATALOG 4 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL
def information_schema KEY_COLUMN_USAGE TABLE_NAME 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL
def information_schema KEY_COLUMN_USAGE TABLE_SCHEMA 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL
+def information_schema OPTIMIZER_TRACE INSUFFICIENT_PRIVILEGES 4 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(1) NEVER NULL
+def information_schema OPTIMIZER_TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE 3 0 NO int NULL NULL 10 0 NULL NULL NULL int(20) NEVER NULL
+def information_schema OPTIMIZER_TRACE QUERY 1 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL
+def information_schema OPTIMIZER_TRACE TRACE 2 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL
def information_schema PARAMETERS CHARACTER_MAXIMUM_LENGTH 8 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL
def information_schema PARAMETERS CHARACTER_OCTET_LENGTH 9 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL
def information_schema PARAMETERS CHARACTER_SET_NAME 13 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL
@@ -743,6 +747,10 @@ NULL information_schema KEY_COLUMN_USAGE POSITION_IN_UNIQUE_CONSTRAINT bigint NU
3.0000 information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema KEY_COLUMN_USAGE REFERENCED_COLUMN_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
+1.0000 information_schema OPTIMIZER_TRACE QUERY longtext 4294967295 4294967295 utf8 utf8_general_ci longtext
+1.0000 information_schema OPTIMIZER_TRACE TRACE longtext 4294967295 4294967295 utf8 utf8_general_ci longtext
+NULL information_schema OPTIMIZER_TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE int NULL NULL NULL NULL int(20)
+NULL information_schema OPTIMIZER_TRACE INSUFFICIENT_PRIVILEGES tinyint NULL NULL NULL NULL tinyint(1)
3.0000 information_schema PARAMETERS SPECIFIC_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512)
3.0000 information_schema PARAMETERS SPECIFIC_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema PARAMETERS SPECIFIC_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
diff --git a/mysql-test/suite/funcs_1/r/is_tables_is.result b/mysql-test/suite/funcs_1/r/is_tables_is.result
index 5fee1e0050a..9af3aa860a0 100644
--- a/mysql-test/suite/funcs_1/r/is_tables_is.result
+++ b/mysql-test/suite/funcs_1/r/is_tables_is.result
@@ -489,6 +489,31 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG def
TABLE_SCHEMA information_schema
+TABLE_NAME OPTIMIZER_TRACE
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 11
+ROW_FORMAT DYNAMIC_OR_PAGE
+TABLE_ROWS #TBLR#
+AVG_ROW_LENGTH #ARL#
+DATA_LENGTH #DL#
+MAX_DATA_LENGTH #MDL#
+INDEX_LENGTH #IL#
+DATA_FREE #DF#
+AUTO_INCREMENT NULL
+CREATE_TIME #CRT#
+UPDATE_TIME #UT#
+CHECK_TIME #CT#
+TABLE_COLLATION utf8_general_ci
+CHECKSUM NULL
+CREATE_OPTIONS #CO#
+TABLE_COMMENT #TC#
+MAX_INDEX_LENGTH #MIL#
+TEMPORARY Y
+user_comment
+Separator -----------------------------------------------------
+TABLE_CATALOG def
+TABLE_SCHEMA information_schema
TABLE_NAME PARAMETERS
TABLE_TYPE SYSTEM VIEW
ENGINE MYISAM_OR_MARIA
@@ -1530,6 +1555,31 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG def
TABLE_SCHEMA information_schema
+TABLE_NAME OPTIMIZER_TRACE
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 11
+ROW_FORMAT DYNAMIC_OR_PAGE
+TABLE_ROWS #TBLR#
+AVG_ROW_LENGTH #ARL#
+DATA_LENGTH #DL#
+MAX_DATA_LENGTH #MDL#
+INDEX_LENGTH #IL#
+DATA_FREE #DF#
+AUTO_INCREMENT NULL
+CREATE_TIME #CRT#
+UPDATE_TIME #UT#
+CHECK_TIME #CT#
+TABLE_COLLATION utf8_general_ci
+CHECKSUM NULL
+CREATE_OPTIONS #CO#
+TABLE_COMMENT #TC#
+MAX_INDEX_LENGTH #MIL#
+TEMPORARY Y
+user_comment
+Separator -----------------------------------------------------
+TABLE_CATALOG def
+TABLE_SCHEMA information_schema
TABLE_NAME PARAMETERS
TABLE_TYPE SYSTEM VIEW
ENGINE MYISAM_OR_MARIA
diff --git a/mysql-test/suite/funcs_1/r/is_tables_is_embedded.result b/mysql-test/suite/funcs_1/r/is_tables_is_embedded.result
index 5fee1e0050a..9af3aa860a0 100644
--- a/mysql-test/suite/funcs_1/r/is_tables_is_embedded.result
+++ b/mysql-test/suite/funcs_1/r/is_tables_is_embedded.result
@@ -489,6 +489,31 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG def
TABLE_SCHEMA information_schema
+TABLE_NAME OPTIMIZER_TRACE
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 11
+ROW_FORMAT DYNAMIC_OR_PAGE
+TABLE_ROWS #TBLR#
+AVG_ROW_LENGTH #ARL#
+DATA_LENGTH #DL#
+MAX_DATA_LENGTH #MDL#
+INDEX_LENGTH #IL#
+DATA_FREE #DF#
+AUTO_INCREMENT NULL
+CREATE_TIME #CRT#
+UPDATE_TIME #UT#
+CHECK_TIME #CT#
+TABLE_COLLATION utf8_general_ci
+CHECKSUM NULL
+CREATE_OPTIONS #CO#
+TABLE_COMMENT #TC#
+MAX_INDEX_LENGTH #MIL#
+TEMPORARY Y
+user_comment
+Separator -----------------------------------------------------
+TABLE_CATALOG def
+TABLE_SCHEMA information_schema
TABLE_NAME PARAMETERS
TABLE_TYPE SYSTEM VIEW
ENGINE MYISAM_OR_MARIA
@@ -1530,6 +1555,31 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG def
TABLE_SCHEMA information_schema
+TABLE_NAME OPTIMIZER_TRACE
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 11
+ROW_FORMAT DYNAMIC_OR_PAGE
+TABLE_ROWS #TBLR#
+AVG_ROW_LENGTH #ARL#
+DATA_LENGTH #DL#
+MAX_DATA_LENGTH #MDL#
+INDEX_LENGTH #IL#
+DATA_FREE #DF#
+AUTO_INCREMENT NULL
+CREATE_TIME #CRT#
+UPDATE_TIME #UT#
+CHECK_TIME #CT#
+TABLE_COLLATION utf8_general_ci
+CHECKSUM NULL
+CREATE_OPTIONS #CO#
+TABLE_COMMENT #TC#
+MAX_INDEX_LENGTH #MIL#
+TEMPORARY Y
+user_comment
+Separator -----------------------------------------------------
+TABLE_CATALOG def
+TABLE_SCHEMA information_schema
TABLE_NAME PARAMETERS
TABLE_TYPE SYSTEM VIEW
ENGINE MYISAM_OR_MARIA
diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def
index 4fe68a794fd..0ad0327f6fc 100644
--- a/mysql-test/suite/galera/disabled.def
+++ b/mysql-test/suite/galera/disabled.def
@@ -51,7 +51,6 @@ galera.galera_var_reject_queries : assertion in inline_mysql_socket_send
query_cache : MDEV-18137: Galera test failure on query_cache
galera.galera_autoinc_sst_mariabackup : MDEV-18177 Galera test failure on galera_autoinc_sst_mariabackup
galera.galera_ist_mariabackup : Leaves port open
-galera.galera_sst_rsync2 : MDEV-18178 Galera test failure on galera_sst_rsync2
galera.galera_kill_largechanges : MDEV-18179 Galera test failure on galera.galera_kill_largechanges
galera.galera_concurrent_ctas : MDEV-18180 Galera test failure on galera.galera_concurrent_ctas
galera.galera_var_retry_autocommit: MDEV-18181 Galera test failure on galera.galera_var_retry_autocommit
diff --git a/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result b/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result
index 604b24a8fab..a0a45446eff 100644
--- a/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result
+++ b/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SET SESSION wsrep_sync_wait = 0;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 LONGBLOB) ENGINE=InnoDB;
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_sst_rsync2.result b/mysql-test/suite/galera/r/galera_sst_rsync2.result
index ff85a7d6c0f..d41d0d34e75 100644
--- a/mysql-test/suite/galera/r/galera_sst_rsync2.result
+++ b/mysql-test/suite/galera/r/galera_sst_rsync2.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
Performing State Transfer on a server that has been shut down cleanly and restarted
diff --git a/mysql-test/suite/galera/r/galera_var_load_data_splitting.result b/mysql-test/suite/galera/r/galera_var_load_data_splitting.result
index 7c5fd44356e..9078e9ea985 100644
--- a/mysql-test/suite/galera/r/galera_var_load_data_splitting.result
+++ b/mysql-test/suite/galera/r/galera_var_load_data_splitting.result
@@ -3,6 +3,8 @@ connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
SET GLOBAL wsrep_load_data_splitting = TRUE;
+Warnings:
+Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release
connection node_2;
SELECT COUNT(*) = 95000 FROM t1;
COUNT(*) = 95000
@@ -11,4 +13,6 @@ wsrep_last_committed_diff
1
connection node_1;
SET GLOBAL wsrep_load_data_splitting = 1;;
+Warnings:
+Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf b/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf
index 0d05038f2fb..af4fedf12ce 100644
--- a/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf
+++ b/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf
@@ -5,7 +5,5 @@
[mysqld.1]
wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true'
-wsrep_sync_wait=0
[mysqld.2]
wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true'
-wsrep_sync_wait=0
diff --git a/mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result b/mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result
index d612e9377a9..3543feff78c 100644
--- a/mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result
+++ b/mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result
@@ -25,5 +25,4 @@ COUNT(*) = 1
DROP TABLE t1;
connection node_3;
Resuming node ...
-connection node_3;
CALL mtr.add_suppression("WSREP: gcs_caused() returned -1 \\(Operation not permitted\\)");
diff --git a/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test b/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test
index aa733442b92..a4767928681 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test
+++ b/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test
@@ -56,8 +56,8 @@ DROP TABLE t1;
# Reconnect node #3 so that MTR's end-of-test checks can run
---source include/galera_resume.inc
--connection node_3
+--source include/galera_resume.inc
--source include/wait_until_connected_again.inc
--disable_query_log
diff --git a/mysql-test/suite/innodb/r/alter_varchar_change.result b/mysql-test/suite/innodb/r/alter_varchar_change.result
index df7d49ca088..25adde6ffe4 100644
--- a/mysql-test/suite/innodb/r/alter_varchar_change.result
+++ b/mysql-test/suite/innodb/r/alter_varchar_change.result
@@ -15,7 +15,7 @@ SET @idx1_id = 0;
CREATE TABLE t1(f1 INT NOT NULL,
f2 VARCHAR(100) PRIMARY KEY)ENGINE=InnoDB;
CALL get_table_id("test/t1", @tbl_id);
-ALTER TABLE t1 MODIFY f2 VARCHAR(200);
+ALTER TABLE t1 MODIFY f2 VARCHAR(200), ALGORITHM=INSTANT;
CALL get_table_id("test/t1", @tbl1_id);
SELECT @tbl1_id = @tbl_id;
@tbl1_id = @tbl_id
@@ -32,7 +32,7 @@ CREATE TABLE t1(f1 INT NOT NULL,
f2 VARCHAR(100),
INDEX idx(f2))ENGINE=InnoDB;
CALL get_table_id("test/t1", @tbl_id);
-ALTER TABLE t1 MODIFY f2 VARCHAR(200);
+ALTER TABLE t1 MODIFY f2 VARCHAR(200), ALGORITHM=INSTANT;
CALL get_table_id("test/t1", @tbl1_id);
SELECT @tbl1_id = @tbl_id;
@tbl1_id = @tbl_id
@@ -49,7 +49,7 @@ CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100), f3 VARCHAR(100),
INDEX idx(f2, f3), index idx1(f3, f2))ENGINE=InnoDB;
CALL get_table_id("test/t1", @tbl_id);
CALL get_index_id(@tbl_id, "idx", @idx_id);
-ALTER TABLE t1 MODIFY f2 VARCHAR(200), MODIFY f3 VARCHAR(150);
+ALTER TABLE t1 MODIFY f2 VARCHAR(200), MODIFY f3 VARCHAR(150), ALGORITHM=INSTANT;
CALL get_table_id("test/t1", @tbl1_id);
CALL get_index_id(@tbl1_id, "idx", @idx1_id);
SELECT @tbl1_id = @tbl_id;
@@ -72,7 +72,7 @@ CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100),
INDEX idx(f2(40)))ENGINE=InnoDB;
CALL get_table_id("test/t1", @tbl_id);
CALL get_index_id(@tbl_id, "idx", @idx_id);
-ALTER TABLE t1 MODIFY f2 VARCHAR(200);
+ALTER TABLE t1 MODIFY f2 VARCHAR(200), ALGORITHM=INSTANT;
CALL get_table_id("test/t1", @tbl1_id);
CALL get_index_id(@tbl1_id, "idx", @idx1_id);
SELECT @tbl1_id = @tbl_id;
@@ -93,7 +93,7 @@ CREATE TABLE t1(f1 INT NOT NULL,
f2 VARCHAR(100), FULLTEXT idx(f2))ENGINE=InnoDB;
CALL get_table_id("test/t1", @tbl_id);
CALL get_index_id(@tbl_id, "idx", @idx_id);
-ALTER TABLE t1 MODIFY f2 VARCHAR(200);
+ALTER TABLE t1 MODIFY f2 VARCHAR(200), ALGORITHM=INSTANT;
CALL get_table_id("test/t1", @tbl1_id);
CALL get_index_id(@tbl1_id, "idx", @idx1_id);
SELECT @tbl1_id = @tbl_id;
@@ -117,7 +117,7 @@ INDEX idx(f3))ENGINE=InnoDB;
INSERT INTO t1(f1, f2) VALUES(1, repeat('a', 40));
CALL get_table_id("test/t1", @tbl_id);
CALL get_index_id(@tbl_id, "idx", @idx_id);
-ALTER TABLE t1 MODIFY f2 VARCHAR(100);
+ALTER TABLE t1 MODIFY f2 VARCHAR(100), ALGORITHM=INSTANT;
CALL get_table_id("test/t1", @tbl1_id);
CALL get_index_id(@tbl1_id, "idx", @idx1_id);
SELECT @tbl1_id = @tbl_id;
@@ -163,7 +163,7 @@ f2 VARCHAR(100),
INDEX idx(f2(10)))ENGINE=InnoDB;
CALL get_table_id("test/t1", @tbl_id);
CALL get_index_id(@tbl_id, "idx", @idx_id);
-ALTER TABLE t1 MODIFY f2 VARCHAR(200), DROP INDEX idx, ADD INDEX idx(f2(10));
+ALTER TABLE t1 MODIFY f2 VARCHAR(200), DROP INDEX idx, ADD INDEX idx(f2(10)), ALGORITHM=INSTANT;
CALL get_table_id("test/t1", @tbl1_id);
CALL get_index_id(@tbl1_id, "idx", @idx1_id);
SELECT @tbl1_id = @tbl_id;
@@ -251,7 +251,7 @@ CREATE TABLE t1(f1 INT NOT NULL,
f2 VARCHAR(100),
INDEX idx(f2))ENGINE=InnoDB;
CALL get_table_id("test/t1", @tbl_id);
-ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT;
+ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT, ALGORITHM=INSTANT;
CALL get_table_id("test/t1", @tbl1_id);
SELECT @tbl1_id = @tbl_id;
@tbl1_id = @tbl_id
@@ -267,7 +267,7 @@ t1 CREATE TABLE `t1` (
DROP TABLE t1;
CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100) PRIMARY KEY)ENGINE=InnoDB;
CALL get_table_id("test/t1", @tbl_id);
-ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT;
+ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT, ALGORITHM=INSTANT;
CALL get_table_id("test/t1", @tbl1_id);
SELECT @tbl1_id = @tbl_id;
@tbl1_id = @tbl_id
diff --git a/mysql-test/suite/innodb/r/instant_alter_bugs.result b/mysql-test/suite/innodb/r/instant_alter_bugs.result
index 91298859e42..5284d021c67 100644
--- a/mysql-test/suite/innodb/r/instant_alter_bugs.result
+++ b/mysql-test/suite/innodb/r/instant_alter_bugs.result
@@ -128,3 +128,50 @@ HANDLER h READ `PRIMARY` PREV WHERE 0;
pk f1 f2 f3 f4 f5 f6 f7 f8 filler
HANDLER h CLOSE;
DROP TABLE t1;
+create table t (
+a varchar(9),
+b int,
+c int,
+row_start bigint unsigned generated always as row start invisible,
+row_end bigint unsigned generated always as row end invisible,
+period for system_time (row_start, row_end)
+) engine=innodb row_format=compressed with system versioning;
+insert into t values (repeat('a', 9), 1, 1);
+set @@system_versioning_alter_history = keep;
+alter table t modify a varchar(10), algorithm=instant;
+alter table t change b bb int, algorithm=instant;
+alter table t modify c int without system versioning, algorithm=instant;
+set @@system_versioning_alter_history = error;
+check table t;
+Table Op Msg_type Msg_text
+test.t check status OK
+drop table t;
+#
+# MDEV-18219 Assertion `index->n_core_null_bytes <= ...' failed
+# in rec_init_offsets after instant DROP COLUMN
+#
+CREATE TABLE t1 (a INT, b INT NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+(0,9),(2,7),(3,1),(3,4),(8,4),(3,7),(6,1),(3,8),(1,2),(4,1),(0,8),(5,3),
+(1,3),(1,6),(2,1),(8,7),(6,0),(1,9),(9,4),(0,6),(9,3),(0,9),(9,4),(2,4),
+(2,7),(7,8),(8,2),(2,5),(6,1),(4,5),(5,3),(6,8),(4,9),(5,7),(7,5),(5,1),
+(8,8),(5,7),(3,8),(0,1),(8,4),(8,3),(9,7),(4,8),(1,1),(0,4),(2,6),(8,5),
+(8,8),(8,7),(6,7),(1,7),(9,6),(3,6),(1,9),(0,3),(5,3),(2,4),(0,6),(2,0),
+(6,5),(1,6),(2,4),(9,1),(3,0),(6,4),(1,3),(0,8),(3,5),(3,1),(8,9),(9,9),
+(7,9),(4,5),(2,2),(3,8),(0,8),(7,1),(2,0),(1,5),(7,3),(4,4),(3,9),(7,2),
+(6,2),(0,4),(2,0),(1,5),(5,7),(4,5),(3,7),(6,0),(2,1),(5,0),(1,0),(2,0),
+(8,4),(5,7),(3,5),(0,5),(7,6),(5,9),(1,2),(4,2),(8,5),(8,7),(2,8),(1,8),
+(4,3),(1,6),(7,8),(3,7),(4,6),(1,1),(3,0),(1,6),(2,0),(3,4),(4,8),(3,9),
+(8,0),(4,9),(4,0),(3,9),(6,4),(7,4),(5,8),(4,7),(7,3),(5,9),(2,3),(7,3),
+(0,4),(5,9),(9,8),(4,2),(3,6),(2,6),(1,8),(7,0),(0,0),(2,3),(1,2),(3,3),
+(2,7),(6,0),(9,0),(6,9),(4,6),(9,8),(0,7),(9,1),(9,6),(4,3),(7,7),(7,7),
+(4,1),(4,7),(7,3),(2,8),(5,8),(8,9),(3,9),(7,7),(0,8),(4,9),(3,2),(5,0),
+(1,7),(0,3),(2,9),(9,7),(7,5),(6,9),(8,5),(3,6),(1,1),(2,8),(7,9),(4,9),
+(6,6),(5,9),(5,3),(9,8),(3,3),(5,6),(0,9),(3,9),(7,9),(7,3),(5,2),(1,4),
+(4,4),(8,2),(2,2),(8,3),(9,1),(4,9),(9,8),(1,8),(1,8),(9,1),(1,1),(3,0),
+(4,6),(9,3),(3,3),(5,2),(0,1),(3,4),(3,2),(1,3),(4,4),(7,0),(4,6),(7,2),
+(4,5),(8,7),(7,8),(8,1),(3,5),(0,6),(3,5),(2,1),(4,4),(3,4),(2,1),(4,1);
+INSERT INTO t1 SELECT * FROM t1;
+ALTER TABLE t1 DROP a;
+ALTER TABLE t1 ADD vb INT AS (b) VIRTUAL;
+DROP TABLE t1;
diff --git a/mysql-test/suite/innodb/r/instant_alter_import.result b/mysql-test/suite/innodb/r/instant_alter_import.result
new file mode 100644
index 00000000000..2d9a39f7886
--- /dev/null
+++ b/mysql-test/suite/innodb/r/instant_alter_import.result
@@ -0,0 +1,72 @@
+set default_storage_engine=innodb;
+#
+# MDEV-18295 IMPORT TABLESPACE fails with instant-altered tables
+#
+create table t2 (x int, z int default 41);
+alter table t2 discard tablespace;
+create table t1 (x int);
+insert into t1 values (1);
+alter table t1 add z int default 42, algorithm instant;
+select * from t1;
+x z
+1 42
+flush tables t1 for export;
+unlock tables;
+# The metadata has to be updated to instant ADD COLUMN.
+alter table t2 import tablespace;
+select * from t2;
+x z
+1 42
+insert into t2 set x=2;
+select * from t2;
+x z
+1 42
+2 41
+alter table t1 discard tablespace;
+flush tables t2 for export;
+unlock tables;
+# Both the metadata and the data file used instant ADD COLUMN.
+alter table t1 import tablespace;
+select * from t1;
+x z
+1 42
+2 41
+drop table t2;
+create table t2 select * from t1;
+alter table t1 discard tablespace;
+flush tables t2 for export;
+unlock tables;
+# The instant ADD COLUMN has to be removed from the metadata.
+alter table t1 import tablespace;
+select * from t1;
+x z
+1 42
+2 41
+# Remove metadata for instant DROP COLUMN, then import
+alter table t1 drop x, add column x int first, algorithm instant;
+select * from t1;
+x z
+NULL 42
+NULL 41
+alter table t1 discard tablespace;
+alter table t1 import tablespace;
+select * from t1;
+x z
+1 42
+2 41
+# Import a data file that contains instant DROP COLUMN metadata
+alter table t2 drop x;
+alter table t1 drop x, force;
+alter table t1 discard tablespace;
+flush tables t2 for export;
+unlock tables;
+alter table t1 import tablespace;
+ERROR HY000: Schema mismatch (Index field count 4 doesn't match tablespace metadata file value 5)
+select * from t1;
+ERROR HY000: Tablespace has been discarded for table `t1`
+alter table t1 import tablespace;
+ERROR HY000: Internal error: Cannot reset LSNs in table `test`.`t1` : Unsupported
+select * from t1;
+ERROR HY000: Tablespace has been discarded for table `t1`
+drop table t2;
+drop table t1;
diff --git a/mysql-test/suite/innodb/t/alter_varchar_change.test b/mysql-test/suite/innodb/t/alter_varchar_change.test
index f435125e581..7e0c99487b5 100644
--- a/mysql-test/suite/innodb/t/alter_varchar_change.test
+++ b/mysql-test/suite/innodb/t/alter_varchar_change.test
@@ -26,7 +26,7 @@ CREATE TABLE t1(f1 INT NOT NULL,
f2 VARCHAR(100) PRIMARY KEY)ENGINE=InnoDB;
CALL get_table_id("test/t1", @tbl_id);
-ALTER TABLE t1 MODIFY f2 VARCHAR(200);
+ALTER TABLE t1 MODIFY f2 VARCHAR(200), ALGORITHM=INSTANT;
CALL get_table_id("test/t1", @tbl1_id);
SELECT @tbl1_id = @tbl_id;
@@ -39,7 +39,7 @@ CREATE TABLE t1(f1 INT NOT NULL,
INDEX idx(f2))ENGINE=InnoDB;
CALL get_table_id("test/t1", @tbl_id);
-ALTER TABLE t1 MODIFY f2 VARCHAR(200);
+ALTER TABLE t1 MODIFY f2 VARCHAR(200), ALGORITHM=INSTANT;
CALL get_table_id("test/t1", @tbl1_id);
SELECT @tbl1_id = @tbl_id;
@@ -51,7 +51,7 @@ CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100), f3 VARCHAR(100),
CALL get_table_id("test/t1", @tbl_id);
CALL get_index_id(@tbl_id, "idx", @idx_id);
-ALTER TABLE t1 MODIFY f2 VARCHAR(200), MODIFY f3 VARCHAR(150);
+ALTER TABLE t1 MODIFY f2 VARCHAR(200), MODIFY f3 VARCHAR(150), ALGORITHM=INSTANT;
CALL get_table_id("test/t1", @tbl1_id);
CALL get_index_id(@tbl1_id, "idx", @idx1_id);
@@ -65,7 +65,7 @@ CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100),
CALL get_table_id("test/t1", @tbl_id);
CALL get_index_id(@tbl_id, "idx", @idx_id);
-ALTER TABLE t1 MODIFY f2 VARCHAR(200);
+ALTER TABLE t1 MODIFY f2 VARCHAR(200), ALGORITHM=INSTANT;
CALL get_table_id("test/t1", @tbl1_id);
CALL get_index_id(@tbl1_id, "idx", @idx1_id);
@@ -80,7 +80,7 @@ CREATE TABLE t1(f1 INT NOT NULL,
CALL get_table_id("test/t1", @tbl_id);
CALL get_index_id(@tbl_id, "idx", @idx_id);
-ALTER TABLE t1 MODIFY f2 VARCHAR(200);
+ALTER TABLE t1 MODIFY f2 VARCHAR(200), ALGORITHM=INSTANT;
CALL get_table_id("test/t1", @tbl1_id);
CALL get_index_id(@tbl1_id, "idx", @idx1_id);
@@ -98,7 +98,7 @@ INSERT INTO t1(f1, f2) VALUES(1, repeat('a', 40));
CALL get_table_id("test/t1", @tbl_id);
CALL get_index_id(@tbl_id, "idx", @idx_id);
-ALTER TABLE t1 MODIFY f2 VARCHAR(100);
+ALTER TABLE t1 MODIFY f2 VARCHAR(100), ALGORITHM=INSTANT;
CALL get_table_id("test/t1", @tbl1_id);
CALL get_index_id(@tbl1_id, "idx", @idx1_id);
@@ -129,7 +129,7 @@ CREATE TABLE t1(f1 INT NOT NULL,
CALL get_table_id("test/t1", @tbl_id);
CALL get_index_id(@tbl_id, "idx", @idx_id);
-ALTER TABLE t1 MODIFY f2 VARCHAR(200), DROP INDEX idx, ADD INDEX idx(f2(10));
+ALTER TABLE t1 MODIFY f2 VARCHAR(200), DROP INDEX idx, ADD INDEX idx(f2(10)), ALGORITHM=INSTANT;
CALL get_table_id("test/t1", @tbl1_id);
CALL get_index_id(@tbl1_id, "idx", @idx1_id);
@@ -192,7 +192,7 @@ CREATE TABLE t1(f1 INT NOT NULL,
INDEX idx(f2))ENGINE=InnoDB;
CALL get_table_id("test/t1", @tbl_id);
-ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT;
+ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT, ALGORITHM=INSTANT;
CALL get_table_id("test/t1", @tbl1_id);
SELECT @tbl1_id = @tbl_id;
@@ -202,7 +202,7 @@ DROP TABLE t1;
CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100) PRIMARY KEY)ENGINE=InnoDB;
CALL get_table_id("test/t1", @tbl_id);
-ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT;
+ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT, ALGORITHM=INSTANT;
CALL get_table_id("test/t1", @tbl1_id);
SELECT @tbl1_id = @tbl_id;
diff --git a/mysql-test/suite/innodb/t/instant_alter_bugs.test b/mysql-test/suite/innodb/t/instant_alter_bugs.test
index 18ace4cc521..7b7ba44f09b 100644
--- a/mysql-test/suite/innodb/t/instant_alter_bugs.test
+++ b/mysql-test/suite/innodb/t/instant_alter_bugs.test
@@ -136,3 +136,52 @@ HANDLER h CLOSE;
DROP TABLE t1;
--let $datadir= `select @@datadir`
--remove_file $datadir/test/load.data
+
+
+create table t (
+ a varchar(9),
+ b int,
+ c int,
+ row_start bigint unsigned generated always as row start invisible,
+ row_end bigint unsigned generated always as row end invisible,
+ period for system_time (row_start, row_end)
+) engine=innodb row_format=compressed with system versioning;
+insert into t values (repeat('a', 9), 1, 1);
+set @@system_versioning_alter_history = keep;
+alter table t modify a varchar(10), algorithm=instant;
+alter table t change b bb int, algorithm=instant;
+alter table t modify c int without system versioning, algorithm=instant;
+set @@system_versioning_alter_history = error;
+check table t;
+drop table t;
+
+--echo #
+--echo # MDEV-18219 Assertion `index->n_core_null_bytes <= ...' failed
+--echo # in rec_init_offsets after instant DROP COLUMN
+--echo #
+CREATE TABLE t1 (a INT, b INT NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+(0,9),(2,7),(3,1),(3,4),(8,4),(3,7),(6,1),(3,8),(1,2),(4,1),(0,8),(5,3),
+(1,3),(1,6),(2,1),(8,7),(6,0),(1,9),(9,4),(0,6),(9,3),(0,9),(9,4),(2,4),
+(2,7),(7,8),(8,2),(2,5),(6,1),(4,5),(5,3),(6,8),(4,9),(5,7),(7,5),(5,1),
+(8,8),(5,7),(3,8),(0,1),(8,4),(8,3),(9,7),(4,8),(1,1),(0,4),(2,6),(8,5),
+(8,8),(8,7),(6,7),(1,7),(9,6),(3,6),(1,9),(0,3),(5,3),(2,4),(0,6),(2,0),
+(6,5),(1,6),(2,4),(9,1),(3,0),(6,4),(1,3),(0,8),(3,5),(3,1),(8,9),(9,9),
+(7,9),(4,5),(2,2),(3,8),(0,8),(7,1),(2,0),(1,5),(7,3),(4,4),(3,9),(7,2),
+(6,2),(0,4),(2,0),(1,5),(5,7),(4,5),(3,7),(6,0),(2,1),(5,0),(1,0),(2,0),
+(8,4),(5,7),(3,5),(0,5),(7,6),(5,9),(1,2),(4,2),(8,5),(8,7),(2,8),(1,8),
+(4,3),(1,6),(7,8),(3,7),(4,6),(1,1),(3,0),(1,6),(2,0),(3,4),(4,8),(3,9),
+(8,0),(4,9),(4,0),(3,9),(6,4),(7,4),(5,8),(4,7),(7,3),(5,9),(2,3),(7,3),
+(0,4),(5,9),(9,8),(4,2),(3,6),(2,6),(1,8),(7,0),(0,0),(2,3),(1,2),(3,3),
+(2,7),(6,0),(9,0),(6,9),(4,6),(9,8),(0,7),(9,1),(9,6),(4,3),(7,7),(7,7),
+(4,1),(4,7),(7,3),(2,8),(5,8),(8,9),(3,9),(7,7),(0,8),(4,9),(3,2),(5,0),
+(1,7),(0,3),(2,9),(9,7),(7,5),(6,9),(8,5),(3,6),(1,1),(2,8),(7,9),(4,9),
+(6,6),(5,9),(5,3),(9,8),(3,3),(5,6),(0,9),(3,9),(7,9),(7,3),(5,2),(1,4),
+(4,4),(8,2),(2,2),(8,3),(9,1),(4,9),(9,8),(1,8),(1,8),(9,1),(1,1),(3,0),
+(4,6),(9,3),(3,3),(5,2),(0,1),(3,4),(3,2),(1,3),(4,4),(7,0),(4,6),(7,2),
+(4,5),(8,7),(7,8),(8,1),(3,5),(0,6),(3,5),(2,1),(4,4),(3,4),(2,1),(4,1);
+INSERT INTO t1 SELECT * FROM t1;
+ALTER TABLE t1 DROP a;
+# Exploit MDEV-17468 to force the table definition to be reloaded
+ALTER TABLE t1 ADD vb INT AS (b) VIRTUAL;
+DROP TABLE t1;
diff --git a/mysql-test/suite/innodb/t/instant_alter_import.test b/mysql-test/suite/innodb/t/instant_alter_import.test
new file mode 100644
index 00000000000..fb187debb51
--- /dev/null
+++ b/mysql-test/suite/innodb/t/instant_alter_import.test
@@ -0,0 +1,84 @@
+--source include/have_innodb.inc
+set default_storage_engine=innodb;
+
+--echo #
+--echo # MDEV-18295 IMPORT TABLESPACE fails with instant-altered tables
+--echo #
+
+create table t2 (x int, z int default 41);
+alter table t2 discard tablespace;
+
+create table t1 (x int);
+insert into t1 values (1);
+alter table t1 add z int default 42, algorithm instant;
+select * from t1;
+flush tables t1 for export;
+--let $MYSQLD_DATADIR= `select @@datadir`
+--move_file $MYSQLD_DATADIR/test/t1.cfg $MYSQLD_DATADIR/test/t2.cfg
+--copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t2.ibd
+unlock tables;
+
+--echo # The metadata has to be updated to instant ADD COLUMN.
+alter table t2 import tablespace;
+
+select * from t2;
+insert into t2 set x=2;
+select * from t2;
+
+alter table t1 discard tablespace;
+flush tables t2 for export;
+--move_file $MYSQLD_DATADIR/test/t2.cfg $MYSQLD_DATADIR/test/t1.cfg
+--copy_file $MYSQLD_DATADIR/test/t2.ibd $MYSQLD_DATADIR/test/t1.ibd
+unlock tables;
+
+--echo # Both the metadata and the data file used instant ADD COLUMN.
+alter table t1 import tablespace;
+select * from t1;
+
+drop table t2;
+create table t2 select * from t1;
+
+alter table t1 discard tablespace;
+flush tables t2 for export;
+--move_file $MYSQLD_DATADIR/test/t2.cfg $MYSQLD_DATADIR/test/t1.cfg
+--copy_file $MYSQLD_DATADIR/test/t2.ibd $MYSQLD_DATADIR/test/t1.ibd
+unlock tables;
+--copy_file $MYSQLD_DATADIR/test/t1.cfg $MYSQLD_DATADIR/test/t1b.cfg
+--copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t1b.ibd
+
+--echo # The instant ADD COLUMN has to be removed from the metadata.
+alter table t1 import tablespace;
+select * from t1;
+
+--echo # Remove metadata for instant DROP COLUMN, then import
+alter table t1 drop x, add column x int first, algorithm instant;
+select * from t1;
+alter table t1 discard tablespace;
+
+--move_file $MYSQLD_DATADIR/test/t1b.cfg $MYSQLD_DATADIR/test/t1.cfg
+--move_file $MYSQLD_DATADIR/test/t1b.ibd $MYSQLD_DATADIR/test/t1.ibd
+alter table t1 import tablespace;
+select * from t1;
+
+--echo # Import a data file that contains instant DROP COLUMN metadata
+alter table t2 drop x;
+alter table t1 drop x, force;
+alter table t1 discard tablespace;
+
+flush tables t2 for export;
+--move_file $MYSQLD_DATADIR/test/t2.cfg $MYSQLD_DATADIR/test/t1.cfg
+--copy_file $MYSQLD_DATADIR/test/t2.ibd $MYSQLD_DATADIR/test/t1.ibd
+unlock tables;
+
+--error ER_TABLE_SCHEMA_MISMATCH
+alter table t1 import tablespace;
+--error ER_TABLESPACE_DISCARDED
+select * from t1;
+--remove_file $MYSQLD_DATADIR/test/t1.cfg
+--error ER_INTERNAL_ERROR
+alter table t1 import tablespace;
+--error ER_TABLESPACE_DISCARDED
+select * from t1;
+
+drop table t2;
+drop table t1;
diff --git a/mysql-test/suite/roles/i_s_applicable_roles_is_default.result b/mysql-test/suite/roles/i_s_applicable_roles_is_default.result
index 32498d11390..ee7d17f3a1f 100644
--- a/mysql-test/suite/roles/i_s_applicable_roles_is_default.result
+++ b/mysql-test/suite/roles/i_s_applicable_roles_is_default.result
@@ -78,4 +78,4 @@ drop role role3;
drop role role2;
drop role role1;
drop user foo;
-update mysql.global_priv set priv=json_remove(priv, '$.default_role');
+update mysql.global_priv set priv=json_compact(json_remove(priv, '$.default_role'));
diff --git a/mysql-test/suite/roles/i_s_applicable_roles_is_default.test b/mysql-test/suite/roles/i_s_applicable_roles_is_default.test
index b6f6f9ba879..0e6436924a9 100644
--- a/mysql-test/suite/roles/i_s_applicable_roles_is_default.test
+++ b/mysql-test/suite/roles/i_s_applicable_roles_is_default.test
@@ -59,4 +59,4 @@ drop role role3;
drop role role2;
drop role role1;
drop user foo;
-update mysql.global_priv set priv=json_remove(priv, '$.default_role');
+update mysql.global_priv set priv=json_compact(json_remove(priv, '$.default_role'));
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff
index 5d47090a875..4ec990dbd6a 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff
@@ -1,6 +1,6 @@
---- sysvars_server_embedded.result 2017-11-17 17:00:22.462630239 +0100
-+++ sysvars_server_embedded,32bit.reject 2017-11-17 19:09:55.472258411 +0100
-@@ -58,7 +58,7 @@
+--- suite/sys_vars/r/sysvars_server_embedded.result 2019-02-09 22:10:13.570328367 +0530
++++ suite/sys_vars/r/sysvars_server_embedded,32bit.reject 2019-02-09 22:35:54.884594853 +0530
+@@ -74,7 +74,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE 1
VARIABLE_SCOPE SESSION
@@ -9,7 +9,7 @@
VARIABLE_COMMENT Auto-increment columns are incremented by this
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 65535
-@@ -72,7 +72,7 @@
+@@ -88,7 +88,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1
VARIABLE_SCOPE SESSION
@@ -18,7 +18,7 @@
VARIABLE_COMMENT Offset added to Auto-increment columns. Used when auto-increment-increment != 1
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 65535
-@@ -86,7 +86,7 @@
+@@ -102,7 +102,7 @@
GLOBAL_VALUE_ORIGIN AUTO
DEFAULT_VALUE 150
VARIABLE_SCOPE GLOBAL
@@ -27,7 +27,7 @@
VARIABLE_COMMENT The number of outstanding connection requests MariaDB can have. This comes into play when the main MariaDB thread gets very many connection requests in a very short time
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 65535
-@@ -159,7 +159,7 @@
+@@ -175,7 +175,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The size of the transactional cache for updates to transactional engines for the binary log. If you often use transactions containing many statements, you can increase this to get more performance
NUMERIC_MIN_VALUE 4096
@@ -36,7 +36,7 @@
NUMERIC_BLOCK_SIZE 4096
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -184,10 +184,10 @@
+@@ -200,10 +200,10 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE GLOBAL
@@ -49,7 +49,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -198,10 +198,10 @@
+@@ -214,10 +214,10 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 100000
VARIABLE_SCOPE GLOBAL
@@ -62,7 +62,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -229,7 +229,7 @@
+@@ -245,7 +245,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The size of file cache for the binary log
NUMERIC_MIN_VALUE 8192
@@ -71,7 +71,7 @@
NUMERIC_BLOCK_SIZE 4096
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -285,7 +285,7 @@
+@@ -301,7 +301,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The size of the statement cache for updates to non-transactional engines for the binary log. If you often use statements updating a great number of rows, you can increase this to get more performance.
NUMERIC_MIN_VALUE 4096
@@ -80,7 +80,7 @@
NUMERIC_BLOCK_SIZE 4096
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -299,7 +299,7 @@
+@@ -315,7 +315,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Size of tree cache used in bulk insert optimisation. Note that this is a limit per thread!
NUMERIC_MIN_VALUE 0
@@ -89,7 +89,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -562,7 +562,7 @@
+@@ -578,7 +578,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE 10
VARIABLE_SCOPE GLOBAL
@@ -98,7 +98,7 @@
VARIABLE_COMMENT The number of seconds the mysqld server is waiting for a connect packet before responding with 'Bad handshake'
NUMERIC_MIN_VALUE 2
NUMERIC_MAX_VALUE 31536000
-@@ -618,7 +618,7 @@
+@@ -648,7 +648,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 15
VARIABLE_SCOPE SESSION
@@ -107,7 +107,7 @@
VARIABLE_COMMENT Long search depth for the two-step deadlock detection
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 33
-@@ -632,7 +632,7 @@
+@@ -662,7 +662,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 4
VARIABLE_SCOPE SESSION
@@ -116,7 +116,7 @@
VARIABLE_COMMENT Short search depth for the two-step deadlock detection
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 32
-@@ -646,7 +646,7 @@
+@@ -676,7 +676,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 50000000
VARIABLE_SCOPE SESSION
@@ -125,7 +125,7 @@
VARIABLE_COMMENT Long timeout for the two-step deadlock detection (in microseconds)
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -660,7 +660,7 @@
+@@ -690,7 +690,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 10000
VARIABLE_SCOPE SESSION
@@ -134,7 +134,7 @@
VARIABLE_COMMENT Short timeout for the two-step deadlock detection (in microseconds)
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -716,7 +716,7 @@
+@@ -746,7 +746,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE SESSION
@@ -143,7 +143,7 @@
VARIABLE_COMMENT The default week format used by WEEK() functions
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 7
-@@ -730,7 +730,7 @@
+@@ -760,7 +760,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 100
VARIABLE_SCOPE GLOBAL
@@ -152,7 +152,7 @@
VARIABLE_COMMENT After inserting delayed_insert_limit rows, the INSERT DELAYED handler will check if there are any SELECT statements pending. If so, it allows these to execute before continuing.
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
-@@ -744,7 +744,7 @@
+@@ -774,7 +774,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 300
VARIABLE_SCOPE GLOBAL
@@ -161,7 +161,7 @@
VARIABLE_COMMENT How long a INSERT DELAYED thread should wait for INSERT statements before terminating
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 31536000
-@@ -758,7 +758,7 @@
+@@ -788,7 +788,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1000
VARIABLE_SCOPE GLOBAL
@@ -170,7 +170,7 @@
VARIABLE_COMMENT What size queue (in rows) should be allocated for handling INSERT DELAYED. If the queue becomes full, any client that does INSERT DELAYED will wait until there is room in the queue again
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
-@@ -786,7 +786,7 @@
+@@ -816,7 +816,7 @@
GLOBAL_VALUE_ORIGIN SQL
DEFAULT_VALUE 4
VARIABLE_SCOPE SESSION
@@ -179,7 +179,7 @@
VARIABLE_COMMENT Precision of the result of '/' operator will be increased on that value
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 38
-@@ -884,7 +884,7 @@
+@@ -928,7 +928,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE GLOBAL
@@ -188,7 +188,7 @@
VARIABLE_COMMENT If non-zero, binary logs will be purged after expire_logs_days days; possible purges happen at startup and at binary log rotation
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 99
-@@ -926,7 +926,7 @@
+@@ -970,7 +970,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1
VARIABLE_SCOPE GLOBAL
@@ -197,7 +197,7 @@
VARIABLE_COMMENT The number of connections on extra-port
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 100000
-@@ -968,7 +968,7 @@
+@@ -1012,7 +1012,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE GLOBAL
@@ -206,7 +206,7 @@
VARIABLE_COMMENT A dedicated thread is created to flush all tables at the given interval
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 31536000
-@@ -1010,7 +1010,7 @@
+@@ -1054,7 +1054,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 84
VARIABLE_SCOPE GLOBAL
@@ -215,7 +215,7 @@
VARIABLE_COMMENT The maximum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable
NUMERIC_MIN_VALUE 10
NUMERIC_MAX_VALUE 84
-@@ -1024,7 +1024,7 @@
+@@ -1068,7 +1068,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 4
VARIABLE_SCOPE GLOBAL
@@ -224,7 +224,7 @@
VARIABLE_COMMENT The minimum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 84
-@@ -1038,7 +1038,7 @@
+@@ -1082,7 +1082,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 20
VARIABLE_SCOPE GLOBAL
@@ -233,7 +233,7 @@
VARIABLE_COMMENT Number of best matches to use for query expansion
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 1000
-@@ -1097,7 +1097,7 @@
+@@ -1141,7 +1141,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The maximum length of the result of function GROUP_CONCAT()
NUMERIC_MIN_VALUE 4
@@ -242,7 +242,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -1248,7 +1248,7 @@
+@@ -1292,7 +1292,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE SESSION
@@ -251,7 +251,7 @@
VARIABLE_COMMENT Number of bytes used for a histogram. If set to 0, no histograms are created by ANALYZE.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 255
-@@ -1276,7 +1276,7 @@
+@@ -1320,7 +1320,7 @@
GLOBAL_VALUE_ORIGIN AUTO
DEFAULT_VALUE 128
VARIABLE_SCOPE GLOBAL
@@ -260,7 +260,7 @@
VARIABLE_COMMENT How many host names should be cached to avoid resolving.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 65536
-@@ -1430,7 +1430,7 @@
+@@ -1474,7 +1474,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 28800
VARIABLE_SCOPE SESSION
@@ -269,20 +269,7 @@
VARIABLE_COMMENT The number of seconds the server waits for activity on an interactive connection before closing it
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 31536000
-@@ -1444,10 +1444,10 @@
- GLOBAL_VALUE_ORIGIN COMPILE-TIME
- DEFAULT_VALUE 1000
- VARIABLE_SCOPE SESSION
--VARIABLE_TYPE BIGINT UNSIGNED
-+VARIABLE_TYPE INT UNSIGNED
- VARIABLE_COMMENT The minimum number of scalar elements in the value list of IN predicate that triggers its conversion to IN subquery
- NUMERIC_MIN_VALUE 0
--NUMERIC_MAX_VALUE 18446744073709551615
-+NUMERIC_MAX_VALUE 4294967295
- NUMERIC_BLOCK_SIZE 1
- ENUM_VALUE_LIST NULL
- READ_ONLY NO
-@@ -1475,7 +1475,7 @@
+@@ -1505,7 +1505,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The size of the buffer that is used for joins
NUMERIC_MIN_VALUE 128
@@ -291,7 +278,7 @@
NUMERIC_BLOCK_SIZE 128
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -1500,7 +1500,7 @@
+@@ -1530,7 +1530,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 2
VARIABLE_SCOPE SESSION
@@ -300,7 +287,7 @@
VARIABLE_COMMENT Controls what join operations can be executed with join buffers. Odd numbers are used for plain join buffers while even numbers are used for linked buffers
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 8
-@@ -1531,7 +1531,7 @@
+@@ -1561,7 +1561,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The size of the buffer used for index blocks for MyISAM tables. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford
NUMERIC_MIN_VALUE 0
@@ -309,7 +296,7 @@
NUMERIC_BLOCK_SIZE 4096
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -1738,7 +1738,7 @@
+@@ -1768,7 +1768,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 86400
VARIABLE_SCOPE SESSION
@@ -318,7 +305,7 @@
VARIABLE_COMMENT Timeout in seconds to wait for a lock before returning an error.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 31536000
-@@ -1906,7 +1906,7 @@
+@@ -1936,7 +1936,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1
VARIABLE_SCOPE SESSION
@@ -327,7 +314,7 @@
VARIABLE_COMMENT Write to slow log every #th slow query. Set to 1 to log everything. Increase it to reduce the size of the slow or the performance impact of slow logging
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
-@@ -1948,7 +1948,7 @@
+@@ -1978,7 +1978,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 2
VARIABLE_SCOPE SESSION
@@ -336,7 +323,7 @@
VARIABLE_COMMENT Log some not critical warnings to the general log file.Value can be between 0 and 11. Higher values mean more verbosity
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -1990,7 +1990,7 @@
+@@ -2020,7 +2020,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 16777216
VARIABLE_SCOPE SESSION
@@ -345,7 +332,7 @@
VARIABLE_COMMENT Max packet length to send to or receive from the server
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 1073741824
-@@ -2000,14 +2000,14 @@
+@@ -2030,14 +2030,14 @@
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME MAX_BINLOG_CACHE_SIZE
SESSION_VALUE NULL
@@ -363,7 +350,7 @@
NUMERIC_BLOCK_SIZE 4096
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -2018,7 +2018,7 @@
+@@ -2048,7 +2048,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1073741824
VARIABLE_SCOPE GLOBAL
@@ -372,7 +359,7 @@
VARIABLE_COMMENT Binary log will be rotated automatically when the size exceeds this value.
NUMERIC_MIN_VALUE 4096
NUMERIC_MAX_VALUE 1073741824
-@@ -2028,14 +2028,14 @@
+@@ -2058,14 +2058,14 @@
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME MAX_BINLOG_STMT_CACHE_SIZE
SESSION_VALUE NULL
@@ -390,16 +377,16 @@
NUMERIC_BLOCK_SIZE 4096
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -2046,7 +2046,7 @@
+@@ -2076,7 +2076,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 151
VARIABLE_SCOPE GLOBAL
-VARIABLE_TYPE BIGINT UNSIGNED
+VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT The number of simultaneous clients allowed
- NUMERIC_MIN_VALUE 1
+ NUMERIC_MIN_VALUE 10
NUMERIC_MAX_VALUE 100000
-@@ -2060,7 +2060,7 @@
+@@ -2090,7 +2090,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 100
VARIABLE_SCOPE GLOBAL
@@ -408,7 +395,7 @@
VARIABLE_COMMENT If there is more than this number of interrupted connections from a host this host will be blocked from further connections
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
-@@ -2074,7 +2074,7 @@
+@@ -2104,7 +2104,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 20
VARIABLE_SCOPE SESSION
@@ -417,7 +404,7 @@
VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 16384
-@@ -2102,7 +2102,7 @@
+@@ -2132,7 +2132,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 64
VARIABLE_SCOPE SESSION
@@ -426,7 +413,7 @@
VARIABLE_COMMENT Max number of errors/warnings to store for a statement
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 65535
-@@ -2119,7 +2119,7 @@
+@@ -2149,7 +2149,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Don't allow creation of heap tables bigger than this
NUMERIC_MIN_VALUE 16384
@@ -435,7 +422,7 @@
NUMERIC_BLOCK_SIZE 1024
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -2130,7 +2130,7 @@
+@@ -2160,7 +2160,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 20
VARIABLE_SCOPE SESSION
@@ -444,7 +431,7 @@
VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 16384
-@@ -2158,7 +2158,7 @@
+@@ -2188,7 +2188,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1024
VARIABLE_SCOPE SESSION
@@ -453,7 +440,7 @@
VARIABLE_COMMENT Max number of bytes in sorted records
NUMERIC_MIN_VALUE 4
NUMERIC_MAX_VALUE 8388608
-@@ -2172,7 +2172,7 @@
+@@ -2202,7 +2202,7 @@
GLOBAL_VALUE_ORIGIN AUTO
DEFAULT_VALUE 1048576
VARIABLE_SCOPE GLOBAL
@@ -462,16 +449,7 @@
VARIABLE_COMMENT The maximum BLOB length to send to server from mysql_send_long_data API. Deprecated option; use max_allowed_packet instead.
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 4294967295
-@@ -2186,7 +2186,7 @@
- GLOBAL_VALUE_ORIGIN COMPILE-TIME
- DEFAULT_VALUE 16382
- VARIABLE_SCOPE GLOBAL
--VARIABLE_TYPE BIGINT UNSIGNED
-+VARIABLE_TYPE INT UNSIGNED
- VARIABLE_COMMENT Maximum number of prepared statements in the server
- NUMERIC_MIN_VALUE 0
- NUMERIC_MAX_VALUE 1048576
-@@ -2200,7 +2200,7 @@
+@@ -2244,7 +2244,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 4294967295
VARIABLE_SCOPE SESSION
@@ -480,7 +458,7 @@
VARIABLE_COMMENT Maximum number of iterations when executing recursive queries
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -2214,7 +2214,7 @@
+@@ -2258,7 +2258,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 4294967295
VARIABLE_SCOPE SESSION
@@ -489,7 +467,7 @@
VARIABLE_COMMENT Limit assumed max number of seeks when looking up rows based on a key
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
-@@ -2242,7 +2242,7 @@
+@@ -2286,7 +2286,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1024
VARIABLE_SCOPE SESSION
@@ -498,7 +476,7 @@
VARIABLE_COMMENT The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored)
NUMERIC_MIN_VALUE 4
NUMERIC_MAX_VALUE 8388608
-@@ -2256,7 +2256,7 @@
+@@ -2300,7 +2300,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE SESSION
@@ -507,7 +485,7 @@
VARIABLE_COMMENT Maximum stored procedure recursion depth
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 255
-@@ -2284,7 +2284,7 @@
+@@ -2328,7 +2328,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 32
VARIABLE_SCOPE SESSION
@@ -516,7 +494,7 @@
VARIABLE_COMMENT Unused, will be removed.
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
-@@ -2312,7 +2312,7 @@
+@@ -2356,7 +2356,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 4294967295
VARIABLE_SCOPE GLOBAL
@@ -525,7 +503,7 @@
VARIABLE_COMMENT After this many write locks, allow some read locks to run in between
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
-@@ -2326,7 +2326,7 @@
+@@ -2370,7 +2370,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1024
VARIABLE_SCOPE GLOBAL
@@ -534,7 +512,7 @@
VARIABLE_COMMENT Unused
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 1048576
-@@ -2340,7 +2340,7 @@
+@@ -2384,7 +2384,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 8
VARIABLE_SCOPE GLOBAL
@@ -543,7 +521,7 @@
VARIABLE_COMMENT Unused
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 1024
-@@ -2354,7 +2354,7 @@
+@@ -2398,7 +2398,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE SESSION
@@ -552,7 +530,7 @@
VARIABLE_COMMENT Don't write queries to slow log that examine fewer rows than that
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -2368,7 +2368,7 @@
+@@ -2412,7 +2412,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 262144
VARIABLE_SCOPE SESSION
@@ -561,7 +539,7 @@
VARIABLE_COMMENT Size of buffer to use when using MRR with range access
NUMERIC_MIN_VALUE 8192
NUMERIC_MAX_VALUE 2147483647
-@@ -2382,10 +2382,10 @@
+@@ -2426,10 +2426,10 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 256
VARIABLE_SCOPE SESSION
@@ -574,7 +552,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -2396,7 +2396,7 @@
+@@ -2440,7 +2440,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1024
VARIABLE_SCOPE GLOBAL
@@ -583,7 +561,7 @@
VARIABLE_COMMENT Block size to be used for MyISAM index pages
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 16384
-@@ -2410,7 +2410,7 @@
+@@ -2454,7 +2454,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 6
VARIABLE_SCOPE GLOBAL
@@ -592,7 +570,7 @@
VARIABLE_COMMENT Default pointer size to be used for MyISAM tables
NUMERIC_MIN_VALUE 2
NUMERIC_MAX_VALUE 7
-@@ -2420,9 +2420,9 @@
+@@ -2464,9 +2464,9 @@
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME MYISAM_MAX_SORT_FILE_SIZE
SESSION_VALUE NULL
@@ -604,7 +582,7 @@
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Don't use the fast sort index method to created index if the temporary file would get bigger than this
-@@ -2434,14 +2434,14 @@
+@@ -2478,14 +2478,14 @@
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME MYISAM_MMAP_SIZE
SESSION_VALUE NULL
@@ -622,7 +600,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY YES
-@@ -2466,10 +2466,10 @@
+@@ -2510,10 +2510,10 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1
VARIABLE_SCOPE SESSION
@@ -635,7 +613,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -2483,7 +2483,7 @@
+@@ -2527,7 +2527,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE
NUMERIC_MIN_VALUE 4096
@@ -644,7 +622,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -2536,7 +2536,7 @@
+@@ -2580,7 +2580,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 16384
VARIABLE_SCOPE SESSION
@@ -653,7 +631,7 @@
VARIABLE_COMMENT Buffer length for TCP/IP and socket communication
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 1048576
-@@ -2550,7 +2550,7 @@
+@@ -2594,7 +2594,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 30
VARIABLE_SCOPE SESSION
@@ -662,7 +640,7 @@
VARIABLE_COMMENT Number of seconds to wait for more data from a connection before aborting the read
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 31536000
-@@ -2564,7 +2564,7 @@
+@@ -2608,7 +2608,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 10
VARIABLE_SCOPE SESSION
@@ -671,7 +649,7 @@
VARIABLE_COMMENT If a read on a communication port is interrupted, retry this many times before giving up
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
-@@ -2578,7 +2578,7 @@
+@@ -2622,7 +2622,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 60
VARIABLE_SCOPE SESSION
@@ -680,7 +658,7 @@
VARIABLE_COMMENT Number of seconds to wait for a block to be written to a connection before aborting the write
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 31536000
-@@ -2648,7 +2648,7 @@
+@@ -2692,7 +2692,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1
VARIABLE_SCOPE SESSION
@@ -689,7 +667,7 @@
VARIABLE_COMMENT Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 1
-@@ -2662,7 +2662,7 @@
+@@ -2706,7 +2706,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 62
VARIABLE_SCOPE SESSION
@@ -698,7 +676,7 @@
VARIABLE_COMMENT Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Values smaller than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 62
-@@ -2676,7 +2676,7 @@
+@@ -2720,7 +2720,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 100
VARIABLE_SCOPE SESSION
@@ -707,16 +685,29 @@
VARIABLE_COMMENT Controls number of record samples to check condition selectivity
NUMERIC_MIN_VALUE 10
NUMERIC_MAX_VALUE 4294967295
-@@ -2704,7 +2704,7 @@
+@@ -2762,10 +2762,10 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
- DEFAULT_VALUE 1
+ DEFAULT_VALUE 1048576
+ VARIABLE_SCOPE SESSION
+-VARIABLE_TYPE BIGINT UNSIGNED
++VARIABLE_TYPE INT UNSIGNED
+ VARIABLE_COMMENT Maximum allowed size of an optimizer trace
+ NUMERIC_MIN_VALUE 0
+-NUMERIC_MAX_VALUE 18446744073709551615
++NUMERIC_MAX_VALUE 4294967295
+ NUMERIC_BLOCK_SIZE 1
+ ENUM_VALUE_LIST NULL
+ READ_ONLY NO
+@@ -2776,7 +2776,7 @@
+ GLOBAL_VALUE_ORIGIN COMPILE-TIME
+ DEFAULT_VALUE 4
VARIABLE_SCOPE SESSION
-VARIABLE_TYPE BIGINT UNSIGNED
+VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 5
-@@ -2732,7 +2732,7 @@
+@@ -2804,7 +2804,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -725,7 +716,7 @@
VARIABLE_COMMENT Maximum number of instrumented user@host accounts. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -2746,7 +2746,7 @@
+@@ -2818,7 +2818,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -734,7 +725,7 @@
VARIABLE_COMMENT Size of the statement digest. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 200
-@@ -2760,7 +2760,7 @@
+@@ -2832,7 +2832,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -743,7 +734,7 @@
VARIABLE_COMMENT Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -2774,7 +2774,7 @@
+@@ -2846,7 +2846,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -752,7 +743,7 @@
VARIABLE_COMMENT Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1024
-@@ -2788,7 +2788,7 @@
+@@ -2860,7 +2860,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -761,7 +752,7 @@
VARIABLE_COMMENT Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -2802,7 +2802,7 @@
+@@ -2874,7 +2874,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -770,7 +761,7 @@
VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_HISTORY. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1024
-@@ -2816,7 +2816,7 @@
+@@ -2888,7 +2888,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -779,7 +770,7 @@
VARIABLE_COMMENT Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -2830,7 +2830,7 @@
+@@ -2902,7 +2902,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -788,7 +779,7 @@
VARIABLE_COMMENT Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1024
-@@ -2844,7 +2844,7 @@
+@@ -2916,7 +2916,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -797,7 +788,7 @@
VARIABLE_COMMENT Maximum number of instrumented hosts. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -2858,7 +2858,7 @@
+@@ -2930,7 +2930,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 80
VARIABLE_SCOPE GLOBAL
@@ -806,7 +797,7 @@
VARIABLE_COMMENT Maximum number of condition instruments.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 256
-@@ -2872,7 +2872,7 @@
+@@ -2944,7 +2944,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -815,7 +806,7 @@
VARIABLE_COMMENT Maximum number of instrumented condition objects. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -2886,7 +2886,7 @@
+@@ -2958,7 +2958,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1024
VARIABLE_SCOPE GLOBAL
@@ -824,7 +815,7 @@
VARIABLE_COMMENT Maximum length considered for digest text, when stored in performance_schema tables.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 1048576
-@@ -2900,7 +2900,7 @@
+@@ -2972,7 +2972,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 50
VARIABLE_SCOPE GLOBAL
@@ -833,7 +824,7 @@
VARIABLE_COMMENT Maximum number of file instruments.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 256
-@@ -2914,7 +2914,7 @@
+@@ -2986,7 +2986,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 32768
VARIABLE_SCOPE GLOBAL
@@ -842,7 +833,7 @@
VARIABLE_COMMENT Maximum number of opened instrumented files.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 1048576
-@@ -2928,7 +2928,7 @@
+@@ -3000,7 +3000,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -851,7 +842,7 @@
VARIABLE_COMMENT Maximum number of instrumented files. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -2942,7 +2942,7 @@
+@@ -3014,7 +3014,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 200
VARIABLE_SCOPE GLOBAL
@@ -860,7 +851,7 @@
VARIABLE_COMMENT Maximum number of mutex instruments.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 256
-@@ -2956,7 +2956,7 @@
+@@ -3028,7 +3028,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -869,7 +860,7 @@
VARIABLE_COMMENT Maximum number of instrumented MUTEX objects. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 104857600
-@@ -2970,7 +2970,7 @@
+@@ -3042,7 +3042,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 40
VARIABLE_SCOPE GLOBAL
@@ -878,7 +869,7 @@
VARIABLE_COMMENT Maximum number of rwlock instruments.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 256
-@@ -2984,7 +2984,7 @@
+@@ -3056,7 +3056,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -887,7 +878,7 @@
VARIABLE_COMMENT Maximum number of instrumented RWLOCK objects. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 104857600
-@@ -2998,7 +2998,7 @@
+@@ -3070,7 +3070,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 10
VARIABLE_SCOPE GLOBAL
@@ -896,7 +887,7 @@
VARIABLE_COMMENT Maximum number of socket instruments.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 256
-@@ -3012,7 +3012,7 @@
+@@ -3084,7 +3084,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -905,7 +896,7 @@
VARIABLE_COMMENT Maximum number of opened instrumented sockets. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -3026,7 +3026,7 @@
+@@ -3098,7 +3098,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 160
VARIABLE_SCOPE GLOBAL
@@ -914,16 +905,16 @@
VARIABLE_COMMENT Maximum number of stage instruments.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 256
-@@ -3040,7 +3040,7 @@
+@@ -3112,7 +3112,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
- DEFAULT_VALUE 191
+ DEFAULT_VALUE 202
VARIABLE_SCOPE GLOBAL
-VARIABLE_TYPE BIGINT UNSIGNED
+VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT Maximum number of statement instruments.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 256
-@@ -3054,7 +3054,7 @@
+@@ -3126,7 +3126,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -932,7 +923,7 @@
VARIABLE_COMMENT Maximum number of opened instrumented tables. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -3068,7 +3068,7 @@
+@@ -3140,7 +3140,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -941,7 +932,7 @@
VARIABLE_COMMENT Maximum number of instrumented tables. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -3082,7 +3082,7 @@
+@@ -3154,7 +3154,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 50
VARIABLE_SCOPE GLOBAL
@@ -950,7 +941,7 @@
VARIABLE_COMMENT Maximum number of thread instruments.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 256
-@@ -3096,7 +3096,7 @@
+@@ -3168,7 +3168,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -959,7 +950,7 @@
VARIABLE_COMMENT Maximum number of instrumented threads. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -3110,7 +3110,7 @@
+@@ -3182,7 +3182,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -968,7 +959,7 @@
VARIABLE_COMMENT Size of session attribute string buffer per thread. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -3124,7 +3124,7 @@
+@@ -3196,7 +3196,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 100
VARIABLE_SCOPE GLOBAL
@@ -977,7 +968,7 @@
VARIABLE_COMMENT Maximum number of rows in SETUP_ACTORS.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 1024
-@@ -3138,7 +3138,7 @@
+@@ -3210,7 +3210,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 100
VARIABLE_SCOPE GLOBAL
@@ -986,7 +977,7 @@
VARIABLE_COMMENT Maximum number of rows in SETUP_OBJECTS.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 1048576
-@@ -3152,7 +3152,7 @@
+@@ -3224,7 +3224,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -995,7 +986,7 @@
VARIABLE_COMMENT Maximum number of instrumented users. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -3222,7 +3222,7 @@
+@@ -3280,7 +3280,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 32768
VARIABLE_SCOPE SESSION
@@ -1004,7 +995,7 @@
VARIABLE_COMMENT The size of the buffer that is allocated when preloading indexes
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 1073741824
-@@ -3250,7 +3250,7 @@
+@@ -3308,7 +3308,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 15
VARIABLE_SCOPE SESSION
@@ -1013,7 +1004,7 @@
VARIABLE_COMMENT Number of statements about which profiling information is maintained. If set to 0, no profiles are stored. See SHOW PROFILES.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 100
-@@ -3264,7 +3264,7 @@
+@@ -3322,7 +3322,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 5
VARIABLE_SCOPE SESSION
@@ -1022,7 +1013,7 @@
VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -3348,7 +3348,7 @@
+@@ -3406,7 +3406,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 16384
VARIABLE_SCOPE SESSION
@@ -1031,7 +1022,7 @@
VARIABLE_COMMENT Allocation block size for query parsing and execution
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 4294967295
-@@ -3362,7 +3362,7 @@
+@@ -3420,7 +3420,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1048576
VARIABLE_SCOPE GLOBAL
@@ -1040,7 +1031,7 @@
VARIABLE_COMMENT Don't cache results that are bigger than this
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -3376,7 +3376,7 @@
+@@ -3434,7 +3434,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 4096
VARIABLE_SCOPE GLOBAL
@@ -1049,7 +1040,7 @@
VARIABLE_COMMENT The minimum size for blocks allocated by the query cache
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -3393,7 +3393,7 @@
+@@ -3451,7 +3451,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The memory allocated to store results from old queries
NUMERIC_MIN_VALUE 0
@@ -1058,7 +1049,7 @@
NUMERIC_BLOCK_SIZE 1024
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -3446,7 +3446,7 @@
+@@ -3504,7 +3504,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 24576
VARIABLE_SCOPE SESSION
@@ -1067,7 +1058,7 @@
VARIABLE_COMMENT Persistent buffer for query parsing and execution
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 4294967295
-@@ -3460,7 +3460,7 @@
+@@ -3518,7 +3518,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 4096
VARIABLE_SCOPE SESSION
@@ -1076,7 +1067,7 @@
VARIABLE_COMMENT Allocation block size for storing ranges during optimization
NUMERIC_MIN_VALUE 4096
NUMERIC_MAX_VALUE 4294967295
-@@ -3474,7 +3474,7 @@
+@@ -3532,7 +3532,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 131072
VARIABLE_SCOPE SESSION
@@ -1085,7 +1076,7 @@
VARIABLE_COMMENT Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value
NUMERIC_MIN_VALUE 8192
NUMERIC_MAX_VALUE 2147483647
-@@ -3502,7 +3502,7 @@
+@@ -3560,7 +3560,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 262144
VARIABLE_SCOPE SESSION
@@ -1094,7 +1085,7 @@
VARIABLE_COMMENT When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 2147483647
-@@ -3516,10 +3516,10 @@
+@@ -3574,10 +3574,10 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 8388608
VARIABLE_SCOPE SESSION
@@ -1107,7 +1098,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -3558,7 +3558,7 @@
+@@ -3630,7 +3630,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE 1
VARIABLE_SCOPE SESSION
@@ -1116,7 +1107,7 @@
VARIABLE_COMMENT Uniquely identifies the server instance in the community of replication partners
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
-@@ -3656,7 +3656,7 @@
+@@ -3728,7 +3728,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1073741824
VARIABLE_SCOPE GLOBAL
@@ -1125,7 +1116,7 @@
VARIABLE_COMMENT The maximum packet length to sent successfully from the master to slave.
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 1073741824
-@@ -3670,7 +3670,7 @@
+@@ -3742,7 +3742,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 2
VARIABLE_SCOPE GLOBAL
@@ -1134,7 +1125,7 @@
VARIABLE_COMMENT If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 31536000
-@@ -3729,7 +3729,7 @@
+@@ -3801,7 +3801,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Each thread that needs to do a sort allocates a buffer of this size
NUMERIC_MIN_VALUE 1024
@@ -1143,7 +1134,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -4020,7 +4020,7 @@
+@@ -4092,7 +4092,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 256
VARIABLE_SCOPE GLOBAL
@@ -1152,7 +1143,7 @@
VARIABLE_COMMENT The soft upper limit for number of cached stored routines for one connection.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 524288
-@@ -4090,7 +4090,7 @@
+@@ -4190,7 +4190,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 400
VARIABLE_SCOPE GLOBAL
@@ -1160,17 +1151,17 @@
+VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT The number of cached table definitions
NUMERIC_MIN_VALUE 400
- NUMERIC_MAX_VALUE 524288
-@@ -4104,7 +4104,7 @@
- GLOBAL_VALUE_ORIGIN COMPILE-TIME
+ NUMERIC_MAX_VALUE 2097152
+@@ -4204,7 +4204,7 @@
+ GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE 2000
VARIABLE_SCOPE GLOBAL
-VARIABLE_TYPE BIGINT UNSIGNED
+VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT The number of cached open tables
- NUMERIC_MIN_VALUE 1
+ NUMERIC_MIN_VALUE 10
NUMERIC_MAX_VALUE 1048576
-@@ -4174,7 +4174,7 @@
+@@ -4288,7 +4288,7 @@
GLOBAL_VALUE_ORIGIN AUTO
DEFAULT_VALUE 256
VARIABLE_SCOPE GLOBAL
@@ -1179,7 +1170,7 @@
VARIABLE_COMMENT How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 16384
-@@ -4188,7 +4188,7 @@
+@@ -4302,7 +4302,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 10
VARIABLE_SCOPE GLOBAL
@@ -1188,7 +1179,7 @@
VARIABLE_COMMENT Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.This variable has no effect, and is deprecated. It will be removed in a future release.
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 512
-@@ -4295,15 +4295,15 @@
+@@ -4409,15 +4409,15 @@
READ_ONLY YES
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME TMP_DISK_TABLE_SIZE
@@ -1208,7 +1199,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -4317,7 +4317,7 @@
+@@ -4431,7 +4431,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. Same as tmp_table_size.
NUMERIC_MIN_VALUE 1024
@@ -1217,7 +1208,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -4331,7 +4331,7 @@
+@@ -4445,7 +4445,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Alias for tmp_memory_table_size. If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table.
NUMERIC_MIN_VALUE 1024
@@ -1226,7 +1217,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -4342,7 +4342,7 @@
+@@ -4456,7 +4456,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 8192
VARIABLE_SCOPE SESSION
@@ -1235,7 +1226,7 @@
VARIABLE_COMMENT Allocation block size for transactions to be stored in binary log
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 134217728
-@@ -4356,7 +4356,7 @@
+@@ -4470,7 +4470,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 4096
VARIABLE_SCOPE SESSION
@@ -1244,7 +1235,7 @@
VARIABLE_COMMENT Persistent buffer for transactions to be stored in binary log
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 134217728
-@@ -4454,7 +4454,7 @@
+@@ -4568,7 +4568,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 28800
VARIABLE_SCOPE SESSION
@@ -1253,7 +1244,7 @@
VARIABLE_COMMENT The number of seconds the server waits for activity on a connection before closing it
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 31536000
-@@ -4559,7 +4559,7 @@
+@@ -4673,7 +4673,7 @@
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME OPEN_FILES_LIMIT
VARIABLE_SCOPE GLOBAL
@@ -1262,7 +1253,7 @@
VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 or autoset then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -4572,7 +4572,7 @@
+@@ -4686,7 +4686,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes
NUMERIC_MIN_VALUE 0
@@ -1271,7 +1262,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -4582,7 +4582,7 @@
+@@ -4696,7 +4696,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes
NUMERIC_MIN_VALUE 0
@@ -1280,7 +1271,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -4677,7 +4677,7 @@
+@@ -4791,7 +4791,7 @@
VARIABLE_NAME LOG_TC_SIZE
GLOBAL_VALUE_ORIGIN AUTO
VARIABLE_SCOPE GLOBAL
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
index 926ac8b2668..c896df1808f 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
@@ -2742,6 +2742,34 @@ NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,default
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
+VARIABLE_NAME OPTIMIZER_TRACE
+SESSION_VALUE enabled=off
+GLOBAL_VALUE enabled=off
+GLOBAL_VALUE_ORIGIN COMPILE-TIME
+DEFAULT_VALUE enabled=off
+VARIABLE_SCOPE SESSION
+VARIABLE_TYPE FLAGSET
+VARIABLE_COMMENT Controls tracing of the Optimizer: optimizer_trace=option=val[,option=val...], where option is one of {enabled} and val is one of {on, off, default}
+NUMERIC_MIN_VALUE NULL
+NUMERIC_MAX_VALUE NULL
+NUMERIC_BLOCK_SIZE NULL
+ENUM_VALUE_LIST enabled,default
+READ_ONLY NO
+COMMAND_LINE_ARGUMENT REQUIRED
+VARIABLE_NAME OPTIMIZER_TRACE_MAX_MEM_SIZE
+SESSION_VALUE 1048576
+GLOBAL_VALUE 1048576
+GLOBAL_VALUE_ORIGIN COMPILE-TIME
+DEFAULT_VALUE 1048576
+VARIABLE_SCOPE SESSION
+VARIABLE_TYPE BIGINT UNSIGNED
+VARIABLE_COMMENT Maximum allowed size of an optimizer trace
+NUMERIC_MIN_VALUE 0
+NUMERIC_MAX_VALUE 18446744073709551615
+NUMERIC_BLOCK_SIZE 1
+ENUM_VALUE_LIST NULL
+READ_ONLY NO
+COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY
SESSION_VALUE 4
GLOBAL_VALUE 4
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff
index cb9e84b81c8..53a74f90032 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff
@@ -1,6 +1,6 @@
---- sysvars_server_notembedded.result 2017-12-15 20:57:40.174654761 +0200
-+++ sysvars_server_notembedded,32bit.reject 2017-12-15 21:02:20.476044700 +0200
-@@ -58,7 +58,7 @@
+--- suite/sys_vars/r/sysvars_server_notembedded.result 2019-02-09 18:56:57.338345161 +0530
++++ suite/sys_vars/r/sysvars_server_notembedded,32bit.reject 2019-02-09 22:24:33.663762812 +0530
+@@ -74,7 +74,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE 1
VARIABLE_SCOPE SESSION
@@ -9,7 +9,7 @@
VARIABLE_COMMENT Auto-increment columns are incremented by this
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 65535
-@@ -72,7 +72,7 @@
+@@ -88,7 +88,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1
VARIABLE_SCOPE SESSION
@@ -18,7 +18,7 @@
VARIABLE_COMMENT Offset added to Auto-increment columns. Used when auto-increment-increment != 1
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 65535
-@@ -86,7 +86,7 @@
+@@ -102,7 +102,7 @@
GLOBAL_VALUE_ORIGIN AUTO
DEFAULT_VALUE 150
VARIABLE_SCOPE GLOBAL
@@ -27,7 +27,7 @@
VARIABLE_COMMENT The number of outstanding connection requests MariaDB can have. This comes into play when the main MariaDB thread gets very many connection requests in a very short time
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 65535
-@@ -159,7 +159,7 @@
+@@ -175,7 +175,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The size of the transactional cache for updates to transactional engines for the binary log. If you often use transactions containing many statements, you can increase this to get more performance
NUMERIC_MIN_VALUE 4096
@@ -36,7 +36,7 @@
NUMERIC_BLOCK_SIZE 4096
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -184,10 +184,10 @@
+@@ -200,10 +200,10 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE GLOBAL
@@ -49,7 +49,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -198,10 +198,10 @@
+@@ -214,10 +214,10 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 100000
VARIABLE_SCOPE GLOBAL
@@ -62,7 +62,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -229,7 +229,7 @@
+@@ -245,7 +245,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The size of file cache for the binary log
NUMERIC_MIN_VALUE 8192
@@ -71,7 +71,7 @@
NUMERIC_BLOCK_SIZE 4096
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -285,7 +285,7 @@
+@@ -301,7 +301,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The size of the statement cache for updates to non-transactional engines for the binary log. If you often use statements updating a great number of rows, you can increase this to get more performance.
NUMERIC_MIN_VALUE 4096
@@ -80,7 +80,7 @@
NUMERIC_BLOCK_SIZE 4096
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -299,7 +299,7 @@
+@@ -315,7 +315,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Size of tree cache used in bulk insert optimisation. Note that this is a limit per thread!
NUMERIC_MIN_VALUE 0
@@ -89,7 +89,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -562,7 +562,7 @@
+@@ -578,7 +578,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE 10
VARIABLE_SCOPE GLOBAL
@@ -98,7 +98,7 @@
VARIABLE_COMMENT The number of seconds the mysqld server is waiting for a connect packet before responding with 'Bad handshake'
NUMERIC_MIN_VALUE 2
NUMERIC_MAX_VALUE 31536000
-@@ -618,7 +618,7 @@
+@@ -648,7 +648,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 15
VARIABLE_SCOPE SESSION
@@ -107,7 +107,7 @@
VARIABLE_COMMENT Long search depth for the two-step deadlock detection
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 33
-@@ -632,7 +632,7 @@
+@@ -662,7 +662,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 4
VARIABLE_SCOPE SESSION
@@ -116,7 +116,7 @@
VARIABLE_COMMENT Short search depth for the two-step deadlock detection
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 32
-@@ -646,7 +646,7 @@
+@@ -676,7 +676,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 50000000
VARIABLE_SCOPE SESSION
@@ -125,7 +125,7 @@
VARIABLE_COMMENT Long timeout for the two-step deadlock detection (in microseconds)
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -660,7 +660,7 @@
+@@ -690,7 +690,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 10000
VARIABLE_SCOPE SESSION
@@ -134,7 +134,7 @@
VARIABLE_COMMENT Short timeout for the two-step deadlock detection (in microseconds)
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -730,7 +730,7 @@
+@@ -760,7 +760,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE SESSION
@@ -143,7 +143,7 @@
VARIABLE_COMMENT The default week format used by WEEK() functions
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 7
-@@ -744,7 +744,7 @@
+@@ -774,7 +774,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 100
VARIABLE_SCOPE GLOBAL
@@ -152,7 +152,7 @@
VARIABLE_COMMENT After inserting delayed_insert_limit rows, the INSERT DELAYED handler will check if there are any SELECT statements pending. If so, it allows these to execute before continuing.
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
-@@ -758,7 +758,7 @@
+@@ -788,7 +788,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 300
VARIABLE_SCOPE GLOBAL
@@ -161,7 +161,7 @@
VARIABLE_COMMENT How long a INSERT DELAYED thread should wait for INSERT statements before terminating
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 31536000
-@@ -772,7 +772,7 @@
+@@ -802,7 +802,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1000
VARIABLE_SCOPE GLOBAL
@@ -170,7 +170,7 @@
VARIABLE_COMMENT What size queue (in rows) should be allocated for handling INSERT DELAYED. If the queue becomes full, any client that does INSERT DELAYED will wait until there is room in the queue again
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
-@@ -800,7 +800,7 @@
+@@ -830,7 +830,7 @@
GLOBAL_VALUE_ORIGIN SQL
DEFAULT_VALUE 4
VARIABLE_SCOPE SESSION
@@ -179,7 +179,7 @@
VARIABLE_COMMENT Precision of the result of '/' operator will be increased on that value
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 38
-@@ -912,7 +912,7 @@
+@@ -956,7 +956,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE GLOBAL
@@ -188,7 +188,7 @@
VARIABLE_COMMENT If non-zero, binary logs will be purged after expire_logs_days days; possible purges happen at startup and at binary log rotation
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 99
-@@ -954,7 +954,7 @@
+@@ -998,7 +998,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1
VARIABLE_SCOPE GLOBAL
@@ -197,7 +197,7 @@
VARIABLE_COMMENT The number of connections on extra-port
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 100000
-@@ -996,7 +996,7 @@
+@@ -1040,7 +1040,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE GLOBAL
@@ -206,7 +206,7 @@
VARIABLE_COMMENT A dedicated thread is created to flush all tables at the given interval
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 31536000
-@@ -1038,7 +1038,7 @@
+@@ -1082,7 +1082,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 84
VARIABLE_SCOPE GLOBAL
@@ -215,7 +215,7 @@
VARIABLE_COMMENT The maximum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable
NUMERIC_MIN_VALUE 10
NUMERIC_MAX_VALUE 84
-@@ -1052,7 +1052,7 @@
+@@ -1096,7 +1096,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 4
VARIABLE_SCOPE GLOBAL
@@ -224,7 +224,7 @@
VARIABLE_COMMENT The minimum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 84
-@@ -1066,7 +1066,7 @@
+@@ -1110,7 +1110,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 20
VARIABLE_SCOPE GLOBAL
@@ -233,7 +233,7 @@
VARIABLE_COMMENT Number of best matches to use for query expansion
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 1000
-@@ -1125,7 +1125,7 @@
+@@ -1169,7 +1169,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The maximum length of the result of function GROUP_CONCAT()
NUMERIC_MIN_VALUE 4
@@ -242,7 +242,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -1374,7 +1374,7 @@
+@@ -1432,7 +1432,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE SESSION
@@ -251,7 +251,7 @@
VARIABLE_COMMENT Number of bytes used for a histogram. If set to 0, no histograms are created by ANALYZE.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 255
-@@ -1402,7 +1402,7 @@
+@@ -1460,7 +1460,7 @@
GLOBAL_VALUE_ORIGIN AUTO
DEFAULT_VALUE 128
VARIABLE_SCOPE GLOBAL
@@ -260,7 +260,7 @@
VARIABLE_COMMENT How many host names should be cached to avoid resolving.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 65536
-@@ -1556,7 +1556,7 @@
+@@ -1614,7 +1614,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 28800
VARIABLE_SCOPE SESSION
@@ -269,20 +269,7 @@
VARIABLE_COMMENT The number of seconds the server waits for activity on an interactive connection before closing it
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 31536000
-@@ -1570,10 +1570,10 @@
- GLOBAL_VALUE_ORIGIN COMPILE-TIME
- DEFAULT_VALUE 1000
- VARIABLE_SCOPE SESSION
--VARIABLE_TYPE BIGINT UNSIGNED
-+VARIABLE_TYPE INT UNSIGNED
- VARIABLE_COMMENT The minimum number of scalar elements in the value list of IN predicate that triggers its conversion to IN subquery
- NUMERIC_MIN_VALUE 0
--NUMERIC_MAX_VALUE 18446744073709551615
-+NUMERIC_MAX_VALUE 4294967295
- NUMERIC_BLOCK_SIZE 1
- ENUM_VALUE_LIST NULL
- READ_ONLY NO
-@@ -1601,7 +1601,7 @@
+@@ -1645,7 +1645,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The size of the buffer that is used for joins
NUMERIC_MIN_VALUE 128
@@ -291,7 +278,7 @@
NUMERIC_BLOCK_SIZE 128
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -1626,7 +1626,7 @@
+@@ -1670,7 +1670,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 2
VARIABLE_SCOPE SESSION
@@ -300,7 +287,7 @@
VARIABLE_COMMENT Controls what join operations can be executed with join buffers. Odd numbers are used for plain join buffers while even numbers are used for linked buffers
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 8
-@@ -1657,7 +1657,7 @@
+@@ -1701,7 +1701,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The size of the buffer used for index blocks for MyISAM tables. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford
NUMERIC_MIN_VALUE 0
@@ -309,7 +296,7 @@
NUMERIC_BLOCK_SIZE 4096
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -1878,7 +1878,7 @@
+@@ -1922,7 +1922,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 86400
VARIABLE_SCOPE SESSION
@@ -318,7 +305,7 @@
VARIABLE_COMMENT Timeout in seconds to wait for a lock before returning an error.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 31536000
-@@ -2088,7 +2088,7 @@
+@@ -2132,7 +2132,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1
VARIABLE_SCOPE SESSION
@@ -327,7 +314,7 @@
VARIABLE_COMMENT Write to slow log every #th slow query. Set to 1 to log everything. Increase it to reduce the size of the slow or the performance impact of slow logging
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
-@@ -2130,7 +2130,7 @@
+@@ -2174,7 +2174,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 2
VARIABLE_SCOPE SESSION
@@ -336,7 +323,7 @@
VARIABLE_COMMENT Log some not critical warnings to the general log file.Value can be between 0 and 11. Higher values mean more verbosity
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -2186,7 +2186,7 @@
+@@ -2230,7 +2230,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 16777216
VARIABLE_SCOPE SESSION
@@ -345,7 +332,7 @@
VARIABLE_COMMENT Max packet length to send to or receive from the server
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 1073741824
-@@ -2196,14 +2196,14 @@
+@@ -2240,14 +2240,14 @@
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME MAX_BINLOG_CACHE_SIZE
SESSION_VALUE NULL
@@ -363,7 +350,7 @@
NUMERIC_BLOCK_SIZE 4096
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -2214,7 +2214,7 @@
+@@ -2258,7 +2258,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1073741824
VARIABLE_SCOPE GLOBAL
@@ -372,7 +359,7 @@
VARIABLE_COMMENT Binary log will be rotated automatically when the size exceeds this value.
NUMERIC_MIN_VALUE 4096
NUMERIC_MAX_VALUE 1073741824
-@@ -2224,14 +2224,14 @@
+@@ -2268,14 +2268,14 @@
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME MAX_BINLOG_STMT_CACHE_SIZE
SESSION_VALUE NULL
@@ -390,16 +377,16 @@
NUMERIC_BLOCK_SIZE 4096
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -2242,7 +2242,7 @@
+@@ -2286,7 +2286,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 151
VARIABLE_SCOPE GLOBAL
-VARIABLE_TYPE BIGINT UNSIGNED
+VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT The number of simultaneous clients allowed
- NUMERIC_MIN_VALUE 1
+ NUMERIC_MIN_VALUE 10
NUMERIC_MAX_VALUE 100000
-@@ -2256,7 +2256,7 @@
+@@ -2300,7 +2300,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 100
VARIABLE_SCOPE GLOBAL
@@ -408,7 +395,7 @@
VARIABLE_COMMENT If there is more than this number of interrupted connections from a host this host will be blocked from further connections
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
-@@ -2270,7 +2270,7 @@
+@@ -2314,7 +2314,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 20
VARIABLE_SCOPE SESSION
@@ -417,7 +404,7 @@
VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 16384
-@@ -2298,7 +2298,7 @@
+@@ -2342,7 +2342,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 64
VARIABLE_SCOPE SESSION
@@ -426,7 +413,7 @@
VARIABLE_COMMENT Max number of errors/warnings to store for a statement
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 65535
-@@ -2315,7 +2315,7 @@
+@@ -2359,7 +2359,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Don't allow creation of heap tables bigger than this
NUMERIC_MIN_VALUE 16384
@@ -435,7 +422,7 @@
NUMERIC_BLOCK_SIZE 1024
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -2326,7 +2326,7 @@
+@@ -2370,7 +2370,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 20
VARIABLE_SCOPE SESSION
@@ -444,7 +431,7 @@
VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 16384
-@@ -2354,7 +2354,7 @@
+@@ -2398,7 +2398,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1024
VARIABLE_SCOPE SESSION
@@ -453,7 +440,7 @@
VARIABLE_COMMENT Max number of bytes in sorted records
NUMERIC_MIN_VALUE 4
NUMERIC_MAX_VALUE 8388608
-@@ -2368,7 +2368,7 @@
+@@ -2412,7 +2412,7 @@
GLOBAL_VALUE_ORIGIN AUTO
DEFAULT_VALUE 1048576
VARIABLE_SCOPE GLOBAL
@@ -462,16 +449,7 @@
VARIABLE_COMMENT The maximum BLOB length to send to server from mysql_send_long_data API. Deprecated option; use max_allowed_packet instead.
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 4294967295
-@@ -2382,7 +2382,7 @@
- GLOBAL_VALUE_ORIGIN COMPILE-TIME
- DEFAULT_VALUE 16382
- VARIABLE_SCOPE GLOBAL
--VARIABLE_TYPE BIGINT UNSIGNED
-+VARIABLE_TYPE INT UNSIGNED
- VARIABLE_COMMENT Maximum number of prepared statements in the server
- NUMERIC_MIN_VALUE 0
- NUMERIC_MAX_VALUE 1048576
-@@ -2396,7 +2396,7 @@
+@@ -2454,7 +2454,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 4294967295
VARIABLE_SCOPE SESSION
@@ -480,7 +458,7 @@
VARIABLE_COMMENT Maximum number of iterations when executing recursive queries
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -2424,7 +2424,7 @@
+@@ -2482,7 +2482,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 4294967295
VARIABLE_SCOPE SESSION
@@ -489,7 +467,7 @@
VARIABLE_COMMENT Limit assumed max number of seeks when looking up rows based on a key
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
-@@ -2452,7 +2452,7 @@
+@@ -2510,7 +2510,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1024
VARIABLE_SCOPE SESSION
@@ -498,7 +476,7 @@
VARIABLE_COMMENT The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored)
NUMERIC_MIN_VALUE 4
NUMERIC_MAX_VALUE 8388608
-@@ -2466,7 +2466,7 @@
+@@ -2524,7 +2524,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE SESSION
@@ -507,7 +485,7 @@
VARIABLE_COMMENT Maximum stored procedure recursion depth
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 255
-@@ -2494,7 +2494,7 @@
+@@ -2552,7 +2552,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 32
VARIABLE_SCOPE SESSION
@@ -516,7 +494,7 @@
VARIABLE_COMMENT Unused, will be removed.
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
-@@ -2522,7 +2522,7 @@
+@@ -2580,7 +2580,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 4294967295
VARIABLE_SCOPE GLOBAL
@@ -525,7 +503,7 @@
VARIABLE_COMMENT After this many write locks, allow some read locks to run in between
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
-@@ -2536,7 +2536,7 @@
+@@ -2594,7 +2594,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1024
VARIABLE_SCOPE GLOBAL
@@ -534,7 +512,7 @@
VARIABLE_COMMENT Unused
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 1048576
-@@ -2550,7 +2550,7 @@
+@@ -2608,7 +2608,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 8
VARIABLE_SCOPE GLOBAL
@@ -543,7 +521,7 @@
VARIABLE_COMMENT Unused
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 1024
-@@ -2564,7 +2564,7 @@
+@@ -2622,7 +2622,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE SESSION
@@ -552,7 +530,7 @@
VARIABLE_COMMENT Don't write queries to slow log that examine fewer rows than that
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -2578,7 +2578,7 @@
+@@ -2636,7 +2636,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 262144
VARIABLE_SCOPE SESSION
@@ -561,7 +539,7 @@
VARIABLE_COMMENT Size of buffer to use when using MRR with range access
NUMERIC_MIN_VALUE 8192
NUMERIC_MAX_VALUE 2147483647
-@@ -2592,10 +2592,10 @@
+@@ -2650,10 +2650,10 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 256
VARIABLE_SCOPE SESSION
@@ -574,7 +552,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -2606,7 +2606,7 @@
+@@ -2664,7 +2664,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1024
VARIABLE_SCOPE GLOBAL
@@ -583,7 +561,7 @@
VARIABLE_COMMENT Block size to be used for MyISAM index pages
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 16384
-@@ -2620,7 +2620,7 @@
+@@ -2678,7 +2678,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 6
VARIABLE_SCOPE GLOBAL
@@ -592,7 +570,7 @@
VARIABLE_COMMENT Default pointer size to be used for MyISAM tables
NUMERIC_MIN_VALUE 2
NUMERIC_MAX_VALUE 7
-@@ -2630,9 +2630,9 @@
+@@ -2688,9 +2688,9 @@
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME MYISAM_MAX_SORT_FILE_SIZE
SESSION_VALUE NULL
@@ -604,7 +582,7 @@
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Don't use the fast sort index method to created index if the temporary file would get bigger than this
-@@ -2644,14 +2644,14 @@
+@@ -2702,14 +2702,14 @@
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME MYISAM_MMAP_SIZE
SESSION_VALUE NULL
@@ -622,7 +600,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY YES
-@@ -2676,10 +2676,10 @@
+@@ -2734,10 +2734,10 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1
VARIABLE_SCOPE SESSION
@@ -635,7 +613,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -2693,7 +2693,7 @@
+@@ -2751,7 +2751,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE
NUMERIC_MIN_VALUE 4096
@@ -644,7 +622,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -2746,7 +2746,7 @@
+@@ -2804,7 +2804,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 16384
VARIABLE_SCOPE SESSION
@@ -653,7 +631,7 @@
VARIABLE_COMMENT Buffer length for TCP/IP and socket communication
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 1048576
-@@ -2760,7 +2760,7 @@
+@@ -2818,7 +2818,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 30
VARIABLE_SCOPE SESSION
@@ -662,7 +640,7 @@
VARIABLE_COMMENT Number of seconds to wait for more data from a connection before aborting the read
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 31536000
-@@ -2774,7 +2774,7 @@
+@@ -2832,7 +2832,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 10
VARIABLE_SCOPE SESSION
@@ -671,7 +649,7 @@
VARIABLE_COMMENT If a read on a communication port is interrupted, retry this many times before giving up
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
-@@ -2788,7 +2788,7 @@
+@@ -2846,7 +2846,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 60
VARIABLE_SCOPE SESSION
@@ -680,7 +658,7 @@
VARIABLE_COMMENT Number of seconds to wait for a block to be written to a connection before aborting the write
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 31536000
-@@ -2858,7 +2858,7 @@
+@@ -2916,7 +2916,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1
VARIABLE_SCOPE SESSION
@@ -689,7 +667,7 @@
VARIABLE_COMMENT Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 1
-@@ -2872,7 +2872,7 @@
+@@ -2930,7 +2930,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 62
VARIABLE_SCOPE SESSION
@@ -698,7 +676,7 @@
VARIABLE_COMMENT Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Values smaller than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 62
-@@ -2886,7 +2886,7 @@
+@@ -2944,7 +2944,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 100
VARIABLE_SCOPE SESSION
@@ -707,16 +685,29 @@
VARIABLE_COMMENT Controls number of record samples to check condition selectivity
NUMERIC_MIN_VALUE 10
NUMERIC_MAX_VALUE 4294967295
-@@ -2914,7 +2914,7 @@
+@@ -2986,10 +2986,10 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
- DEFAULT_VALUE 1
+ DEFAULT_VALUE 1048576
+ VARIABLE_SCOPE SESSION
+-VARIABLE_TYPE BIGINT UNSIGNED
++VARIABLE_TYPE INT UNSIGNED
+ VARIABLE_COMMENT Maximum allowed size of an optimizer trace
+ NUMERIC_MIN_VALUE 0
+-NUMERIC_MAX_VALUE 18446744073709551615
++NUMERIC_MAX_VALUE 4294967295
+ NUMERIC_BLOCK_SIZE 1
+ ENUM_VALUE_LIST NULL
+ READ_ONLY NO
+@@ -3000,7 +3000,7 @@
+ GLOBAL_VALUE_ORIGIN COMPILE-TIME
+ DEFAULT_VALUE 4
VARIABLE_SCOPE SESSION
-VARIABLE_TYPE BIGINT UNSIGNED
+VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 5
-@@ -2942,7 +2942,7 @@
+@@ -3028,7 +3028,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -725,7 +716,7 @@
VARIABLE_COMMENT Maximum number of instrumented user@host accounts. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -2956,7 +2956,7 @@
+@@ -3042,7 +3042,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -734,7 +725,7 @@
VARIABLE_COMMENT Size of the statement digest. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 200
-@@ -2970,7 +2970,7 @@
+@@ -3056,7 +3056,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -743,7 +734,7 @@
VARIABLE_COMMENT Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -2984,7 +2984,7 @@
+@@ -3070,7 +3070,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -752,7 +743,7 @@
VARIABLE_COMMENT Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1024
-@@ -2998,7 +2998,7 @@
+@@ -3084,7 +3084,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -761,7 +752,7 @@
VARIABLE_COMMENT Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -3012,7 +3012,7 @@
+@@ -3098,7 +3098,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -770,7 +761,7 @@
VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_HISTORY. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1024
-@@ -3026,7 +3026,7 @@
+@@ -3112,7 +3112,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -779,7 +770,7 @@
VARIABLE_COMMENT Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -3040,7 +3040,7 @@
+@@ -3126,7 +3126,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -788,7 +779,7 @@
VARIABLE_COMMENT Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1024
-@@ -3054,7 +3054,7 @@
+@@ -3140,7 +3140,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -797,7 +788,7 @@
VARIABLE_COMMENT Maximum number of instrumented hosts. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -3068,7 +3068,7 @@
+@@ -3154,7 +3154,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 80
VARIABLE_SCOPE GLOBAL
@@ -806,7 +797,7 @@
VARIABLE_COMMENT Maximum number of condition instruments.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 256
-@@ -3082,7 +3082,7 @@
+@@ -3168,7 +3168,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -815,7 +806,7 @@
VARIABLE_COMMENT Maximum number of instrumented condition objects. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -3096,7 +3096,7 @@
+@@ -3182,7 +3182,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1024
VARIABLE_SCOPE GLOBAL
@@ -824,7 +815,7 @@
VARIABLE_COMMENT Maximum length considered for digest text, when stored in performance_schema tables.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 1048576
-@@ -3110,7 +3110,7 @@
+@@ -3196,7 +3196,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 50
VARIABLE_SCOPE GLOBAL
@@ -833,7 +824,7 @@
VARIABLE_COMMENT Maximum number of file instruments.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 256
-@@ -3124,7 +3124,7 @@
+@@ -3210,7 +3210,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 32768
VARIABLE_SCOPE GLOBAL
@@ -842,7 +833,7 @@
VARIABLE_COMMENT Maximum number of opened instrumented files.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 1048576
-@@ -3138,7 +3138,7 @@
+@@ -3224,7 +3224,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -851,7 +842,7 @@
VARIABLE_COMMENT Maximum number of instrumented files. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -3152,7 +3152,7 @@
+@@ -3238,7 +3238,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 200
VARIABLE_SCOPE GLOBAL
@@ -860,7 +851,7 @@
VARIABLE_COMMENT Maximum number of mutex instruments.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 256
-@@ -3166,7 +3166,7 @@
+@@ -3252,7 +3252,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -869,7 +860,7 @@
VARIABLE_COMMENT Maximum number of instrumented MUTEX objects. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 104857600
-@@ -3180,7 +3180,7 @@
+@@ -3266,7 +3266,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 40
VARIABLE_SCOPE GLOBAL
@@ -878,7 +869,7 @@
VARIABLE_COMMENT Maximum number of rwlock instruments.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 256
-@@ -3194,7 +3194,7 @@
+@@ -3280,7 +3280,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -887,7 +878,7 @@
VARIABLE_COMMENT Maximum number of instrumented RWLOCK objects. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 104857600
-@@ -3208,7 +3208,7 @@
+@@ -3294,7 +3294,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 10
VARIABLE_SCOPE GLOBAL
@@ -896,7 +887,7 @@
VARIABLE_COMMENT Maximum number of socket instruments.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 256
-@@ -3222,7 +3222,7 @@
+@@ -3308,7 +3308,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -905,7 +896,7 @@
VARIABLE_COMMENT Maximum number of opened instrumented sockets. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -3236,7 +3236,7 @@
+@@ -3322,7 +3322,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 160
VARIABLE_SCOPE GLOBAL
@@ -914,16 +905,16 @@
VARIABLE_COMMENT Maximum number of stage instruments.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 256
-@@ -3250,7 +3250,7 @@
+@@ -3336,7 +3336,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
- DEFAULT_VALUE 191
+ DEFAULT_VALUE 202
VARIABLE_SCOPE GLOBAL
-VARIABLE_TYPE BIGINT UNSIGNED
+VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT Maximum number of statement instruments.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 256
-@@ -3264,7 +3264,7 @@
+@@ -3350,7 +3350,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -932,7 +923,7 @@
VARIABLE_COMMENT Maximum number of opened instrumented tables. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -3278,7 +3278,7 @@
+@@ -3364,7 +3364,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -941,7 +932,7 @@
VARIABLE_COMMENT Maximum number of instrumented tables. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -3292,7 +3292,7 @@
+@@ -3378,7 +3378,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 50
VARIABLE_SCOPE GLOBAL
@@ -950,7 +941,7 @@
VARIABLE_COMMENT Maximum number of thread instruments.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 256
-@@ -3306,7 +3306,7 @@
+@@ -3392,7 +3392,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -959,7 +950,7 @@
VARIABLE_COMMENT Maximum number of instrumented threads. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -3320,7 +3320,7 @@
+@@ -3406,7 +3406,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -968,7 +959,7 @@
VARIABLE_COMMENT Size of session attribute string buffer per thread. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -3334,7 +3334,7 @@
+@@ -3420,7 +3420,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 100
VARIABLE_SCOPE GLOBAL
@@ -977,7 +968,7 @@
VARIABLE_COMMENT Maximum number of rows in SETUP_ACTORS.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 1024
-@@ -3348,7 +3348,7 @@
+@@ -3434,7 +3434,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 100
VARIABLE_SCOPE GLOBAL
@@ -986,7 +977,7 @@
VARIABLE_COMMENT Maximum number of rows in SETUP_OBJECTS.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 1048576
-@@ -3362,7 +3362,7 @@
+@@ -3448,7 +3448,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE -1
VARIABLE_SCOPE GLOBAL
@@ -995,7 +986,7 @@
VARIABLE_COMMENT Maximum number of instrumented users. Use 0 to disable, -1 for automated sizing.
NUMERIC_MIN_VALUE -1
NUMERIC_MAX_VALUE 1048576
-@@ -3432,7 +3432,7 @@
+@@ -3504,7 +3504,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 32768
VARIABLE_SCOPE SESSION
@@ -1004,7 +995,7 @@
VARIABLE_COMMENT The size of the buffer that is allocated when preloading indexes
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 1073741824
-@@ -3460,7 +3460,7 @@
+@@ -3532,7 +3532,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 15
VARIABLE_SCOPE SESSION
@@ -1013,7 +1004,7 @@
VARIABLE_COMMENT Number of statements about which profiling information is maintained. If set to 0, no profiles are stored. See SHOW PROFILES.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 100
-@@ -3474,7 +3474,7 @@
+@@ -3546,7 +3546,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 5
VARIABLE_SCOPE SESSION
@@ -1022,7 +1013,7 @@
VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -3558,7 +3558,7 @@
+@@ -3630,7 +3630,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 16384
VARIABLE_SCOPE SESSION
@@ -1031,7 +1022,7 @@
VARIABLE_COMMENT Allocation block size for query parsing and execution
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 4294967295
-@@ -3572,7 +3572,7 @@
+@@ -3644,7 +3644,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1048576
VARIABLE_SCOPE GLOBAL
@@ -1040,7 +1031,7 @@
VARIABLE_COMMENT Don't cache results that are bigger than this
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -3586,7 +3586,7 @@
+@@ -3658,7 +3658,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 4096
VARIABLE_SCOPE GLOBAL
@@ -1049,7 +1040,7 @@
VARIABLE_COMMENT The minimum size for blocks allocated by the query cache
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -3603,7 +3603,7 @@
+@@ -3675,7 +3675,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The memory allocated to store results from old queries
NUMERIC_MIN_VALUE 0
@@ -1058,7 +1049,7 @@
NUMERIC_BLOCK_SIZE 1024
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -3656,7 +3656,7 @@
+@@ -3728,7 +3728,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 24576
VARIABLE_SCOPE SESSION
@@ -1067,7 +1058,7 @@
VARIABLE_COMMENT Persistent buffer for query parsing and execution
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 4294967295
-@@ -3670,7 +3670,7 @@
+@@ -3742,7 +3742,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 4096
VARIABLE_SCOPE SESSION
@@ -1076,7 +1067,7 @@
VARIABLE_COMMENT Allocation block size for storing ranges during optimization
NUMERIC_MIN_VALUE 4096
NUMERIC_MAX_VALUE 4294967295
-@@ -3687,7 +3687,7 @@
+@@ -3759,7 +3759,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Maximum speed(KB/s) to read binlog from master (0 = no limit)
NUMERIC_MIN_VALUE 0
@@ -1085,7 +1076,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -3698,7 +3698,7 @@
+@@ -3770,7 +3770,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 131072
VARIABLE_SCOPE SESSION
@@ -1094,7 +1085,7 @@
VARIABLE_COMMENT Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value
NUMERIC_MIN_VALUE 8192
NUMERIC_MAX_VALUE 2147483647
-@@ -3726,7 +3726,7 @@
+@@ -3798,7 +3798,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 262144
VARIABLE_SCOPE SESSION
@@ -1103,7 +1094,7 @@
VARIABLE_COMMENT When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 2147483647
-@@ -4006,10 +4006,10 @@
+@@ -4078,10 +4078,10 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 8388608
VARIABLE_SCOPE SESSION
@@ -1116,7 +1107,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -4034,10 +4034,10 @@
+@@ -4106,10 +4106,10 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 10000
VARIABLE_SCOPE GLOBAL
@@ -1129,7 +1120,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -4048,10 +4048,10 @@
+@@ -4120,10 +4120,10 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 32
VARIABLE_SCOPE GLOBAL
@@ -1142,7 +1133,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -4132,10 +4132,10 @@
+@@ -4204,10 +4204,10 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 32
VARIABLE_SCOPE GLOBAL
@@ -1155,7 +1146,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -4174,7 +4174,7 @@
+@@ -4260,7 +4260,7 @@
GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE 1
VARIABLE_SCOPE SESSION
@@ -1164,7 +1155,7 @@
VARIABLE_COMMENT Uniquely identifies the server instance in the community of replication partners
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
-@@ -4356,7 +4356,7 @@
+@@ -4442,7 +4442,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE GLOBAL
@@ -1173,7 +1164,7 @@
VARIABLE_COMMENT Maximum number of parallel threads to use on slave for events in a single replication domain. When using multiple domains, this can be used to limit a single domain from grabbing all threads and thus stalling other domains. The default of 0 means to allow a domain to grab as many threads as it wants, up to the value of slave_parallel_threads.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 16383
-@@ -4398,7 +4398,7 @@
+@@ -4484,7 +4484,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1073741824
VARIABLE_SCOPE GLOBAL
@@ -1182,7 +1173,7 @@
VARIABLE_COMMENT The maximum packet length to sent successfully from the master to slave.
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 1073741824
-@@ -4426,7 +4426,7 @@
+@@ -4512,7 +4512,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 131072
VARIABLE_SCOPE GLOBAL
@@ -1191,7 +1182,7 @@
VARIABLE_COMMENT Limit on how much memory SQL threads should use per parallel replication thread when reading ahead in the relay log looking for opportunities for parallel replication. Only used when --slave-parallel-threads > 0.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 2147483647
-@@ -4454,7 +4454,7 @@
+@@ -4540,7 +4540,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE GLOBAL
@@ -1200,7 +1191,7 @@
VARIABLE_COMMENT If non-zero, number of threads to spawn to apply in parallel events on the slave that were group-committed on the master or were logged with GTID in different replication domains. Note that these threads are in addition to the IO and SQL threads, which are always created by a replication slave
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 16383
-@@ -4468,7 +4468,7 @@
+@@ -4554,7 +4554,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE GLOBAL
@@ -1209,7 +1200,7 @@
VARIABLE_COMMENT Alias for slave_parallel_threads
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 16383
-@@ -4524,7 +4524,7 @@
+@@ -4610,7 +4610,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 10
VARIABLE_SCOPE GLOBAL
@@ -1218,7 +1209,7 @@
VARIABLE_COMMENT Number of times the slave SQL thread will retry a transaction in case it failed with a deadlock, elapsed lock wait timeout or listed in slave_transaction_retry_errors, before giving up and stopping
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -4552,7 +4552,7 @@
+@@ -4638,7 +4638,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE GLOBAL
@@ -1227,7 +1218,7 @@
VARIABLE_COMMENT Interval of the slave SQL thread will retry a transaction in case it failed with a deadlock or elapsed lock wait timeout or listed in slave_transaction_retry_errors
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 3600
-@@ -4580,7 +4580,7 @@
+@@ -4666,7 +4666,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 2
VARIABLE_SCOPE GLOBAL
@@ -1236,7 +1227,7 @@
VARIABLE_COMMENT If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 31536000
-@@ -4639,7 +4639,7 @@
+@@ -4725,7 +4725,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Each thread that needs to do a sort allocates a buffer of this size
NUMERIC_MIN_VALUE 1024
@@ -1245,7 +1236,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -4944,7 +4944,7 @@
+@@ -5030,7 +5030,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 256
VARIABLE_SCOPE GLOBAL
@@ -1254,7 +1245,7 @@
VARIABLE_COMMENT The soft upper limit for number of cached stored routines for one connection.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 524288
-@@ -5042,7 +5042,7 @@
+@@ -5156,7 +5156,7 @@
GLOBAL_VALUE_ORIGIN AUTO
DEFAULT_VALUE 400
VARIABLE_SCOPE GLOBAL
@@ -1262,17 +1253,17 @@
+VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT The number of cached table definitions
NUMERIC_MIN_VALUE 400
- NUMERIC_MAX_VALUE 524288
-@@ -5056,7 +5056,7 @@
- GLOBAL_VALUE_ORIGIN COMPILE-TIME
+ NUMERIC_MAX_VALUE 2097152
+@@ -5170,7 +5170,7 @@
+ GLOBAL_VALUE_ORIGIN CONFIG
DEFAULT_VALUE 2000
VARIABLE_SCOPE GLOBAL
-VARIABLE_TYPE BIGINT UNSIGNED
+VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT The number of cached open tables
- NUMERIC_MIN_VALUE 1
+ NUMERIC_MIN_VALUE 10
NUMERIC_MAX_VALUE 1048576
-@@ -5126,7 +5126,7 @@
+@@ -5254,7 +5254,7 @@
GLOBAL_VALUE_ORIGIN AUTO
DEFAULT_VALUE 256
VARIABLE_SCOPE GLOBAL
@@ -1281,7 +1272,7 @@
VARIABLE_COMMENT How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 16384
-@@ -5140,7 +5140,7 @@
+@@ -5268,7 +5268,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 10
VARIABLE_SCOPE GLOBAL
@@ -1290,7 +1281,7 @@
VARIABLE_COMMENT Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.This variable has no effect, and is deprecated. It will be removed in a future release.
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 512
-@@ -5345,15 +5345,15 @@
+@@ -5473,15 +5473,15 @@
READ_ONLY YES
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME TMP_DISK_TABLE_SIZE
@@ -1310,7 +1301,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -5367,7 +5367,7 @@
+@@ -5495,7 +5495,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. Same as tmp_table_size.
NUMERIC_MIN_VALUE 1024
@@ -1319,7 +1310,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -5381,7 +5381,7 @@
+@@ -5509,7 +5509,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Alias for tmp_memory_table_size. If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table.
NUMERIC_MIN_VALUE 1024
@@ -1328,7 +1319,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -5392,7 +5392,7 @@
+@@ -5520,7 +5520,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 8192
VARIABLE_SCOPE SESSION
@@ -1337,7 +1328,7 @@
VARIABLE_COMMENT Allocation block size for transactions to be stored in binary log
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 134217728
-@@ -5406,7 +5406,7 @@
+@@ -5534,7 +5534,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 4096
VARIABLE_SCOPE SESSION
@@ -1346,7 +1337,7 @@
VARIABLE_COMMENT Persistent buffer for transactions to be stored in binary log
NUMERIC_MIN_VALUE 1024
NUMERIC_MAX_VALUE 134217728
-@@ -5504,7 +5504,7 @@
+@@ -5632,7 +5632,7 @@
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 28800
VARIABLE_SCOPE SESSION
@@ -1355,7 +1346,7 @@
VARIABLE_COMMENT The number of seconds the server waits for activity on a connection before closing it
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 31536000
-@@ -5609,7 +5609,7 @@
+@@ -5737,7 +5737,7 @@
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME OPEN_FILES_LIMIT
VARIABLE_SCOPE GLOBAL
@@ -1364,7 +1355,7 @@
VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 or autoset then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
-@@ -5622,7 +5622,7 @@
+@@ -5750,7 +5750,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes
NUMERIC_MIN_VALUE 0
@@ -1373,7 +1364,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -5632,7 +5632,7 @@
+@@ -5760,7 +5760,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes
NUMERIC_MIN_VALUE 0
@@ -1382,7 +1373,7 @@
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
-@@ -5727,7 +5727,7 @@
+@@ -5855,7 +5855,7 @@
VARIABLE_NAME LOG_TC_SIZE
GLOBAL_VALUE_ORIGIN AUTO
VARIABLE_SCOPE GLOBAL
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
index 219b550d83e..631b75b7196 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
@@ -2966,6 +2966,34 @@ NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,default
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
+VARIABLE_NAME OPTIMIZER_TRACE
+SESSION_VALUE enabled=off
+GLOBAL_VALUE enabled=off
+GLOBAL_VALUE_ORIGIN COMPILE-TIME
+DEFAULT_VALUE enabled=off
+VARIABLE_SCOPE SESSION
+VARIABLE_TYPE FLAGSET
+VARIABLE_COMMENT Controls tracing of the Optimizer: optimizer_trace=option=val[,option=val...], where option is one of {enabled} and val is one of {on, off, default}
+NUMERIC_MIN_VALUE NULL
+NUMERIC_MAX_VALUE NULL
+NUMERIC_BLOCK_SIZE NULL
+ENUM_VALUE_LIST enabled,default
+READ_ONLY NO
+COMMAND_LINE_ARGUMENT REQUIRED
+VARIABLE_NAME OPTIMIZER_TRACE_MAX_MEM_SIZE
+SESSION_VALUE 1048576
+GLOBAL_VALUE 1048576
+GLOBAL_VALUE_ORIGIN COMPILE-TIME
+DEFAULT_VALUE 1048576
+VARIABLE_SCOPE SESSION
+VARIABLE_TYPE BIGINT UNSIGNED
+VARIABLE_COMMENT Maximum allowed size of an optimizer trace
+NUMERIC_MIN_VALUE 0
+NUMERIC_MAX_VALUE 18446744073709551615
+NUMERIC_BLOCK_SIZE 1
+ENUM_VALUE_LIST NULL
+READ_ONLY NO
+COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY
SESSION_VALUE 4
GLOBAL_VALUE 4
diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c
index 3dc38cbe29b..79b7e32cbb1 100644
--- a/mysys/my_fopen.c
+++ b/mysys/my_fopen.c
@@ -171,10 +171,7 @@ int my_fclose(FILE *fd, myf MyFlags)
my_file_info[file].type= UNOPEN;
}
#ifndef _WIN32
- do
- {
- err= fclose(fd);
- } while (err == -1 && errno == EINTR);
+ err= fclose(fd);
#else
err= my_win_fclose(fd);
#endif
diff --git a/plugin/user_variables/mysql-test/user_variables/basic.result b/plugin/user_variables/mysql-test/user_variables/basic.result
index 5650fa0dcce..a4d01957830 100644
--- a/plugin/user_variables/mysql-test/user_variables/basic.result
+++ b/plugin/user_variables/mysql-test/user_variables/basic.result
@@ -7,7 +7,7 @@ PLUGIN_AUTHOR Sergey Vojtovich
PLUGIN_DESCRIPTION User-defined variables
PLUGIN_LICENSE GPL
LOAD_OPTION ON
-PLUGIN_MATURITY Gamma
+PLUGIN_MATURITY Stable
SHOW CREATE TABLE INFORMATION_SCHEMA.USER_VARIABLES;
Table Create Table
user_variables CREATE TEMPORARY TABLE `user_variables` (
diff --git a/plugin/user_variables/user_variables.cc b/plugin/user_variables/user_variables.cc
index 80bf58612b5..8d7fe038bbd 100644
--- a/plugin/user_variables/user_variables.cc
+++ b/plugin/user_variables/user_variables.cc
@@ -135,6 +135,6 @@ maria_declare_plugin(user_variables)
NULL,
NULL,
"1.0",
- MariaDB_PLUGIN_MATURITY_GAMMA
+ MariaDB_PLUGIN_MATURITY_STABLE
}
maria_declare_plugin_end;
diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh
index 82a8e175753..54b5bed4546 100644
--- a/scripts/mysql_install_db.sh
+++ b/scripts/mysql_install_db.sh
@@ -37,8 +37,8 @@ force=0
in_rpm=0
ip_only=0
cross_bootstrap=0
-auth_root_authentication_method=normal
-auth_root_socket_user='root'
+auth_root_authentication_method=socket
+auth_root_socket_user=""
skip_test_db=0
usage()
@@ -46,17 +46,17 @@ usage()
cat <<EOF
Usage: $0 [OPTIONS]
--auth-root-authentication-method=normal|socket
- Chooses the authentication method for the created initial
- root user. The default is 'normal' to creates a root user
- that can login without password, which can be insecure.
- The alternative 'socket' allows only the system root user
- to login as MariaDB root; this requires the unix socket
- authentication plugin.
+ Chooses the authentication method for the created
+ initial root user. The historical behavior is 'normal'
+ to creates a root user that can login without password,
+ which can be insecure. The default behavior 'socket'
+ sets an invalid root password but allows the system root
+ user to login as MariaDB root without a password.
--auth-root-socket-user=user
Used with --auth-root-authentication-method=socket. It
- specifies the name of the MariaDB root account, as well
- as of the system account allowed to access it. Defaults
- to 'root'.
+ specifies the name of the second MariaDB root account,
+ as well as of the system account allowed to access it.
+ Defaults to the value of --user.
--basedir=path The path to the MariaDB installation directory.
--builddir=path If using --srcdir with out-of-directory builds, you
will need to set this to the location of the build
@@ -505,13 +505,16 @@ cat_sql()
{
echo "use mysql;"
+ # Use $auth_root_socket_user if explicitly specified.
+ # Otherwise use the owner of datadir - ${user:-$USER}
+ # Use 'root' as a fallback
+ auth_root_socket_user=${auth_root_socket_user:-${user:-${USER:-root}}}
+
case "$auth_root_authentication_method" in
normal)
- echo "SET @skip_auth_root_nopasswd=NULL;"
echo "SET @auth_root_socket=NULL;"
;;
socket)
- echo "SET @skip_auth_root_nopasswd=1;"
echo "SET @auth_root_socket='$auth_root_socket_user';"
;;
esac
diff --git a/scripts/mysql_secure_installation.sh b/scripts/mysql_secure_installation.sh
index 1bd21513d4d..6441bbdabbd 100644
--- a/scripts/mysql_secure_installation.sh
+++ b/scripts/mysql_secure_installation.sh
@@ -17,6 +17,7 @@
config=".my.cnf.$$"
command=".mysql.$$"
+output=".my.output.$$"
trap "interrupt" 1 2 3 6 15
@@ -216,7 +217,7 @@ prepare() {
do_query() {
echo "$1" >$command
#sed 's,^,> ,' < $command # Debugging
- $mysql_command --defaults-file=$config $defaults_extra_file $no_defaults $args <$command
+ $mysql_command --defaults-file=$config $defaults_extra_file $no_defaults $args <$command >$output
return $?
}
@@ -268,15 +269,18 @@ get_root_password() {
echo
stty echo
if [ "x$password" = "x" ]; then
- hadpass=0
+ emptypass=1
else
- hadpass=1
+ emptypass=0
fi
rootpass=$password
make_config
- do_query ""
+ do_query "show create user root@localhost"
status=$?
done
+ if grep -q unix_socket $output; then
+ emptypass=0
+ fi
echo "OK, successfully used password, moving on..."
echo
}
@@ -386,7 +390,7 @@ interrupt() {
cleanup() {
echo "Cleaning up..."
- rm -f $config $command
+ rm -f $config $command $output
}
# Remove the files before exiting.
@@ -405,9 +409,8 @@ echo "NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB"
echo " SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!"
echo
echo "In order to log into MariaDB to secure it, we'll need the current"
-echo "password for the root user. If you've just installed MariaDB, and"
-echo "you haven't set the root password yet, the password will be blank,"
-echo "so you should just press enter here."
+echo "password for the root user. If you've just installed MariaDB, and"
+echo "haven't set the root password yet, you should just press enter here."
echo
get_root_password
@@ -417,15 +420,47 @@ get_root_password
# Set the root password
#
-echo "Setting the root password ensures that nobody can log into the MariaDB"
-echo "root user without the proper authorisation."
+echo "Setting the root password or using the unix_socket ensures that nobody"
+echo "can log into the MariaDB root user without the proper authorisation."
+echo
+
+while true ; do
+ if [ $emptypass -eq 1 ]; then
+ echo $echo_n "Enable unix_socket authentication? [Y/n] $echo_c"
+ else
+ echo "You already have your root account protected, so you can safely answer 'n'."
+ echo
+ echo $echo_n "Switch to unix_socket authentication [Y/n] $echo_c"
+ fi
+ read reply
+ validate_reply $reply && break
+done
+
+if [ "$reply" = "n" ]; then
+ echo " ... skipping."
+else
+ emptypass=0
+ do_query "UPDATE mysql.global_priv SET priv=json_set(priv, '$.plugin', 'mysql_native_password', '$.authentication_string', 'invalid', '$.auth_or', json_array(json_object(), json_object('plugin', 'unix_socket'))) WHERE User='root';"
+ if [ $? -eq 0 ]; then
+ echo "Enabled successfully!"
+ echo "Reloading privilege tables.."
+ reload_privilege_tables
+ if [ $? -eq 1 ]; then
+ clean_and_exit
+ fi
+ echo
+ else
+ echo "Failed!"
+ clean_and_exit
+ fi
+fi
echo
while true ; do
- if [ $hadpass -eq 0 ]; then
+ if [ $emptypass -eq 1 ]; then
echo $echo_n "Set root password? [Y/n] $echo_c"
else
- echo "You already have a root password set, so you can safely answer 'n'."
+ echo "You already have your root account protected, so you can safely answer 'n'."
echo
echo $echo_n "Change the root password? [Y/n] $echo_c"
fi
diff --git a/scripts/mysql_system_tables_data.sql b/scripts/mysql_system_tables_data.sql
index 60867fc2bc3..9d0088aa333 100644
--- a/scripts/mysql_system_tables_data.sql
+++ b/scripts/mysql_system_tables_data.sql
@@ -25,7 +25,9 @@
-- add escape character in front of wildcard character to convert "_" or "%" to
-- a plain character
SELECT LOWER( REPLACE((SELECT REPLACE(@@hostname,'_','\_')),'%','\%') )INTO @current_hostname;
-SELECT json_object('access',cast(-1 as unsigned)) INTO @all_privileges;
+SELECT '{"access":18446744073709551615}' INTO @all_privileges;
+SELECT '{"access":18446744073709551615,"plugin":"mysql_native_password","authentication_string":"invalid","auth_or":[{},{"plugin":"unix_socket"}]}' into @all_with_auth;
+
-- Fill "global_priv" table with default users allowing root access
-- from local machine if "global_priv" table didn't exist before
@@ -37,12 +39,13 @@ REPLACE INTO tmp_user_nopasswd SELECT @current_hostname,'root',@all_privileges F
REPLACE INTO tmp_user_nopasswd VALUES ('127.0.0.1','root',@all_privileges);
REPLACE INTO tmp_user_nopasswd VALUES ('::1','root',@all_privileges);
-- More secure root account using unix socket auth.
-INSERT INTO tmp_user_socket VALUES ('localhost',IFNULL(@auth_root_socket, 'root'),json_set(@all_privileges, '$.plugin', 'unix_socket'));
+INSERT INTO tmp_user_socket VALUES ('localhost', 'root',@all_with_auth);
+REPLACE INTO tmp_user_socket VALUES ('localhost',IFNULL(@auth_root_socket, 'root'),@all_with_auth);
IF @auth_root_socket is not null THEN
IF not exists(select 1 from information_schema.plugins where plugin_name='unix_socket') THEN
INSTALL SONAME 'auth_socket'; END IF; END IF;
-INSERT INTO global_priv SELECT * FROM tmp_user_nopasswd WHERE @had_user_table=0 AND @skip_auth_root_nopasswd IS NULL;
+INSERT INTO global_priv SELECT * FROM tmp_user_nopasswd WHERE @had_user_table=0 AND @auth_root_socket IS NULL;
INSERT INTO global_priv SELECT * FROM tmp_user_socket WHERE @had_user_table=0 AND @auth_root_socket IS NOT NULL;
DROP TABLE tmp_user_nopasswd, tmp_user_socket;
diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh
index 5362389a59d..1e018f1a515 100644
--- a/scripts/wsrep_sst_mariabackup.sh
+++ b/scripts/wsrep_sst_mariabackup.sh
@@ -753,8 +753,8 @@ else
if [[ "$sstlogarchive" -eq 1 ]]
then
- ARCHIVETIMESTAMP=$(date "+%Y.%m.%d-%H.%M.%S")
- newfile=""
+ ARCHIVETIMESTAMP=$(date "+%Y.%m.%d-%H.%M.%S.%N")
+ newfile=""
if [[ ! -z "$sstlogarchivedir" ]]
then
diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh
index 1fecb6f09d9..6a71d7bbfb3 100644
--- a/scripts/wsrep_sst_rsync.sh
+++ b/scripts/wsrep_sst_rsync.sh
@@ -147,6 +147,7 @@ if ! [ -z $WSREP_SST_OPT_BINLOG_INDEX ]
then
BINLOG_INDEX_DIRNAME=$(dirname $WSREP_SST_OPT_BINLOG_INDEX)
BINLOG_INDEX_FILENAME=$(basename $WSREP_SST_OPT_BINLOG_INDEX)
+ BINLOG_INDEX_FILENAME=${BINLOG_INDEX_FILENAME%.index}.index
fi
WSREP_LOG_DIR=${WSREP_LOG_DIR:-""}
@@ -268,12 +269,12 @@ EOF
OLD_PWD="$(pwd)"
cd $BINLOG_DIRNAME
- if ! [ -z $WSREP_SST_OPT_BINLOG_INDEX ]
+ if [ -z $WSREP_SST_OPT_BINLOG_INDEX ]
then
- binlog_files_full=$(tail -n $BINLOG_N_FILES ${BINLOG_FILENAME}.index)
+ binlog_files_full=$(tail -n $BINLOG_N_FILES ${BINLOG_FILENAME}.index)
else
- cd $BINLOG_INDEX_DIRNAME
- binlog_files_full=$(tail -n $BINLOG_N_FILES ${BINLOG_INDEX_FILENAME}.index)
+ cd $BINLOG_INDEX_DIRNAME
+ binlog_files_full=$(tail -n $BINLOG_N_FILES ${BINLOG_INDEX_FILENAME})
fi
cd $BINLOG_DIRNAME
@@ -510,16 +511,16 @@ EOF
# Clean up old binlog files first
rm -f ${BINLOG_FILENAME}.*
wsrep_log_info "Extracting binlog files:"
- tar -xvf $BINLOG_TAR_FILE >&2
- for ii in $(ls -1 ${BINLOG_FILENAME}.*)
- do
- if ! [ -z $WSREP_SST_OPT_BINLOG_INDEX ]
+ tar -xvf $BINLOG_TAR_FILE >> _binlog_tmp_files_$!
+ while read bin_file; do
+ if [ -z $WSREP_SST_OPT_BINLOG_INDEX ]
then
- echo ${BINLOG_DIRNAME}/${ii} >> ${BINLOG_FILENAME}.index
+ echo ${BINLOG_DIRNAME}/${bin_file} >> ${BINLOG_FILENAME}.index
else
- echo ${BINLOG_DIRNAME}/${ii} >> ${BINLOG_INDEX_DIRNAME}/${BINLOG_INDEX_FILENAME}.index
+ echo ${BINLOG_DIRNAME}/${bin_file} >> ${BINLOG_INDEX_DIRNAME}/${BINLOG_INDEX_FILENAME}
fi
- done
+ done < _binlog_tmp_files_$!
+ rm -f _binlog_tmp_files_$!
fi
cd "$OLD_PWD"
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 43977c0d97f..0befcd25204 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -139,6 +139,7 @@ SET (SQL_SOURCE
sql_sequence.cc sql_sequence.h ha_sequence.h
sql_tvc.cc sql_tvc.h
opt_split.cc
+ opt_trace.cc
${WSREP_SOURCES}
table_cache.cc encryption.cc temporary_tables.cc
proxy_protocol.cc backup.cc
diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc
index a199892f971..65bb0daf8cf 100644
--- a/sql/ha_sequence.cc
+++ b/sql/ha_sequence.cc
@@ -443,6 +443,6 @@ maria_declare_plugin(sql_sequence)
NULL, /* status variables */
NULL, /* system variables */
"1.0", /* string version */
- MariaDB_PLUGIN_MATURITY_ALPHA /* maturity */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
}
maria_declare_plugin_end;
diff --git a/sql/handler.h b/sql/handler.h
index 20868165169..350d881a934 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -993,6 +993,7 @@ enum enum_schema_tables
SCH_KEY_CACHES,
SCH_KEY_COLUMN_USAGE,
SCH_OPEN_TABLES,
+ SCH_OPT_TRACE,
SCH_PARAMETERS,
SCH_PARTITIONS,
SCH_PLUGINS,
diff --git a/sql/my_json_writer.cc b/sql/my_json_writer.cc
index d219e88b98b..7ae0c58bd7d 100644
--- a/sql/my_json_writer.cc
+++ b/sql/my_json_writer.cc
@@ -16,7 +16,6 @@
#include "mariadb.h"
#include "sql_priv.h"
#include "sql_string.h"
-
#include "my_json_writer.h"
void Json_writer::append_indent()
@@ -62,6 +61,7 @@ void Json_writer::end_object()
indent_level-=INDENT_SIZE;
if (!first_child)
append_indent();
+ first_child= false;
output.append("}");
}
@@ -129,7 +129,6 @@ void Json_writer::add_ll(longlong val)
add_unquoted_str(buf);
}
-
/* Add a memory size, printing in Kb, Kb, Gb if necessary */
void Json_writer::add_size(longlong val)
{
@@ -173,7 +172,7 @@ void Json_writer::add_null()
void Json_writer::add_unquoted_str(const char* str)
{
- if (fmt_helper.on_add_str(str))
+ if (fmt_helper.on_add_str(str, 0))
return;
if (!element_started)
@@ -183,10 +182,9 @@ void Json_writer::add_unquoted_str(const char* str)
element_started= false;
}
-
void Json_writer::add_str(const char *str)
{
- if (fmt_helper.on_add_str(str))
+ if (fmt_helper.on_add_str(str, 0))
return;
if (!element_started)
@@ -198,12 +196,72 @@ void Json_writer::add_str(const char *str)
element_started= false;
}
+/*
+ This function is used to add only num_bytes of str to the output string
+*/
+
+void Json_writer::add_str(const char* str, size_t num_bytes)
+{
+ if (fmt_helper.on_add_str(str, num_bytes))
+ return;
+
+ if (!element_started)
+ start_element();
+
+ output.append('"');
+ output.append(str, num_bytes);
+ output.append('"');
+ element_started= false;
+}
void Json_writer::add_str(const String &str)
{
- add_str(str.ptr());
+ add_str(str.ptr(), str.length());
}
+Json_writer_object::Json_writer_object(THD *thd) :
+ Json_writer_struct(thd)
+{
+ if (my_writer)
+ my_writer->start_object();
+}
+
+Json_writer_object::Json_writer_object(THD* thd, const char *str)
+ : Json_writer_struct(thd)
+{
+ if (my_writer)
+ my_writer->add_member(str).start_object();
+}
+
+Json_writer_object::~Json_writer_object()
+{
+ if (!closed && my_writer)
+ my_writer->end_object();
+ closed= TRUE;
+}
+
+Json_writer_array::Json_writer_array(THD *thd) :
+ Json_writer_struct(thd)
+{
+ if (my_writer)
+ my_writer->start_array();
+}
+
+Json_writer_array::Json_writer_array(THD *thd, const char *str)
+ :Json_writer_struct(thd)
+{
+ if (my_writer)
+ my_writer->add_member(str).start_array();
+
+}
+Json_writer_array::~Json_writer_array()
+{
+ if (!closed && my_writer)
+ {
+ my_writer->end_array();
+ closed= TRUE;
+ }
+}
bool Single_line_formatting_helper::on_add_member(const char *name)
{
@@ -267,11 +325,12 @@ void Single_line_formatting_helper::on_start_object()
}
-bool Single_line_formatting_helper::on_add_str(const char *str)
+bool Single_line_formatting_helper::on_add_str(const char *str,
+ size_t num_bytes)
{
if (state == IN_ARRAY)
{
- size_t len= strlen(str);
+ size_t len= num_bytes ? num_bytes : strlen(str);
// New length will be:
// "$string",
diff --git a/sql/my_json_writer.h b/sql/my_json_writer.h
index 3c127bd178c..4701cb4165b 100644
--- a/sql/my_json_writer.h
+++ b/sql/my_json_writer.h
@@ -13,7 +13,15 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */
+#ifndef JSON_WRITER_INCLUDED
+#define JSON_WRITER_INCLUDED
+#include "my_base.h"
+#include "sql_select.h"
+class Opt_trace_stmt;
+class Opt_trace_context;
class Json_writer;
+struct TABLE_LIST;
+
/*
Single_line_formatting_helper is used by Json_writer to do better formatting
@@ -85,7 +93,7 @@ public:
void on_start_object();
// on_end_object() is not needed.
- bool on_add_str(const char *str);
+ bool on_add_str(const char *str, size_t num_bytes);
void flush_on_one_line();
void disable_and_flush();
@@ -93,6 +101,80 @@ public:
/*
+ Something that looks like class String, but has an internal limit of
+ how many bytes one can append to it.
+
+ Bytes that were truncated due to the size limitation are counted.
+*/
+
+class String_with_limit
+{
+public:
+
+ String_with_limit() : size_limit(SIZE_MAX), truncated_len(0)
+ {
+ str.length(0);
+ }
+
+ size_t get_truncated_bytes() const { return truncated_len; }
+ size_t get_size_limit() { return size_limit; }
+
+ void set_size_limit(size_t limit_arg)
+ {
+ // Setting size limit to be shorter than length will not have the desired
+ // effect
+ DBUG_ASSERT(str.length() < size_limit);
+ size_limit= limit_arg;
+ }
+
+ void append(const char *s, size_t size)
+ {
+ if (str.length() + size <= size_limit)
+ {
+ // Whole string can be added, just do it
+ str.append(s, size);
+ }
+ else
+ {
+ // We cannot add the whole string
+ if (str.length() < size_limit)
+ {
+ // But we can still add something
+ size_t bytes_to_add = size_limit - str.length();
+ str.append(s, bytes_to_add);
+ truncated_len += size - bytes_to_add;
+ }
+ else
+ truncated_len += size;
+ }
+ }
+
+ void append(const char *s)
+ {
+ append(s, strlen(s));
+ }
+
+ void append(char c)
+ {
+ if (str.length() + 1 > size_limit)
+ truncated_len++;
+ else
+ str.append(c);
+ }
+
+ const String *get_string() { return &str; }
+ size_t length() { return str.length(); }
+private:
+ String str;
+
+ // str must not get longer than this many bytes.
+ size_t size_limit;
+
+ // How many bytes were truncated from the string
+ size_t truncated_len;
+};
+
+/*
A class to write well-formed JSON documents. The documents are also formatted
for human readability.
*/
@@ -105,7 +187,11 @@ public:
/* Add atomic values */
void add_str(const char* val);
+ void add_str(const char* val, size_t num_bytes);
void add_str(const String &str);
+ void add_str(Item *item);
+ void add_table_name(const JOIN_TAB *tab);
+ void add_table_name(const TABLE* table);
void add_ll(longlong val);
void add_size(longlong val);
@@ -123,9 +209,18 @@ public:
void end_object();
void end_array();
+ /*
+ One can set a limit of how large a JSON document should be.
+ Writes beyond that size will be counted, but will not be collected.
+ */
+ void set_size_limit(size_t mem_size) { output.set_size_limit(mem_size); }
+
+ // psergey: return how many bytes would be required to store everything
+ size_t get_truncated_bytes() { return output.get_truncated_bytes(); }
+
Json_writer() :
indent_level(0), document_start(true), element_started(false),
- first_child(true)
+ first_child(true), allowed_mem_size(0)
{
fmt_helper.init(this);
}
@@ -140,15 +235,335 @@ private:
bool element_started;
bool first_child;
+ /*
+ True when we are using the optimizer trace
+ FALSE otherwise
+ */
+ size_t allowed_mem_size;
+
Single_line_formatting_helper fmt_helper;
void append_indent();
void start_element();
void start_sub_element();
- //const char *new_member_name;
public:
- String output;
+ String_with_limit output;
+};
+
+/* A class to add values to Json_writer_object and Json_writer_array */
+class Json_value_helper
+{
+ Json_writer* writer;
+
+public:
+ void init(Json_writer *my_writer) { writer= my_writer; }
+ void add_str(const char* val)
+ {
+ if (writer)
+ writer->add_str(val);
+ }
+ void add_str(const char* val, size_t length)
+ {
+ if (writer)
+ writer->add_str(val);
+ }
+ void add_str(const String &str)
+ {
+ if (writer)
+ writer->add_str(str);
+ }
+ void add_str(LEX_CSTRING str)
+ {
+ if (writer)
+ writer->add_str(str.str);
+ }
+ void add_str(Item *item)
+ {
+ if (writer)
+ writer->add_str(item);
+ }
+
+ void add_ll(longlong val)
+ {
+ if (writer)
+ writer->add_ll(val);
+ }
+ void add_size(longlong val)
+ {
+ if (writer)
+ writer->add_size(val);
+ }
+ void add_double(double val)
+ {
+ if (writer)
+ writer->add_double(val);
+ }
+ void add_bool(bool val)
+ {
+ if (writer)
+ writer->add_bool(val);
+ }
+ void add_null()
+ {
+ if (writer)
+ writer->add_null();
+ }
+ void add_table_name(const JOIN_TAB *tab)
+ {
+ if (writer)
+ writer->add_table_name(tab);
+ }
+ void add_table_name(const TABLE* table)
+ {
+ if (writer)
+ writer->add_table_name(table);
+ }
+};
+
+/* A common base for Json_writer_object and Json_writer_array */
+class Json_writer_struct
+{
+protected:
+ Json_writer* my_writer;
+ Json_value_helper context;
+ /*
+ Tells when a json_writer_struct has been closed or not
+ */
+ bool closed;
+
+public:
+ explicit Json_writer_struct(THD *thd)
+ {
+ my_writer= thd->opt_trace.get_current_json();
+ context.init(my_writer);
+ closed= false;
+ }
+};
+
+
+/*
+ RAII-based class to start/end writing a JSON object into the JSON document
+
+ There is "ignore mode": one can initialize Json_writer_object with a NULL
+ Json_writer argument, and then all its calls will do nothing. This is used
+ by optimizer trace which can be enabled or disabled.
+*/
+
+class Json_writer_object : public Json_writer_struct
+{
+private:
+ void add_member(const char *name)
+ {
+ if (my_writer)
+ my_writer->add_member(name);
+ }
+public:
+ explicit Json_writer_object(THD *thd);
+ explicit Json_writer_object(THD *thd, const char *str);
+
+ Json_writer_object& add(const char *name, bool value)
+ {
+ DBUG_ASSERT(!closed);
+ add_member(name);
+ context.add_bool(value);
+ return *this;
+ }
+ Json_writer_object& add(const char *name, ulonglong value)
+ {
+ DBUG_ASSERT(!closed);
+ add_member(name);
+ context.add_ll(static_cast<longlong>(value));
+ return *this;
+ }
+ Json_writer_object& add(const char *name, longlong value)
+ {
+ DBUG_ASSERT(!closed);
+ add_member(name);
+ context.add_ll(value);
+ return *this;
+ }
+ Json_writer_object& add(const char *name, double value)
+ {
+ DBUG_ASSERT(!closed);
+ add_member(name);
+ context.add_double(value);
+ return *this;
+ }
+ #ifndef _WIN64
+ Json_writer_object& add(const char *name, size_t value)
+ {
+ DBUG_ASSERT(!closed);
+ add_member(name);
+ context.add_ll(static_cast<longlong>(value));
+ return *this;
+ }
+ #endif
+ Json_writer_object& add(const char *name, const char *value)
+ {
+ DBUG_ASSERT(!closed);
+ add_member(name);
+ context.add_str(value);
+ return *this;
+ }
+ Json_writer_object& add(const char *name, const char *value, size_t num_bytes)
+ {
+ add_member(name);
+ context.add_str(value, num_bytes);
+ return *this;
+ }
+ Json_writer_object& add(const char *name, LEX_CSTRING value)
+ {
+ DBUG_ASSERT(!closed);
+ add_member(name);
+ context.add_str(value.str);
+ return *this;
+ }
+ Json_writer_object& add(const char *name, Item *value)
+ {
+ DBUG_ASSERT(!closed);
+ add_member(name);
+ context.add_str(value);
+ return *this;
+ }
+ Json_writer_object& add_null(const char*name)
+ {
+ DBUG_ASSERT(!closed);
+ add_member(name);
+ context.add_null();
+ return *this;
+ }
+ Json_writer_object& add_table_name(const JOIN_TAB *tab)
+ {
+ DBUG_ASSERT(!closed);
+ add_member("table");
+ context.add_table_name(tab);
+ return *this;
+ }
+ Json_writer_object& add_table_name(const TABLE *table)
+ {
+ DBUG_ASSERT(!closed);
+ add_member("table");
+ context.add_table_name(table);
+ return *this;
+ }
+ Json_writer_object& add_select_number(uint select_number)
+ {
+ DBUG_ASSERT(!closed);
+ add_member("select_id");
+ if (unlikely(select_number >= INT_MAX))
+ context.add_str("fake");
+ else
+ context.add_ll(static_cast<longlong>(select_number));
+ return *this;
+ }
+ void end()
+ {
+ DBUG_ASSERT(!closed);
+ if (my_writer)
+ my_writer->end_object();
+ closed= TRUE;
+ }
+ ~Json_writer_object();
+};
+
+
+/*
+ RAII-based class to start/end writing a JSON array into the JSON document
+
+ There is "ignore mode": one can initialize Json_writer_array with a NULL
+ Json_writer argument, and then all its calls will do nothing. This is used
+ by optimizer trace which can be enabled or disabled.
+*/
+
+class Json_writer_array : public Json_writer_struct
+{
+public:
+ Json_writer_array(THD *thd);
+ Json_writer_array(THD *thd, const char *str);
+ void end()
+ {
+ DBUG_ASSERT(!closed);
+ if (my_writer)
+ my_writer->end_array();
+ closed= TRUE;
+ }
+
+ Json_writer_array& add(bool value)
+ {
+ DBUG_ASSERT(!closed);
+ context.add_bool(value);
+ return *this;
+ }
+ Json_writer_array& add(ulonglong value)
+ {
+ DBUG_ASSERT(!closed);
+ context.add_ll(static_cast<longlong>(value));
+ return *this;
+ }
+ Json_writer_array& add(longlong value)
+ {
+ DBUG_ASSERT(!closed);
+ context.add_ll(value);
+ return *this;
+ }
+ Json_writer_array& add(double value)
+ {
+ DBUG_ASSERT(!closed);
+ context.add_double(value);
+ return *this;
+ }
+ #ifndef _WIN64
+ Json_writer_array& add(size_t value)
+ {
+ DBUG_ASSERT(!closed);
+ context.add_ll(static_cast<longlong>(value));
+ return *this;
+ }
+ #endif
+ Json_writer_array& add(const char *value)
+ {
+ DBUG_ASSERT(!closed);
+ context.add_str(value);
+ return *this;
+ }
+ Json_writer_array& add(const char *value, size_t num_bytes)
+ {
+ DBUG_ASSERT(!closed);
+ context.add_str(value, num_bytes);
+ return *this;
+ }
+ Json_writer_array& add(LEX_CSTRING value)
+ {
+ DBUG_ASSERT(!closed);
+ context.add_str(value.str);
+ return *this;
+ }
+ Json_writer_array& add(Item *value)
+ {
+ DBUG_ASSERT(!closed);
+ context.add_str(value);
+ return *this;
+ }
+ Json_writer_array& add_null()
+ {
+ DBUG_ASSERT(!closed);
+ context.add_null();
+ return *this;
+ }
+ Json_writer_array& add_table_name(const JOIN_TAB *tab)
+ {
+ DBUG_ASSERT(!closed);
+ context.add_table_name(tab);
+ return *this;
+ }
+ Json_writer_array& add_table_name(const TABLE *table)
+ {
+ DBUG_ASSERT(!closed);
+ context.add_table_name(table);
+ return *this;
+ }
+ ~Json_writer_array();
};
@@ -192,4 +607,4 @@ public:
#endif
};
-
+#endif
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index d4ca35b36cc..b43f0772602 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -647,8 +647,6 @@ Lt_creator lt_creator;
Ge_creator ge_creator;
Le_creator le_creator;
-int bootstrap_error;
-
THD_list server_threads;
Rpl_filter* cur_rpl_filter;
Rpl_filter* global_rpl_filter;
@@ -1105,7 +1103,7 @@ static PSI_cond_info all_server_conds[]=
{ &key_TABLE_SHARE_COND_rotation, "TABLE_SHARE::COND_rotation", 0}
};
-PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert,
+PSI_thread_key key_thread_delayed_insert,
key_thread_handle_manager, key_thread_main,
key_thread_one_connection, key_thread_signal_hand,
key_thread_slave_background, key_rpl_parallel_thread;
@@ -1113,7 +1111,6 @@ PSI_thread_key key_thread_ack_receiver;
static PSI_thread_info all_server_threads[]=
{
- { &key_thread_bootstrap, "bootstrap", PSI_FLAG_GLOBAL},
{ &key_thread_delayed_insert, "delayed_insert", 0},
{ &key_thread_handle_manager, "manager", PSI_FLAG_GLOBAL},
{ &key_thread_main, "main", PSI_FLAG_GLOBAL},
@@ -5768,9 +5765,9 @@ int mysqld_main(int argc, char **argv)
if (opt_bootstrap)
{
select_thread_in_use= 0; // Allow 'kill' to work
- bootstrap(mysql_stdin);
+ int bootstrap_error= bootstrap(mysql_stdin);
if (!abort_loop)
- unireg_abort(bootstrap_error ? 1 : 0);
+ unireg_abort(bootstrap_error);
else
{
sleep(2); // Wait for kill
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 320dedc4671..a05b4726c64 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -297,7 +297,6 @@ extern "C" MYSQL_PLUGIN_IMPORT char **orig_argv;
extern pthread_attr_t connection_attrib;
extern my_bool old_mode;
extern LEX_STRING opt_init_connect, opt_init_slave;
-extern int bootstrap_error;
extern char err_shared_dir[];
extern ulong connection_errors_select;
extern ulong connection_errors_accept;
@@ -394,7 +393,7 @@ extern PSI_cond_key key_COND_rpl_thread, key_COND_rpl_thread_queue,
extern PSI_cond_key key_COND_wait_gtid, key_COND_gtid_ignore_duplicates;
extern PSI_cond_key key_TABLE_SHARE_COND_rotation;
-extern PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert,
+extern PSI_thread_key key_thread_delayed_insert,
key_thread_handle_manager, key_thread_kill_server, key_thread_main,
key_thread_one_connection, key_thread_signal_hand,
key_thread_slave_background, key_rpl_parallel_thread;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index eca51b54dab..c87a0595a7d 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -119,6 +119,7 @@
#include "sql_select.h"
#include "sql_statistics.h"
#include "uniques.h"
+#include "my_json_writer.h"
#ifndef EXTRA_DEBUG
#define test_rb_tree(A,B) {}
@@ -429,6 +430,18 @@ static int and_range_trees(RANGE_OPT_PARAM *param,
SEL_TREE *result);
static bool remove_nonrange_trees(RANGE_OPT_PARAM *param, SEL_TREE *tree);
+static void print_key_value(String *out, const KEY_PART_INFO *key_part,
+ const uchar *key);
+
+static void append_range_all_keyparts(Json_writer_array *range_trace,
+ String *range_string,
+ String *range_so_far, const SEL_ARG *keypart,
+ const KEY_PART_INFO *key_parts);
+
+static
+void append_range(String *out, const KEY_PART_INFO *key_parts,
+ const uchar *min_key, const uchar *max_key, const uint flag);
+
/*
SEL_IMERGE is a list of possible ways to do index merge, i.e. it is
@@ -2191,6 +2204,14 @@ public:
static void operator delete(void *ptr,size_t size) { TRASH_FREE(ptr, size); }
static void operator delete(void *ptr, MEM_ROOT *mem_root) { /* Never called */ }
virtual ~TABLE_READ_PLAN() {} /* Remove gcc warning */
+ /**
+ Add basic info for this TABLE_READ_PLAN to the optimizer trace.
+
+ @param param Parameters for range analysis of this table
+ @param trace_object The optimizer trace object the info is appended to
+ */
+ virtual void trace_basic_info(const PARAM *param,
+ Json_writer_object *trace_object) const = 0;
};
@@ -2232,8 +2253,34 @@ public:
}
DBUG_RETURN(quick);
}
+ void trace_basic_info(const PARAM *param,
+ Json_writer_object *trace_object) const;
};
+void TRP_RANGE::trace_basic_info(const PARAM *param,
+ Json_writer_object *trace_object) const
+{
+ DBUG_ASSERT(param->using_real_indexes);
+ const uint keynr_in_table = param->real_keynr[key_idx];
+
+ const KEY &cur_key = param->table->key_info[keynr_in_table];
+ const KEY_PART_INFO *key_part = cur_key.key_part;
+
+ trace_object->add("type", "range_scan")
+ .add("index", cur_key.name)
+ .add("rows", records);
+
+ Json_writer_array trace_range(param->thd, "ranges");
+
+ // TRP_RANGE should not be created if there are no range intervals
+ DBUG_ASSERT(key);
+
+ String range_info;
+ range_info.length(0);
+ range_info.set_charset(system_charset_info);
+ append_range_all_keyparts(&trace_range, NULL, &range_info, key, key_part);
+}
+
/* Plan for QUICK_ROR_INTERSECT_SELECT scan. */
@@ -2251,9 +2298,12 @@ public:
struct st_ror_scan_info *cpk_scan; /* Clustered PK scan, if there is one */
bool is_covering; /* TRUE if no row retrieval phase is necessary */
double index_scan_costs; /* SUM(cost(index_scan)) */
+ void trace_basic_info(const PARAM *param,
+ Json_writer_object *trace_object) const;
};
+
/*
Plan for QUICK_ROR_UNION_SELECT scan.
QUICK_ROR_UNION_SELECT always retrieves full rows, so retrieve_full_rows
@@ -2269,8 +2319,22 @@ public:
MEM_ROOT *parent_alloc);
TABLE_READ_PLAN **first_ror; /* array of ptrs to plans for merged scans */
TABLE_READ_PLAN **last_ror; /* end of the above array */
+ void trace_basic_info(const PARAM *param,
+ Json_writer_object *trace_object) const;
};
+void TRP_ROR_UNION::trace_basic_info(const PARAM *param,
+ Json_writer_object *trace_object) const
+{
+ THD *thd= param->thd;
+ trace_object->add("type", "index_roworder_union");
+ Json_writer_array smth_trace(thd, "union_of");
+ for (TABLE_READ_PLAN **current = first_ror; current != last_ror; current++)
+ {
+ Json_writer_object trp_info(thd);
+ (*current)->trace_basic_info(param, &trp_info);
+ }
+}
/*
Plan for QUICK_INDEX_INTERSECT_SELECT scan.
@@ -2288,9 +2352,25 @@ public:
TRP_RANGE **range_scans; /* array of ptrs to plans of intersected scans */
TRP_RANGE **range_scans_end; /* end of the array */
/* keys whose scans are to be filtered by cpk conditions */
- key_map filtered_scans;
+ key_map filtered_scans;
+ void trace_basic_info(const PARAM *param,
+ Json_writer_object *trace_object) const;
+
};
+void TRP_INDEX_INTERSECT::trace_basic_info(const PARAM *param,
+ Json_writer_object *trace_object) const
+{
+ THD *thd= param->thd;
+ trace_object->add("type", "index_sort_intersect");
+ Json_writer_array smth_trace(thd, "index_sort_intersect_of");
+ for (TRP_RANGE **current = range_scans; current != range_scans_end;
+ current++)
+ {
+ Json_writer_object trp_info(thd);
+ (*current)->trace_basic_info(param, &trp_info);
+ }
+}
/*
Plan for QUICK_INDEX_MERGE_SELECT scan.
@@ -2307,8 +2387,22 @@ public:
MEM_ROOT *parent_alloc);
TRP_RANGE **range_scans; /* array of ptrs to plans of merged scans */
TRP_RANGE **range_scans_end; /* end of the array */
+ void trace_basic_info(const PARAM *param,
+ Json_writer_object *trace_object) const;
};
+void TRP_INDEX_MERGE::trace_basic_info(const PARAM *param,
+ Json_writer_object *trace_object) const
+{
+ THD *thd= param->thd;
+ trace_object->add("type", "index_merge");
+ Json_writer_array smth_trace(thd, "index_merge_of");
+ for (TRP_RANGE **current= range_scans; current != range_scans_end; current++)
+ {
+ Json_writer_object trp_info(thd);
+ (*current)->trace_basic_info(param, &trp_info);
+ }
+}
/*
Plan for a QUICK_GROUP_MIN_MAX_SELECT scan.
@@ -2360,9 +2454,51 @@ public:
QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows,
MEM_ROOT *parent_alloc);
void use_index_scan() { is_index_scan= TRUE; }
+ void trace_basic_info(const PARAM *param,
+ Json_writer_object *trace_object) const;
};
+void TRP_GROUP_MIN_MAX::trace_basic_info(const PARAM *param,
+ Json_writer_object *trace_object) const
+{
+ THD *thd= param->thd;
+ trace_object->add("type", "index_group").add("index", index_info->name);
+
+ if (min_max_arg_part)
+ trace_object->add("group_attribute", min_max_arg_part->field->field_name);
+ else
+ trace_object->add_null("group_attribute");
+
+ trace_object->add("min_aggregate", have_min)
+ .add("max_aggregate", have_max)
+ .add("distinct_aggregate", have_agg_distinct)
+ .add("rows", records)
+ .add("cost", read_cost);
+
+ const KEY_PART_INFO *key_part = index_info->key_part;
+ {
+ Json_writer_array trace_keyparts(thd, "key_parts_used_for_access");
+ for (uint partno = 0; partno < used_key_parts; partno++)
+ {
+ const KEY_PART_INFO *cur_key_part = key_part + partno;
+ trace_keyparts.add(cur_key_part->field->field_name);
+ }
+ }
+
+ Json_writer_array trace_range(thd, "ranges");
+
+ // can have group quick without ranges
+ if (index_tree)
+ {
+ String range_info;
+ range_info.set_charset(system_charset_info);
+ append_range_all_keyparts(&trace_range, NULL, &range_info, index_tree,
+ key_part);
+ }
+}
+
+
typedef struct st_index_scan_info
{
uint idx; /* # of used key in param->keys */
@@ -2538,6 +2674,17 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
DBUG_PRINT("info",("Time to scan table: %g", read_time));
+ Json_writer_object table_records(thd);
+ if (head->reginfo.join_tab)
+ table_records.add_table_name(head->reginfo.join_tab);
+ else
+ table_records.add_table_name(head);
+ Json_writer_object trace_range(thd, "range_analysis");
+ {
+ Json_writer_object table_rec(thd, "table_scan");
+ table_rec.add("rows", records).add("cost", read_time);
+ }
+
keys_to_use.intersect(head->keys_in_use_for_query);
if (!keys_to_use.is_clear_all())
{
@@ -2591,19 +2738,33 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
*/
key_info= head->key_info;
uint max_key_len= 0;
+
+ Json_writer_array trace_idx(thd, "potential_range_indexes");
+
for (idx=0 ; idx < head->s->keys ; idx++, key_info++)
{
+ Json_writer_object trace_idx_details(thd);
+ trace_idx_details.add("index", key_info->name);
KEY_PART_INFO *key_part_info;
uint n_key_parts= head->actual_n_key_parts(key_info);
if (!keys_to_use.is_set(idx))
- continue;
+ {
+ trace_idx_details.add("usable", false)
+ .add("cause", "not applicable");
+ continue;
+ }
if (key_info->flags & HA_FULLTEXT)
- continue; // ToDo: ft-keys in non-ft ranges, if possible SerG
+ {
+ trace_idx_details.add("usable", false).add("cause", "fulltext");
+ continue; // ToDo: ft-keys in non-ft ranges, if possible SerG
+ }
+ trace_idx_details.add("usable", true);
param.key[param.keys]=key_parts;
key_part_info= key_info->key_part;
uint cur_key_len= 0;
+ Json_writer_array trace_keypart(thd, "key_parts");
for (uint part= 0 ; part < n_key_parts ;
part++, key_parts++, key_part_info++)
{
@@ -2618,11 +2779,14 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
(key_info->flags & HA_SPATIAL) ? Field::itMBR : Field::itRAW;
/* Only HA_PART_KEY_SEG is used */
key_parts->flag= (uint8) key_part_info->key_part_flag;
+ trace_keypart.add(key_parts->field->field_name);
}
param.real_keynr[param.keys++]=idx;
if (cur_key_len > max_key_len)
max_key_len= cur_key_len;
}
+ trace_idx.end();
+
param.key_parts_end=key_parts;
param.alloced_sel_args= 0;
@@ -2644,8 +2808,18 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
(double) records / TIME_FOR_COMPARE;
DBUG_PRINT("info", ("'all'+'using index' scan will be using key %d, "
"read time %g", key_for_use, key_read_time));
+
+ Json_writer_object trace_cov(thd, "best_covering_index_scan");
+ bool chosen= FALSE;
if (key_read_time < read_time)
+ {
read_time= key_read_time;
+ chosen= TRUE;
+ }
+ trace_cov.add("index", head->key_info[key_for_use].name)
+ .add("cost", key_read_time).add("chosen", chosen);
+ if (!chosen)
+ trace_cov.add("cause", "cost");
}
TABLE_READ_PLAN *best_trp= NULL;
@@ -2654,12 +2828,18 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
if (cond)
{
- if ((tree= cond->get_mm_tree(&param, &cond)))
+ {
+ Json_writer_array trace_range_summary(thd,
+ "setup_range_conditions");
+ tree= cond->get_mm_tree(&param, &cond);
+ }
+ if (tree)
{
if (tree->type == SEL_TREE::IMPOSSIBLE)
{
records=0L; /* Return -1 from this function. */
read_time= (double) HA_POS_ERROR;
+ trace_range.add("impossible_range", true);
goto free_mem;
}
/*
@@ -2667,7 +2847,10 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
can construct a group-min-max quick select
*/
if (tree->type != SEL_TREE::KEY && tree->type != SEL_TREE::KEY_SMALLER)
+ {
+ trace_range.add("range_scan_possible", false);
tree= NULL;
+ }
}
}
@@ -2680,11 +2863,19 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
{
param.table->quick_condition_rows= MY_MIN(group_trp->records,
head->stat_records());
+ Json_writer_object grp_summary(thd, "best_group_range_summary");
+
+ if (unlikely(thd->trace_started()))
+ group_trp->trace_basic_info(&param, &grp_summary);
+
if (group_trp->read_cost < best_read_time)
{
+ grp_summary.add("chosen", true);
best_trp= group_trp;
best_read_time= best_trp->read_cost;
}
+ else
+ grp_summary.add("chosen", false).add("cause", "cost");
}
if (tree)
@@ -2697,7 +2888,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
TRP_ROR_INTERSECT *rori_trp;
TRP_INDEX_INTERSECT *intersect_trp;
bool can_build_covering= FALSE;
-
+ Json_writer_object trace_range(thd, "analyzing_range_alternatives");
+
remove_nonrange_trees(&param, tree);
/* Get best 'range' plan and prepare data for making other plans */
@@ -2764,6 +2956,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
DBUG_PRINT("info",("No range reads possible,"
" trying to construct index_merge"));
List_iterator_fast<SEL_IMERGE> it(tree->merges);
+ Json_writer_array trace_idx_merge(thd, "analyzing_index_merge_union");
while ((imerge= it++))
{
new_conj_trp= get_best_disjunct_quick(&param, imerge, best_read_time);
@@ -2798,6 +2991,19 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
possible_keys= param.possible_keys;
free_mem:
+ if (unlikely(quick && best_trp && thd->trace_started()))
+ {
+ Json_writer_object trace_range_summary(thd,
+ "chosen_range_access_summary");
+ {
+ Json_writer_object trace_range_plan(thd, "range_access_plan");
+ best_trp->trace_basic_info(&param, &trace_range_plan);
+ }
+ trace_range_summary.add("rows_for_plan", quick->records)
+ .add("cost_for_plan", quick->read_time)
+ .add("chosen", true);
+ }
+
free_root(&alloc,MYF(0)); // Return memory & allocator
thd->mem_root= param.old_root;
thd->no_errors=0;
@@ -3060,6 +3266,9 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
estimate sources.
*/
+ Json_writer_object trace_wrapper(thd);
+ Json_writer_array selectivity_for_indexes(thd, "selectivity_for_indexes");
+
for (keynr= 0; keynr < table->s->keys; keynr++)
{
if (table->quick_keys.is_set(keynr))
@@ -3109,6 +3318,10 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
not yet been accounted for.
*/
table->cond_selectivity*= quick_cond_selectivity;
+ Json_writer_object selectivity_for_index(thd);
+ selectivity_for_index.add("index_name", key_info->name)
+ .add("selectivity_from_index",
+ quick_cond_selectivity);
if (i != used_key_parts)
{
/*
@@ -3128,7 +3341,9 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
*/
selectivity_mult= ((double)(i+1)) / i;
}
- table->cond_selectivity*= selectivity_mult;
+ table->cond_selectivity*= selectivity_mult;
+ selectivity_for_index.add("selectivity_multiplier",
+ selectivity_mult);
}
/*
We need to set selectivity for fields supported by indexes.
@@ -3149,12 +3364,14 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
}
}
}
+ selectivity_for_indexes.end();
/*
Second step: calculate the selectivity of the range conditions not
supported by any index and selectivity of the range condition
over the fields whose selectivity has not been set yet.
*/
+ Json_writer_array selectivity_for_columns(thd, "selectivity_for_columns");
if (thd->variables.optimizer_use_condition_selectivity > 2 &&
!bitmap_is_clear_all(used_fields) &&
@@ -3214,17 +3431,25 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
SEL_ARG *key= tree->keys[idx];
if (key)
{
+ Json_writer_object selectivity_for_column(thd);
+ selectivity_for_column.add("column_name", key->field->field_name);
if (key->type == SEL_ARG::IMPOSSIBLE)
- {
+ {
rows= 0;
table->reginfo.impossible_range= 1;
+ selectivity_for_column.add("selectivity_from_histograms", rows);
+ selectivity_for_column.add("cause", "impossible range");
goto free_alloc;
}
else
{
rows= records_in_column_ranges(&param, idx, key);
if (rows != DBL_MAX)
+ {
key->field->cond_selectivity= rows/table_records;
+ selectivity_for_column.add("selectivity_from_histograms",
+ key->field->cond_selectivity);
+ }
}
}
}
@@ -4791,6 +5016,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
ha_rows roru_total_records;
double roru_intersect_part= 1.0;
size_t n_child_scans;
+ THD *thd= param->thd;
DBUG_ENTER("get_best_disjunct_quick");
DBUG_PRINT("info", ("Full table scan cost: %g", read_time));
@@ -4816,6 +5042,8 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
sizeof(TRP_RANGE*)*
n_child_scans)))
DBUG_RETURN(NULL);
+ Json_writer_object trace_best_disjunct(thd);
+ Json_writer_array to_merge(thd, "indexes_to_merge");
/*
Collect best 'range' scan for each of disjuncts, and, while doing so,
analyze possibility of ROR scans. Also calculate some values needed by
@@ -4827,6 +5055,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
{
DBUG_EXECUTE("info", print_sel_tree(param, *ptree, &(*ptree)->keys_map,
"tree in SEL_IMERGE"););
+ Json_writer_object trace_idx(thd);
if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, FALSE, read_time)))
{
/*
@@ -4838,8 +5067,11 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
imerge_too_expensive= TRUE;
}
if (imerge_too_expensive)
+ {
+ trace_idx.add("chosen", false).add("cause", "cost");
continue;
-
+ }
+ const uint keynr_in_table = param->real_keynr[(*cur_child)->key_idx];
imerge_cost += (*cur_child)->read_cost;
all_scans_ror_able &= ((*ptree)->n_ror_scans > 0);
all_scans_rors &= (*cur_child)->is_ror;
@@ -4852,9 +5084,16 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
}
else
non_cpk_scan_records += (*cur_child)->records;
+ trace_idx.add("index_to_merge",
+ param->table->key_info[keynr_in_table].name)
+ .add("cumulated_cost", imerge_cost);
}
+ to_merge.end();
+
DBUG_PRINT("info", ("index_merge scans cost %g", imerge_cost));
+ trace_best_disjunct.add("cost_of_reading_ranges", imerge_cost);
+
if (imerge_too_expensive || (imerge_cost > read_time) ||
((non_cpk_scan_records+cpk_scan_records >=
param->table->stat_records()) &&
@@ -4866,6 +5105,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
*/
DBUG_PRINT("info", ("Sum of index_merge scans is more expensive than "
"full table scan, bailing out"));
+ trace_best_disjunct.add("chosen", false).add("cause", "cost");
DBUG_RETURN(NULL);
}
@@ -4878,6 +5118,9 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_UNION))
{
roru_read_plans= (TABLE_READ_PLAN**)range_scans;
+ trace_best_disjunct.add("use_roworder_union", true)
+ .add("cause",
+ "always cheaper than non roworder retrieval");
goto skip_to_ror_scan;
}
@@ -4887,16 +5130,26 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
Add one ROWID comparison for each row retrieved on non-CPK scan. (it
is done in QUICK_RANGE_SELECT::row_in_ranges)
*/
- imerge_cost += non_cpk_scan_records / TIME_FOR_COMPARE_ROWID;
+ double rid_comp_cost= static_cast<double>(non_cpk_scan_records) /
+ TIME_FOR_COMPARE_ROWID;
+ imerge_cost += rid_comp_cost;
+ trace_best_disjunct.add("cost_of_mapping_rowid_in_non_clustered_pk_scan",
+ rid_comp_cost);
}
/* Calculate cost(rowid_to_row_scan) */
- imerge_cost += get_sweep_read_cost(param, non_cpk_scan_records);
+ {
+ double sweep_cost= get_sweep_read_cost(param, non_cpk_scan_records);
+ imerge_cost += sweep_cost;
+ trace_best_disjunct.add("cost_sort_rowid_and_read_disk", sweep_cost);
+ }
DBUG_PRINT("info",("index_merge cost with rowid-to-row scan: %g",
imerge_cost));
if (imerge_cost > read_time ||
!optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION))
{
+ trace_best_disjunct.add("use_roworder_index_merge", true);
+ trace_best_disjunct.add("cause", "cost");
goto build_ror_index_merge;
}
@@ -4913,12 +5166,18 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
param->imerge_cost_buff_size= unique_calc_buff_size;
}
- imerge_cost +=
- Unique::get_use_cost(param->imerge_cost_buff, (uint)non_cpk_scan_records,
- param->table->file->ref_length,
- (size_t)param->thd->variables.sortbuff_size,
- TIME_FOR_COMPARE_ROWID,
- FALSE, NULL);
+ {
+ const double dup_removal_cost = Unique::get_use_cost(
+ param->imerge_cost_buff, (uint)non_cpk_scan_records,
+ param->table->file->ref_length,
+ (size_t)param->thd->variables.sortbuff_size,
+ TIME_FOR_COMPARE_ROWID,
+ FALSE, NULL);
+ imerge_cost+= dup_removal_cost;
+ trace_best_disjunct.add("cost_duplicate_removal", dup_removal_cost)
+ .add("total_cost", imerge_cost);
+ }
+
DBUG_PRINT("info",("index_merge total cost: %g (wanted: less then %g)",
imerge_cost, read_time));
if (imerge_cost < read_time)
@@ -4961,11 +5220,16 @@ skip_to_ror_scan:
roru_total_records= 0;
cur_roru_plan= roru_read_plans;
+ Json_writer_array trace_analyze_ror(thd, "analyzing_roworder_scans");
+
/* Find 'best' ROR scan for each of trees in disjunction */
for (ptree= imerge->trees, cur_child= range_scans;
ptree != imerge->trees_next;
ptree++, cur_child++, cur_roru_plan++)
{
+ Json_writer_object trp_info(thd);
+ if (unlikely(thd->trace_started()))
+ (*cur_child)->trace_basic_info(param, &trp_info);
/*
Assume the best ROR scan is the one that has cheapest full-row-retrieval
scan cost.
@@ -5001,7 +5265,7 @@ skip_to_ror_scan:
roru_intersect_part *= (*cur_roru_plan)->records /
param->table->stat_records();
}
-
+ trace_analyze_ror.end();
/*
rows to retrieve=
SUM(rows_in_scan_i) - table_rows * PROD(rows_in_scan_i / table_rows).
@@ -5027,11 +5291,14 @@ skip_to_ror_scan:
DBUG_PRINT("info", ("ROR-union: cost %g, %zu members",
roru_total_cost, n_child_scans));
+ trace_best_disjunct.add("index_roworder_union_cost", roru_total_cost)
+ .add("members", n_child_scans);
TRP_ROR_UNION* roru;
if (roru_total_cost < read_time)
{
if ((roru= new (param->mem_root) TRP_ROR_UNION))
{
+ trace_best_disjunct.add("chosen", true);
roru->first_ror= roru_read_plans;
roru->last_ror= roru_read_plans + n_child_scans;
roru->read_cost= roru_total_cost;
@@ -5039,7 +5306,9 @@ skip_to_ror_scan:
DBUG_RETURN(roru);
}
}
- DBUG_RETURN(imerge_trp);
+ else
+ trace_best_disjunct.add("chosen", false);
+ DBUG_RETURN(imerge_trp);
}
@@ -5300,6 +5569,15 @@ ha_rows get_table_cardinality_for_index_intersect(TABLE *table)
}
}
+static
+void print_keyparts(THD *thd, KEY *key, uint key_parts)
+{
+ KEY_PART_INFO *part= key->key_part;
+ Json_writer_array keyparts= Json_writer_array(thd, "keyparts");
+ for(uint i= 0; i < key_parts; i++, part++)
+ keyparts.add(part->field->field_name);
+}
+
static
ha_rows records_in_index_intersect_extension(PARTIAL_INDEX_INTERSECT_INFO *curr,
@@ -5352,8 +5630,9 @@ bool prepare_search_best_index_intersect(PARAM *param,
INDEX_SCAN_INFO *cpk_scan= NULL;
TABLE *table= param->table;
uint n_index_scans= (uint)(tree->index_scans_end - tree->index_scans);
+ THD *thd= param->thd;
- if (!n_index_scans)
+ if (n_index_scans <= 1)
return 1;
bzero(init, sizeof(*init));
@@ -5370,9 +5649,6 @@ bool prepare_search_best_index_intersect(PARAM *param,
common->table_cardinality=
get_table_cardinality_for_index_intersect(table);
- if (n_index_scans <= 1)
- return TRUE;
-
if (table->file->primary_key_is_clustered())
{
INDEX_SCAN_INFO **index_scan_end;
@@ -5397,23 +5673,38 @@ bool prepare_search_best_index_intersect(PARAM *param,
bzero(common->search_scans, sizeof(INDEX_SCAN_INFO *) * i);
INDEX_SCAN_INFO **selected_index_scans= common->search_scans;
-
+ Json_writer_array potential_idx_scans(thd, "potential_index_scans");
for (i=0, index_scan= tree->index_scans; i < n_index_scans; i++, index_scan++)
{
+ Json_writer_object idx_scan(thd);
uint used_key_parts= (*index_scan)->used_key_parts;
KEY *key_info= (*index_scan)->key_info;
+ idx_scan.add("index", key_info->name);
if (*index_scan == cpk_scan)
+ {
+ idx_scan.add("chosen", "false")
+ .add("cause", "clustered index used for filtering");
continue;
+ }
if (cpk_scan && cpk_scan->used_key_parts >= used_key_parts &&
same_index_prefix(cpk_scan->key_info, key_info, used_key_parts))
+ {
+ idx_scan.add("chosen", "false")
+ .add("cause", "clustered index used for filtering");
continue;
+ }
cost= table->file->keyread_time((*index_scan)->keynr,
(*index_scan)->range_count,
(*index_scan)->records);
+ idx_scan.add("cost", cost);
if (cost >= cutoff_cost)
+ {
+ idx_scan.add("chosen", false);
+ idx_scan.add("cause", "cost");
continue;
+ }
for (scan_ptr= selected_index_scans; *scan_ptr ; scan_ptr++)
{
@@ -5430,10 +5721,20 @@ bool prepare_search_best_index_intersect(PARAM *param,
}
if (!*scan_ptr || cost < (*scan_ptr)->index_read_cost)
{
+ idx_scan.add("chosen", true);
+ if (!*scan_ptr)
+ idx_scan.add("cause", "first occurence of index prefix");
+ else
+ idx_scan.add("cause", "better cost for same idx prefix");
*scan_ptr= *index_scan;
(*scan_ptr)->index_read_cost= cost;
}
- }
+ else
+ {
+ idx_scan.add("chosen", false).add("cause", "cost");
+ }
+ }
+ potential_idx_scans.end();
ha_rows records_in_scans= 0;
@@ -5443,6 +5744,7 @@ bool prepare_search_best_index_intersect(PARAM *param,
return TRUE;
records_in_scans+= (*scan_ptr)->records;
}
+
n_search_scans= i;
if (cpk_scan && create_fields_bitmap(param, &cpk_scan->used_fields))
@@ -5472,6 +5774,7 @@ bool prepare_search_best_index_intersect(PARAM *param,
my_qsort(selected_index_scans, n_search_scans, sizeof(INDEX_SCAN_INFO *),
(qsort_cmp) cmp_intersect_index_scan);
+ Json_writer_array selected_idx_scans(thd, "selected_index_scans");
if (cpk_scan)
{
PARTIAL_INDEX_INTERSECT_INFO curr;
@@ -5484,16 +5787,36 @@ bool prepare_search_best_index_intersect(PARAM *param,
curr.length= 1;
for (scan_ptr=selected_index_scans; *scan_ptr; scan_ptr++)
{
+ KEY *key_info= (*scan_ptr)->key_info;
ha_rows scan_records= (*scan_ptr)->records;
ha_rows records= records_in_index_intersect_extension(&curr, *scan_ptr);
(*scan_ptr)->filtered_out= records >= scan_records ?
- 0 : scan_records-records;
+ 0 : scan_records-records;
+ if (thd->trace_started())
+ {
+ Json_writer_object selected_idx(thd);
+ selected_idx.add("index", key_info->name);
+ print_keyparts(thd, key_info, (*scan_ptr)->used_key_parts);
+ selected_idx.add("records", (*scan_ptr)->records)
+ .add("filtered_records", (*scan_ptr)->filtered_out);
+ }
}
}
else
{
for (scan_ptr=selected_index_scans; *scan_ptr; scan_ptr++)
+ {
+ KEY *key_info= (*scan_ptr)->key_info;
(*scan_ptr)->filtered_out= 0;
+ if (thd->trace_started())
+ {
+ Json_writer_object selected_idx(thd);
+ selected_idx.add("index", key_info->name);
+ print_keyparts(thd, key_info, (*scan_ptr)->used_key_parts);
+ selected_idx.add("records", (*scan_ptr)->records)
+ .add("filtered_records", (*scan_ptr)->filtered_out);
+ }
+ }
}
return FALSE;
@@ -5950,10 +6273,12 @@ TRP_INDEX_INTERSECT *get_best_index_intersect(PARAM *param, SEL_TREE *tree,
PARTIAL_INDEX_INTERSECT_INFO init;
TRP_INDEX_INTERSECT *intersect_trp= NULL;
TABLE *table= param->table;
-
+ THD *thd= param->thd;
DBUG_ENTER("get_best_index_intersect");
+ Json_writer_object trace_idx_interect(thd, "analyzing_sort_intersect");
+
if (prepare_search_best_index_intersect(param, tree, &common, &init,
read_time))
DBUG_RETURN(NULL);
@@ -6015,11 +6340,15 @@ TRP_INDEX_INTERSECT *get_best_index_intersect(PARAM *param, SEL_TREE *tree,
if ((intersect_trp= new (param->mem_root)TRP_INDEX_INTERSECT))
{
+
intersect_trp->read_cost= common.best_cost;
intersect_trp->records= common.best_records;
intersect_trp->range_scans= range_scans;
intersect_trp->range_scans_end= cur_range;
intersect_trp->filtered_scans= common.filtered_scans;
+ trace_idx_interect.add("rows", intersect_trp->records)
+ .add("cost", intersect_trp->read_cost)
+ .add("chosen",true);
}
DBUG_RETURN(intersect_trp);
}
@@ -6029,6 +6358,46 @@ typedef struct st_ror_scan_info : INDEX_SCAN_INFO
{
} ROR_SCAN_INFO;
+void TRP_ROR_INTERSECT::trace_basic_info(const PARAM *param,
+ Json_writer_object *trace_object) const
+{
+ THD *thd= param->thd;
+ trace_object->add("type", "index_roworder_intersect");
+ trace_object->add("rows", records);
+ trace_object->add("cost", read_cost);
+ trace_object->add("covering", is_covering);
+ trace_object->add("clustered_pk_scan", cpk_scan != NULL);
+
+ Json_writer_array smth_trace(thd, "intersect_of");
+ for (ROR_SCAN_INFO **cur_scan = first_scan; cur_scan != last_scan;
+ cur_scan++)
+ {
+ const KEY &cur_key = param->table->key_info[(*cur_scan)->keynr];
+ const KEY_PART_INFO *key_part = cur_key.key_part;
+
+ Json_writer_object trace_isect_idx(thd);
+ trace_isect_idx.add("type", "range_scan");
+ trace_isect_idx.add("index", cur_key.name);
+ trace_isect_idx.add("rows", (*cur_scan)->records);
+
+ Json_writer_array trace_range(thd, "ranges");
+ for (const SEL_ARG *current = (*cur_scan)->sel_arg->first(); current;
+ current = current->next)
+ {
+ String range_info;
+ range_info.set_charset(system_charset_info);
+ for (const SEL_ARG *part = current; part;
+ part = part->next_key_part ? part->next_key_part : nullptr)
+ {
+ const KEY_PART_INFO *cur_key_part = key_part + part->part;
+ append_range(&range_info, cur_key_part, part->min_value,
+ part->max_value, part->min_flag | part->max_flag);
+ }
+ trace_range.add(range_info.ptr(), range_info.length());
+ }
+ }
+}
+
/*
Create ROR_SCAN_INFO* structure with a single ROR scan on index idx using
@@ -6414,7 +6783,9 @@ static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info,
*/
static bool ror_intersect_add(ROR_INTERSECT_INFO *info,
- ROR_SCAN_INFO* ror_scan, bool is_cpk_scan)
+ ROR_SCAN_INFO* ror_scan,
+ Json_writer_object *trace_costs,
+ bool is_cpk_scan)
{
double selectivity_mult= 1.0;
@@ -6441,13 +6812,16 @@ static bool ror_intersect_add(ROR_INTERSECT_INFO *info,
each record of every scan. Assuming 1/TIME_FOR_COMPARE_ROWID
per check this gives us:
*/
- info->index_scan_costs += rows2double(info->index_records) /
+ const double idx_cost= rows2double(info->index_records) /
TIME_FOR_COMPARE_ROWID;
+ info->index_scan_costs += idx_cost;
+ trace_costs->add("index_scan_cost", idx_cost);
}
else
{
info->index_records += info->param->quick_rows[ror_scan->keynr];
info->index_scan_costs += ror_scan->index_read_cost;
+ trace_costs->add("index_scan_cost", ror_scan->index_read_cost);
bitmap_union(&info->covered_fields, &ror_scan->covered_fields);
if (!info->is_covering && bitmap_is_subset(&info->param->needed_fields,
&info->covered_fields))
@@ -6458,13 +6832,19 @@ static bool ror_intersect_add(ROR_INTERSECT_INFO *info,
}
info->total_cost= info->index_scan_costs;
+ trace_costs->add("cumulateed_index_scan_cost", info->index_scan_costs);
DBUG_PRINT("info", ("info->total_cost: %g", info->total_cost));
if (!info->is_covering)
{
- info->total_cost +=
- get_sweep_read_cost(info->param, double2rows(info->out_rows));
+ double sweep_cost= get_sweep_read_cost(info->param,
+ double2rows(info->out_rows));
+ info->total_cost += sweep_cost;
+ trace_costs->add("disk_sweep_cost", sweep_cost);
DBUG_PRINT("info", ("info->total_cost= %g", info->total_cost));
}
+ else
+ trace_costs->add("disk_sweep_cost", static_cast<longlong>(0));
+
DBUG_PRINT("info", ("New out_rows: %g", info->out_rows));
DBUG_PRINT("info", ("New cost: %g, %scovering", info->total_cost,
info->is_covering?"" : "non-"));
@@ -6544,10 +6924,16 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
uint idx;
double min_cost= DBL_MAX;
DBUG_ENTER("get_best_ror_intersect");
+ THD *thd= param->thd;
+ Json_writer_object trace_ror(thd, "analyzing_roworder_intersect");
if ((tree->n_ror_scans < 2) || !param->table->stat_records() ||
!optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT))
- DBUG_RETURN(NULL);
+ {
+ if (tree->n_ror_scans < 2)
+ trace_ror.add("cause", "too few roworder scans");
+ DBUG_RETURN(NULL);
+ }
/*
Step1: Collect ROR-able SEL_ARGs and create ROR_SCAN_INFO for each of
@@ -6622,15 +7008,27 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
ROR_SCAN_INFO **intersect_scans_best;
cur_ror_scan= tree->ror_scans;
intersect_scans_best= intersect_scans;
+ Json_writer_array trace_isect_idx(thd, "intersecting_indexes");
while (cur_ror_scan != tree->ror_scans_end && !intersect->is_covering)
{
+ Json_writer_object trace_idx(thd);
+ trace_idx.add("index",
+ param->table->key_info[(*cur_ror_scan)->keynr].name);
+
/* S= S + first(R); R= R - first(R); */
- if (!ror_intersect_add(intersect, *cur_ror_scan, FALSE))
+ if (!ror_intersect_add(intersect, *cur_ror_scan, &trace_idx, FALSE))
{
+ trace_idx.add("usable", false)
+ .add("cause", "does not reduce cost of intersect");
cur_ror_scan++;
continue;
}
+ trace_idx.add("cumulative_total_cost", intersect->total_cost)
+ .add("usable", true)
+ .add("matching_rows_now", intersect->out_rows)
+ .add("intersect_covering_with_this_index", intersect->is_covering);
+
*(intersect_scans_end++)= *(cur_ror_scan++);
if (intersect->total_cost < min_cost)
@@ -6639,12 +7037,21 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
ror_intersect_cpy(intersect_best, intersect);
intersect_scans_best= intersect_scans_end;
min_cost = intersect->total_cost;
+ trace_idx.add("chosen", true);
+ }
+ else
+ {
+ trace_idx.add("chosen", false)
+ .add("cause", "does not reduce cost");
}
}
+ trace_isect_idx.end();
if (intersect_scans_best == intersect_scans)
{
DBUG_PRINT("info", ("None of scans increase selectivity"));
+ trace_ror.add("chosen", false)
+ .add("cause","does not increase selectivity");
DBUG_RETURN(NULL);
}
@@ -6662,16 +7069,31 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
Check if we should add a CPK scan. If the obtained ROR-intersection is
covering, it doesn't make sense to add CPK scan.
*/
+ Json_writer_object trace_cpk(thd, "clustered_pk");
if (cpk_scan && !intersect->is_covering)
{
- if (ror_intersect_add(intersect, cpk_scan, TRUE) &&
+ if (ror_intersect_add(intersect, cpk_scan, &trace_cpk, TRUE) &&
(intersect->total_cost < min_cost))
+ {
+ trace_cpk.add("clustered_pk_scan_added_to_intersect", true)
+ .add("cumulated_cost", intersect->total_cost);
intersect_best= intersect; //just set pointer here
+ }
else
+ {
+ trace_cpk.add("clustered_pk_added_to_intersect", false)
+ .add("cause", "cost");
cpk_scan= 0; // Don't use cpk_scan
+ }
}
else
+ {
+ trace_cpk.add("clustered_pk_added_to_intersect", false)
+ .add("cause", cpk_scan ? "roworder is covering"
+ : "no clustered pk index");
cpk_scan= 0; // Don't use cpk_scan
+ }
+ trace_cpk.end();
/* Ok, return ROR-intersect plan if we have found one */
TRP_ROR_INTERSECT *trp= NULL;
@@ -6698,6 +7120,17 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
DBUG_PRINT("info", ("Returning non-covering ROR-intersect plan:"
"cost %g, records %lu",
trp->read_cost, (ulong) trp->records));
+ trace_ror.add("rows", trp->records)
+ .add("cost", trp->read_cost)
+ .add("covering", trp->is_covering)
+ .add("chosen", true);
+ }
+ else
+ {
+ trace_ror.add("chosen", false)
+ .add("cause", (read_time > min_cost)
+ ? "too few indexes to merge"
+ : "cost");
}
DBUG_RETURN(trp);
}
@@ -6885,6 +7318,7 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
UNINIT_VAR(best_buf_size); /* protected by key_to_read */
TRP_RANGE* read_plan= NULL;
DBUG_ENTER("get_key_scans_params");
+ THD *thd= param->thd;
/*
Note that there may be trees that have type SEL_TREE::KEY but contain no
key reads at all, e.g. tree for expression "key1 is not null" where key1
@@ -6892,6 +7326,8 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
*/
DBUG_EXECUTE("info", print_sel_tree(param, tree, &tree->keys_map,
"tree scans"););
+ Json_writer_array range_scan_alt(thd, "range_scan_alternatives");
+
tree->ror_scans_map.clear_all();
tree->n_ror_scans= 0;
tree->index_scans= 0;
@@ -6920,6 +7356,9 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
bool read_index_only= index_read_must_be_used ? TRUE :
(bool) param->table->covering_keys.is_set(keynr);
+ Json_writer_object trace_idx(thd);
+ trace_idx.add("index", param->table->key_info[keynr].name);
+
found_records= check_quick_select(param, idx, read_index_only, key,
update_tbl_stats, &mrr_flags,
&buf_size, &cost);
@@ -6928,6 +7367,14 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
(index_scan= (INDEX_SCAN_INFO *)alloc_root(param->mem_root,
sizeof(INDEX_SCAN_INFO))))
{
+ Json_writer_array trace_range(thd, "ranges");
+
+ const KEY &cur_key = param->table->key_info[keynr];
+ const KEY_PART_INFO *key_part = cur_key.key_part;
+
+ String range_info;
+ range_info.set_charset(system_charset_info);
+
index_scan->idx= idx;
index_scan->keynr= keynr;
index_scan->key_info= &param->table->key_info[keynr];
@@ -6936,6 +7383,17 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
index_scan->records= found_records;
index_scan->sel_arg= key;
*tree->index_scans_end++= index_scan;
+
+ if (unlikely(thd->trace_started()))
+ append_range_all_keyparts(&trace_range, NULL, &range_info, key,
+ key_part);
+ trace_range.end();
+
+ trace_idx.add("rowid_ordered", param->is_ror_scan)
+ .add("using_mrr", !(mrr_flags & HA_MRR_USE_DEFAULT_IMPL))
+ .add("index_only", read_index_only)
+ .add("rows", found_records)
+ .add("cost", cost.total_cost());
}
if ((found_records != HA_POS_ERROR) && param->is_ror_scan)
{
@@ -6951,6 +7409,18 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
best_idx= idx;
best_mrr_flags= mrr_flags;
best_buf_size= buf_size;
+ trace_idx.add("chosen", true);
+ }
+ else
+ {
+ trace_idx.add("chosen", false);
+ if (found_records == HA_POS_ERROR)
+ if (key->type == SEL_ARG::Type::MAYBE_KEY)
+ trace_idx.add("cause", "depends on unread values");
+ else
+ trace_idx.add("cause", "unknown");
+ else
+ trace_idx.add("cause", "cost");
}
}
}
@@ -7055,10 +7525,11 @@ QUICK_SELECT_I *TRP_ROR_INTERSECT::make_quick(PARAM *param,
"creating ROR-intersect",
first_scan, last_scan););
alloc= parent_alloc? parent_alloc: &quick_intrsect->alloc;
- for (; first_scan != last_scan;++first_scan)
+ for (ROR_SCAN_INFO **curr_scan= first_scan; curr_scan != last_scan;
+ ++curr_scan)
{
- if (!(quick= get_quick_select(param, (*first_scan)->idx,
- (*first_scan)->sel_arg,
+ if (!(quick= get_quick_select(param, (*curr_scan)->idx,
+ (*curr_scan)->sel_arg,
HA_MRR_USE_DEFAULT_IMPL | HA_MRR_SORTED,
0, alloc)) ||
quick_intrsect->push_quick_back(alloc, quick))
@@ -12584,16 +13055,27 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
DBUG_ENTER("get_best_group_min_max");
+ Json_writer_object trace_group(thd, "group_index_range");
+ const char* cause= NULL;
+
/* Perform few 'cheap' tests whether this access method is applicable. */
- if (!join)
- DBUG_RETURN(NULL); /* This is not a select statement. */
- if ((join->table_count != 1) || /* The query must reference one table. */
- (join->select_lex->olap == ROLLUP_TYPE)) /* Check (B3) for ROLLUP */
+ if (!join) /* This is not a select statement. */
+ cause= "no join";
+ else if (join->table_count != 1) /* The query must reference one table. */
+ cause= "not single_table";
+ else if (join->select_lex->olap == ROLLUP_TYPE) /* Check (B3) for ROLLUP */
+ cause= "rollup";
+ else if (table->s->keys == 0) /* There are no indexes to use. */
+ cause= "no index";
+ else if (join->conds && join->conds->used_tables()
+ & OUTER_REF_TABLE_BIT) /* Cannot execute with correlated conditions. */
+ cause= "correlated conditions";
+
+ if (cause)
+ {
+ trace_group.add("chosen", false).add("cause", cause);
DBUG_RETURN(NULL);
- if (table->s->keys == 0) /* There are no indexes to use. */
- DBUG_RETURN(NULL);
- if (join->conds && join->conds->used_tables() & OUTER_REF_TABLE_BIT)
- DBUG_RETURN(NULL); /* Cannot execute with correlated conditions. */
+ }
/* Check (SA1,SA4) and store the only MIN/MAX argument - the C attribute.*/
List_iterator<Item> select_items_it(join->fields_list);
@@ -12602,7 +13084,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
if ((!join->group_list) && /* Neither GROUP BY nor a DISTINCT query. */
(!join->select_distinct) &&
!is_agg_distinct)
+ {
+ trace_group.add("chosen", false).add("cause","no group by or distinct");
DBUG_RETURN(NULL);
+ }
/* Analyze the query in more detail. */
if (join->sum_funcs[0])
@@ -12621,7 +13106,11 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
min_max_item->sum_func() == Item_sum::AVG_DISTINCT_FUNC))
continue;
else
+ {
+ trace_group.add("chosen", false)
+ .add("cause", "not applicable aggregate function");
DBUG_RETURN(NULL);
+ }
/* The argument of MIN/MAX. */
Item *expr= min_max_item->get_arg(0)->real_item();
@@ -12630,26 +13119,41 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
if (! min_max_arg_item)
min_max_arg_item= (Item_field*) expr;
else if (! min_max_arg_item->eq(expr, 1))
+ {
+ trace_group.add("chosen", false)
+ .add("cause", "arguments different in min max function");
DBUG_RETURN(NULL);
+ }
}
else
+ {
+ trace_group.add("chosen", false)
+ .add("cause", "no field item in min max function");
DBUG_RETURN(NULL);
+ }
}
}
/* Check (SA7). */
if (is_agg_distinct && (have_max || have_min))
{
+ trace_group.add("chosen", false)
+ .add("cause", "have both agg distinct and min max");
DBUG_RETURN(NULL);
}
/* Check (SA5). */
if (join->select_distinct)
{
+ trace_group.add("distinct_query", true);
while ((item= select_items_it++))
{
if (item->real_item()->type() != Item::FIELD_ITEM)
+ {
+ trace_group.add("chosen", false)
+ .add("cause", "distinct field is expression");
DBUG_RETURN(NULL);
+ }
}
}
@@ -12658,7 +13162,11 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
for (tmp_group= join->group_list; tmp_group; tmp_group= tmp_group->next)
{
if ((*tmp_group->item)->real_item()->type() != Item::FIELD_ITEM)
+ {
+ trace_group.add("chosen", false)
+ .add("cause", "group field is expression");
DBUG_RETURN(NULL);
+ }
elements_in_group++;
}
@@ -12680,10 +13188,16 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
ha_rows cur_quick_prefix_records= 0;
// We go through allowed indexes
+ Json_writer_array trace_indexes(thd, "potential_group_range_indexes");
+
for (uint cur_param_idx= 0; cur_param_idx < param->keys ; ++cur_param_idx)
{
const uint cur_index= param->real_keynr[cur_param_idx];
KEY *const cur_index_info= &table->key_info[cur_index];
+
+ Json_writer_object trace_idx(thd);
+ trace_idx.add("index", cur_index_info->name);
+
KEY_PART_INFO *cur_part;
KEY_PART_INFO *end_part; /* Last part for loops. */
/* Last index part. */
@@ -12708,7 +13222,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
*/
if (!table->covering_keys.is_set(cur_index) ||
!table->keys_in_use_for_group_by.is_set(cur_index))
- continue;
+ {
+ cause= "not covering";
+ goto next_index;
+ }
/*
This function is called on the precondition that the index is covering.
@@ -12716,7 +13233,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
these are duplicates. The GROUP BY list cannot be a prefix of the index.
*/
if (elements_in_group > table->actual_n_key_parts(cur_index_info))
- continue;
+ {
+ cause= "group key parts greater than index key parts";
+ goto next_index;
+ }
/*
Unless extended keys can be used for cur_index:
@@ -12742,10 +13262,15 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
*/
if (bitmap_is_set(table->read_set, cur_field->field_index) &&
!cur_field->part_of_key_not_clustered.is_set(cur_index))
+ {
+ cause= "not covering";
goto next_index; // Field was not part of key
+ }
}
}
+ trace_idx.add("covering", true);
+
max_key_part= 0;
used_key_parts_map.clear_all();
@@ -12776,7 +13301,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
used_key_parts_map.set_bit(max_key_part);
}
else
+ {
+ cause= "group attribute not prefix in index";
goto next_index;
+ }
}
}
/*
@@ -12805,7 +13333,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
/* not doing loose index scan for derived tables */
if (!item_field->field)
+ {
+ cause= "derived table";
goto next_index;
+ }
/* Find the order of the key part in the index. */
key_part_nr= get_field_keypart(cur_index_info, item_field->field);
@@ -12817,7 +13348,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
continue;
if (key_part_nr < 1 ||
(!is_agg_distinct && key_part_nr > join->fields_list.elements))
+ {
+ cause= "select attribute not prefix in index";
goto next_index;
+ }
cur_part= cur_index_info->key_part + key_part_nr - 1;
cur_group_prefix_len+= cur_part->store_length;
used_key_parts_map.set_bit(key_part_nr);
@@ -12842,7 +13376,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
{
key_part_nr= get_field_keypart(cur_index_info, min_max_arg_item->field);
if (key_part_nr <= cur_group_key_parts)
+ {
+ cause = "aggregate column not suffix in idx";
goto next_index;
+ }
min_max_arg_part= cur_index_info->key_part + key_part_nr - 1;
}
@@ -12853,6 +13390,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
if (cur_index_info->flags & HA_NOSAME &&
cur_group_key_parts == cur_index_info->user_defined_key_parts)
{
+ cause= "using unique index";
goto next_index;
}
@@ -12892,7 +13430,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
last_part, thd, cur_key_infix,
&cur_key_infix_len,
&first_non_infix_part))
+ {
+ cause = "nonconst equality gap attribute";
goto next_index;
+ }
}
else if (min_max_arg_part &&
(min_max_arg_part - first_non_group_part > 0))
@@ -12901,6 +13442,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
There is a gap but no range tree, thus no predicates at all for the
non-group keyparts.
*/
+ cause = "no nongroup keypart predicate";
goto next_index;
}
else if (first_non_group_part && join->conds)
@@ -12924,7 +13466,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
/* Check if cur_part is referenced in the WHERE clause. */
if (join->conds->walk(&Item::find_item_in_field_list_processor, 0,
key_part_range))
+ {
+ cause = "keypart reference from where clause";
goto next_index;
+ }
}
}
@@ -12939,7 +13484,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
for (; cur_part != last_part; cur_part++)
{
if (bitmap_is_set(table->read_set, cur_part->field->field_index))
+ {
+ cause = "keypart after infix in query";
goto next_index;
+ }
}
}
@@ -12956,6 +13504,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
index_range_tree, &cur_range) ||
(cur_range && cur_range->type != SEL_ARG::KEY_RANGE))
{
+ cause = "minmax keypart in disjunctive query";
goto next_index;
}
}
@@ -12978,6 +13527,17 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
cur_index_tree, TRUE,
&mrr_flags, &mrr_bufsize,
&dummy_cost);
+ if (unlikely(cur_index_tree && thd->trace_started()))
+ {
+ Json_writer_array trace_range(thd, "ranges");
+
+ const KEY_PART_INFO *key_part = cur_index_info->key_part;
+
+ String range_info;
+ range_info.set_charset(system_charset_info);
+ append_range_all_keyparts(&trace_range, NULL, &range_info,
+ cur_index_tree, key_part);
+ }
}
cost_group_min_max(table, cur_index_info, cur_used_key_parts,
cur_group_key_parts, tree, cur_index_tree,
@@ -12988,6 +13548,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
Do not compare doubles directly because they may have different
representations (64 vs. 80 bits).
*/
+ trace_idx.add("rows", cur_records).add("cost", cur_read_cost);
+
if (cur_read_cost < best_read_cost - (DBL_EPSILON * cur_read_cost))
{
index_info= cur_index_info;
@@ -13005,8 +13567,16 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
used_key_parts= cur_used_key_parts;
}
- next_index:;
+ next_index:
+ if (cause)
+ {
+ trace_idx.add("usable", false).add("cause", cause);
+ cause = NULL;
+ }
}
+
+ trace_indexes.end();
+
if (!index_info) /* No usable index found. */
DBUG_RETURN(NULL);
@@ -13017,14 +13587,22 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
(index_info->flags & HA_SPATIAL) ?
Field::itMBR : Field::itRAW,
&has_min_max_fld, &has_other_fld))
+ {
+ trace_group.add("usable", false)
+ .add("cause", "unsupported predicate on agg attribute");
DBUG_RETURN(NULL);
+ }
/*
Check (SA6) if clustered key is used
*/
if (is_agg_distinct && index == table->s->primary_key &&
table->file->primary_key_is_clustered())
+ {
+ trace_group.add("usable", false)
+ .add("cause", "index is clustered");
DBUG_RETURN(NULL);
+ }
/* The query passes all tests, so construct a new TRP object. */
read_plan= new (param->mem_root)
@@ -13045,6 +13623,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
read_plan->records= best_records;
if (read_time < best_read_cost && is_agg_distinct)
{
+ trace_group.add("index_scan", true);
read_plan->read_cost= 0;
read_plan->use_index_scan();
}
@@ -15002,7 +15581,6 @@ static void print_quick(QUICK_SELECT_I *quick, const key_map *needed_reg)
DBUG_VOID_RETURN;
}
-
void QUICK_RANGE_SELECT::dbug_dump(int indent, bool verbose)
{
/* purecov: begin inspected */
@@ -15130,3 +15708,174 @@ void QUICK_GROUP_MIN_MAX_SELECT::dbug_dump(int indent, bool verbose)
}
#endif /* !DBUG_OFF */
+static
+void append_range(String *out, const KEY_PART_INFO *key_part,
+ const uchar *min_key, const uchar *max_key, const uint flag)
+{
+ if (out->length() > 0)
+ out->append(STRING_WITH_LEN(" AND "));
+
+ if (flag & GEOM_FLAG)
+ {
+ /*
+ The flags of GEOM ranges do not work the same way as for other
+ range types, so printing "col < some_geom" doesn't make sense.
+ Just print the column name, not operator.
+ */
+ out->append(key_part->field->field_name);
+ out->append(STRING_WITH_LEN(" "));
+ print_key_value(out, key_part, min_key);
+ return;
+ }
+
+ if (!(flag & NO_MIN_RANGE))
+ {
+ print_key_value(out, key_part, min_key);
+ if (flag & NEAR_MIN)
+ out->append(STRING_WITH_LEN(" < "));
+ else
+ out->append(STRING_WITH_LEN(" <= "));
+ }
+
+ out->append(key_part->field->field_name);
+
+ if (!(flag & NO_MAX_RANGE))
+ {
+ if (flag & NEAR_MAX)
+ out->append(STRING_WITH_LEN(" < "));
+ else
+ out->append(STRING_WITH_LEN(" <= "));
+ print_key_value(out, key_part, max_key);
+ }
+}
+
+/*
+
+ Add ranges to the trace
+ For ex:
+ query: select * from t1 where a=2 ;
+ and we have an index on a , so we create a range
+ 2 <= a <= 2
+ this is added to the trace
+*/
+
+static void append_range_all_keyparts(Json_writer_array *range_trace,
+ String *range_string,
+ String *range_so_far, const SEL_ARG *keypart,
+ const KEY_PART_INFO *key_parts)
+{
+
+ DBUG_ASSERT(keypart);
+ DBUG_ASSERT(keypart && keypart != &null_element);
+
+ // Navigate to first interval in red-black tree
+ const KEY_PART_INFO *cur_key_part = key_parts + keypart->part;
+ const SEL_ARG *keypart_range = keypart->first();
+ const size_t save_range_so_far_length = range_so_far->length();
+
+
+ while (keypart_range)
+ {
+ // Append the current range predicate to the range String
+ switch (keypart->type)
+ {
+ case SEL_ARG::Type::KEY_RANGE:
+ append_range(range_so_far, cur_key_part, keypart_range->min_value,
+ keypart_range->max_value,
+ keypart_range->min_flag | keypart_range->max_flag);
+ break;
+ case SEL_ARG::Type::MAYBE_KEY:
+ range_so_far->append("MAYBE_KEY");
+ break;
+ case SEL_ARG::Type::IMPOSSIBLE:
+ range_so_far->append("IMPOSSIBLE");
+ break;
+ default:
+ DBUG_ASSERT(false);
+ break;
+ }
+
+ if (keypart_range->next_key_part &&
+ keypart_range->next_key_part->part ==
+ keypart_range->part + 1 &&
+ keypart_range->is_singlepoint())
+ {
+ append_range_all_keyparts(range_trace, range_string, range_so_far,
+ keypart_range->next_key_part, key_parts);
+ }
+ else
+ range_trace->add(range_so_far->c_ptr_safe(), range_so_far->length());
+ keypart_range= keypart_range->next;
+ range_so_far->length(save_range_so_far_length);
+ }
+}
+
+/**
+ Print a key to a string
+
+ @param[out] out String the key is appended to
+ @param[in] key_part Index components description
+ @param[in] key Key tuple
+*/
+static void print_key_value(String *out, const KEY_PART_INFO *key_part,
+ const uchar *key)
+{
+ Field *field = key_part->field;
+
+ if (field->flags & BLOB_FLAG) {
+ // Byte 0 of a nullable key is the null-byte. If set, key is NULL.
+ if (field->real_maybe_null() && *key)
+ out->append(STRING_WITH_LEN("NULL"));
+ else
+ (field->type() == MYSQL_TYPE_GEOMETRY)
+ ? out->append(STRING_WITH_LEN("unprintable_geometry_value"))
+ : out->append(STRING_WITH_LEN("unprintable_blob_value"));
+ return;
+ }
+
+ uint store_length = key_part->store_length;
+
+ if (field->real_maybe_null())
+ {
+ /*
+ Byte 0 of key is the null-byte. If set, key is NULL.
+ Otherwise, print the key value starting immediately after the
+ null-byte
+ */
+ if (*key) {
+ out->append(STRING_WITH_LEN("NULL"));
+ return;
+ }
+ key++; // Skip null byte
+ store_length--;
+ }
+
+ /*
+ Binary data cannot be converted to UTF8 which is what the
+ optimizer trace expects. If the column is binary, the hex
+ representation is printed to the trace instead.
+ */
+ if (field->flags & BINARY_FLAG) {
+ out->append("0x");
+ for (uint i = 0; i < store_length; i++) {
+ out->append(_dig_vec_lower[*(key + i) >> 4]);
+ out->append(_dig_vec_lower[*(key + i) & 0x0F]);
+ }
+ return;
+ }
+
+ StringBuffer<128> tmp(system_charset_info);
+ TABLE *table = field->table;
+ my_bitmap_map *old_sets[2];
+
+ dbug_tmp_use_all_columns(table, old_sets, table->read_set, table->write_set);
+
+ field->set_key_image(key, key_part->length);
+ if (field->type() == MYSQL_TYPE_BIT)
+ (void)field->val_int_as_str(&tmp, 1); // may change tmp's charset
+ else
+ field->val_str(&tmp); // may change tmp's charset
+ out->append(tmp.ptr(), tmp.length(), tmp.charset());
+
+ dbug_tmp_restore_column_maps(table->read_set, table->write_set, old_sets);
+}
diff --git a/sql/opt_range.h b/sql/opt_range.h
index d5416988b88..7e92e1f54ee 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -566,7 +566,7 @@ public:
FALSE Otherwise
*/
- bool is_singlepoint()
+ bool is_singlepoint() const
{
/*
Check for NEAR_MIN ("strictly less") and NO_MIN_RANGE (-inf < field)
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index c4c30c9b50d..228fcd0f7e6 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -33,6 +33,7 @@
#include "opt_subselect.h"
#include "sql_test.h"
#include <my_bit.h>
+#include "opt_trace.h"
/*
This file contains optimizations for semi-join subqueries.
@@ -437,7 +438,7 @@ Currently, solution #2 is implemented.
LEX_CSTRING weedout_key= {STRING_WITH_LEN("weedout_key")};
static
-bool subquery_types_allow_materialization(Item_in_subselect *in_subs);
+bool subquery_types_allow_materialization(THD *thd, Item_in_subselect *in_subs);
static bool replace_where_subcondition(JOIN *, Item **, Item *, Item *, bool);
static int subq_sj_candidate_cmp(Item_in_subselect* el1, Item_in_subselect* el2,
void *arg);
@@ -521,7 +522,7 @@ bool is_materialization_applicable(THD *thd, Item_in_subselect *in_subs,
parent_unit->first_select()->leaf_tables.elements && // 2
child_select->outer_select() &&
child_select->outer_select()->leaf_tables.elements && // 2A
- subquery_types_allow_materialization(in_subs) &&
+ subquery_types_allow_materialization(thd, in_subs) &&
(in_subs->is_top_level_item() || //3
optimizer_flag(thd,
OPTIMIZER_SWITCH_PARTIAL_MATCH_ROWID_MERGE) || //3
@@ -682,7 +683,7 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
{
DBUG_PRINT("info", ("Subquery is semi-join conversion candidate"));
- (void)subquery_types_allow_materialization(in_subs);
+ (void)subquery_types_allow_materialization(thd, in_subs);
in_subs->is_flattenable_semijoin= TRUE;
@@ -696,6 +697,9 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
if (arena)
thd->restore_active_arena(arena, &backup);
in_subs->is_registered_semijoin= TRUE;
+ OPT_TRACE_TRANSFORM(thd, oto0, oto1, select_lex->select_number,
+ "IN (SELECT)", "semijoin");
+ oto1.add("chosen", true);
}
}
else
@@ -823,7 +827,7 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
*/
static
-bool subquery_types_allow_materialization(Item_in_subselect *in_subs)
+bool subquery_types_allow_materialization(THD* thd, Item_in_subselect *in_subs)
{
DBUG_ENTER("subquery_types_allow_materialization");
@@ -831,9 +835,14 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs)
List_iterator<Item> it(in_subs->unit->first_select()->item_list);
uint elements= in_subs->unit->first_select()->item_list.elements;
+ const char* cause= NULL;
in_subs->types_allow_materialization= FALSE; // Assign default values
in_subs->sjm_scan_allowed= FALSE;
+
+ OPT_TRACE_TRANSFORM(thd, oto0, oto1,
+ in_subs->get_select_lex()->select_number,
+ "IN (SELECT)", "materialization");
bool all_are_fields= TRUE;
uint32 total_key_length = 0;
@@ -846,7 +855,11 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs)
total_key_length += inner->max_length;
if (!inner->type_handler()->subquery_type_allows_materialization(inner,
outer))
+ {
+ oto1.add("possible", false);
+ oto1.add("cause", "types mismatch");
DBUG_RETURN(FALSE);
+ }
}
/*
@@ -856,14 +869,23 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs)
Make sure that the length of the key for the temp_table is atleast
greater than 0.
*/
- if (!total_key_length || total_key_length > tmp_table_max_key_length() ||
- elements > tmp_table_max_key_parts())
- DBUG_RETURN(FALSE);
-
- in_subs->types_allow_materialization= TRUE;
- in_subs->sjm_scan_allowed= all_are_fields;
- DBUG_PRINT("info",("subquery_types_allow_materialization: ok, allowed"));
- DBUG_RETURN(TRUE);
+ if (!total_key_length)
+ cause= "zero length key for materialized table";
+ else if (total_key_length > tmp_table_max_key_length())
+ cause= "length of key greater than allowed key length for materialized tables";
+ else if (elements > tmp_table_max_key_parts())
+ cause= "#keyparts greater than allowed key parts for materialized tables";
+ else
+ {
+ in_subs->types_allow_materialization= TRUE;
+ in_subs->sjm_scan_allowed= all_are_fields;
+ oto1.add("sjm_scan_allowed", all_are_fields)
+ .add("possible", true);
+ DBUG_PRINT("info",("subquery_types_allow_materialization: ok, allowed"));
+ DBUG_RETURN(TRUE);
+ }
+ oto1.add("possible", false).add("cause", cause);
+ DBUG_RETURN(FALSE);
}
@@ -1213,15 +1235,30 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
/* Stop processing if we've reached a subquery that's attached to the ON clause */
if (in_subq->do_not_convert_to_sj)
+ {
+ OPT_TRACE_TRANSFORM(thd, oto0, oto1,
+ in_subq->get_select_lex()->select_number,
+ "IN (SELECT)", "semijoin");
+ oto1.add("converted_to_semi_join", false)
+ .add("cause", "subquery attached to the ON clause");
break;
+ }
if (in_subq->is_flattenable_semijoin)
{
+ OPT_TRACE_TRANSFORM(thd, oto0, oto1,
+ in_subq->get_select_lex()->select_number,
+ "IN (SELECT)", "semijoin");
if (join->table_count +
in_subq->unit->first_select()->join->table_count >= MAX_TABLES)
+ {
+ oto1.add("converted_to_semi_join", false);
+ oto1.add("cause", "table in parent join now exceeds MAX_TABLES");
break;
+ }
if (convert_subq_to_sj(join, in_subq))
goto restore_arena_and_fail;
+ oto1.add("converted_to_semi_join", true);
}
else
{
@@ -2340,8 +2377,13 @@ int pull_out_semijoin_tables(JOIN *join)
bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
{
DBUG_ENTER("optimize_semijoin_nests");
+ THD *thd= join->thd;
List_iterator<TABLE_LIST> sj_list_it(join->select_lex->sj_nests);
TABLE_LIST *sj_nest;
+ Json_writer_object wrapper(thd);
+ Json_writer_object trace_semijoin_nest(thd,
+ "execution_plan_for_potential_materialization");
+ Json_writer_array trace_steps_array(thd, "steps");
while ((sj_nest= sj_list_it++))
{
/* semi-join nests with only constant tables are not valid */
diff --git a/sql/opt_table_elimination.cc b/sql/opt_table_elimination.cc
index 74d1e775c43..03516146de2 100644
--- a/sql/opt_table_elimination.cc
+++ b/sql/opt_table_elimination.cc
@@ -31,6 +31,8 @@
#include "mariadb.h"
#include "my_bit.h"
#include "sql_select.h"
+#include "opt_trace.h"
+#include "my_json_writer.h"
/*
OVERVIEW
@@ -522,7 +524,8 @@ eliminate_tables_for_list(JOIN *join,
List<TABLE_LIST> *join_list,
table_map tables_in_list,
Item *on_expr,
- table_map tables_used_elsewhere);
+ table_map tables_used_elsewhere,
+ Json_writer_array* eliminate_tables);
static
bool check_func_dependency(JOIN *join,
table_map dep_tables,
@@ -541,7 +544,8 @@ static
Dep_module_expr *merge_eq_mods(Dep_module_expr *start,
Dep_module_expr *new_fields,
Dep_module_expr *end, uint and_level);
-static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl);
+static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl,
+ Json_writer_array* eliminate_tables);
static
void add_module_expr(Dep_analysis_context *dac, Dep_module_expr **eq_mod,
uint and_level, Dep_value_field *field_val, Item *right,
@@ -608,6 +612,8 @@ void eliminate_tables(JOIN *join)
if (!optimizer_flag(thd, OPTIMIZER_SWITCH_TABLE_ELIMINATION))
DBUG_VOID_RETURN; /* purecov: inspected */
+ Json_writer_object trace_wrapper(thd);
+
/* Find the tables that are referred to from WHERE/HAVING */
used_tables= (join->conds? join->conds->used_tables() : 0) |
(join->having? join->having->used_tables() : 0);
@@ -663,13 +669,14 @@ void eliminate_tables(JOIN *join)
}
}
}
-
+
table_map all_tables= join->all_tables_map();
+ Json_writer_array eliminated_tables(thd,"eliminated_tables");
if (all_tables & ~used_tables)
{
/* There are some tables that we probably could eliminate. Try it. */
eliminate_tables_for_list(join, join->join_list, all_tables, NULL,
- used_tables);
+ used_tables, &eliminated_tables);
}
DBUG_VOID_RETURN;
}
@@ -712,7 +719,8 @@ void eliminate_tables(JOIN *join)
static bool
eliminate_tables_for_list(JOIN *join, List<TABLE_LIST> *join_list,
table_map list_tables, Item *on_expr,
- table_map tables_used_elsewhere)
+ table_map tables_used_elsewhere,
+ Json_writer_array *eliminate_tables)
{
TABLE_LIST *tbl;
List_iterator<TABLE_LIST> it(*join_list);
@@ -734,9 +742,9 @@ eliminate_tables_for_list(JOIN *join, List<TABLE_LIST> *join_list,
&tbl->nested_join->join_list,
tbl->nested_join->used_tables,
tbl->on_expr,
- outside_used_tables))
+ outside_used_tables, eliminate_tables))
{
- mark_as_eliminated(join, tbl);
+ mark_as_eliminated(join, tbl, eliminate_tables);
}
else
all_eliminated= FALSE;
@@ -748,7 +756,7 @@ eliminate_tables_for_list(JOIN *join, List<TABLE_LIST> *join_list,
check_func_dependency(join, tbl->table->map, NULL, tbl,
tbl->on_expr))
{
- mark_as_eliminated(join, tbl);
+ mark_as_eliminated(join, tbl, eliminate_tables);
}
else
all_eliminated= FALSE;
@@ -1788,7 +1796,8 @@ Dep_module* Dep_value_field::get_next_unbound_module(Dep_analysis_context *dac,
Mark one table or the whole join nest as eliminated.
*/
-static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl)
+static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl,
+ Json_writer_array* eliminate_tables)
{
TABLE *table;
/*
@@ -1801,7 +1810,7 @@ static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl)
TABLE_LIST *child;
List_iterator<TABLE_LIST> it(tbl->nested_join->join_list);
while ((child= it++))
- mark_as_eliminated(join, child);
+ mark_as_eliminated(join, child, eliminate_tables);
}
else if ((table= tbl->table))
{
@@ -1812,6 +1821,7 @@ static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl)
tab->type= JT_CONST;
tab->table->const_table= 1;
join->eliminated_tables |= table->map;
+ eliminate_tables->add(table->alias.c_ptr_safe());
join->const_table_map|= table->map;
set_position(join, join->const_tables++, tab, (KEYUSE*)0);
}
diff --git a/sql/opt_trace.cc b/sql/opt_trace.cc
new file mode 100644
index 00000000000..ca05f36579a
--- /dev/null
+++ b/sql/opt_trace.cc
@@ -0,0 +1,722 @@
+/* This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "mariadb.h"
+#include "sql_array.h"
+#include "sql_string.h"
+#include "sql_class.h"
+#include "sql_show.h"
+#include "field.h"
+#include "table.h"
+#include "opt_trace.h"
+#include "sql_parse.h"
+#include "set_var.h"
+#include "my_json_writer.h"
+#include "sp_head.h"
+
+const char I_S_table_name[] = "OPTIMIZER_TRACE";
+
+/**
+ Whether a list of tables contains information_schema.OPTIMIZER_TRACE.
+ @param tbl list of tables
+
+ Can we do better than this here??
+ @note this does not catch that a stored routine or view accesses
+ the OPTIMIZER_TRACE table. So using a stored routine or view to read
+ OPTIMIZER_TRACE will overwrite OPTIMIZER_TRACE as it runs and provide
+ uninteresting info.
+*/
+bool list_has_optimizer_trace_table(const TABLE_LIST *tbl)
+{
+ for (; tbl; tbl = tbl->next_global)
+ {
+ if (tbl->schema_table &&
+ 0 == strcmp(tbl->schema_table->table_name, I_S_table_name))
+ return true;
+ }
+ return false;
+}
+
+/*
+ Returns if a query has a set command with optimizer_trace being switched on/off.
+ True: Don't trace the query(uninteresting)
+*/
+
+bool sets_var_optimizer_trace(enum enum_sql_command sql_command,
+ List<set_var_base> *set_vars)
+{
+ if (sql_command == SQLCOM_SET_OPTION)
+ {
+ List_iterator_fast<set_var_base> it(*set_vars);
+ const set_var_base *var;
+ while ((var = it++))
+ if (var->is_var_optimizer_trace()) return true;
+ }
+ return false;
+}
+
+
+ST_FIELD_INFO optimizer_trace_info[] = {
+ /* name, length, type, value, maybe_null, old_name, open_method */
+ {"QUERY", 65535, MYSQL_TYPE_STRING, 0, false, NULL, SKIP_OPEN_TABLE},
+ {"TRACE", 65535, MYSQL_TYPE_STRING, 0, false, NULL, SKIP_OPEN_TABLE},
+ {"MISSING_BYTES_BEYOND_MAX_MEM_SIZE", 20, MYSQL_TYPE_LONG, 0, false, NULL,
+ SKIP_OPEN_TABLE},
+ {"INSUFFICIENT_PRIVILEGES", 1, MYSQL_TYPE_TINY, 0, false, NULL,
+ SKIP_OPEN_TABLE},
+ {NULL, 0, MYSQL_TYPE_STRING, 0, true, NULL, 0}};
+
+/*
+ TODO: one-line needs to be implemented seperately
+*/
+const char *Opt_trace_context::flag_names[] = {"enabled", "default",
+ NullS};
+
+/*
+ Returns if a particular command will be traced or not
+*/
+
+inline bool sql_command_can_be_traced(enum enum_sql_command sql_command)
+{
+ /*
+ For first iteration we are only allowing select queries.
+ TODO: change to allow other queries.
+ */
+ return sql_command == SQLCOM_SELECT ||
+ sql_command == SQLCOM_UPDATE ||
+ sql_command == SQLCOM_DELETE ||
+ sql_command == SQLCOM_DELETE_MULTI ||
+ sql_command == SQLCOM_UPDATE_MULTI;
+}
+
+void opt_trace_print_expanded_query(THD *thd, SELECT_LEX *select_lex,
+ Json_writer_object *writer)
+
+{
+ if (!thd->trace_started())
+ return;
+ char buff[1024];
+ String str(buff, sizeof(buff), system_charset_info);
+ str.length(0);
+ select_lex->print(thd, &str,
+ enum_query_type(QT_TO_SYSTEM_CHARSET |
+ QT_SHOW_SELECT_NUMBER |
+ QT_ITEM_IDENT_SKIP_DB_NAMES |
+ QT_VIEW_INTERNAL
+ ));
+ /*
+ The output is not very pretty lots of back-ticks, the output
+ is as the one in explain extended , lets try to improved it here.
+ */
+ writer->add("expanded_query", str.c_ptr_safe(), str.length());
+}
+
+void opt_trace_disable_if_no_security_context_access(THD *thd)
+{
+ if (likely(!(thd->variables.optimizer_trace &
+ Opt_trace_context::FLAG_ENABLED)) || // (1)
+ thd->system_thread) // (2)
+ {
+ /*
+ (1) We know that the routine's execution starts with "enabled=off".
+ If it stays so until the routine ends, we needn't do security checks on
+ the routine.
+ If it does not stay so, it means the definer sets it to "on" somewhere
+ in the routine's body. Then it is his conscious decision to generate
+ traces, thus it is still correct to skip the security check.
+
+ (2) Threads of the Events Scheduler have an unusual security context
+ (thd->m_main_security_ctx.priv_user==NULL, see comment in
+ Security_context::change_security_context()).
+ */
+ return;
+ }
+ Opt_trace_context *const trace = &thd->opt_trace;
+ if (!thd->trace_started())
+ {
+ /*
+ @@optimizer_trace has "enabled=on" but trace is not started.
+ Either Opt_trace_start ctor was not called for our statement (3), or it
+ was called but at that time, the variable had "enabled=off" (4).
+
+ There are no known cases of (3).
+
+ (4) suggests that the user managed to change the variable during
+ execution of the statement, and this statement is using
+ view/routine (note that we have not been able to provoke this, maybe
+ this is impossible). If it happens it is suspicious.
+
+ We disable I_S output. And we cannot do otherwise: we have no place to
+ store a possible "missing privilege" information (no Opt_trace_stmt, as
+ is_started() is false), so cannot do security checks, so cannot safely
+ do tracing, so have to disable I_S output. And even then, we don't know
+ when to re-enable I_S output, as we have no place to store the
+ information "re-enable tracing at the end of this statement", and we
+ don't even have a notion of statement here (statements in the optimizer
+ trace world mean an Opt_trace_stmt object, and there is none here). So
+ we must disable for the session's life.
+
+ COM_FIELD_LIST opens views, thus used to be a case of (3). To avoid
+ disabling I_S output for the session's life when this command is issued
+ (like in: "SET OPTIMIZER_TRACE='ENABLED=ON';USE somedb;" in the 'mysql'
+ command-line client), we have decided to create a Opt_trace_start for
+ this command. The command itself is not traced though
+ (SQLCOM_SHOW_FIELDS does not have CF_OPTIMIZER_TRACE).
+ */
+ return;
+ }
+ /*
+ Note that thd->main_security_ctx.master_access is probably invariant
+ accross the life of THD: GRANT/REVOKE don't affect global privileges of an
+ existing connection, per the manual.
+ */
+ if (!(thd->main_security_ctx.check_access(GLOBAL_ACLS & ~GRANT_ACL)) &&
+ (0 != strcmp(thd->main_security_ctx.priv_user,
+ thd->security_context()->priv_user) ||
+ 0 != my_strcasecmp(system_charset_info,
+ thd->main_security_ctx.priv_host,
+ thd->security_context()->priv_host)))
+ trace->missing_privilege();
+ return;
+}
+
+void opt_trace_disable_if_no_stored_proc_func_access(THD *thd, sp_head *sp)
+{
+ if (likely(!(thd->variables.optimizer_trace &
+ Opt_trace_context::FLAG_ENABLED)) ||
+ thd->system_thread)
+ return;
+
+ Opt_trace_context *const trace = &thd->opt_trace;
+ if (!thd->trace_started())
+ return;
+ bool full_access;
+ Security_context *const backup_thd_sctx = thd->security_context();
+ thd->set_security_context(&thd->main_security_ctx);
+ const bool rc = check_show_routine_access(thd, sp, &full_access) || !full_access;
+ thd->set_security_context(backup_thd_sctx);
+ if (rc)
+ trace->missing_privilege();
+ return;
+}
+
+/**
+ If tracing is on, checks additional privileges on a list of tables/views,
+ to make sure that the user has the right to do SHOW CREATE TABLE/VIEW and
+ "SELECT *". For that:
+ - this functions checks table-level SELECT
+ - which is sufficient for SHOW CREATE TABLE and "SELECT *", if a base table
+ - if a view, if the view has not been identified as such then
+ opt_trace_disable_if_no_view_access() will be later called and check SHOW
+ VIEW; other we check SHOW VIEW here; SHOW VIEW + SELECT is sufficient for
+ SHOW CREATE VIEW.
+ If a privilege is missing, notifies the trace system.
+
+ @param thd
+ @param tbl list of tables to check
+*/
+
+void opt_trace_disable_if_no_tables_access(THD *thd, TABLE_LIST *tbl)
+{
+ if (likely(!(thd->variables.optimizer_trace &
+ Opt_trace_context::FLAG_ENABLED)) || thd->system_thread)
+ return;
+ Opt_trace_context *const trace = &thd->opt_trace;
+
+ if (!thd->trace_started())
+ return;
+
+ Security_context *const backup_thd_sctx = thd->security_context();
+ thd->set_security_context(&thd->main_security_ctx);
+ const TABLE_LIST *const first_not_own_table = thd->lex->first_not_own_table();
+ for (TABLE_LIST *t = tbl; t != NULL && t != first_not_own_table;
+ t = t->next_global)
+ {
+ /*
+ Anonymous derived tables (as in
+ "SELECT ... FROM (SELECT ...)") don't have their grant.privilege set.
+ */
+ if (!t->is_anonymous_derived_table())
+ {
+ const GRANT_INFO backup_grant_info = t->grant;
+ Security_context *const backup_table_sctx = t->security_ctx;
+ t->security_ctx = NULL;
+ /*
+ (1) check_table_access() fills t->grant.privilege.
+ (2) Because SELECT privileges can be column-based,
+ check_table_access() will return 'false' as long as there is SELECT
+ privilege on one column. But we want a table-level privilege.
+ */
+
+ bool rc =
+ check_table_access(thd, SELECT_ACL, t, false, 1, true) || // (1)
+ ((t->grant.privilege & SELECT_ACL) == 0); // (2)
+ if (t->is_view())
+ {
+ /*
+ It's a view which has already been opened: we are executing a
+ prepared statement. The view has been unfolded in the global list of
+ tables. So underlying tables will be automatically checked in the
+ present function, but we need an explicit check of SHOW VIEW:
+ */
+ rc |= check_table_access(thd, SHOW_VIEW_ACL, t, false, 1, true);
+ }
+ t->security_ctx = backup_table_sctx;
+ t->grant = backup_grant_info;
+ if (rc)
+ {
+ trace->missing_privilege();
+ break;
+ }
+ }
+ }
+ thd->set_security_context(backup_thd_sctx);
+ return;
+}
+
+void opt_trace_disable_if_no_view_access(THD *thd, TABLE_LIST *view,
+ TABLE_LIST *underlying_tables)
+{
+
+ if (likely(!(thd->variables.optimizer_trace &
+ Opt_trace_context::FLAG_ENABLED)) ||
+ thd->system_thread)
+ return;
+ Opt_trace_context *const trace = &thd->opt_trace;
+ if (!thd->trace_started())
+ return;
+
+ Security_context *const backup_table_sctx = view->security_ctx;
+ Security_context *const backup_thd_sctx = thd->security_context();
+ const GRANT_INFO backup_grant_info = view->grant;
+
+ view->security_ctx = NULL; // no SUID context for view
+ // no SUID context for THD
+ thd->set_security_context(&thd->main_security_ctx);
+ const int rc = check_table_access(thd, SHOW_VIEW_ACL, view, false, 1, true);
+
+ view->security_ctx = backup_table_sctx;
+ thd->set_security_context(backup_thd_sctx);
+ view->grant = backup_grant_info;
+
+ if (rc)
+ {
+ trace->missing_privilege();
+ return;
+ }
+ /*
+ We needn't check SELECT privilege on this view. Some
+ opt_trace_disable_if_no_tables_access() call has or will check it.
+
+ Now we check underlying tables/views of our view:
+ */
+ opt_trace_disable_if_no_tables_access(thd, underlying_tables);
+ return;
+}
+
+
+/**
+ @class Opt_trace_stmt
+
+ The trace of one statement.
+*/
+
+class Opt_trace_stmt {
+ public:
+ /**
+ Constructor, starts a trace for information_schema and dbug.
+ @param ctx_arg context
+ */
+ Opt_trace_stmt(Opt_trace_context *ctx_arg)
+ {
+ ctx= ctx_arg;
+ current_json= new Json_writer();
+ missing_priv= false;
+ I_S_disabled= 0;
+ }
+ ~Opt_trace_stmt()
+ {
+ delete current_json;
+ missing_priv= false;
+ ctx= NULL;
+ I_S_disabled= 0;
+ }
+ void set_query(const char *query_ptr, size_t length, const CHARSET_INFO *charset);
+ void open_struct(const char *key, char opening_bracket);
+ void close_struct(const char *saved_key, char closing_bracket);
+ void fill_info(Opt_trace_info* info);
+ void add(const char *key, char *opening_bracket, size_t val_length);
+ Json_writer* get_current_json(){return current_json;}
+ void missing_privilege();
+ void disable_tracing_for_children();
+ void enable_tracing_for_children();
+ bool is_enabled();
+
+ void set_allowed_mem_size(size_t mem_size);
+ size_t get_length() { return current_json->output.length(); }
+ size_t get_truncated_bytes() { return current_json->get_truncated_bytes(); }
+ bool get_missing_priv() { return missing_priv; }
+
+private:
+ Opt_trace_context *ctx;
+ String query; // store the query sent by the user
+ Json_writer *current_json; // stores the trace
+ bool missing_priv; ///< whether user lacks privilege to see this trace
+ uint I_S_disabled;
+};
+
+void Opt_trace_stmt::set_query(const char *query_ptr, size_t length,
+ const CHARSET_INFO *charset)
+{
+ query.append(query_ptr, length, charset);
+}
+
+Json_writer* Opt_trace_context::get_current_json()
+{
+ if (!is_started())
+ return NULL;
+ return current_trace->get_current_json();
+}
+
+void Opt_trace_context::missing_privilege()
+{
+ if (current_trace)
+ current_trace->missing_privilege();
+}
+
+void Opt_trace_context::set_allowed_mem_size(size_t mem_size)
+{
+ current_trace->set_allowed_mem_size(mem_size);
+}
+
+/*
+ TODO: In future when we would be saving multiple trace,
+ this function would return
+ max_mem_size - memory_occupied_by_the_saved_traces
+*/
+
+size_t Opt_trace_context::remaining_mem_size()
+{
+ return max_mem_size;
+}
+
+bool Opt_trace_context::disable_tracing_if_required()
+{
+ if (current_trace)
+ {
+ current_trace->disable_tracing_for_children();
+ return true;
+ }
+ return false;
+}
+
+bool Opt_trace_context::enable_tracing_if_required()
+{
+ if (current_trace)
+ {
+ current_trace->enable_tracing_for_children();
+ return true;
+ }
+ return false;
+}
+
+bool Opt_trace_context::is_enabled()
+{
+ if (current_trace)
+ return current_trace->is_enabled();
+ return false;
+}
+
+Opt_trace_context::Opt_trace_context()
+{
+ current_trace= NULL;
+ inited= FALSE;
+ traces= NULL;
+ max_mem_size= 0;
+}
+Opt_trace_context::~Opt_trace_context()
+{
+ inited= FALSE;
+ /*
+ would be nice to move this to a function
+ */
+ if (traces)
+ {
+ while (traces->elements())
+ {
+ Opt_trace_stmt *prev= traces->at(0);
+ delete prev;
+ traces->del(0);
+ }
+ delete traces;
+ traces= NULL;
+ }
+ max_mem_size= 0;
+}
+
+void Opt_trace_context::set_query(const char *query, size_t length, const CHARSET_INFO *charset)
+{
+ current_trace->set_query(query, length, charset);
+}
+
+void Opt_trace_context::start(THD *thd, TABLE_LIST *tbl,
+ enum enum_sql_command sql_command,
+ const char *query,
+ size_t query_length,
+ const CHARSET_INFO *query_charset,
+ ulong max_mem_size_arg)
+{
+ /*
+ This is done currently because we don't want to have multiple
+ traces open at the same time, so as soon as a new trace is created
+ we forcefully end the previous one, if it has not ended by itself.
+ This would mostly happen with stored functions or procedures.
+
+ TODO: handle multiple traces
+ */
+ DBUG_ASSERT(!current_trace);
+ current_trace= new Opt_trace_stmt(this);
+ max_mem_size= max_mem_size_arg;
+ if (!inited)
+ {
+ traces= new Dynamic_array<Opt_trace_stmt*>();
+ inited= TRUE;
+ }
+ set_allowed_mem_size(remaining_mem_size());
+}
+
+void Opt_trace_context::end()
+{
+ if (current_trace)
+ traces->push(current_trace);
+
+ if (!traces->elements())
+ return;
+ if (traces->elements() > 1)
+ {
+ Opt_trace_stmt *prev= traces->at(0);
+ delete prev;
+ traces->del(0);
+ }
+ current_trace= NULL;
+}
+
+Opt_trace_start::Opt_trace_start(THD *thd, TABLE_LIST *tbl,
+ enum enum_sql_command sql_command,
+ List<set_var_base> *set_vars,
+ const char *query,
+ size_t query_length,
+ const CHARSET_INFO *query_charset):ctx(&thd->opt_trace)
+{
+ /*
+ if optimizer trace is enabled and the statment we have is traceable,
+ then we start the context.
+ */
+ const ulonglong var = thd->variables.optimizer_trace;
+ traceable= FALSE;
+ if (unlikely(var & Opt_trace_context::FLAG_ENABLED) &&
+ sql_command_can_be_traced(sql_command) &&
+ !list_has_optimizer_trace_table(tbl) &&
+ !sets_var_optimizer_trace(sql_command, set_vars) &&
+ !thd->system_thread &&
+ !ctx->disable_tracing_if_required())
+ {
+ ctx->start(thd, tbl, sql_command, query, query_length, query_charset,
+ thd->variables.optimizer_trace_max_mem_size);
+ ctx->set_query(query, query_length, query_charset);
+ traceable= TRUE;
+ opt_trace_disable_if_no_tables_access(thd, tbl);
+ }
+}
+
+Opt_trace_start::~Opt_trace_start()
+{
+ if (traceable)
+ {
+ ctx->end();
+ traceable= FALSE;
+ }
+ else
+ {
+ ctx->enable_tracing_if_required();
+ }
+}
+
+void Opt_trace_stmt::fill_info(Opt_trace_info* info)
+{
+ if (unlikely(info->missing_priv = get_missing_priv()))
+ {
+ info->trace_ptr = info->query_ptr = "";
+ info->trace_length = info->query_length = 0;
+ info->query_charset = &my_charset_bin;
+ info->missing_bytes = 0;
+ }
+ else
+ {
+ info->trace_ptr = current_json->output.get_string()->ptr();
+ info->trace_length = get_length();
+ info->query_ptr = query.ptr();
+ info->query_length = query.length();
+ info->query_charset = query.charset();
+ info->missing_bytes = get_truncated_bytes();
+ info->missing_priv= get_missing_priv();
+ }
+}
+
+void Opt_trace_stmt::missing_privilege()
+{
+ missing_priv= true;
+}
+
+void Opt_trace_stmt::disable_tracing_for_children()
+{
+ ++I_S_disabled;
+}
+
+void Opt_trace_stmt::enable_tracing_for_children()
+{
+ if (I_S_disabled)
+ --I_S_disabled;
+}
+
+bool Opt_trace_stmt::is_enabled()
+{
+ return I_S_disabled == 0;
+}
+
+void Opt_trace_stmt::set_allowed_mem_size(size_t mem_size)
+{
+ current_json->set_size_limit(mem_size);
+}
+
+/*
+ Prefer this when you are iterating over JOIN_TABs
+*/
+
+void Json_writer::add_table_name(const JOIN_TAB *tab)
+{
+ if (tab != NULL)
+ {
+ char table_name_buffer[SAFE_NAME_LEN];
+ if (tab->table && tab->table->derived_select_number)
+ {
+ /* Derived table name generation */
+ size_t len= my_snprintf(table_name_buffer, sizeof(table_name_buffer)-1,
+ "<derived%u>",
+ tab->table->derived_select_number);
+ add_str(table_name_buffer, len);
+ }
+ else if (tab->bush_children)
+ {
+ JOIN_TAB *ctab= tab->bush_children->start;
+ size_t len= my_snprintf(table_name_buffer,
+ sizeof(table_name_buffer)-1,
+ "<subquery%d>",
+ ctab->emb_sj_nest->sj_subq_pred->get_identifier());
+ add_str(table_name_buffer, len);
+ }
+ else
+ {
+ TABLE_LIST *real_table= tab->table->pos_in_table_list;
+ add_str(real_table->alias.str, real_table->alias.length);
+ }
+ }
+ else
+ DBUG_ASSERT(0);
+}
+
+void Json_writer::add_table_name(const TABLE *table)
+{
+ add_str(table->pos_in_table_list->alias.str);
+}
+
+
+void add_table_scan_values_to_trace(THD *thd, JOIN_TAB *tab)
+{
+ Json_writer_object table_records(thd);
+ table_records.add_table_name(tab);
+ Json_writer_object table_rec(thd, "table_scan");
+ table_rec.add("rows", tab->found_records)
+ .add("cost", tab->read_time);
+}
+/*
+ Introduce enum_query_type flags parameter, maybe also allow
+ EXPLAIN also use this function.
+*/
+
+void Json_writer::add_str(Item *item)
+{
+ if (item)
+ {
+ THD *thd= current_thd;
+ char buff[256];
+ String str(buff, sizeof(buff), system_charset_info);
+ str.length(0);
+
+ ulonglong save_option_bits= thd->variables.option_bits;
+ thd->variables.option_bits &= ~OPTION_QUOTE_SHOW_CREATE;
+ item->print(&str,
+ enum_query_type(QT_TO_SYSTEM_CHARSET | QT_SHOW_SELECT_NUMBER
+ | QT_ITEM_IDENT_SKIP_DB_NAMES));
+ thd->variables.option_bits= save_option_bits;
+ add_str(str.c_ptr_safe());
+ }
+ else
+ add_null();
+}
+
+void Opt_trace_context::flush_optimizer_trace()
+{
+ inited= false;
+ if (traces)
+ {
+ while (traces->elements())
+ {
+ Opt_trace_stmt *prev= traces->at(0);
+ delete prev;
+ traces->del(0);
+ }
+ delete traces;
+ traces= NULL;
+ }
+}
+
+
+int fill_optimizer_trace_info(THD *thd, TABLE_LIST *tables, Item *)
+{
+ TABLE *table = tables->table;
+ Opt_trace_info info;
+
+ /* get_values of trace, query , missing bytes and missing_priv
+
+ @todo: Need an iterator here to walk over all the traces
+ */
+ Opt_trace_context* ctx= &thd->opt_trace;
+
+ if (thd->opt_trace.empty())
+ {
+ Opt_trace_stmt *stmt= ctx->get_top_trace();
+ stmt->fill_info(&info);
+
+ table->field[0]->store(info.query_ptr, static_cast<uint>(info.query_length),
+ info.query_charset);
+ table->field[1]->store(info.trace_ptr, static_cast<uint>(info.trace_length),
+ system_charset_info);
+ table->field[2]->store(info.missing_bytes, true);
+ table->field[3]->store(info.missing_priv, true);
+ // Store in IS
+ if (schema_table_store_record(thd, table))
+ return 1;
+ }
+ return 0;
+}
diff --git a/sql/opt_trace.h b/sql/opt_trace.h
new file mode 100644
index 00000000000..0e2d0146a49
--- /dev/null
+++ b/sql/opt_trace.h
@@ -0,0 +1,201 @@
+#ifndef OPT_TRACE_INCLUDED
+#define OPT_TRACE_INCLUDED
+/* This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "opt_trace_context.h" // Opt_trace_context
+#include "sql_lex.h"
+#include "my_json_writer.h"
+#include "sql_select.h"
+class Item;
+class THD;
+struct TABLE_LIST;
+
+class Opt_trace_stmt;
+
+/*
+ User-visible information about a trace.
+*/
+
+struct Opt_trace_info
+{
+ /**
+ String containing trace.
+ If trace has been end()ed, this is 0-terminated, which is only to aid
+ debugging or unit testing; this property is not relied upon in normal
+ server usage.
+ If trace has not been ended, this is not 0-terminated. That rare case can
+ happen when a substatement reads OPTIMIZER_TRACE (at that stage, the top
+ statement is still executing so its trace is not ended yet, but may still
+ be read by the sub-statement).
+ */
+ const char *trace_ptr;
+ size_t trace_length;
+ //// String containing original query.
+ const char *query_ptr;
+ size_t query_length;
+ const CHARSET_INFO *query_charset; ///< charset of query string
+ /**
+ How many bytes this trace is missing (for traces which were truncated
+ because of @@@@optimizer-trace-max-mem-size).
+ The trace is not extended beyond trace-max-mem-size.
+ */
+ size_t missing_bytes;
+ /*
+ Whether user lacks privilege to see this trace.
+ If this is set to TRUE, then we return an empty trace
+ */
+ bool missing_priv;
+};
+
+/**
+ Instantiate this class to start tracing a THD's actions (generally at a
+ statement's start), and to set the "original" query (not transformed, as
+ sent by client) for the new trace. Destructor will end the trace.
+
+ @param thd the THD
+ @param tbl list of tables read/written by the statement.
+ @param sql_command SQL command being prepared or executed
+ @param set_vars what variables are set by this command (only used if
+ sql_command is SQLCOM_SET_OPTION)
+ @param query query
+ @param length query's length
+ @param charset charset which was used to encode this query
+*/
+
+
+class Opt_trace_start {
+ public:
+ Opt_trace_start(THD *thd_arg, TABLE_LIST *tbl,
+ enum enum_sql_command sql_command,
+ List<set_var_base> *set_vars,
+ const char *query,
+ size_t query_length,
+ const CHARSET_INFO *query_charset);
+ ~Opt_trace_start();
+
+ private:
+ Opt_trace_context *const ctx;
+ /*
+ True: the query will be traced
+ False: otherwise
+ */
+ bool traceable;
+};
+
+/**
+ Prints SELECT query to optimizer trace. It is not the original query (as in
+ @c Opt_trace_context::set_query()) but a printout of the parse tree
+ (Item-s).
+ @param thd the THD
+ @param select_lex query's parse tree
+ @param trace_object Json_writer object to which the query will be added
+*/
+void opt_trace_print_expanded_query(THD *thd, SELECT_LEX *select_lex,
+ Json_writer_object *trace_object);
+
+void add_table_scan_values_to_trace(THD *thd, JOIN_TAB *tab);
+
+/*
+ Security related (need to add a proper comment here)
+*/
+
+/**
+ If the security context is not that of the connected user, inform the trace
+ system that a privilege is missing. With one exception: see below.
+
+ @param thd
+
+ This serves to eliminate the following issue.
+ Any information readable by a SELECT may theoretically end up in
+ the trace. And a SELECT may read information from other places than tables:
+ - from views (reading their bodies)
+ - from stored routines (reading their bodies)
+ - from files (reading their content), with LOAD_FILE()
+ - from the list of connections (reading their queries...), with
+ I_S.PROCESSLIST.
+ If the connected user has EXECUTE privilege on a routine which does a
+ security context change, the routine can retrieve information internally
+ (if allowed by the SUID context's privileges), and present only a portion
+ of it to the connected user. But with tracing on, all information is
+ possibly in the trace. So the connected user receives more information than
+ the routine's definer intended to provide. Fixing this issue would require
+ adding, near many privilege checks in the server, a new
+ optimizer-trace-specific check done against the connected user's context,
+ to verify that the connected user has the right to see the retrieved
+ information.
+
+ Instead, our chosen simpler solution is that if we see a security context
+ change where SUID user is not the connected user, we disable tracing. With
+ only one safe exception: if the connected user has all global privileges
+ (because then she/he can find any information anyway). By "all global
+ privileges" we mean everything but WITH GRANT OPTION (that latter one isn't
+ related to information gathering).
+
+ Read access to I_S.OPTIMIZER_TRACE by another user than the connected user
+ is restricted: @see fill_optimizer_trace_info().
+*/
+void opt_trace_disable_if_no_security_context_access(THD *thd);
+
+void opt_trace_disable_if_no_tables_access(THD *thd, TABLE_LIST *tbl);
+
+/**
+ If tracing is on, checks additional privileges for a view, to make sure
+ that the user has the right to do SHOW CREATE VIEW. For that:
+ - this function checks SHOW VIEW
+ - SELECT is tested in opt_trace_disable_if_no_tables_access()
+ - SELECT + SHOW VIEW is sufficient for SHOW CREATE VIEW.
+ We also check underlying tables.
+ If a privilege is missing, notifies the trace system.
+ This function should be called when the view's underlying tables have not
+ yet been merged.
+
+ @param thd THD context
+ @param view view to check
+ @param underlying_tables underlying tables/views of 'view'
+ */
+
+void opt_trace_disable_if_no_view_access(THD *thd, TABLE_LIST *view,
+ TABLE_LIST *underlying_tables);
+
+/**
+ If tracing is on, checks additional privileges on a stored routine, to make
+ sure that the user has the right to do SHOW CREATE PROCEDURE/FUNCTION. For
+ that, we use the same checks as in those SHOW commands.
+ If a privilege is missing, notifies the trace system.
+
+ This function is not redundant with
+ opt_trace_disable_if_no_security_context_access().
+ Indeed, for a SQL SECURITY INVOKER routine, there is no context change, but
+ we must still verify that the invoker can do SHOW CREATE.
+
+ For triggers, see note in sp_head::execute_trigger().
+
+ @param thd
+ @param sp routine to check
+ */
+void opt_trace_disable_if_no_stored_proc_func_access(THD *thd, sp_head *sp);
+
+/**
+ Fills information_schema.OPTIMIZER_TRACE with rows (one per trace)
+ @retval 0 ok
+ @retval 1 error
+*/
+int fill_optimizer_trace_info(THD *thd, TABLE_LIST *tables, Item *);
+
+#define OPT_TRACE_TRANSFORM(writer, object_level0, object_level1, \
+ select_number, from, to) \
+ Json_writer_object object_level0(writer); \
+ Json_writer_object object_level1(writer, "transformation"); \
+ object_level1.add_select_number(select_number).add("from", from).add("to", to);
+#endif \ No newline at end of file
diff --git a/sql/opt_trace_context.h b/sql/opt_trace_context.h
new file mode 100644
index 00000000000..87317f67e22
--- /dev/null
+++ b/sql/opt_trace_context.h
@@ -0,0 +1,92 @@
+#ifndef OPT_TRACE_CONTEXT_INCLUDED
+#define OPT_TRACE_CONTEXT_INCLUDED
+
+#include "sql_array.h"
+
+class Opt_trace_stmt;
+
+class Opt_trace_context
+{
+public:
+ Opt_trace_context();
+ ~Opt_trace_context();
+
+ void start(THD *thd, TABLE_LIST *tbl,
+ enum enum_sql_command sql_command,
+ const char *query,
+ size_t query_length,
+ const CHARSET_INFO *query_charset,
+ ulong max_mem_size_arg);
+ void end();
+ void set_query(const char *query, size_t length, const CHARSET_INFO *charset);
+ void flush_optimizer_trace();
+ void set_allowed_mem_size(size_t mem_size);
+ size_t remaining_mem_size();
+
+private:
+ Opt_trace_stmt* top_trace()
+ {
+ return *(traces->front());
+ }
+
+public:
+
+ /*
+ This returns the top trace from the list of traces. This function
+ is used when we want to see the contents of the INFORMATION_SCHEMA.OPTIMIZER_TRACE
+ table.
+ */
+
+ Opt_trace_stmt* get_top_trace()
+ {
+ if (!traces || !traces->elements())
+ return NULL;
+ return top_trace();
+ }
+
+ /*
+ This returns the current trace, to which we are still writing and has not been finished
+ */
+
+ Json_writer* get_current_json();
+
+ bool empty()
+ {
+ return traces && (static_cast<uint>(traces->elements()) != 0);
+ }
+
+ bool is_started()
+ {
+ return current_trace && is_enabled();
+ }
+
+ bool disable_tracing_if_required();
+
+ bool enable_tracing_if_required();
+
+ bool is_enabled();
+
+ void missing_privilege();
+
+ static const char *flag_names[];
+ enum
+ {
+ FLAG_DEFAULT = 0,
+ FLAG_ENABLED = 1 << 0
+ };
+
+private:
+ /*
+ List of traces (currently it stores only 1 trace)
+ */
+ Dynamic_array<Opt_trace_stmt*> *traces;
+ Opt_trace_stmt *current_trace;
+ /*
+ TRUE: if we allocate memory for list of traces
+ FALSE: otherwise
+ */
+ bool inited;
+ size_t max_mem_size;
+};
+
+#endif /* OPT_TRACE_CONTEXT_INCLUDED */
diff --git a/sql/set_var.h b/sql/set_var.h
index 6097b28e76f..8a82e07fd6b 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -275,6 +275,10 @@ public:
virtual int update(THD *thd)=0; /* To set the value */
virtual int light_check(THD *thd) { return check(thd); } /* for PS */
virtual bool is_system() { return FALSE; }
+ /**
+ @returns whether this variable is @@@@optimizer_trace.
+ */
+ virtual bool is_var_optimizer_trace() const { return false; }
};
@@ -306,6 +310,11 @@ public:
int check(THD *thd);
int update(THD *thd);
int light_check(THD *thd);
+ virtual bool is_var_optimizer_trace() const
+ {
+ extern sys_var *Sys_optimizer_trace_ptr;
+ return var == Sys_optimizer_trace_ptr;
+ }
};
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 8345a9efe61..11c1234e2db 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -29,6 +29,8 @@
#include "sql_derived.h" // mysql_handle_derived
#include "sql_cte.h"
#include "sql_select.h" // Virtual_tmp_table
+#include "opt_trace.h"
+#include "my_json_writer.h"
#ifdef USE_PRAGMA_IMPLEMENTATION
#pragma implementation
@@ -1146,6 +1148,8 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
if (check_stack_overrun(thd, 7 * STACK_MIN_SIZE, (uchar*)&old_packet))
DBUG_RETURN(TRUE);
+ opt_trace_disable_if_no_security_context_access(thd);
+
/* init per-instruction memroot */
init_sql_alloc(&execute_mem_root, "per_instruction_memroot",
MEM_ROOT_BLOCK_SIZE, 0, MYF(0));
@@ -1982,6 +1986,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
thd->variables.option_bits&= ~OPTION_BIN_LOG;
}
+ opt_trace_disable_if_no_stored_proc_func_access(thd, this);
/*
Switch to call arena/mem_root so objects like sp_cursor or
Item_cache holders for case expressions can be allocated on it.
@@ -2272,6 +2277,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
err_status= set_routine_security_ctx(thd, this, &save_security_ctx);
#endif
+ opt_trace_disable_if_no_stored_proc_func_access(thd, this);
if (!err_status)
{
err_status= execute(thd, TRUE);
@@ -3297,6 +3303,13 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
thd->lex->safe_to_cache_query= 0;
#endif
+ Opt_trace_start ots(thd, m_lex->query_tables,
+ SQLCOM_SELECT, &m_lex->var_list,
+ NULL, 0,
+ thd->variables.character_set_client);
+
+ Json_writer_object trace_command(thd);
+ Json_writer_array trace_command_steps(thd, "steps");
if (open_tables)
res= check_dependencies_in_with_clauses(m_lex->with_clauses_list) ||
instr->exec_open_and_lock_tables(thd, m_lex->query_tables);
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 8db6ecac9e7..f59da93d8aa 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -2024,6 +2024,7 @@ private:
}; // class sp_instr_set_case_expr : public sp_instr_opt_meta
+bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bool
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 81db3c286ad..97e3bde97dd 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -71,6 +71,7 @@
#include "wsrep_thd.h"
#include "wsrep_trans_observer.h"
#endif /* WITH_WSREP */
+#include "opt_trace.h"
#ifdef HAVE_SYS_SYSCALL_H
#include <sys/syscall.h>
@@ -1410,6 +1411,7 @@ void THD::change_user(void)
sp_cache_clear(&sp_func_cache);
sp_cache_clear(&sp_package_spec_cache);
sp_cache_clear(&sp_package_body_cache);
+ opt_trace.flush_optimizer_trace();
}
/**
@@ -2187,6 +2189,11 @@ void THD::reset_globals()
net.thd= 0;
}
+bool THD::trace_started()
+{
+ return opt_trace.is_started();
+}
+
/*
Cleanup after query.
@@ -4337,6 +4344,13 @@ bool Security_context::set_user(char *user_arg)
return user == 0;
}
+bool Security_context::check_access(ulong want_access, bool match_any)
+{
+ DBUG_ENTER("Security_context::check_access");
+ DBUG_RETURN((match_any ? (master_access & want_access)
+ : ((master_access & want_access) == want_access)));
+}
+
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/**
Initialize this security context from the passed in credentials
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 402a114aadd..d6da0566bbe 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -28,6 +28,7 @@
#include "rpl_tblmap.h"
#include "mdl.h"
#include "field.h" // Create_field
+#include "opt_trace_context.h"
#include "probes_mysql.h"
#include "sql_locale.h" /* my_locale_st */
#include "sql_profile.h" /* PROFILING */
@@ -569,6 +570,8 @@ typedef struct system_variables
ulonglong long_query_time;
ulonglong max_statement_time;
ulonglong optimizer_switch;
+ ulonglong optimizer_trace;
+ ulong optimizer_trace_max_mem_size;
sql_mode_t sql_mode; ///< which non-standard SQL behaviour should be enabled
sql_mode_t old_behavior; ///< which old SQL behaviour should be enabled
ulonglong option_bits; ///< OPTION_xxx constants, e.g. OPTION_PROFILING
@@ -1350,6 +1353,14 @@ public:
restore_security_context(THD *thd, Security_context *backup);
#endif
bool user_matches(Security_context *);
+ /**
+ Check global access
+ @param want_access The required privileges
+ @param match_any if the security context must match all or any of the req.
+ * privileges.
+ @return True if the security context fulfills the access requirements.
+ */
+ bool check_access(ulong want_access, bool match_any = false);
};
@@ -2306,6 +2317,8 @@ public:
Security_context main_security_ctx;
Security_context *security_ctx;
+ Security_context *security_context() const { return security_ctx; }
+ void set_security_context(Security_context *sctx) { security_ctx = sctx; }
/*
Points to info-string that we show in SHOW PROCESSLIST
@@ -2989,6 +3002,7 @@ public:
ulonglong bytes_sent_old;
ulonglong affected_rows; /* Number of changed rows */
+ Opt_trace_context opt_trace;
pthread_t real_id; /* For debugging */
my_thread_id thread_id, thread_dbug_id;
uint32 os_thread_id;
@@ -3297,6 +3311,7 @@ public:
void reset_for_reuse();
bool store_globals();
void reset_globals();
+ bool trace_started();
#ifdef SIGNAL_WITH_VIO_CLOSE
inline void set_active_vio(Vio* vio)
{
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index fbd8365e619..a3a53320ac0 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -33,6 +33,7 @@
#include "sql_acl.h" // SELECT_ACL
#include "sql_class.h"
#include "sql_cte.h"
+#include "my_json_writer.h"
typedef bool (*dt_processor)(THD *thd, LEX *lex, TABLE_LIST *derived);
@@ -199,6 +200,7 @@ mysql_handle_single_derived(LEX *lex, TABLE_LIST *derived, uint phases)
if ((res= (*processors[phase])(lex->thd, lex, derived)))
break;
}
+
lex->thd->derived_tables_processing= FALSE;
DBUG_RETURN(res);
}
@@ -369,6 +371,7 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived)
DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
(derived->alias.str ? derived->alias.str : "<NULL>"),
derived->get_unit()));
+ const char *cause= NULL;
if (derived->merged)
{
@@ -380,6 +383,7 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived)
if (dt_select->uncacheable & UNCACHEABLE_RAND)
{
/* There is random function => fall back to materialization. */
+ cause= "Random function in the select";
derived->change_refs_to_fields();
derived->set_materialized_derived();
DBUG_RETURN(FALSE);
@@ -409,15 +413,11 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived)
and small subqueries, and the bigger one can't be merged it wouldn't
block the smaller one.
*/
- if (parent_lex->get_free_table_map(&map, &tablenr))
- {
- /* There is no enough table bits, fall back to materialization. */
- goto unconditional_materialization;
- }
-
- if (dt_select->leaf_tables.elements + tablenr > MAX_TABLES)
+ if (parent_lex->get_free_table_map(&map, &tablenr) ||
+ dt_select->leaf_tables.elements + tablenr > MAX_TABLES)
{
/* There is no enough table bits, fall back to materialization. */
+ cause= "Not enough table bits to merge subquery";
goto unconditional_materialization;
}
@@ -494,6 +494,24 @@ exit_merge:
DBUG_RETURN(res);
unconditional_materialization:
+
+ if (unlikely(thd->trace_started()))
+ {
+ /*
+ Add to the optimizer trace the change in choice for merged
+ derived tables/views to materialised ones.
+ */
+ Json_writer_object trace_wrapper(thd);
+ Json_writer_object trace_derived(thd, derived->is_derived() ?
+ "derived" : "view");
+ trace_derived.add("table", derived->alias.str ? derived->alias.str : "<NULL>")
+ .add_select_number(derived->get_unit()->
+ first_select()->select_number)
+ .add("initial_choice", "merged")
+ .add("final_choice", "materialized")
+ .add("cause", cause);
+ }
+
derived->change_refs_to_fields();
derived->set_materialized_derived();
if (!derived->table || !derived->table->is_created())
@@ -662,7 +680,6 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
DBUG_ENTER("mysql_derived_prepare");
DBUG_PRINT("enter", ("unit: %p table_list: %p alias: '%s'",
unit, derived, derived->alias.str));
-
if (!unit)
DBUG_RETURN(FALSE);
@@ -755,6 +772,22 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
}
}
+ if (unlikely(thd->trace_started()))
+ {
+ /*
+ Add to optimizer trace whether a derived table/view
+ is merged into the parent select or not.
+ */
+ Json_writer_object trace_wrapper(thd);
+ Json_writer_object trace_derived(thd, derived->is_derived() ?
+ "derived" : "view");
+ trace_derived.add("table", derived->alias.str ? derived->alias.str : "<NULL>")
+ .add_select_number(derived->get_unit()->first_select()->select_number);
+ if (derived->is_materialized_derived())
+ trace_derived.add("materialized", true);
+ if (derived->is_merged_derived())
+ trace_derived.add("merged", true);
+ }
/*
Above cascade call of prepare is important for PS protocol, but after it
is called we can check if we really need prepare for this derived
diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc
index 7bb04fe6be4..aa3c90c3ee1 100644
--- a/sql/sql_explain.cc
+++ b/sql/sql_explain.cc
@@ -236,7 +236,7 @@ void Explain_query::print_explain_json(select_result_sink *output,
CHARSET_INFO *cs= system_charset_info;
List<Item> item_list;
- String *buf= &writer.output;
+ const String *buf= writer.output.get_string();
item_list.push_back(new (thd->mem_root)
Item_string(thd, buf->ptr(), buf->length(), cs),
thd->mem_root);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 1335461506d..25dfdbcbc71 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -100,6 +100,7 @@
#include "set_var.h"
#include "sql_bootstrap.h"
#include "sql_sequence.h"
+#include "opt_trace.h"
#include "my_json_writer.h"
@@ -979,8 +980,9 @@ static char *fgets_fn(char *buffer, size_t size, fgets_input_t input, int *error
}
-void bootstrap(MYSQL_FILE *file)
+int bootstrap(MYSQL_FILE *file)
{
+ int bootstrap_error= 0;
DBUG_ENTER("handle_bootstrap");
THD *thd= new THD(next_thread_id());
@@ -1105,7 +1107,7 @@ void bootstrap(MYSQL_FILE *file)
thd->lex->restore_set_statement_var();
}
delete thd;
- DBUG_VOID_RETURN;
+ DBUG_RETURN(bootstrap_error);
}
@@ -3411,6 +3413,13 @@ mysql_execute_command(THD *thd)
#ifdef HAVE_REPLICATION
} /* endif unlikely slave */
#endif
+ Opt_trace_start ots(thd, all_tables, lex->sql_command, &lex->var_list,
+ thd->query(), thd->query_length(),
+ thd->variables.character_set_client);
+
+ Json_writer_object trace_command(thd);
+ Json_writer_array trace_command_steps(thd, "steps");
+
#ifdef WITH_WSREP
if (WSREP(thd))
{
diff --git a/sql/sql_parse.h b/sql/sql_parse.h
index f458c4279dd..7c8ba37f1de 100644
--- a/sql/sql_parse.h
+++ b/sql/sql_parse.h
@@ -99,7 +99,7 @@ void create_table_set_open_action_and_adjust_tables(LEX *lex);
void mysql_init_multi_delete(LEX *lex);
bool multi_delete_set_locks_and_link_aux_tables(LEX *lex);
void create_table_set_open_action_and_adjust_tables(LEX *lex);
-void bootstrap(MYSQL_FILE *file);
+int bootstrap(MYSQL_FILE *file);
int mysql_execute_command(THD *thd);
bool do_command(THD *thd);
bool dispatch_command(enum enum_server_command command, THD *thd,
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index c8cc64dba7e..6c3ad9c6924 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -112,6 +112,7 @@ When one supplies long data for a placeholder:
#include "sp_cache.h"
#include "sql_handler.h" // mysql_ha_rm_tables
#include "probes_mysql.h"
+#include "opt_trace.h"
#ifdef EMBEDDED_LIBRARY
/* include MYSQL_BIND headers */
#include <mysql.h>
@@ -2273,6 +2274,17 @@ static bool check_prepared_statement(Prepared_statement *stmt)
lex->first_select_lex()->context.resolve_in_table_list_only(select_lex->
get_table_list());
+ /*
+ For the optimizer trace, this is the symmetric, for statement preparation,
+ of what is done at statement execution (in mysql_execute_command()).
+ */
+ Opt_trace_start ots(thd, tables, lex->sql_command, &lex->var_list,
+ thd->query(), thd->query_length(),
+ thd->variables.character_set_client);
+
+ Json_writer_object trace_command(thd);
+ Json_writer_array trace_command_steps(thd, "steps");
+
/* Reset warning count for each query that uses tables */
if (tables)
thd->get_stmt_da()->opt_clear_warning_info(thd->query_id);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 38b0e7eb6e7..1f12490b49f 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -65,6 +65,8 @@
#include "sp_head.h"
#include "sp_rcontext.h"
#include "select_handler.h"
+#include "my_json_writer.h"
+#include "opt_trace.h"
/*
A key part number that means we're using a fulltext scan.
@@ -296,6 +298,8 @@ void set_postjoin_aggr_write_func(JOIN_TAB *tab);
static Item **get_sargable_cond(JOIN *join, TABLE *table);
+static void trace_plan_prefix(JOIN *join, uint idx, table_map remaining_tables);
+
#ifndef DBUG_OFF
/*
@@ -346,6 +350,40 @@ bool dbug_user_var_equals_int(THD *thd, const char *name, int value)
}
#endif
+static void trace_table_dependencies(THD *thd,
+ JOIN_TAB *join_tabs, uint table_count)
+{
+ Json_writer_object trace_wrapper(thd);
+ Json_writer_array trace_dep(thd, "table_dependencies");
+ for (uint i = 0; i < table_count; i++)
+ {
+ TABLE_LIST *table_ref = join_tabs[i].tab_list;
+ Json_writer_object trace_one_table(thd);
+ trace_one_table.add_table_name(&join_tabs[i]);
+ trace_one_table.add("row_may_be_null",
+ (bool)table_ref->table->maybe_null);
+ const table_map map = table_ref->get_map();
+ DBUG_ASSERT(map < (1ULL << table_count));
+ for (uint j = 0; j < table_count; j++)
+ {
+ if (map & (1ULL << j))
+ {
+ trace_one_table.add("map_bit", static_cast<longlong>(j));
+ break;
+ }
+ }
+ Json_writer_array depends_on(thd, "depends_on_map_bits");
+ static_assert(sizeof(table_ref->get_map()) <= 64,
+ "RAND_TABLE_BIT may be in join_tabs[i].dependent, so we test "
+ "all 64 bits.");
+ for (uint j = 0; j < 64; j++)
+ {
+ if (join_tabs[i].dependent & (1ULL << j))
+ depends_on.add(static_cast<longlong>(j));
+ }
+ }
+}
+
/**
This handles SELECT with and without UNION.
@@ -995,6 +1033,11 @@ JOIN::prepare(TABLE_LIST *tables_init,
join_list= &select_lex->top_join_list;
union_part= unit_arg->is_unit_op();
+ Json_writer_object trace_wrapper(thd);
+ Json_writer_object trace_prepare(thd, "join_preparation");
+ trace_prepare.add_select_number(select_lex->select_number);
+ Json_writer_array trace_steps(thd, "steps");
+
// simple check that we got usable conds
dbug_print_item(conds);
@@ -1337,6 +1380,11 @@ JOIN::prepare(TABLE_LIST *tables_init,
}
}
+ {
+ Json_writer_object trace_wrapper(thd);
+ opt_trace_print_expanded_query(thd, select_lex, &trace_wrapper);
+ }
+
if (!procedure && result && result->prepare(fields_list, unit_arg))
goto err; /* purecov: inspected */
@@ -1527,6 +1575,11 @@ JOIN::optimize_inner()
set_allowed_join_cache_types();
need_distinct= TRUE;
+ Json_writer_object trace_wrapper(thd);
+ Json_writer_object trace_prepare(thd, "join_optimization");
+ trace_prepare.add_select_number(select_lex->select_number);
+ Json_writer_array trace_steps(thd, "steps");
+
/*
Needed in case optimizer short-cuts,
set properly in make_aggr_tables_info()
@@ -3924,6 +3977,12 @@ void JOIN::exec_inner()
limit in order to produce the partial query result stored in the
UNION temp table.
*/
+
+ Json_writer_object trace_wrapper(thd);
+ Json_writer_object trace_exec(thd, "join_execution");
+ trace_exec.add_select_number(select_lex->select_number);
+ Json_writer_array trace_steps(thd, "steps");
+
if (!select_lex->outer_select() && // (1)
select_lex != select_lex->master_unit()->fake_select_lex) // (2)
thd->lex->set_limit_rows_examined();
@@ -4502,6 +4561,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
SARGABLE_PARAM *sargables= 0;
List_iterator<TABLE_LIST> ti(tables_list);
TABLE_LIST *tables;
+ THD *thd= join->thd;
DBUG_ENTER("make_join_statistics");
table_count=join->table_count;
@@ -4697,9 +4757,12 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
}
}
+ if (thd->trace_started())
+ trace_table_dependencies(thd, stat, join->table_count);
+
if (join->conds || outer_join)
{
- if (update_ref_and_keys(join->thd, keyuse_array, stat, join->table_count,
+ if (update_ref_and_keys(thd, keyuse_array, stat, join->table_count,
join->conds, ~outer_join, join->select_lex, &sargables))
goto error;
/*
@@ -4711,10 +4774,12 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
((Item_in_subselect*)join->unit->item)->test_strategy(SUBS_IN_TO_EXISTS));
if (keyuse_array->elements &&
- sort_and_filter_keyuse(join->thd, keyuse_array,
+ sort_and_filter_keyuse(thd, keyuse_array,
skip_unprefixed_keyparts))
goto error;
DBUG_EXECUTE("opt", print_keyuse_array(keyuse_array););
+ if (thd->trace_started())
+ print_keyuse_array_for_trace(thd, keyuse_array);
}
join->const_table_map= no_rows_const_tables;
@@ -4999,143 +5064,160 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
/* Calc how many (possible) matched records in each table */
- for (s=stat ; s < stat_end ; s++)
+ /*
+ Todo: add a function so that we can add these Json_writer_objects
+ easily.
+ Another way would be to enclose them in a scope {};
+ */
{
- s->startup_cost= 0;
- if (s->type == JT_SYSTEM || s->type == JT_CONST)
- {
- /* Only one matching row */
- s->found_records= s->records= 1;
- s->read_time=1.0;
- s->worst_seeks=1.0;
- continue;
- }
- /* Approximate found rows and time to read them */
- if (s->table->is_filled_at_execution())
- {
- get_delayed_table_estimates(s->table, &s->records, &s->read_time,
- &s->startup_cost);
- s->found_records= s->records;
- table->quick_condition_rows=s->records;
- }
- else
- {
- s->scan_time();
- }
-
- if (s->table->is_splittable())
- s->add_keyuses_for_splitting();
+ Json_writer_object rows_estimation_wrapper(thd);
+ Json_writer_array rows_estimation(thd, "rows_estimation");
+ for (s=stat ; s < stat_end ; s++)
+ {
+ s->startup_cost= 0;
+ if (s->type == JT_SYSTEM || s->type == JT_CONST)
+ {
+
+ Json_writer_object table_records(thd);
+ /* Only one matching row */
+ s->found_records= s->records= 1;
+ s->read_time=1.0;
+ s->worst_seeks=1.0;
+ table_records.add_table_name(s)
+ .add("rows", s->found_records)
+ .add("cost", s->read_time)
+ .add("table_type", s->type == JT_CONST ?
+ "const" :
+ "system");
+ continue;
+ }
+ /* Approximate found rows and time to read them */
+ if (s->table->is_filled_at_execution())
+ {
+ get_delayed_table_estimates(s->table, &s->records, &s->read_time,
+ &s->startup_cost);
+ s->found_records= s->records;
+ table->quick_condition_rows=s->records;
+ }
+ else
+ s->scan_time();
- /*
- Set a max range of how many seeks we can expect when using keys
- This is can't be to high as otherwise we are likely to use
- table scan.
- */
- s->worst_seeks= MY_MIN((double) s->found_records / 10,
- (double) s->read_time*3);
- if (s->worst_seeks < 2.0) // Fix for small tables
- s->worst_seeks=2.0;
+ if (s->table->is_splittable())
+ s->add_keyuses_for_splitting();
- /*
- Add to stat->const_keys those indexes for which all group fields or
- all select distinct fields participate in one index.
- */
- add_group_and_distinct_keys(join, s);
+ /*
+ Set a max range of how many seeks we can expect when using keys
+ This is can't be to high as otherwise we are likely to use
+ table scan.
+ */
+ s->worst_seeks= MY_MIN((double) s->found_records / 10,
+ (double) s->read_time*3);
+ if (s->worst_seeks < 2.0) // Fix for small tables
+ s->worst_seeks=2.0;
- s->table->cond_selectivity= 1.0;
-
- /*
- Perform range analysis if there are keys it could use (1).
- Don't do range analysis for materialized subqueries (2).
- Don't do range analysis for materialized derived tables (3)
- */
- if ((!s->const_keys.is_clear_all() ||
- !bitmap_is_clear_all(&s->table->cond_set)) && // (1)
- !s->table->is_filled_at_execution() && // (2)
- !(s->table->pos_in_table_list->derived && // (3)
- s->table->pos_in_table_list->is_materialized_derived())) // (3)
- {
- bool impossible_range= FALSE;
- ha_rows records= HA_POS_ERROR;
- SQL_SELECT *select= 0;
- Item **sargable_cond= NULL;
- if (!s->const_keys.is_clear_all())
- {
- sargable_cond= get_sargable_cond(join, s->table);
-
- select= make_select(s->table, found_const_table_map,
- found_const_table_map,
- *sargable_cond,
- (SORT_INFO*) 0,
- 1, &error);
- if (!select)
- goto error;
- records= get_quick_record_count(join->thd, select, s->table,
- &s->const_keys, join->row_limit);
+ /*
+ Add to stat->const_keys those indexes for which all group fields or
+ all select distinct fields participate in one index.
+ */
+ add_group_and_distinct_keys(join, s);
- /*
- Range analyzer might have modified the condition. Put it the new
- condition to where we got it from.
- */
- *sargable_cond= select->cond;
+ s->table->cond_selectivity= 1.0;
- s->quick=select->quick;
- s->needed_reg=select->needed_reg;
- select->quick=0;
- impossible_range= records == 0 && s->table->reginfo.impossible_range;
- }
- if (!impossible_range)
- {
- if (!sargable_cond)
+ /*
+ Perform range analysis if there are keys it could use (1).
+ Don't do range analysis for materialized subqueries (2).
+ Don't do range analysis for materialized derived tables (3)
+ */
+ if ((!s->const_keys.is_clear_all() ||
+ !bitmap_is_clear_all(&s->table->cond_set)) && // (1)
+ !s->table->is_filled_at_execution() && // (2)
+ !(s->table->pos_in_table_list->derived && // (3)
+ s->table->pos_in_table_list->is_materialized_derived())) // (3)
+ {
+ bool impossible_range= FALSE;
+ ha_rows records= HA_POS_ERROR;
+ SQL_SELECT *select= 0;
+ Item **sargable_cond= NULL;
+ if (!s->const_keys.is_clear_all())
+ {
sargable_cond= get_sargable_cond(join, s->table);
- if (join->thd->variables.optimizer_use_condition_selectivity > 1)
- calculate_cond_selectivity_for_table(join->thd, s->table,
- sargable_cond);
- if (s->table->reginfo.impossible_range)
- {
- impossible_range= TRUE;
- records= 0;
+
+ select= make_select(s->table, found_const_table_map,
+ found_const_table_map,
+ *sargable_cond,
+ (SORT_INFO*) 0, 1, &error);
+ if (!select)
+ goto error;
+ records= get_quick_record_count(join->thd, select, s->table,
+ &s->const_keys, join->row_limit);
+
+ /*
+ Range analyzer might have modified the condition. Put it the new
+ condition to where we got it from.
+ */
+ *sargable_cond= select->cond;
+
+ s->quick=select->quick;
+ s->needed_reg=select->needed_reg;
+ select->quick=0;
+ impossible_range= records == 0 && s->table->reginfo.impossible_range;
}
- }
- if (impossible_range)
- {
- /*
- Impossible WHERE or ON expression
- In case of ON, we mark that the we match one empty NULL row.
- In case of WHERE, don't set found_const_table_map to get the
- caller to abort with a zero row result.
- */
- TABLE_LIST *emb= s->table->pos_in_table_list->embedding;
- if (emb && !emb->sj_on_expr)
+ if (!impossible_range)
{
- /* Mark all tables in a multi-table join nest as const */
- mark_join_nest_as_const(join, emb, &found_const_table_map,
- &const_count);
+ if (!sargable_cond)
+ sargable_cond= get_sargable_cond(join, s->table);
+ if (join->thd->variables.optimizer_use_condition_selectivity > 1)
+ calculate_cond_selectivity_for_table(join->thd, s->table,
+ sargable_cond);
+ if (s->table->reginfo.impossible_range)
+ {
+ impossible_range= TRUE;
+ records= 0;
+ }
}
- else
+ if (impossible_range)
{
- join->const_table_map|= s->table->map;
- set_position(join,const_count++,s,(KEYUSE*) 0);
- s->type= JT_CONST;
- s->table->const_table= 1;
- if (*s->on_expr_ref)
+ /*
+ Impossible WHERE or ON expression
+ In case of ON, we mark that the we match one empty NULL row.
+ In case of WHERE, don't set found_const_table_map to get the
+ caller to abort with a zero row result.
+ */
+ TABLE_LIST *emb= s->table->pos_in_table_list->embedding;
+ if (emb && !emb->sj_on_expr)
+ {
+ /* Mark all tables in a multi-table join nest as const */
+ mark_join_nest_as_const(join, emb, &found_const_table_map,
+ &const_count);
+ }
+ else
{
- /* Generate empty row */
- s->info= ET_IMPOSSIBLE_ON_CONDITION;
- found_const_table_map|= s->table->map;
- mark_as_null_row(s->table); // All fields are NULL
+ join->const_table_map|= s->table->map;
+ set_position(join,const_count++,s,(KEYUSE*) 0);
+ s->type= JT_CONST;
+ s->table->const_table= 1;
+ if (*s->on_expr_ref)
+ {
+ /* Generate empty row */
+ s->info= ET_IMPOSSIBLE_ON_CONDITION;
+ found_const_table_map|= s->table->map;
+ mark_as_null_row(s->table); // All fields are NULL
+ }
}
}
+ if (records != HA_POS_ERROR)
+ {
+ s->found_records=records;
+ s->read_time= s->quick ? s->quick->read_time : 0.0;
+ }
+ if (select)
+ delete select;
+ else
+ add_table_scan_values_to_trace(thd, s);
}
- if (records != HA_POS_ERROR)
- {
- s->found_records=records;
- s->read_time= s->quick ? s->quick->read_time : 0.0;
- }
- if (select)
- delete select;
+ else
+ add_table_scan_values_to_trace(thd, s);
}
-
}
if (pull_out_semijoin_tables(join))
@@ -6894,11 +6976,15 @@ best_access_path(JOIN *join,
MY_BITMAP *eq_join_set= &s->table->eq_join_set;
KEYUSE *hj_start_key= 0;
SplM_plan_info *spl_plan= 0;
+ const char* cause= NULL;
disable_jbuf= disable_jbuf || idx == join->const_tables;
Loose_scan_opt loose_scan_opt;
DBUG_ENTER("best_access_path");
+
+ Json_writer_object trace_wrapper(thd, "best_access_path");
+ Json_writer_array trace_paths(thd, "considered_access_paths");
bitmap_clear_all(eq_join_set);
@@ -7013,6 +7099,7 @@ best_access_path(JOIN *join,
if (rec < MATCHING_ROWS_IN_OTHER_TABLE)
rec= MATCHING_ROWS_IN_OTHER_TABLE; // Fix for small tables
+ Json_writer_object trace_access_idx(thd);
/*
ft-keys require special treatment
*/
@@ -7024,6 +7111,8 @@ best_access_path(JOIN *join,
*/
tmp= prev_record_reads(join->positions, idx, found_ref);
records= 1.0;
+ trace_access_idx.add("access_type", "fulltext")
+ .add("index", keyinfo->name);
}
else
{
@@ -7038,11 +7127,15 @@ best_access_path(JOIN *join,
if ((key_flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME ||
MY_TEST(key_flags & HA_EXT_NOSAME))
{
+ trace_access_idx.add("access_type", "eq_ref")
+ .add("index", keyinfo->name);
tmp = prev_record_reads(join->positions, idx, found_ref);
records=1.0;
}
else
{
+ trace_access_idx.add("access_type", "ref")
+ .add("index", keyinfo->name);
if (!found_ref)
{ /* We found a const key */
/*
@@ -7063,11 +7156,16 @@ best_access_path(JOIN *join,
empty interval we wouldn't have got here).
*/
if (table->quick_keys.is_set(key))
+ {
records= (double) table->quick_rows[key];
+ trace_access_idx.add("used_range_estimates", true);
+ }
else
{
/* quick_range couldn't use key! */
records= (double) s->records/rec;
+ trace_access_idx.add("used_range_estimates", false)
+ .add("cause", "not available");
}
}
else
@@ -7099,7 +7197,23 @@ best_access_path(JOIN *join,
table->quick_n_ranges[key] == 1 &&
records > (double) table->quick_rows[key])
{
+
records= (double) table->quick_rows[key];
+ trace_access_idx.add("used_range_estimates", true);
+ }
+ else
+ {
+ if (table->quick_keys.is_set(key))
+ {
+ trace_access_idx.add("used_range_estimates",false)
+ .add("cause",
+ "not better than ref estimates");
+ }
+ else
+ {
+ trace_access_idx.add("used_range_estimates", false)
+ .add("cause", "not available");
+ }
}
}
/* Limit the number of matched rows */
@@ -7115,6 +7229,9 @@ best_access_path(JOIN *join,
}
else
{
+ trace_access_idx.add("access_type",
+ ref_or_null_part ? "ref_or_null" : "ref")
+ .add("index", keyinfo->name);
/*
Use as much key-parts as possible and a uniq key is better
than a not unique key
@@ -7169,6 +7286,7 @@ best_access_path(JOIN *join,
table->quick_n_ranges[key] == 1 + MY_TEST(ref_or_null_part)) //(C3)
{
tmp= records= (double) table->quick_rows[key];
+ trace_access_idx.add("used_range_estimates", true);
}
else
{
@@ -7194,7 +7312,19 @@ best_access_path(JOIN *join,
if (!found_ref && table->quick_keys.is_set(key) && // (1)
table->quick_key_parts[key] > max_key_part && // (2)
records < (double)table->quick_rows[key]) // (3)
+ {
+ trace_access_idx.add("used_range_estimates", true);
records= (double)table->quick_rows[key];
+ }
+ else
+ {
+ if (table->quick_keys.is_set(key) &&
+ table->quick_key_parts[key] < max_key_part)
+ {
+ trace_access_idx.add("chosen", false);
+ cause= "range uses more keyparts";
+ }
+ }
tmp= records;
}
@@ -7278,15 +7408,22 @@ best_access_path(JOIN *join,
tmp*= record_count;
}
else
+ {
+ if (!(found_part & 1))
+ cause= "no predicate for first keypart";
tmp= best_time; // Do nothing
+ }
}
tmp += s->startup_cost;
loose_scan_opt.check_ref_access_part2(key, start_key, records, tmp);
} /* not ft_key */
+ trace_access_idx.add("rows", records).add("cost", tmp);
+
if (tmp + 0.0001 < best_time - records/(double) TIME_FOR_COMPARE)
{
+ trace_access_idx.add("chosen", true);
best_time= tmp + records/(double) TIME_FOR_COMPARE;
best= tmp;
best_records= records;
@@ -7294,6 +7431,12 @@ best_access_path(JOIN *join,
best_max_key_part= max_key_part;
best_ref_depends_map= found_ref;
}
+ else
+ {
+ trace_access_idx.add("chosen", false)
+ .add("cause", cause ? cause : "cost");
+ }
+ cause= NULL;
} /* for each key */
records= best_records;
}
@@ -7315,6 +7458,7 @@ best_access_path(JOIN *join,
(!(s->table->map & join->outer_join) ||
join->allowed_outer_join_with_cache)) // (2)
{
+ Json_writer_object trace_access_hash(thd);
double join_sel= 0.1;
/* Estimate the cost of the hash join access to the table */
double rnd_records= matching_candidates_in_table(s, found_constraint,
@@ -7334,7 +7478,12 @@ best_access_path(JOIN *join,
best_key= hj_start_key;
best_ref_depends_map= 0;
best_uses_jbuf= TRUE;
- }
+ trace_access_hash.add("type", "hash");
+ trace_access_hash.add("index", "hj-key");
+ trace_access_hash.add("cost", rnd_records);
+ trace_access_hash.add("cost", best);
+ trace_access_hash.add("chosen", true);
+ }
/*
Don't test table scan if it can't be better.
@@ -7369,6 +7518,7 @@ best_access_path(JOIN *join,
can be [considered to be] more expensive, which causes lookups not to
be used for cases with small datasets, which is annoying.
*/
+ Json_writer_object trace_access_scan(thd);
if ((records >= s->found_records || best > s->read_time) && // (1)
!(s->quick && best_key && s->quick->index == best_key->key && // (2)
best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&// (2)
@@ -7388,6 +7538,10 @@ best_access_path(JOIN *join,
if (s->quick)
{
+ trace_access_scan.add("access_type", "range");
+ /*
+ should have some info about all the different QUICK_SELECT
+ */
/*
For each record we:
- read record range through 'quick'
@@ -7405,6 +7559,7 @@ best_access_path(JOIN *join,
}
else
{
+ trace_access_scan.add("access_type", "scan");
/* Estimate cost of reading table. */
if (s->table->force_index && !best_key) // index scan
tmp= s->table->file->read_time(s->ref.key, 1, s->records);
@@ -7449,6 +7604,8 @@ best_access_path(JOIN *join,
as record_count * rnd_records / TIME_FOR_COMPARE. This cost plus
tmp give us total cost of using TABLE SCAN
*/
+ trace_access_scan.add("resulting_rows", rnd_records);
+ trace_access_scan.add("cost", tmp);
if (best == DBL_MAX ||
(tmp + record_count/(double) TIME_FOR_COMPARE*rnd_records <
(best_key->is_for_hash_join() ? best_time :
@@ -7467,6 +7624,13 @@ best_access_path(JOIN *join,
join->outer_join)));
spl_plan= 0;
}
+ trace_access_scan.add("chosen", best_key == NULL);
+ }
+ else
+ {
+ trace_access_scan.add("type", "scan");
+ trace_access_scan.add("chosen", false);
+ trace_access_scan.add("cause", "cost");
}
/* Update the cost information for the current partial plan */
@@ -7485,7 +7649,10 @@ best_access_path(JOIN *join,
idx == join->const_tables &&
s->table == join->sort_by_table &&
join->unit->select_limit_cnt >= records)
+ {
+ trace_access_scan.add("use_tmp_table", true);
join->sort_by_table= (TABLE*) 1; // Must use temporary table
+ }
DBUG_VOID_RETURN;
}
@@ -7628,6 +7795,7 @@ choose_plan(JOIN *join, table_map join_tables)
uint use_cond_selectivity=
join->thd->variables.optimizer_use_condition_selectivity;
bool straight_join= MY_TEST(join->select_options & SELECT_STRAIGHT_JOIN);
+ THD *thd= join->thd;
DBUG_ENTER("choose_plan");
join->cur_embedding_map= 0;
@@ -7664,6 +7832,9 @@ choose_plan(JOIN *join, table_map join_tables)
join->table_count - join->const_tables, sizeof(JOIN_TAB*),
jtab_sort_func, (void*)join->emb_sjm_nest);
+ Json_writer_object wrapper(thd);
+ Json_writer_array trace_plan(thd,"considered_execution_plans");
+
if (!join->emb_sjm_nest)
{
choose_initial_table_order(join);
@@ -7957,9 +8128,16 @@ optimize_straight_join(JOIN *join, table_map join_tables)
uint use_cond_selectivity=
join->thd->variables.optimizer_use_condition_selectivity;
POSITION loose_scan_pos;
+ THD *thd= join->thd;
for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
{
+ Json_writer_object trace_one_table(thd);
+ if (unlikely(thd->trace_started()))
+ {
+ trace_plan_prefix(join, idx, join_tables);
+ trace_one_table.add_table_name(s);
+ }
/* Find the best access method from 's' to the current partial plan */
best_access_path(join, s, join_tables, idx, disable_jbuf, record_count,
join->positions + idx, &loose_scan_pos);
@@ -8688,6 +8866,18 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
}
+static void trace_plan_prefix(JOIN *join, uint idx, table_map remaining_tables)
+{
+ THD *const thd = join->thd;
+ Json_writer_array plan_prefix(thd, "plan_prefix");
+ for (uint i = 0; i < idx; i++)
+ {
+ TABLE_LIST *const tr = join->positions[i].table->tab_list;
+ if (!(tr->map & remaining_tables))
+ plan_prefix.add_table_name(join->positions[i].table);
+ }
+}
+
/**
Find a good, possibly optimal, query execution plan (QEP) by a possibly
exhaustive search.
@@ -8865,6 +9055,13 @@ best_extension_by_limited_search(JOIN *join,
double current_record_count, current_read_time;
POSITION *position= join->positions + idx;
+ Json_writer_object trace_one_table(thd);
+ if (unlikely(thd->trace_started()))
+ {
+ trace_plan_prefix(join, idx, remaining_tables);
+ trace_one_table.add_table_name(s);
+ }
+
/* Find the best access method from 's' to the current partial plan */
POSITION loose_scan_pos;
best_access_path(join, s, remaining_tables, idx, disable_jbuf,
@@ -8878,6 +9075,9 @@ best_extension_by_limited_search(JOIN *join,
current_read_time=read_time + position->read_time +
current_record_count / (double) TIME_FOR_COMPARE;
+ /*
+ TODO add filtering estimates here
+ */
advance_sj_state(join, remaining_tables, idx, &current_record_count,
&current_read_time, &loose_scan_pos);
@@ -8889,6 +9089,7 @@ best_extension_by_limited_search(JOIN *join,
read_time,
current_read_time,
"prune_by_cost"););
+ trace_one_table.add("pruned_by_cost", true);
restore_prev_nj_state(s);
restore_prev_sj_state(remaining_tables, s, idx);
continue;
@@ -8922,6 +9123,7 @@ best_extension_by_limited_search(JOIN *join,
read_time,
current_read_time,
"pruned_by_heuristic"););
+ trace_one_table.add("pruned_by_heuristic", true);
restore_prev_nj_state(s);
restore_prev_sj_state(remaining_tables, s, idx);
continue;
@@ -8939,6 +9141,7 @@ best_extension_by_limited_search(JOIN *join,
if ( (search_depth > 1) && (remaining_tables & ~real_table_bit) & allowed_tables )
{ /* Recursively expand the current partial plan */
swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
+ Json_writer_array trace_rest(thd, "rest_of_plan");
if (best_extension_by_limited_search(join,
remaining_tables & ~real_table_bit,
idx + 1,
@@ -10540,23 +10743,40 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
there inside the triggers.
*/
{ // Check const tables
- join->exec_const_cond=
- make_cond_for_table(thd, cond,
+ Item* const_cond= NULL;
+ const_cond= make_cond_for_table(thd, cond,
join->const_table_map,
(table_map) 0, -1, FALSE, FALSE);
/* Add conditions added by add_not_null_conds(). */
for (uint i= 0 ; i < join->const_tables ; i++)
- add_cond_and_fix(thd, &join->exec_const_cond,
+ add_cond_and_fix(thd, &const_cond,
join->join_tab[i].select_cond);
- DBUG_EXECUTE("where",print_where(join->exec_const_cond,"constants",
+ DBUG_EXECUTE("where",print_where(const_cond,"constants",
QT_ORDINARY););
- if (join->exec_const_cond && !join->exec_const_cond->is_expensive() &&
- !join->exec_const_cond->val_int())
+
+ if (const_cond)
{
- DBUG_PRINT("info",("Found impossible WHERE condition"));
- join->exec_const_cond= NULL;
- DBUG_RETURN(1); // Impossible const condition
+ Json_writer_object trace_const_cond(thd);
+ trace_const_cond.add("condition_on_constant_tables", const_cond);
+ if (const_cond->is_expensive())
+ {
+ trace_const_cond.add("evalualted", "false")
+ .add("cause", "expensive cond");
+ }
+ else
+ {
+ const bool const_cond_result = const_cond->val_int() != 0;
+ if (!const_cond_result)
+ {
+ DBUG_PRINT("info",("Found impossible WHERE condition"));
+ trace_const_cond.add("evalualted", "true")
+ .add("found", "impossible where");
+ join->exec_const_cond= NULL;
+ DBUG_RETURN(1);
+ }
+ }
+ join->exec_const_cond= const_cond;
}
if (join->table_count != join->const_tables)
@@ -10593,6 +10813,11 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
/*
Step #2: Extract WHERE/ON parts
*/
+ Json_writer_object trace_wrapper(thd);
+ Json_writer_object trace_conditions(thd, "attaching_conditions_to_tables");
+ trace_conditions.add("original_condition", cond);
+ Json_writer_array trace_attached_comp(thd,
+ "attached_conditions_computation");
uint i;
for (i= join->top_join_tab_count - 1; i >= join->const_tables; i--)
{
@@ -10655,10 +10880,19 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
(!is_hash_join_key_no(tab->ref.key) &&
tab->table->intersect_keys.is_set(tab->ref.key))))
{
- /* Range uses longer key; Use this instead of ref on key */
- tab->type=JT_ALL;
- use_quick_range=1;
- tab->use_quick=1;
+ /* Range uses longer key; Use this instead of ref on key */
+
+ /*
+ We can trace here, changing ref access to range access here
+ have a range that uses longer key.
+ Lets take @spetrunia's opinion
+ */
+ Json_writer_object ref_to_range(thd);
+ ref_to_range.add("ref_to_range", true);
+ ref_to_range.add("cause", "range uses longer key");
+ tab->type=JT_ALL;
+ use_quick_range=1;
+ tab->use_quick=1;
tab->ref.key= -1;
tab->ref.key_parts=0; // Don't use ref key.
join->best_positions[i].records_read= rows2double(tab->quick->records);
@@ -11096,6 +11330,20 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
if (!tab->bush_children)
i++;
}
+
+ trace_attached_comp.end();
+ Json_writer_array trace_attached_summary(thd,
+ "attached_conditions_summary");
+ for (tab= first_depth_first_tab(join); tab;
+ tab= next_depth_first_tab(join, tab))
+ {
+ if (!tab->table)
+ continue;
+ Item *const cond = tab->select_cond;
+ Json_writer_object trace_one_table(thd);
+ trace_one_table.add_table_name(tab);
+ trace_one_table.add("attached", cond);
+ }
}
DBUG_RETURN(0);
}
@@ -16021,12 +16269,24 @@ optimize_cond(JOIN *join, COND *conds,
that occurs in a function set a pointer to the multiple equality
predicate. Substitute a constant instead of this field if the
multiple equality contains a constant.
- */
+ */
+
+ Json_writer_object trace_wrapper(thd);
+ Json_writer_object trace_cond(thd, "condition_processing");
+ trace_cond.add("condition", join->conds == conds ? "WHERE" : "HAVING")
+ .add("original_condition", conds);
+
+ Json_writer_array trace_steps(thd, "steps");
DBUG_EXECUTE("where", print_where(conds, "original", QT_ORDINARY););
conds= build_equal_items(join, conds, NULL, join_list,
ignore_on_conds, cond_equal,
MY_TEST(flags & OPT_LINK_EQUAL_FIELDS));
DBUG_EXECUTE("where",print_where(conds,"after equal_items", QT_ORDINARY););
+ {
+ Json_writer_object equal_prop_wrapper(thd);
+ equal_prop_wrapper.add("transformation", "equality_propagation")
+ .add("resulting_condition", conds);
+ }
/* change field = field to field = const for each found field = const */
propagate_cond_constants(thd, (I_List<COND_CMP> *) 0, conds, conds);
@@ -16035,10 +16295,21 @@ optimize_cond(JOIN *join, COND *conds,
Remove all and-levels where CONST item != CONST item
*/
DBUG_EXECUTE("where",print_where(conds,"after const change", QT_ORDINARY););
+ {
+ Json_writer_object const_prop_wrapper(thd);
+ const_prop_wrapper.add("transformation", "constant_propagation")
+ .add("resulting_condition", conds);
+ }
conds= conds->remove_eq_conds(thd, cond_value, true);
if (conds && conds->type() == Item::COND_ITEM &&
((Item_cond*) conds)->functype() == Item_func::COND_AND_FUNC)
*cond_equal= &((Item_cond_and*) conds)->m_cond_equal;
+
+ {
+ Json_writer_object cond_removal_wrapper(thd);
+ cond_removal_wrapper.add("transformation", "trivial_condition_removal")
+ .add("resulting_condition", conds);
+ }
DBUG_EXECUTE("info",print_where(conds,"after remove", QT_ORDINARY););
}
DBUG_RETURN(conds);
@@ -26171,7 +26442,8 @@ void TABLE_LIST::print(THD *thd, table_map eliminated_tables, String *str,
// A view
if (!(belong_to_view &&
- belong_to_view->compact_view_format))
+ belong_to_view->compact_view_format) &&
+ !(query_type & QT_ITEM_IDENT_SKIP_DB_NAMES))
{
append_identifier(thd, str, &view_db);
str->append('.');
@@ -26200,7 +26472,8 @@ void TABLE_LIST::print(THD *thd, table_map eliminated_tables, String *str,
// A normal table
if (!(belong_to_view &&
- belong_to_view->compact_view_format))
+ belong_to_view->compact_view_format) &&
+ !(query_type & QT_ITEM_IDENT_SKIP_DB_NAMES))
{
append_identifier(thd, str, &db);
str->append('.');
@@ -26935,6 +27208,12 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
bool group= join && join->group && order == join->group_list;
ha_rows refkey_rows_estimate= table->quick_condition_rows;
const bool has_limit= (select_limit_arg != HA_POS_ERROR);
+ THD* thd= join ? join->thd : table->in_use;
+
+ Json_writer_object trace_wrapper(thd);
+ Json_writer_object trace_cheaper_ordering(
+ thd, "reconsidering_access_paths_for_index_ordering");
+ trace_cheaper_ordering.add("clause", group ? "GROUP BY" : "ORDER BY");
/*
If not used with LIMIT, only use keys if the whole query can be
@@ -26973,11 +27252,12 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
else
read_time= table->file->scan_time();
+ trace_cheaper_ordering.add("fanout", fanout);
/*
TODO: add cost of sorting here.
*/
read_time += COST_EPS;
-
+ trace_cheaper_ordering.add("read_time", read_time);
/*
Calculate the selectivity of the ref_key for REF_ACCESS. For
RANGE_ACCESS we use table->quick_condition_rows.
@@ -26994,11 +27274,20 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
set_if_bigger(refkey_rows_estimate, 1);
}
+ if (tab)
+ trace_cheaper_ordering.add_table_name(tab);
+ else
+ trace_cheaper_ordering.add_table_name(table);
+ trace_cheaper_ordering.add("rows_estimation", refkey_rows_estimate);
+
+ Json_writer_array possible_keys(thd,"possible_keys");
for (nr=0; nr < table->s->keys ; nr++)
{
int direction;
ha_rows select_limit= select_limit_arg;
uint used_key_parts= 0;
+ Json_writer_object possible_key(thd);
+ possible_key.add("index", table->key_info[nr].name);
if (keys.is_set(nr) &&
(direction= test_if_order_by_key(join, order, table, nr,
@@ -27011,6 +27300,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
*/
DBUG_ASSERT (ref_key != (int) nr);
+ possible_key.add("can_resolve_order", true);
bool is_covering= (table->covering_keys.is_set(nr) ||
(table->file->index_flags(nr, 0, 1) &
HA_CLUSTERED_INDEX));
@@ -27141,6 +27431,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
select_limit= (ha_rows) (select_limit *
(double) table_records /
refkey_rows_estimate);
+ possible_key.add("updated_limit", select_limit);
rec_per_key= keyinfo->actual_rec_per_key(keyinfo->user_defined_key_parts-1);
set_if_bigger(rec_per_key, 1);
/*
@@ -27160,9 +27451,11 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
if (get_range_limit_read_cost(tab, table, table_records, nr,
select_limit, &range_scan_time))
{
+ possible_key.add("range_scan_time", range_scan_time);
if (range_scan_time < index_scan_time)
index_scan_time= range_scan_time;
}
+ possible_key.add("index_scan_time", index_scan_time);
if ((ref_key < 0 && (group || table->force_index || is_covering)) ||
index_scan_time < read_time)
@@ -27173,17 +27466,29 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
table->covering_keys.is_set(ref_key)) ?
refkey_rows_estimate :
HA_POS_ERROR;
- if ((is_best_covering && !is_covering) ||
- (is_covering && refkey_select_limit < select_limit))
+ if (is_best_covering && !is_covering)
+ {
+ possible_key.add("chosen", false);
+ possible_key.add("cause", "covering index already found");
+ continue;
+ }
+
+ if (is_covering && refkey_select_limit < select_limit)
+ {
+ possible_key.add("chosen", false);
+ possible_key.add("cause", "ref estimates better");
continue;
+ }
if (table->quick_keys.is_set(nr))
quick_records= table->quick_rows[nr];
+ possible_key.add("records", quick_records);
if (best_key < 0 ||
(select_limit <= MY_MIN(quick_records,best_records) ?
keyinfo->user_defined_key_parts < best_key_parts :
quick_records < best_records) ||
(!is_best_covering && is_covering))
{
+ possible_key.add("chosen", true);
best_key= nr;
best_key_parts= keyinfo->user_defined_key_parts;
if (saved_best_key_parts)
@@ -27193,8 +27498,47 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
best_key_direction= direction;
best_select_limit= select_limit;
}
+ else
+ {
+ char const *cause;
+ possible_key.add("chosen", false);
+ if (is_covering)
+ cause= "covering index already found";
+ else
+ {
+ if (select_limit <= MY_MIN(quick_records,best_records))
+ cause= "keyparts greater than the current best keyparts";
+ else
+ cause= "rows estimation greater";
+ }
+ possible_key.add("cause", cause);
+ }
+ }
+ else
+ {
+ possible_key.add("usable", false);
+ possible_key.add("cause", "cost");
}
- }
+ }
+ else
+ {
+ possible_key.add("usable", false);
+ if (!group && select_limit == HA_POS_ERROR)
+ possible_key.add("cause", "order by without limit");
+ }
+ }
+ else
+ {
+ if (keys.is_set(nr))
+ {
+ possible_key.add("can_resolve_order", false);
+ possible_key.add("cause", "order can not be resolved by key");
+ }
+ else
+ {
+ possible_key.add("can_resolve_order", false);
+ possible_key.add("cause", "not usable index for the query");
+ }
}
}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 3d2723081a3..80884d66590 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -63,6 +63,7 @@
#include "ha_partition.h"
#endif
#include "transaction.h"
+#include "opt_trace.h"
enum enum_i_s_events_fields
{
@@ -9764,6 +9765,10 @@ ST_FIELD_INFO check_constraints_fields_info[]=
OPEN_FULL_TABLE},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
};
+
+/** For creating fields of information_schema.OPTIMIZER_TRACE */
+extern ST_FIELD_INFO optimizer_trace_info[];
+
/*
Description of ST_FIELD_INFO in table.h
@@ -9816,6 +9821,8 @@ ST_SCHEMA_TABLE schema_tables[]=
OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY},
{"OPEN_TABLES", open_tables_fields_info, 0,
fill_open_tables, make_old_format, 0, -1, -1, 1, 0},
+ {"OPTIMIZER_TRACE", optimizer_trace_info, 0,
+ fill_optimizer_trace_info, NULL, NULL, -1, -1, false, 0},
{"PARAMETERS", parameters_fields_info, 0,
fill_schema_proc, 0, 0, -1, -1, 0, 0},
{"PARTITIONS", partitions_fields_info, 0,
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index 3d43c35177d..f247fb10f89 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -24,6 +24,7 @@
#include "sql_show.h" // calc_sum_of_all_status
#include "sql_select.h"
#include "keycaches.h"
+#include "my_json_writer.h"
#include <hash.h>
#include <thr_alarm.h>
#if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_H)
@@ -36,6 +37,8 @@
#include "events.h"
#endif
+#define FT_KEYPART (MAX_FIELDS+10)
+
static const char *lock_descriptions[] =
{
/* TL_UNLOCK */ "No lock",
@@ -225,8 +228,6 @@ TEST_join(JOIN *join)
}
-#define FT_KEYPART (MAX_FIELDS+10)
-
static void print_keyuse(KEYUSE *keyuse)
{
char buff[256];
@@ -263,7 +264,6 @@ void print_keyuse_array(DYNAMIC_ARRAY *keyuse_array)
DBUG_UNLOCK_FILE;
}
-
/*
Print the current state during query optimization.
@@ -655,3 +655,24 @@ Memory allocated by threads: %s\n",
puts("");
fflush(stdout);
}
+
+void print_keyuse_array_for_trace(THD *thd, DYNAMIC_ARRAY *keyuse_array)
+{
+ Json_writer_object wrapper(thd);
+ Json_writer_array trace_key_uses(thd, "ref_optimizer_key_uses");
+ for(uint i=0; i < keyuse_array->elements; i++)
+ {
+ KEYUSE *keyuse= (KEYUSE*)dynamic_array_ptr(keyuse_array, i);
+ Json_writer_object keyuse_elem(thd);
+ keyuse_elem.add_table_name(keyuse->table->reginfo.join_tab);
+ keyuse_elem.add("field", (keyuse->keypart == FT_KEYPART) ? "<fulltext>"
+ : (keyuse->is_for_hash_join()
+ ? keyuse->table->field[keyuse->keypart]
+ ->field_name.str
+ : keyuse->table->key_info[keyuse->key]
+ .key_part[keyuse->keypart]
+ .field->field_name.str));
+ keyuse_elem.add("equals",keyuse->val);
+ keyuse_elem.add("null_rejecting",keyuse->null_rejecting);
+ }
+}
diff --git a/sql/sql_test.h b/sql/sql_test.h
index 867582a9569..cbef581b784 100644
--- a/sql/sql_test.h
+++ b/sql/sql_test.h
@@ -17,6 +17,7 @@
#define SQL_TEST_INCLUDED
#include "mysqld.h"
+#include "opt_trace_context.h"
class JOIN;
struct TABLE_LIST;
@@ -34,6 +35,7 @@ void print_keyuse_array(DYNAMIC_ARRAY *keyuse_array);
void print_sjm(SJ_MATERIALIZATION_INFO *sjm);
void dump_TABLE_LIST_graph(SELECT_LEX *select_lex, TABLE_LIST* tl);
#endif
+void print_keyuse_array_for_trace(THD *thd, DYNAMIC_ARRAY *keyuse_array);
void mysql_print_status();
#endif /* SQL_TEST_INCLUDED */
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 5f53c5f4aae..3eb7d39742c 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -2435,6 +2435,12 @@ public:
length(0); // safety
}
int save_in_field(Field *field, uint decimals) const;
+ Datetime to_datetime(THD *thd) const
+ {
+ return is_zero_datetime() ?
+ Datetime() :
+ Datetime(thd, Timestamp_or_zero_datetime(*this).tv());
+ }
bool is_zero_datetime() const
{
return length() == 0;
@@ -2459,7 +2465,7 @@ public:
Datetime to_datetime(THD *thd) const
{
return is_null() ? Datetime() :
- Datetime(thd, Timestamp_or_zero_datetime(*this).tv());
+ Timestamp_or_zero_datetime_native::to_datetime(thd);
}
void to_TIME(THD *thd, MYSQL_TIME *to)
{
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index e475a3d3719..31032c5cd5e 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -36,6 +36,7 @@
#include "datadict.h" // dd_frm_is_view()
#include "sql_derived.h"
#include "sql_cte.h" // check_dependencies_in_with_clauses()
+#include "opt_trace.h"
#define MD5_BUFF_LENGTH 33
@@ -1420,6 +1421,15 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
goto err;
/*
+ Check rights to run commands which show underlying tables.
+ In the optimizer trace we would not like to show trace for
+ cases when the current user does not have rights for the
+ underlying tables.
+ */
+ if (!table->prelocking_placeholder)
+ opt_trace_disable_if_no_view_access(thd, table, view_tables);
+
+ /*
Check rights to run commands (ANALYZE SELECT, EXPLAIN SELECT &
SHOW CREATE) which show underlying tables.
Skip this step if we are opening view for prelocking only.
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 7241685fb61..a8b557c90c8 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -53,6 +53,7 @@
#include <myisam.h>
#include "debug_sync.h" // DEBUG_SYNC
#include "sql_show.h"
+#include "opt_trace_context.h"
#include "log_event.h"
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
@@ -2542,6 +2543,23 @@ static Sys_var_flagset Sys_optimizer_switch(
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
ON_UPDATE(fix_optimizer_switch));
+static Sys_var_flagset Sys_optimizer_trace(
+ "optimizer_trace",
+ "Controls tracing of the Optimizer:"
+ " optimizer_trace=option=val[,option=val...], where option is one of"
+ " {enabled}"
+ " and val is one of {on, off, default}",
+ SESSION_VAR(optimizer_trace), CMD_LINE(REQUIRED_ARG),
+ Opt_trace_context::flag_names, DEFAULT(Opt_trace_context::FLAG_DEFAULT));
+ // @see set_var::is_var_optimizer_trace()
+export sys_var *Sys_optimizer_trace_ptr = &Sys_optimizer_trace;
+
+static Sys_var_ulong Sys_optimizer_trace_max_mem_size(
+ "optimizer_trace_max_mem_size",
+ "Maximum allowed size of an optimizer trace",
+ SESSION_VAR(optimizer_trace_max_mem_size), CMD_LINE(REQUIRED_ARG),
+ VALID_RANGE(0, ULONG_MAX), DEFAULT(1024 * 1024), BLOCK_SIZE(1));
+
static Sys_var_charptr Sys_pid_file(
"pid_file", "Pid file used by safe_mysqld",
READ_ONLY GLOBAL_VAR(pidfile_name_ptr), CMD_LINE(REQUIRED_ARG),
diff --git a/sql/table.cc b/sql/table.cc
index 375f7a3f65f..d5c88b226c7 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -44,6 +44,7 @@
#include "sql_cte.h"
#include "ha_sequence.h"
#include "sql_show.h"
+#include "opt_trace.h"
/* For MySQL 5.7 virtual fields */
#define MYSQL57_GENERATED_FIELD 128
@@ -5714,6 +5715,7 @@ bool TABLE_LIST::prepare_security(THD *thd)
if (prepare_view_security_context(thd))
DBUG_RETURN(TRUE);
thd->security_ctx= find_view_security_context(thd);
+ opt_trace_disable_if_no_security_context_access(thd);
while ((tbl= tb++))
{
DBUG_ASSERT(tbl->referencing_view);
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 7a9c8922296..401b40590df 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -1884,7 +1884,6 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
}
static void wsrep_TOI_end(THD *thd) {
- int ret;
wsrep_to_isolation--;
wsrep::client_state& client_state(thd->wsrep_cs());
DBUG_ASSERT(wsrep_thd_is_local_toi(thd));
@@ -1894,18 +1893,8 @@ static void wsrep_TOI_end(THD *thd) {
if (wsrep_thd_is_local_toi(thd))
{
wsrep_set_SE_checkpoint(client_state.toi_meta().gtid());
- if (thd->is_error() && !wsrep_must_ignore_error(thd))
- {
- wsrep_apply_error err;
- err.store(thd);
- client_state.leave_toi();
- }
- else
- {
- ret= client_state.leave_toi();
- }
-
- if (ret == 0)
+ int ret= client_state.leave_toi();
+ if (!ret)
{
WSREP_DEBUG("TO END: %lld", client_state.toi_meta().seqno().get());
}
diff --git a/sql/wsrep_server_state.cc b/sql/wsrep_server_state.cc
index 4571201b07d..7fe0e216f25 100644
--- a/sql/wsrep_server_state.cc
+++ b/sql/wsrep_server_state.cc
@@ -34,6 +34,7 @@ Wsrep_server_state::Wsrep_server_state(const std::string& name,
: wsrep::server_state(m_mutex,
m_cond,
m_service,
+ NULL,
name,
incoming_address,
address,
diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc
index afbcd4d6c52..103afa1c412 100644
--- a/sql/wsrep_sst.cc
+++ b/sql/wsrep_sst.cc
@@ -337,7 +337,8 @@ static int generate_binlog_index_opt_val(char** ret)
{
DBUG_ASSERT(ret);
*ret= NULL;
- if (opt_binlog_index_name) {
+ if (opt_bin_log)
+ {
*ret= strcmp(opt_binlog_index_name, "0") ?
my_strdup(opt_binlog_index_name, MYF(0)) : my_strdup("", MYF(0));
}
@@ -1293,7 +1294,9 @@ static int sst_donate_other (const char* method,
}
const char* binlog_opt= "";
+ const char* binlog_index_opt= "";
char* binlog_opt_val= NULL;
+ char* binlog_index_opt_val= NULL;
int ret;
if ((ret= generate_binlog_opt_val(&binlog_opt_val)))
@@ -1301,7 +1304,15 @@ static int sst_donate_other (const char* method,
WSREP_ERROR("sst_donate_other(): generate_binlog_opt_val() failed: %d",ret);
return ret;
}
+
+ if ((ret= generate_binlog_index_opt_val(&binlog_index_opt_val)))
+ {
+ WSREP_ERROR("sst_prepare_other(): generate_binlog_index_opt_val() failed %d",
+ ret);
+ }
+
if (strlen(binlog_opt_val)) binlog_opt= WSREP_SST_OPT_BINLOG;
+ if (strlen(binlog_index_opt_val)) binlog_index_opt= WSREP_SST_OPT_BINLOG_INDEX;
make_wsrep_defaults_file();
@@ -1315,15 +1326,18 @@ static int sst_donate_other (const char* method,
WSREP_SST_OPT_DATA " '%s' "
" %s "
" %s '%s' "
+ " %s '%s' "
WSREP_SST_OPT_GTID " '%s:%lld' "
WSREP_SST_OPT_GTID_DOMAIN_ID " '%d'"
"%s",
method, addr, mysqld_unix_port, mysql_real_data_home,
wsrep_defaults_file,
binlog_opt, binlog_opt_val,
+ binlog_index_opt, binlog_index_opt_val,
uuid_oss.str().c_str(), gtid.seqno().get(), wsrep_gtid_domain_id,
bypass ? " " WSREP_SST_OPT_BYPASS : "");
my_free(binlog_opt_val);
+ my_free(binlog_index_opt_val);
if (ret < 0 || ret >= cmd_len)
{
@@ -1397,4 +1411,3 @@ int wsrep_sst_donate(const std::string& msg,
return (ret >= 0 ? 0 : 1);
}
-
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
index 1b3ea2eb487..29696f96aa0 100644
--- a/storage/innobase/btr/btr0btr.cc
+++ b/storage/innobase/btr/btr0btr.cc
@@ -2,7 +2,7 @@
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2014, 2018, MariaDB Corporation.
+Copyright (c) 2014, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -225,7 +225,7 @@ btr_root_block_get(
buf_block_t* block = btr_block_get(
page_id_t(index->table->space_id, index->page),
- page_size_t(index->table->space->flags), mode,
+ index->table->space->zip_size(), mode,
index, mtr);
if (!block) {
@@ -363,7 +363,7 @@ btr_root_adjust_on_import(
page_zip_des_t* page_zip;
dict_table_t* table = index->table;
const page_id_t page_id(table->space_id, index->page);
- const page_size_t page_size(table->space->flags);
+ const ulint zip_size = table->space->zip_size();
DBUG_EXECUTE_IF("ib_import_trigger_corruption_3",
return(DB_CORRUPTION););
@@ -372,7 +372,7 @@ btr_root_adjust_on_import(
mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO);
- block = btr_block_get(page_id, page_size, RW_X_LATCH, index, &mtr);
+ block = btr_block_get(page_id, zip_size, RW_X_LATCH, index, &mtr);
page = buf_block_get_frame(block);
page_zip = buf_block_get_page_zip(block);
@@ -474,7 +474,7 @@ btr_page_alloc_for_ibuf(
new_block = buf_page_get(
page_id_t(index->table->space_id, node_addr.page),
- page_size_t(index->table->space->flags),
+ index->table->space->zip_size(),
RW_X_LATCH, mtr);
new_page = buf_block_get_frame(new_block);
@@ -928,7 +928,7 @@ btr_node_ptr_get_child(
return btr_block_get(
page_id_t(index->table->space_id,
btr_node_ptr_get_child_page_no(node_ptr, offsets)),
- page_size_t(index->table->space->flags),
+ index->table->space->zip_size(),
RW_SX_LATCH, index, mtr);
}
@@ -1137,7 +1137,7 @@ btr_free_root_invalidate(
/** Prepare to free a B-tree.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] index_id PAGE_INDEX_ID contents
@param[in,out] mtr mini-transaction
@return root block, to invoke btr_free_but_not_root() and btr_free_root()
@@ -1146,7 +1146,7 @@ static MY_ATTRIBUTE((warn_unused_result))
buf_block_t*
btr_free_root_check(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
index_id_t index_id,
mtr_t* mtr)
{
@@ -1154,7 +1154,7 @@ btr_free_root_check(
ut_ad(index_id != BTR_FREED_INDEX_ID);
buf_block_t* block = buf_page_get(
- page_id, page_size, RW_X_LATCH, mtr);
+ page_id, zip_size, RW_X_LATCH, mtr);
if (block) {
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
@@ -1368,18 +1368,18 @@ top_loop:
/** Free a persistent index tree if it exists.
@param[in] page_id root page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] index_id PAGE_INDEX_ID contents
@param[in,out] mtr mini-transaction */
void
btr_free_if_exists(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
index_id_t index_id,
mtr_t* mtr)
{
buf_block_t* root = btr_free_root_check(
- page_id, page_size, index_id, mtr);
+ page_id, zip_size, index_id, mtr);
if (root == NULL) {
return;
@@ -1392,20 +1392,15 @@ btr_free_if_exists(
btr_free_root_invalidate(root, mtr);
}
-/** Free an index tree in a temporary tablespace or during TRUNCATE TABLE.
-@param[in] page_id root page id
-@param[in] page_size page size */
-void
-btr_free(
- const page_id_t page_id,
- const page_size_t& page_size)
+/** Free an index tree in a temporary tablespace.
+@param[in] page_id root page id */
+void btr_free(const page_id_t page_id)
{
mtr_t mtr;
mtr.start();
mtr.set_log_mode(MTR_LOG_NO_REDO);
- buf_block_t* block = buf_page_get(
- page_id, page_size, RW_X_LATCH, &mtr);
+ buf_block_t* block = buf_page_get(page_id, 0, RW_X_LATCH, &mtr);
if (block) {
ut_ad(page_is_root(block->frame));
@@ -1431,7 +1426,7 @@ btr_read_autoinc(dict_index_t* index)
ib_uint64_t autoinc;
if (buf_block_t* block = buf_page_get(
page_id_t(index->table->space_id, index->page),
- page_size_t(index->table->space->flags),
+ index->table->space->zip_size(),
RW_S_LATCH, &mtr)) {
autoinc = page_get_autoinc(block->frame);
} else {
@@ -1463,7 +1458,7 @@ btr_read_autoinc_with_fallback(const dict_table_t* table, unsigned col_no)
mtr.start();
buf_block_t* block = buf_page_get(
page_id_t(index->table->space_id, index->page),
- page_size_t(index->table->space->flags),
+ index->table->space->zip_size(),
RW_S_LATCH, &mtr);
ib_uint64_t autoinc = block ? page_get_autoinc(block->frame) : 0;
@@ -1508,7 +1503,7 @@ btr_write_autoinc(dict_index_t* index, ib_uint64_t autoinc, bool reset)
fil_space_t* space = index->table->space;
mtr.set_named_space(space);
page_set_autoinc(buf_page_get(page_id_t(space->id, index->page),
- page_size_t(space->flags),
+ space->zip_size(),
RW_SX_LATCH, &mtr),
index, autoinc, &mtr, reset);
mtr.commit();
@@ -2683,12 +2678,12 @@ btr_attach_half_pages(
/* for consistency, both blocks should be locked, before change */
if (prev_page_no != FIL_NULL && direction == FSP_DOWN) {
prev_block = btr_block_get(
- page_id_t(space, prev_page_no), block->page.size,
+ page_id_t(space, prev_page_no), block->zip_size(),
RW_X_LATCH, index, mtr);
}
if (next_page_no != FIL_NULL && direction != FSP_DOWN) {
next_block = btr_block_get(
- page_id_t(space, next_page_no), block->page.size,
+ page_id_t(space, next_page_no), block->zip_size(),
RW_X_LATCH, index, mtr);
}
@@ -2838,7 +2833,7 @@ btr_insert_into_right_sibling(
const ulint space = block->page.id.space();
next_block = btr_block_get(
- page_id_t(space, next_page_no), block->page.size,
+ page_id_t(space, next_page_no), block->zip_size(),
RW_X_LATCH, cursor->index, mtr);
next_page = buf_block_get_frame(next_block);
@@ -2864,7 +2859,7 @@ btr_insert_into_right_sibling(
if (rec == NULL) {
if (is_leaf
- && next_block->page.size.is_compressed()
+ && next_block->page.zip.ssize
&& !dict_index_is_clust(cursor->index)
&& !cursor->index->table->is_temporary()) {
/* Reset the IBUF_BITMAP_FREE bits, because
@@ -2912,7 +2907,7 @@ btr_insert_into_right_sibling(
/* Update the free bits of the B-tree page in the
insert buffer bitmap. */
- if (next_block->page.size.is_compressed()) {
+ if (next_block->page.zip.ssize) {
ibuf_update_free_bits_zip(next_block, mtr);
} else {
ibuf_update_free_bits_if_full(
@@ -3357,16 +3352,16 @@ func_exit:
return(rec);
}
-/** Removes a page from the level list of pages.
+/** Remove a page from the level list of pages.
@param[in] space space where removed
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] page page to remove
@param[in] index index tree
@param[in,out] mtr mini-transaction */
void
btr_level_list_remove_func(
ulint space,
- const page_size_t& page_size,
+ ulint zip_size,
page_t* page,
dict_index_t* index,
mtr_t* mtr)
@@ -3385,7 +3380,7 @@ btr_level_list_remove_func(
if (prev_page_no != FIL_NULL) {
buf_block_t* prev_block
= btr_block_get(page_id_t(space, prev_page_no),
- page_size, RW_X_LATCH, index, mtr);
+ zip_size, RW_X_LATCH, index, mtr);
page_t* prev_page
= buf_block_get_frame(prev_block);
@@ -3403,7 +3398,7 @@ btr_level_list_remove_func(
if (next_page_no != FIL_NULL) {
buf_block_t* next_block
= btr_block_get(
- page_id_t(space, next_page_no), page_size,
+ page_id_t(space, next_page_no), zip_size,
RW_X_LATCH, index, mtr);
page_t* next_page
@@ -3774,7 +3769,7 @@ btr_compress(
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
MONITOR_INC(MONITOR_INDEX_MERGE_ATTEMPTS);
@@ -3932,7 +3927,7 @@ retry:
/* Remove the page from the level list */
btr_level_list_remove(index->table->space_id,
- page_size, page, index, mtr);
+ zip_size, page, index, mtr);
if (dict_index_is_spatial(index)) {
rec_t* my_rec = father_cursor.page_cur.rec;
@@ -4062,7 +4057,7 @@ retry:
/* Remove the page from the level list */
btr_level_list_remove(index->table->space_id,
- page_size, page, index, mtr);
+ zip_size, page, index, mtr);
ut_ad(btr_node_ptr_get_child_page_no(
btr_cur_get_rec(&father_cursor), offsets)
@@ -4170,7 +4165,7 @@ retry:
committed mini-transaction, because in crash recovery,
the free bits could momentarily be set too high. */
- if (page_size.is_compressed()) {
+ if (zip_size) {
/* Because the free bits may be incremented
and we cannot update the insert buffer bitmap
in the same mini-transaction, the only safe
@@ -4230,7 +4225,7 @@ func_exit:
err_exit:
/* We play it safe and reset the free bits. */
- if (page_size.is_compressed()
+ if (zip_size
&& merge_page
&& page_is_leaf(merge_page)
&& !dict_index_is_clust(index)) {
@@ -4405,12 +4400,12 @@ btr_discard_page(
left_page_no = btr_page_get_prev(buf_block_get_frame(block), mtr);
right_page_no = btr_page_get_next(buf_block_get_frame(block), mtr);
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
if (left_page_no != FIL_NULL) {
merge_block = btr_block_get(
page_id_t(index->table->space_id, left_page_no),
- page_size, RW_X_LATCH, index, mtr);
+ zip_size, RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
@@ -4426,7 +4421,7 @@ btr_discard_page(
} else if (right_page_no != FIL_NULL) {
merge_block = btr_block_get(
page_id_t(index->table->space_id, right_page_no),
- page_size, RW_X_LATCH, index, mtr);
+ zip_size, RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
@@ -4474,7 +4469,7 @@ btr_discard_page(
}
/* Remove the page from the level list */
- btr_level_list_remove(index->table->space_id, page_size,
+ btr_level_list_remove(index->table->space_id, zip_size,
page, index, mtr);
#ifdef UNIV_ZIP_DEBUG
@@ -5038,19 +5033,7 @@ btr_validate_level(
#endif
fil_space_t* space = index->table->space;
- const page_size_t table_page_size(
- dict_table_page_size(index->table));
- const page_size_t space_page_size(space->flags);
-
- if (!table_page_size.equals_to(space_page_size)) {
-
- ib::warn() << "Flags mismatch: table=" << index->table->flags
- << ", tablespace=" << space->flags;
-
- mtr_commit(&mtr);
-
- return(false);
- }
+ const ulint zip_size = space->zip_size();
while (level != btr_page_get_level(page)) {
const rec_t* node_ptr;
@@ -5103,7 +5086,7 @@ btr_validate_level(
block = btr_block_get(
page_id_t(index->table->space_id,
left_page_no),
- table_page_size,
+ zip_size,
RW_SX_LATCH, index, &mtr);
page = buf_block_get_frame(block);
left_page_no = btr_page_get_prev(page, &mtr);
@@ -5174,7 +5157,7 @@ loop:
right_block = btr_block_get(
page_id_t(index->table->space_id, right_page_no),
- table_page_size,
+ zip_size,
RW_SX_LATCH, index, &mtr);
right_page = buf_block_get_frame(right_block);
@@ -5352,13 +5335,13 @@ loop:
btr_block_get(
page_id_t(index->table->space_id,
parent_right_page_no),
- table_page_size,
+ zip_size,
RW_SX_LATCH, index, &mtr);
right_block = btr_block_get(
page_id_t(index->table->space_id,
right_page_no),
- table_page_size,
+ zip_size,
RW_SX_LATCH, index, &mtr);
}
@@ -5436,21 +5419,21 @@ node_ptr_fails:
page_id_t(
index->table->space_id,
parent_right_page_no),
- table_page_size,
+ zip_size,
RW_SX_LATCH, index, &mtr);
}
} else if (parent_page_no != FIL_NULL) {
btr_block_get(
page_id_t(index->table->space_id,
parent_page_no),
- table_page_size,
+ zip_size,
RW_SX_LATCH, index, &mtr);
}
}
block = btr_block_get(
page_id_t(index->table->space_id, right_page_no),
- table_page_size,
+ zip_size,
RW_SX_LATCH, index, &mtr);
page = buf_block_get_frame(block);
@@ -5556,9 +5539,9 @@ btr_can_merge_with_page(
page = btr_cur_get_page(cursor);
const page_id_t page_id(index->table->space_id, page_no);
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
- mblock = btr_block_get(page_id, page_size, RW_X_LATCH, index, mtr);
+ mblock = btr_block_get(page_id, zip_size, RW_X_LATCH, index, mtr);
mpage = buf_block_get_frame(mblock);
n_recs = page_get_n_recs(page);
@@ -5574,7 +5557,7 @@ btr_can_merge_with_page(
/* If compression padding tells us that merging will result in
too packed up page i.e.: which is likely to cause compression
failure then don't merge the pages. */
- if (page_size.is_compressed() && page_is_leaf(mpage)
+ if (zip_size && page_is_leaf(mpage)
&& (page_get_data_size(mpage) + data_size
>= dict_index_zip_pad_optimal_page_size(index))) {
diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc
index 09f31259e8e..9cad745aa0d 100644
--- a/storage/innobase/btr/btr0bulk.cc
+++ b/storage/innobase/btr/btr0bulk.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2018, MariaDB Corporation.
+Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -121,7 +121,7 @@ PageBulk::init()
} else {
new_block = btr_block_get(
page_id_t(m_index->table->space_id, m_page_no),
- page_size_t(m_index->table->space->flags),
+ m_index->table->space->zip_size(),
RW_X_LATCH, m_index, &m_mtr);
new_page = buf_block_get_frame(new_block);
@@ -589,8 +589,9 @@ PageBulk::needExt(
const dtuple_t* tuple,
ulint rec_size)
{
- return(page_zip_rec_needs_ext(rec_size, m_is_comp,
- dtuple_get_n_fields(tuple), m_block->page.size));
+ return page_zip_rec_needs_ext(rec_size, m_is_comp,
+ dtuple_get_n_fields(tuple),
+ m_block->zip_size());
}
/** Store external record
@@ -664,7 +665,7 @@ PageBulk::latch()
__FILE__, __LINE__, &m_mtr)) {
m_block = buf_page_get_gen(
page_id_t(m_index->table->space_id, m_page_no),
- page_size_t(m_index->table->space->flags),
+ m_index->table->space->zip_size(),
RW_X_LATCH, m_block, BUF_GET_IF_IN_POOL,
__FILE__, __LINE__, &m_mtr, &m_err);
@@ -1017,7 +1018,7 @@ BtrBulk::finish(dberr_t err)
ut_ad(last_page_no != FIL_NULL);
last_block = btr_block_get(
page_id_t(m_index->table->space_id, last_page_no),
- page_size_t(m_index->table->space->flags),
+ m_index->table->space->zip_size(),
RW_X_LATCH, m_index, &mtr);
first_rec = page_rec_get_next(
page_get_infimum_rec(last_block->frame));
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index f4cbb4e51a3..59704201c4e 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -210,6 +210,7 @@ btr_rec_free_externally_stored_fields(
/** Latches the leaf page or pages requested.
@param[in] block leaf page where the search converged
@param[in] page_id page id of the leaf
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] latch_mode BTR_SEARCH_LEAF, ...
@param[in] cursor cursor
@param[in] mtr mini-transaction
@@ -218,7 +219,7 @@ btr_latch_leaves_t
btr_cur_latch_leaves(
buf_block_t* block,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint latch_mode,
btr_cur_t* cursor,
mtr_t* mtr)
@@ -249,7 +250,7 @@ btr_cur_latch_leaves(
mode = latch_mode == BTR_MODIFY_LEAF ? RW_X_LATCH : RW_S_LATCH;
latch_leaves.savepoints[1] = mtr_set_savepoint(mtr);
- get_block = btr_block_get(page_id, page_size, mode,
+ get_block = btr_block_get(page_id, zip_size, mode,
cursor->index, mtr);
latch_leaves.blocks[1] = get_block;
#ifdef UNIV_BTR_DEBUG
@@ -282,7 +283,7 @@ btr_cur_latch_leaves(
latch_leaves.savepoints[0] = mtr_set_savepoint(mtr);
get_block = btr_block_get(
page_id_t(page_id.space(), left_page_no),
- page_size, RW_X_LATCH, cursor->index, mtr);
+ zip_size, RW_X_LATCH, cursor->index, mtr);
latch_leaves.blocks[0] = get_block;
if (spatial) {
@@ -298,7 +299,7 @@ btr_cur_latch_leaves(
latch_leaves.savepoints[1] = mtr_set_savepoint(mtr);
get_block = btr_block_get(
- page_id, page_size, RW_X_LATCH, cursor->index, mtr);
+ page_id, zip_size, RW_X_LATCH, cursor->index, mtr);
latch_leaves.blocks[1] = get_block;
#ifdef UNIV_BTR_DEBUG
@@ -329,7 +330,7 @@ btr_cur_latch_leaves(
latch_leaves.savepoints[2] = mtr_set_savepoint(mtr);
get_block = btr_block_get(
page_id_t(page_id.space(), right_page_no),
- page_size, RW_X_LATCH, cursor->index, mtr);
+ zip_size, RW_X_LATCH, cursor->index, mtr);
latch_leaves.blocks[2] = get_block;
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame)
@@ -357,7 +358,7 @@ btr_cur_latch_leaves(
latch_leaves.savepoints[0] = mtr_set_savepoint(mtr);
get_block = btr_block_get(
page_id_t(page_id.space(), left_page_no),
- page_size, mode, cursor->index, mtr);
+ zip_size, mode, cursor->index, mtr);
latch_leaves.blocks[0] = get_block;
cursor->left_block = get_block;
#ifdef UNIV_BTR_DEBUG
@@ -369,7 +370,7 @@ btr_cur_latch_leaves(
}
latch_leaves.savepoints[1] = mtr_set_savepoint(mtr);
- get_block = btr_block_get(page_id, page_size, mode,
+ get_block = btr_block_get(page_id, zip_size, mode,
cursor->index, mtr);
latch_leaves.blocks[1] = get_block;
#ifdef UNIV_BTR_DEBUG
@@ -509,7 +510,7 @@ incompatible:
buf_block_t* block = buf_page_get(
page_id_t(space->id,
mach_read_from_4(ptr + BTR_EXTERN_PAGE_NO)),
- univ_page_size, RW_S_LATCH, mtr);
+ 0, RW_S_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE);
if (fil_page_get_type(block->frame) != FIL_PAGE_TYPE_BLOB
|| mach_read_from_4(&block->frame[FIL_PAGE_DATA
@@ -591,7 +592,7 @@ inconsistent:
} else {
col->def_val.data = btr_copy_externally_stored_field(
&col->def_val.len, data,
- cur.page_cur.block->page.size,
+ cur.page_cur.block->zip_size(),
len, index->table->heap);
}
}
@@ -756,8 +757,7 @@ btr_cur_optimistic_latch_leaves(
cursor->left_block = btr_block_get(
page_id_t(cursor->index->table->space_id,
left_page_no),
- page_size_t(cursor->index->table->space
- ->flags),
+ cursor->index->table->space->zip_size(),
mode, cursor->index, mtr);
} else {
cursor->left_block = NULL;
@@ -865,7 +865,7 @@ btr_cur_latch_for_root_leaf(
@param[in] lock_intention lock intention for the tree operation
@param[in] rec record (current node_ptr)
@param[in] rec_size size of the record or max size of node_ptr
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] mtr mtr
@return true if tree modification is needed */
static
@@ -876,7 +876,7 @@ btr_cur_will_modify_tree(
btr_intention_t lock_intention,
const rec_t* rec,
ulint rec_size,
- const page_size_t& page_size,
+ ulint zip_size,
mtr_t* mtr)
{
ut_ad(!page_is_leaf(page));
@@ -964,9 +964,8 @@ btr_cur_will_modify_tree(
This is based on the worst case, and we could invoke
page_zip_available() on the block->page.zip. */
/* needs 2 records' space also for worst compress rate. */
- if (page_size.is_compressed()
- && page_zip_empty_size(index->n_fields,
- page_size.physical())
+ if (zip_size
+ && page_zip_empty_size(index->n_fields, zip_size)
<= rec_size * 2 + page_get_data_size(page)
+ page_dir_calc_reserved_space(n_recs + 2)) {
return(true);
@@ -1462,7 +1461,7 @@ btr_cur_search_to_nth_level_func(
page_cursor = btr_cur_get_page_cur(cursor);
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
/* Start with the root page. */
page_id_t page_id(index->table->space_id, index->page);
@@ -1545,7 +1544,7 @@ search_loop:
retry_page_get:
ut_ad(n_blocks < BTR_MAX_LEVELS);
tree_savepoints[n_blocks] = mtr_set_savepoint(mtr);
- block = buf_page_get_gen(page_id, page_size, rw_latch, guess,
+ block = buf_page_get_gen(page_id, zip_size, rw_latch, guess,
buf_mode, file, line, mtr, &err);
tree_blocks[n_blocks] = block;
@@ -1581,7 +1580,7 @@ retry_page_get:
ut_ad(!dict_index_is_spatial(index));
if (ibuf_insert(IBUF_OP_INSERT, tuple, index,
- page_id, page_size, cursor->thr)) {
+ page_id, zip_size, cursor->thr)) {
cursor->flag = BTR_CUR_INSERT_TO_IBUF;
@@ -1594,7 +1593,7 @@ retry_page_get:
ut_ad(!dict_index_is_spatial(index));
if (ibuf_insert(IBUF_OP_DELETE_MARK, tuple,
- index, page_id, page_size,
+ index, page_id, zip_size,
cursor->thr)) {
cursor->flag = BTR_CUR_DEL_MARK_IBUF;
@@ -1614,7 +1613,7 @@ retry_page_get:
/* The record cannot be purged yet. */
cursor->flag = BTR_CUR_DELETE_REF;
} else if (ibuf_insert(IBUF_OP_DELETE, tuple,
- index, page_id, page_size,
+ index, page_id, zip_size,
cursor->thr)) {
/* The purge was buffered. */
@@ -1661,7 +1660,7 @@ retry_page_get:
= mtr_set_savepoint(mtr);
get_block = buf_page_get_gen(
page_id_t(page_id.space(), left_page_no),
- page_size, rw_latch, NULL, buf_mode,
+ zip_size, rw_latch, NULL, buf_mode,
file, line, mtr, &err);
prev_tree_blocks[prev_n_blocks] = get_block;
prev_n_blocks++;
@@ -1691,7 +1690,7 @@ retry_page_get:
tree_blocks[n_blocks]);
tree_savepoints[n_blocks] = mtr_set_savepoint(mtr);
- block = buf_page_get_gen(page_id, page_size, rw_latch, NULL,
+ block = buf_page_get_gen(page_id, zip_size, rw_latch, NULL,
buf_mode, file, line, mtr, &err);
tree_blocks[n_blocks] = block;
@@ -1789,7 +1788,7 @@ retry_page_get:
if (rw_latch == RW_NO_LATCH) {
latch_leaves = btr_cur_latch_leaves(
- block, page_id, page_size, latch_mode,
+ block, page_id, zip_size, latch_mode,
cursor, mtr);
}
@@ -2153,7 +2152,7 @@ need_opposite_intention:
&& latch_mode == BTR_MODIFY_TREE
&& !btr_cur_will_modify_tree(
index, page, lock_intention, node_ptr,
- node_ptr_max_size, page_size, mtr)
+ node_ptr_max_size, zip_size, mtr)
&& !rtree_parent_modified) {
ut_ad(upper_rw_latch == RW_X_LATCH);
ut_ad(n_releases <= n_blocks);
@@ -2351,12 +2350,12 @@ need_opposite_intention:
if (latch_mode == BTR_CONT_MODIFY_TREE) {
child_block = btr_block_get(
- page_id, page_size, RW_X_LATCH,
+ page_id, zip_size, RW_X_LATCH,
index, mtr);
} else {
ut_ad(latch_mode == BTR_CONT_SEARCH_TREE);
child_block = btr_block_get(
- page_id, page_size, RW_SX_LATCH,
+ page_id, zip_size, RW_SX_LATCH,
index, mtr);
}
@@ -2574,7 +2573,7 @@ btr_cur_open_at_index_side_func(
cursor->index = index;
page_id_t page_id(index->table->space_id, index->page);
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
if (root_leaf_rw_latch == RW_X_LATCH) {
node_ptr_max_size = btr_node_ptr_max_size(index);
@@ -2597,7 +2596,7 @@ btr_cur_open_at_index_side_func(
}
tree_savepoints[n_blocks] = mtr_set_savepoint(mtr);
- block = buf_page_get_gen(page_id, page_size, rw_latch, NULL,
+ block = buf_page_get_gen(page_id, zip_size, rw_latch, NULL,
BUF_GET, file, line, mtr, &err);
ut_ad((block != NULL) == (err == DB_SUCCESS));
tree_blocks[n_blocks] = block;
@@ -2653,12 +2652,12 @@ btr_cur_open_at_index_side_func(
if (height == level) {
if (srv_read_only_mode) {
btr_cur_latch_leaves(
- block, page_id, page_size,
+ block, page_id, zip_size,
latch_mode, cursor, mtr);
} else if (height == 0) {
if (rw_latch == RW_NO_LATCH) {
btr_cur_latch_leaves(
- block, page_id, page_size,
+ block, page_id, zip_size,
latch_mode, cursor, mtr);
}
/* In versions <= 3.23.52 we had
@@ -2789,7 +2788,7 @@ btr_cur_open_at_index_side_func(
if (latch_mode == BTR_MODIFY_TREE
&& !btr_cur_will_modify_tree(
cursor->index, page, lock_intention, node_ptr,
- node_ptr_max_size, page_size, mtr)) {
+ node_ptr_max_size, zip_size, mtr)) {
ut_ad(upper_rw_latch == RW_X_LATCH);
ut_ad(n_releases <= n_blocks);
@@ -2931,7 +2930,7 @@ btr_cur_open_at_rnd_pos_func(
cursor->index = index;
page_id_t page_id(index->table->space_id, index->page);
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
dberr_t err = DB_SUCCESS;
if (root_leaf_rw_latch == RW_X_LATCH) {
@@ -2955,7 +2954,7 @@ btr_cur_open_at_rnd_pos_func(
}
tree_savepoints[n_blocks] = mtr_set_savepoint(mtr);
- block = buf_page_get_gen(page_id, page_size, rw_latch, NULL,
+ block = buf_page_get_gen(page_id, zip_size, rw_latch, NULL,
BUF_GET, file, line, mtr, &err);
tree_blocks[n_blocks] = block;
@@ -3008,7 +3007,7 @@ btr_cur_open_at_rnd_pos_func(
if (rw_latch == RW_NO_LATCH
|| srv_read_only_mode) {
btr_cur_latch_leaves(
- block, page_id, page_size,
+ block, page_id, zip_size,
latch_mode, cursor, mtr);
}
@@ -3084,7 +3083,7 @@ btr_cur_open_at_rnd_pos_func(
if (latch_mode == BTR_MODIFY_TREE
&& !btr_cur_will_modify_tree(
cursor->index, page, lock_intention, node_ptr,
- node_ptr_max_size, page_size, mtr)) {
+ node_ptr_max_size, zip_size, mtr)) {
ut_ad(upper_rw_latch == RW_X_LATCH);
ut_ad(n_releases <= n_blocks);
@@ -3297,12 +3296,12 @@ btr_cur_prefetch_siblings(
if (left_page_no != FIL_NULL) {
buf_read_page_background(
page_id_t(block->page.id.space(), left_page_no),
- block->page.size, false);
+ block->zip_size(), false);
}
if (right_page_no != FIL_NULL) {
buf_read_page_background(
page_id_t(block->page.id.space(), right_page_no),
- block->page.size, false);
+ block->zip_size(), false);
}
if (left_page_no != FIL_NULL
|| right_page_no != FIL_NULL) {
@@ -3369,12 +3368,11 @@ btr_cur_optimistic_insert(
|| (flags & BTR_CREATE_FLAG));
ut_ad(dtuple_check_typed(entry));
- const page_size_t& page_size = block->page.size;
-
#ifdef UNIV_DEBUG_VALGRIND
- if (page_size.is_compressed()) {
- UNIV_MEM_ASSERT_RW(page, page_size.logical());
- UNIV_MEM_ASSERT_RW(block->page.zip.data, page_size.physical());
+ if (block->page.zip.data) {
+ UNIV_MEM_ASSERT_RW(page, srv_page_size);
+ UNIV_MEM_ASSERT_RW(block->page.zip.data,
+ block->zip_size());
}
#endif /* UNIV_DEBUG_VALGRIND */
@@ -3389,7 +3387,8 @@ btr_cur_optimistic_insert(
rec_size = rec_get_converted_size(index, entry, n_ext);
if (page_zip_rec_needs_ext(rec_size, page_is_comp(page),
- dtuple_get_n_fields(entry), page_size)) {
+ dtuple_get_n_fields(entry),
+ block->zip_size())) {
convert_big_rec:
/* The record is so big that we have to store some fields
externally on separate database pages */
@@ -3403,7 +3402,7 @@ convert_big_rec:
rec_size = rec_get_converted_size(index, entry, n_ext);
}
- if (page_size.is_compressed() && page_zip_is_too_big(index, entry)) {
+ if (block->page.zip.data && page_zip_is_too_big(index, entry)) {
if (big_rec_vec != NULL) {
dtuple_convert_back_big_rec(index, entry, big_rec_vec);
}
@@ -3414,7 +3413,7 @@ convert_big_rec:
LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page),
goto fail);
- if (leaf && page_size.is_compressed()
+ if (block->page.zip.data && leaf
&& (page_get_data_size(page) + rec_size
>= dict_index_zip_pad_optimal_page_size(index))) {
/* If compression padding tells us that insertion will
@@ -3457,7 +3456,7 @@ fail_err:
we have to split the page to reserve enough free space for
future updates of records. */
- if (leaf && !page_size.is_compressed() && dict_index_is_clust(index)
+ if (leaf && !block->page.zip.data && dict_index_is_clust(index)
&& page_get_n_recs(page) >= 2
&& dict_index_get_space_reserve() + rec_size > max_size
&& (btr_page_get_split_rec_to_right(cursor, &dummy)
@@ -3520,7 +3519,7 @@ fail_err:
}
if (*rec) {
- } else if (page_size.is_compressed()) {
+ } else if (block->page.zip.data) {
ut_ad(!index->table->is_temporary());
/* Reset the IBUF_BITMAP_FREE bits, because
page_cur_tuple_insert() will have attempted page
@@ -3596,7 +3595,7 @@ fail_err:
committed mini-transaction, because in crash recovery,
the free bits could momentarily be set too high. */
- if (page_size.is_compressed()) {
+ if (block->page.zip.data) {
/* Update the bits in the same mini-transaction. */
ibuf_update_free_bits_zip(block, mtr);
} else {
@@ -3696,7 +3695,7 @@ btr_cur_pessimistic_insert(
if (page_zip_rec_needs_ext(rec_get_converted_size(index, entry, n_ext),
index->table->not_redundant(),
dtuple_get_n_fields(entry),
- btr_cur_get_block(cursor)->page.size)
+ btr_cur_get_block(cursor)->zip_size())
|| UNIV_UNLIKELY(entry->is_alter_metadata()
&& !dfield_is_ext(
dtuple_get_nth_field(
@@ -4337,7 +4336,7 @@ static void btr_cur_trim_alter_metadata(dtuple_t* entry,
buf_block_t* block = buf_page_get(
page_id_t(index->table->space->id,
mach_read_from_4(ptr + BTR_EXTERN_PAGE_NO)),
- univ_page_size, RW_S_LATCH, &mtr);
+ 0, RW_S_LATCH, &mtr);
buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE);
ut_ad(fil_page_get_type(block->frame) == FIL_PAGE_TYPE_BLOB);
ut_ad(mach_read_from_4(&block->frame[FIL_PAGE_DATA
@@ -4570,7 +4569,7 @@ any_extern:
if (page_zip_rec_needs_ext(new_rec_size, page_is_comp(page),
dict_index_get_n_fields(index),
- block->page.size)) {
+ block->zip_size())) {
goto any_extern;
}
@@ -4749,7 +4748,8 @@ btr_cur_pess_upd_restore_supremum(
const page_id_t page_id(block->page.id.space(), prev_page_no);
ut_ad(prev_page_no != FIL_NULL);
- prev_block = buf_page_get_with_no_latch(page_id, block->page.size, mtr);
+ prev_block = buf_page_get_with_no_latch(page_id, block->zip_size(),
+ mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_next(prev_block->frame, mtr)
== page_get_page_no(page));
@@ -4938,7 +4938,7 @@ btr_cur_pessimistic_update(
rec_get_converted_size(index, new_entry, n_ext),
page_is_comp(page),
dict_index_get_n_fields(index),
- block->page.size)
+ block->zip_size())
|| (UNIV_UNLIKELY(update->is_alter_metadata())
&& !dfield_is_ext(dtuple_get_nth_field(
new_entry,
@@ -6062,7 +6062,7 @@ discard_page:
|| btr_cur_will_modify_tree(
index, page, BTR_INTENTION_DELETE, rec,
btr_node_ptr_max_size(index),
- block->page.size, mtr);
+ block->zip_size(), mtr);
page_cur_delete_rec(btr_cur_get_page_cur(cursor), index,
offsets, mtr);
#ifdef UNIV_ZIP_DEBUG
@@ -6212,7 +6212,7 @@ btr_estimate_n_rows_in_range_on_level(
const fil_space_t* space = index->table->space;
page_id_t page_id(space->id, slot1->page_no);
- const page_size_t page_size(space->flags);
+ const ulint zip_size = space->zip_size();
level = slot1->page_level;
@@ -6229,7 +6229,7 @@ btr_estimate_n_rows_in_range_on_level(
attempting to read a page that is no longer part of
the B-tree. We pass BUF_GET_POSSIBLY_FREED in order to
silence a debug assertion about this. */
- block = buf_page_get_gen(page_id, page_size, RW_S_LATCH,
+ block = buf_page_get_gen(page_id, zip_size, RW_S_LATCH,
NULL, BUF_GET_POSSIBLY_FREED,
__FILE__, __LINE__, &mtr, &err);
@@ -7450,7 +7450,7 @@ struct btr_blob_log_check_t {
mtr_x_lock(dict_index_get_lock(index), m_mtr);
m_pcur->btr_cur.page_cur.block = btr_block_get(
page_id_t(index->table->space_id, page_no),
- page_size_t(index->table->space->flags),
+ index->table->space->zip_size(),
RW_X_LATCH, index, m_mtr);
m_pcur->btr_cur.page_cur.rec
= m_pcur->btr_cur.page_cur.block->frame
@@ -7538,9 +7538,6 @@ btr_store_big_rec_extern_fields(
ut_ad(buf_block_get_frame(rec_block) == page_align(rec));
ut_a(dict_index_is_clust(index));
- ut_ad(dict_table_page_size(index->table)
- .equals_to(rec_block->page.size));
-
btr_blob_log_check_t redo_log(pcur, btr_mtr, offsets, &rec_block,
&rec, op);
page_zip = buf_block_get_page_zip(rec_block);
@@ -7585,7 +7582,7 @@ btr_store_big_rec_extern_fields(
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
/* Space available in compressed page to carry blob data */
- const ulint payload_size_zip = rec_block->page.size.physical()
+ const ulint payload_size_zip = rec_block->physical_size()
- FIL_PAGE_DATA;
/* Space available in uncompressed page to carry blob data */
@@ -7646,7 +7643,7 @@ btr_store_big_rec_extern_fields(
mtr.set_flush_observer(btr_mtr->get_flush_observer());
buf_page_get(rec_block->page.id,
- rec_block->page.size, RW_X_LATCH, &mtr);
+ rec_block->zip_size(), RW_X_LATCH, &mtr);
if (prev_page_no == FIL_NULL) {
hint_page_no = 1 + rec_page_no;
@@ -7694,7 +7691,7 @@ btr_store_big_rec_extern_fields(
prev_block = buf_page_get(
page_id_t(space_id, prev_page_no),
- rec_block->page.size,
+ rec_block->zip_size(),
RW_X_LATCH, &mtr);
buf_block_dbg_add_level(prev_block,
@@ -8057,10 +8054,9 @@ btr_free_externally_stored_field(
ut_ad(space_id == index->table->space->id);
ut_ad(space_id == index->table->space_id);
- const page_size_t ext_page_size(dict_table_page_size(index->table));
- const page_size_t& rec_page_size(rec == NULL
- ? univ_page_size
- : ext_page_size);
+ const ulint ext_zip_size = index->table->space->zip_size();
+ const ulint rec_zip_size = rec ? ext_zip_size : 0;
+
if (rec == NULL) {
/* This is a call from row_purge_upd_exist_or_extern(). */
ut_ad(!page_zip);
@@ -8087,7 +8083,7 @@ btr_free_externally_stored_field(
#ifdef UNIV_DEBUG
rec_block =
#endif /* UNIV_DEBUG */
- buf_page_get(page_id, rec_page_size, RW_X_LATCH, &mtr);
+ buf_page_get(page_id, rec_zip_size, RW_X_LATCH, &mtr);
buf_block_dbg_add_level(rec_block, SYNC_NO_ORDER_CHECK);
page_no = mach_read_from_4(field_ref + BTR_EXTERN_PAGE_NO);
@@ -8113,13 +8109,13 @@ btr_free_externally_stored_field(
}
ext_block = buf_page_get(
- page_id_t(space_id, page_no), ext_page_size,
+ page_id_t(space_id, page_no), ext_zip_size,
RW_X_LATCH, &mtr);
buf_block_dbg_add_level(ext_block, SYNC_EXTERN_STORAGE);
page = buf_block_get_frame(ext_block);
- if (ext_page_size.is_compressed()) {
+ if (ext_zip_size) {
/* Note that page_zip will be NULL
in row_purge_upd_exist_or_extern(). */
switch (fil_page_get_type(page)) {
@@ -8294,7 +8290,7 @@ btr_copy_blob_prefix(
mtr_start(&mtr);
block = buf_page_get(page_id_t(space_id, page_no),
- univ_page_size, RW_S_LATCH, &mtr);
+ 0, RW_S_LATCH, &mtr);
buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE);
page = buf_block_get_frame(block);
@@ -8332,7 +8328,7 @@ by a lock or a page latch.
@param[out] buf the externally stored part of the field,
or a prefix of it
@param[in] len length of buf, in bytes
-@param[in] page_size compressed BLOB page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size
@param[in] space_id space id of the BLOB pages
@param[in] offset offset on the first BLOB page
@return number of bytes written to buf */
@@ -8341,7 +8337,7 @@ ulint
btr_copy_zblob_prefix(
byte* buf,
ulint len,
- const page_size_t& page_size,
+ ulint zip_size,
ulint space_id,
ulint page_no,
ulint offset)
@@ -8361,7 +8357,8 @@ btr_copy_zblob_prefix(
heap = mem_heap_create(40000);
page_zip_set_alloc(&d_stream, heap);
- ut_ad(page_size.is_compressed());
+ ut_ad(zip_size);
+ ut_ad(ut_is_2pow(zip_size));
ut_ad(space_id);
err = inflateInit(&d_stream);
@@ -8376,7 +8373,7 @@ btr_copy_zblob_prefix(
is being held on the clustered index record, or,
in row_merge_copy_blobs(), by an exclusive table lock. */
bpage = buf_page_get_zip(page_id_t(space_id, page_no),
- page_size);
+ zip_size);
if (UNIV_UNLIKELY(!bpage)) {
ib::error() << "Cannot load compressed BLOB "
@@ -8408,8 +8405,7 @@ btr_copy_zblob_prefix(
}
d_stream.next_in = bpage->zip.data + offset;
- d_stream.avail_in = static_cast<uInt>(page_size.physical()
- - offset);
+ d_stream.avail_in = uInt(zip_size - offset);
err = inflate(&d_stream, Z_NO_FLUSH);
switch (err) {
@@ -8479,7 +8475,7 @@ by a lock or a page latch.
@param[out] buf the externally stored part of the
field, or a prefix of it
@param[in] len length of buf, in bytes
-@param[in] page_size BLOB page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] space_id space id of the first BLOB page
@param[in] page_no page number of the first BLOB page
@param[in] offset offset on the first BLOB page
@@ -8489,7 +8485,7 @@ ulint
btr_copy_externally_stored_field_prefix_low(
byte* buf,
ulint len,
- const page_size_t& page_size,
+ ulint zip_size,
ulint space_id,
ulint page_no,
ulint offset)
@@ -8498,11 +8494,10 @@ btr_copy_externally_stored_field_prefix_low(
return(0);
}
- if (page_size.is_compressed()) {
- return(btr_copy_zblob_prefix(buf, len, page_size,
+ if (zip_size) {
+ return(btr_copy_zblob_prefix(buf, len, zip_size,
space_id, page_no, offset));
} else {
- ut_ad(page_size.equals_to(univ_page_size));
return(btr_copy_blob_prefix(buf, len, space_id,
page_no, offset));
}
@@ -8512,7 +8507,7 @@ btr_copy_externally_stored_field_prefix_low(
The clustered index record must be protected by a lock or a page latch.
@param[out] buf the field, or a prefix of it
@param[in] len length of buf, in bytes
-@param[in] page_size BLOB page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] data 'internally' stored part of the field
containing also the reference to the external part; must be protected by
a lock or a page latch
@@ -8523,7 +8518,7 @@ ulint
btr_copy_externally_stored_field_prefix(
byte* buf,
ulint len,
- const page_size_t& page_size,
+ ulint zip_size,
const byte* data,
ulint local_len)
{
@@ -8562,7 +8557,7 @@ btr_copy_externally_stored_field_prefix(
return(local_len
+ btr_copy_externally_stored_field_prefix_low(buf + local_len,
len - local_len,
- page_size,
+ zip_size,
space_id, page_no,
offset));
}
@@ -8573,7 +8568,7 @@ The clustered index record must be protected by a lock or a page latch.
@param[in] data 'internally' stored part of the field
containing also the reference to the external part; must be protected by
a lock or a page latch
-@param[in] page_size BLOB page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] local_len length of data
@param[in,out] heap mem heap
@return the whole field copied to heap */
@@ -8581,7 +8576,7 @@ byte*
btr_copy_externally_stored_field(
ulint* len,
const byte* data,
- const page_size_t& page_size,
+ ulint zip_size,
ulint local_len,
mem_heap_t* heap)
{
@@ -8612,7 +8607,7 @@ btr_copy_externally_stored_field(
*len = local_len
+ btr_copy_externally_stored_field_prefix_low(buf + local_len,
extern_len,
- page_size,
+ zip_size,
space_id,
page_no, offset);
@@ -8623,7 +8618,7 @@ btr_copy_externally_stored_field(
@param[in] rec record in a clustered index; must be
protected by a lock or a page latch
@param[in] offset array returned by rec_get_offsets()
-@param[in] page_size BLOB page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] no field number
@param[out] len length of the field
@param[in,out] heap mem heap
@@ -8632,7 +8627,7 @@ byte*
btr_rec_copy_externally_stored_field(
const rec_t* rec,
const ulint* offsets,
- const page_size_t& page_size,
+ ulint zip_size,
ulint no,
ulint* len,
mem_heap_t* heap)
@@ -8666,5 +8661,5 @@ btr_rec_copy_externally_stored_field(
}
return(btr_copy_externally_stored_field(len, data,
- page_size, local_len, heap));
+ zip_size, local_len, heap));
}
diff --git a/storage/innobase/btr/btr0defragment.cc b/storage/innobase/btr/btr0defragment.cc
index 86daa90dc0b..ffdc448a68e 100644
--- a/storage/innobase/btr/btr0defragment.cc
+++ b/storage/innobase/btr/btr0defragment.cc
@@ -167,7 +167,7 @@ btr_defragment_add_index(
// Load index rood page.
buf_block_t* block = btr_block_get(
page_id_t(index->table->space_id, index->page),
- page_size_t(index->table->space->flags),
+ index->table->space->zip_size(),
RW_NO_LATCH, index, &mtr);
page_t* page = NULL;
@@ -376,7 +376,7 @@ btr_defragment_merge_pages(
dict_index_t* index, /*!< in: index tree */
buf_block_t* from_block, /*!< in: origin of merge */
buf_block_t* to_block, /*!< in: destination of merge */
- const page_size_t page_size, /*!< in: page size of the block */
+ ulint zip_size, /*!< in: ROW_FORMAT=COMPRESSED size */
ulint reserved_space, /*!< in: space reserved for future
insert to avoid immediate page split */
ulint* max_data_size, /*!< in/out: max data size to
@@ -404,7 +404,7 @@ btr_defragment_merge_pages(
// Estimate how many records can be moved from the from_page to
// the to_page.
- if (page_size.is_compressed()) {
+ if (zip_size) {
ulint page_diff = srv_page_size - *max_data_size;
max_ins_size_to_use = (max_ins_size_to_use > page_diff)
? max_ins_size_to_use - page_diff : 0;
@@ -472,7 +472,7 @@ btr_defragment_merge_pages(
// Set ibuf free bits if necessary.
if (!dict_index_is_clust(index)
&& page_is_leaf(to_page)) {
- if (page_size.is_compressed()) {
+ if (zip_size) {
ibuf_reset_free_bits(to_block);
} else {
ibuf_update_free_bits_if_full(
@@ -489,7 +489,7 @@ btr_defragment_merge_pages(
btr_search_drop_page_hash_index(from_block);
btr_level_list_remove(
index->table->space_id,
- page_size, from_page, index, mtr);
+ zip_size, from_page, index, mtr);
btr_node_ptr_delete(index, from_block, mtr);
/* btr_blob_dbg_remove(from_page, index,
"btr_defragment_n_pages"); */
@@ -573,7 +573,7 @@ btr_defragment_n_pages(
}
first_page = buf_block_get_frame(block);
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
/* 1. Load the pages and calculate the total data size. */
blocks[0] = block;
@@ -589,7 +589,7 @@ btr_defragment_n_pages(
}
blocks[i] = btr_block_get(page_id_t(index->table->space_id,
- page_no), page_size,
+ page_no), zip_size,
RW_X_LATCH, index, mtr);
}
@@ -615,7 +615,7 @@ btr_defragment_n_pages(
optimal_page_size = page_get_free_space_of_empty(
page_is_comp(first_page));
// For compressed pages, we take compression failures into account.
- if (page_size.is_compressed()) {
+ if (zip_size) {
ulint size = 0;
uint i = 0;
// We estimate the optimal data size of the index use samples of
@@ -658,7 +658,7 @@ btr_defragment_n_pages(
// Start from the second page.
for (uint i = 1; i < n_pages; i ++) {
buf_block_t* new_block = btr_defragment_merge_pages(
- index, blocks[i], current_block, page_size,
+ index, blocks[i], current_block, zip_size,
reserved_space, &max_data_size, heap, mtr);
if (new_block != current_block) {
n_defragmented ++;
diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc
index 20cb199fbe5..f0cc6b245d4 100644
--- a/storage/innobase/btr/btr0pcur.cc
+++ b/storage/innobase/btr/btr0pcur.cc
@@ -476,7 +476,7 @@ btr_pcur_move_to_next_page(
next_block = btr_block_get(
page_id_t(block->page.id.space(), next_page_no),
- block->page.size, mode,
+ block->zip_size(), mode,
btr_pcur_get_btr_cur(cursor)->index, mtr);
if (UNIV_UNLIKELY(!next_block)) {
diff --git a/storage/innobase/btr/btr0scrub.cc b/storage/innobase/btr/btr0scrub.cc
index 7d8966d4109..a4ae24b8946 100644
--- a/storage/innobase/btr/btr0scrub.cc
+++ b/storage/innobase/btr/btr0scrub.cc
@@ -434,7 +434,7 @@ btr_pessimistic_scrub(
const ulint page_no = mach_read_from_4(page + FIL_PAGE_OFFSET);
const ulint left_page_no = mach_read_from_4(page + FIL_PAGE_PREV);
const ulint right_page_no = mach_read_from_4(page + FIL_PAGE_NEXT);
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
/**
* When splitting page, we need X-latches on left/right brothers
@@ -449,16 +449,16 @@ btr_pessimistic_scrub(
*/
mtr->release_block_at_savepoint(scrub_data->savepoint, block);
- buf_block_t* get_block __attribute__((unused)) = btr_block_get(
+ btr_block_get(
page_id_t(index->table->space_id, left_page_no),
- page_size, RW_X_LATCH, index, mtr);
+ zip_size, RW_X_LATCH, index, mtr);
/**
* Refetch block and re-initialize page
*/
block = btr_block_get(
page_id_t(index->table->space_id, page_no),
- page_size, RW_X_LATCH, index, mtr);
+ zip_size, RW_X_LATCH, index, mtr);
page = buf_block_get_frame(block);
@@ -470,9 +470,9 @@ btr_pessimistic_scrub(
}
if (right_page_no != FIL_NULL) {
- buf_block_t* get_block __attribute__((unused))= btr_block_get(
+ btr_block_get(
page_id_t(index->table->space_id, right_page_no),
- page_size, RW_X_LATCH, index, mtr);
+ zip_size, RW_X_LATCH, index, mtr);
}
/* arguments to btr_page_split_and_insert */
@@ -842,13 +842,15 @@ btr_scrub_start_space(
ulint space, /*!< in: space */
btr_scrub_t* scrub_data) /*!< in/out: scrub data */
{
- bool found;
scrub_data->space = space;
scrub_data->current_table = NULL;
scrub_data->current_index = NULL;
- const page_size_t page_size = fil_space_get_page_size(space, &found);
-
- scrub_data->compressed = page_size.is_compressed();
+ if (fil_space_t* s = fil_space_acquire_silent(space)) {
+ scrub_data->compressed = s->zip_size();
+ s->release();
+ } else {
+ scrub_data->compressed = 0;
+ }
scrub_data->scrubbing = check_scrub_setting(scrub_data);
return scrub_data->scrubbing;
}
diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc
index 37a839727ec..2d5f6a9bf05 100644
--- a/storage/innobase/btr/btr0sea.cc
+++ b/storage/innobase/btr/btr0sea.cc
@@ -1287,7 +1287,7 @@ void btr_search_drop_page_hash_when_freed(const page_id_t page_id)
are possibly holding, we cannot s-latch the page, but must
(recursively) x-latch it, even though we are only reading. */
- block = buf_page_get_gen(page_id, univ_page_size, RW_X_LATCH, NULL,
+ block = buf_page_get_gen(page_id, 0, RW_X_LATCH, NULL,
BUF_PEEK_IF_IN_POOL, __FILE__, __LINE__,
&mtr, &err);
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index b707761354e..d82cd9b829b 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -2,7 +2,7 @@
Copyright (c) 1995, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
-Copyright (c) 2013, 2018, MariaDB Corporation.
+Copyright (c) 2013, 2019, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -33,7 +33,6 @@ Created 11/5/1995 Heikki Tuuri
#include "mtr0types.h"
#include "mach0data.h"
-#include "page0size.h"
#include "buf0buf.h"
#include "buf0checksum.h"
#include <string.h>
@@ -517,7 +516,8 @@ decompress_with_slot:
+ dst_frame)) {
/* Verify encryption checksum before we even try to
decrypt. */
- if (!fil_space_verify_crypt_checksum(dst_frame, bpage->size)) {
+ if (!fil_space_verify_crypt_checksum(
+ dst_frame, space->zip_size())) {
decrypt_failed:
ib::error() << "Encrypted page " << bpage->id
<< " in file " << space->chain.start->name
@@ -889,14 +889,14 @@ buf_page_is_checksum_valid_none(
/** Check if a page is corrupt.
@param[in] check_lsn whether the LSN should be checked
@param[in] read_buf database page
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] space tablespace
@return whether the page is corrupted */
bool
buf_page_is_corrupted(
bool check_lsn,
const byte* read_buf,
- const page_size_t& page_size,
+ ulint zip_size,
#ifndef UNIV_INNOCHECKSUM
const fil_space_t* space)
#else
@@ -931,9 +931,9 @@ buf_page_is_corrupted(
return(false);
}
- if (!page_size.is_compressed()
+ if (!zip_size
&& memcmp(read_buf + FIL_PAGE_LSN + 4,
- read_buf + page_size.logical()
+ read_buf + srv_page_size
- FIL_PAGE_END_LSN_OLD_CHKSUM + 4, 4)) {
/* Stored log sequence numbers at the start and the end
@@ -980,16 +980,15 @@ buf_page_is_corrupted(
return(false);
}
- if (page_size.is_compressed()) {
- return(!page_zip_verify_checksum(read_buf,
- page_size.physical()));
+ if (zip_size) {
+ return !page_zip_verify_checksum(read_buf, zip_size);
}
checksum_field1 = mach_read_from_4(
read_buf + FIL_PAGE_SPACE_OR_CHKSUM);
checksum_field2 = mach_read_from_4(
- read_buf + page_size.logical() - FIL_PAGE_END_LSN_OLD_CHKSUM);
+ read_buf + srv_page_size - FIL_PAGE_END_LSN_OLD_CHKSUM);
compile_time_assert(!(FIL_PAGE_LSN % 8));
@@ -1000,7 +999,7 @@ buf_page_is_corrupted(
read_buf + FIL_PAGE_LSN) == 0) {
/* make sure that the page is really empty */
- for (ulint i = 0; i < page_size.logical(); i++) {
+ for (ulint i = 0; i < srv_page_size; i++) {
if (read_buf[i] != 0) {
return(true);
}
@@ -1198,20 +1197,19 @@ buf_madvise_do_dump()
/** Dump a page to stderr.
@param[in] read_buf database page
-@param[in] page_size page size */
-UNIV_INTERN
-void
-buf_page_print(const byte* read_buf, const page_size_t& page_size)
+@param[in] zip_size compressed page size, or 0 */
+void buf_page_print(const byte* read_buf, ulint zip_size)
{
+ const ulint size = zip_size ? zip_size : srv_page_size;
dict_index_t* index;
ib::info() << "Page dump in ascii and hex ("
- << page_size.physical() << " bytes):";
+ << size << " bytes):";
- ut_print_buf(stderr, read_buf, page_size.physical());
+ ut_print_buf(stderr, read_buf, size);
fputs("\nInnoDB: End of page dump\n", stderr);
- if (page_size.is_compressed()) {
+ if (zip_size) {
/* Print compressed page. */
ib::info() << "Compressed page type ("
<< fil_page_get_type(read_buf)
@@ -1223,21 +1221,21 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size)
SRV_CHECKSUM_ALGORITHM_CRC32)
<< " "
<< page_zip_calc_checksum(
- read_buf, page_size.physical(),
+ read_buf, zip_size,
SRV_CHECKSUM_ALGORITHM_CRC32)
<< ", "
<< buf_checksum_algorithm_name(
SRV_CHECKSUM_ALGORITHM_INNODB)
<< " "
<< page_zip_calc_checksum(
- read_buf, page_size.physical(),
+ read_buf, zip_size,
SRV_CHECKSUM_ALGORITHM_INNODB)
<< ", "
<< buf_checksum_algorithm_name(
SRV_CHECKSUM_ALGORITHM_NONE)
<< " "
<< page_zip_calc_checksum(
- read_buf, page_size.physical(),
+ read_buf, zip_size,
SRV_CHECKSUM_ALGORITHM_NONE)
<< "; page LSN "
<< mach_read_from_8(read_buf + FIL_PAGE_LSN)
@@ -1270,7 +1268,7 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size)
SRV_CHECKSUM_ALGORITHM_NONE) << " "
<< BUF_NO_CHECKSUM_MAGIC
<< ", stored checksum in field2 "
- << mach_read_from_4(read_buf + page_size.logical()
+ << mach_read_from_4(read_buf + srv_page_size
- FIL_PAGE_END_LSN_OLD_CHKSUM)
<< ", calculated checksums for field2: "
<< buf_checksum_algorithm_name(
@@ -1289,7 +1287,7 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size)
<< " "
<< mach_read_from_4(read_buf + FIL_PAGE_LSN + 4)
<< ", low 4 bytes of LSN at page end "
- << mach_read_from_4(read_buf + page_size.logical()
+ << mach_read_from_4(read_buf + srv_page_size
- FIL_PAGE_END_LSN_OLD_CHKSUM + 4)
<< ", page number (if stored to page already) "
<< mach_read_from_4(read_buf + FIL_PAGE_OFFSET)
@@ -3718,12 +3716,9 @@ be implemented at a higher level. In other words, all possible
accesses to a given page through this function must be protected by
the same set of mutexes or latches.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size
@return pointer to the block */
-buf_page_t*
-buf_page_get_zip(
- const page_id_t page_id,
- const page_size_t& page_size)
+buf_page_t* buf_page_get_zip(const page_id_t page_id, ulint zip_size)
{
buf_page_t* bpage;
BPageMutex* block_mutex;
@@ -3732,6 +3727,8 @@ buf_page_get_zip(
ibool must_read;
buf_pool_t* buf_pool = buf_pool_get(page_id);
+ ut_ad(zip_size);
+ ut_ad(ut_is_2pow(zip_size));
buf_pool->stat.n_page_gets++;
for (;;) {
@@ -3749,7 +3746,7 @@ lookup:
/* Page not in buf_pool: needs to be read from file */
ut_ad(!hash_lock);
- dberr_t err = buf_read_page(page_id, page_size);
+ dberr_t err = buf_read_page(page_id, zip_size);
if (err != DB_SUCCESS) {
ib::error() << "Reading compressed page " << page_id
@@ -3900,7 +3897,7 @@ buf_zip_decompress(
&& (!crypt_data->is_default_encryption()
|| srv_encrypt_tables);
- ut_ad(block->page.size.is_compressed());
+ ut_ad(block->zip_size());
ut_a(block->page.id.space() != 0);
if (UNIV_UNLIKELY(check && !page_zip_verify_checksum(frame, size))) {
@@ -3945,7 +3942,7 @@ buf_zip_decompress(
case FIL_PAGE_TYPE_ZBLOB:
case FIL_PAGE_TYPE_ZBLOB2:
/* Copy to uncompressed storage. */
- memcpy(block->frame, frame, block->page.size.physical());
+ memcpy(block->frame, frame, block->zip_size());
if (space) {
space->release_for_io();
}
@@ -4162,6 +4159,7 @@ buf_wait_for_read(
/** This is the general function used to get access to a database page.
@param[in] page_id page id
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH
@param[in] guess guessed block or NULL
@param[in] mode BUF_GET, BUF_GET_IF_IN_POOL,
@@ -4169,11 +4167,12 @@ BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH, or BUF_GET_IF_IN_POOL_OR_WATCH
@param[in] file file name
@param[in] line line where called
@param[in] mtr mini-transaction
+@param[out] err DB_SUCCESS or error code
@return pointer to the block or NULL */
buf_block_t*
buf_page_get_gen(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint rw_latch,
buf_block_t* guess,
ulint mode,
@@ -4221,16 +4220,15 @@ buf_page_get_gen(
case BUF_GET_IF_IN_POOL:
case BUF_GET_IF_IN_POOL_OR_WATCH:
case BUF_GET_POSSIBLY_FREED:
- bool found;
- const page_size_t& space_page_size
- = fil_space_get_page_size(page_id.space(), &found);
- ut_ad(found);
- ut_ad(page_size.equals_to(space_page_size));
+ fil_space_t* s = fil_space_acquire_for_io(page_id.space());
+ ut_ad(s);
+ ut_ad(s->zip_size() == zip_size);
+ s->release_for_io();
}
#endif /* UNIV_DEBUG */
ut_ad(!mtr || !ibuf_inside(mtr)
- || ibuf_page_low(page_id, page_size, FALSE, file, line, NULL));
+ || ibuf_page_low(page_id, zip_size, FALSE, file, line, NULL));
buf_pool->stat.n_page_gets++;
hash_lock = buf_page_hash_lock_get(buf_pool, page_id);
@@ -4339,10 +4337,10 @@ loop:
corrupted, or if an encrypted page with a valid
checksum cannot be decypted. */
- dberr_t local_err = buf_read_page(page_id, page_size);
+ dberr_t local_err = buf_read_page(page_id, zip_size);
if (local_err == DB_SUCCESS) {
- buf_read_ahead_random(page_id, page_size,
+ buf_read_ahead_random(page_id, zip_size,
ibuf_inside(mtr));
retries = 0;
@@ -4423,8 +4421,10 @@ loop:
rw_lock_s_unlock(hash_lock);
got_block:
-
switch (mode) {
+ default:
+ ut_ad(block->zip_size() == zip_size);
+ break;
case BUF_GET_IF_IN_POOL:
case BUF_PEEK_IF_IN_POOL:
case BUF_EVICT_IF_IN_POOL:
@@ -4633,7 +4633,7 @@ evict_from_pool:
#endif /* UNIV_IBUF_COUNT_DEBUG */
} else {
ibuf_merge_or_delete_for_page(
- block, page_id, &page_size, TRUE);
+ block, block->page.id, zip_size, true);
}
}
@@ -4833,7 +4833,7 @@ evict_from_pool:
/* In the case of a first access, try to apply linear
read-ahead */
- buf_read_ahead_linear(page_id, page_size, ibuf_inside(mtr));
+ buf_read_ahead_linear(page_id, zip_size, ibuf_inside(mtr));
}
#ifdef UNIV_IBUF_COUNT_DEBUG
@@ -4889,7 +4889,7 @@ buf_page_optimistic_get(
buf_page_make_young_if_needed(&block->page);
ut_ad(!ibuf_inside(mtr)
- || ibuf_page(block->page.id, block->page.size, NULL));
+ || ibuf_page(block->page.id, block->zip_size(), NULL));
mtr_memo_type_t fix_type;
@@ -4949,7 +4949,7 @@ buf_page_optimistic_get(
if (!access_time) {
/* In the case of a first access, try to apply linear
read-ahead */
- buf_read_ahead_linear(block->page.id, block->page.size,
+ buf_read_ahead_linear(block->page.id, block->zip_size(),
ibuf_inside(mtr));
}
@@ -5189,13 +5189,14 @@ buf_page_init_low(
/** Inits a page to the buffer buf_pool.
@param[in,out] buf_pool buffer pool
@param[in] page_id page id
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] block block to init */
static
void
buf_page_init(
buf_pool_t* buf_pool,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
buf_block_t* block)
{
buf_page_t* hash_page;
@@ -5263,14 +5264,11 @@ buf_page_init(
ut_d(block->page.in_page_hash = TRUE);
block->page.id = page_id;
- block->page.size.copy_from(page_size);
HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
page_id.fold(), &block->page);
- if (page_size.is_compressed()) {
- page_zip_set_size(&block->page.zip, page_size.physical());
- }
+ page_zip_set_size(&block->page.zip, zip_size);
}
/** Initialize a page for read to the buffer buf_pool. If the page is
@@ -5284,6 +5282,7 @@ and the lock released later.
@param[out] err DB_SUCCESS or DB_TABLESPACE_DELETED
@param[in] mode BUF_READ_IBUF_PAGES_ONLY, ...
@param[in] page_id page id
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] unzip whether the uncompressed page is
requested (for ROW_FORMAT=COMPRESSED)
@return pointer to the block
@@ -5293,7 +5292,7 @@ buf_page_init_for_read(
dberr_t* err,
ulint mode,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
bool unzip)
{
buf_block_t* block;
@@ -5312,12 +5311,12 @@ buf_page_init_for_read(
if (mode == BUF_READ_IBUF_PAGES_ONLY) {
/* It is a read-ahead within an ibuf routine */
- ut_ad(!ibuf_bitmap_page(page_id, page_size));
+ ut_ad(!ibuf_bitmap_page(page_id, zip_size));
ibuf_mtr_start(&mtr);
- if (!recv_no_ibuf_operations &&
- !ibuf_page(page_id, page_size, &mtr)) {
+ if (!recv_no_ibuf_operations
+ && !ibuf_page(page_id, zip_size, &mtr)) {
ibuf_mtr_commit(&mtr);
@@ -5327,7 +5326,7 @@ buf_page_init_for_read(
ut_ad(mode == BUF_READ_ANY_PAGE);
}
- if (page_size.is_compressed() && !unzip && !recv_recovery_is_on()) {
+ if (zip_size && !unzip && !recv_recovery_is_on()) {
block = NULL;
} else {
block = buf_LRU_get_free_block(buf_pool);
@@ -5362,7 +5361,7 @@ buf_page_init_for_read(
ut_ad(buf_pool_from_bpage(bpage) == buf_pool);
- buf_page_init(buf_pool, page_id, page_size, block);
+ buf_page_init(buf_pool, page_id, zip_size, block);
/* Note: We are using the hash_lock for protection. This is
safe because no other thread can lookup the block from the
@@ -5386,7 +5385,7 @@ buf_page_init_for_read(
rw_lock_x_lock_gen(&block->lock, BUF_IO_READ);
- if (page_size.is_compressed()) {
+ if (zip_size) {
/* buf_pool->mutex may be released and
reacquired by buf_buddy_alloc(). Thus, we
must release block->mutex in order not to
@@ -5396,8 +5395,7 @@ buf_page_init_for_read(
been added to buf_pool->LRU and
buf_pool->page_hash. */
buf_page_mutex_exit(block);
- data = buf_buddy_alloc(buf_pool, page_size.physical(),
- &lru);
+ data = buf_buddy_alloc(buf_pool, zip_size, &lru);
buf_page_mutex_enter(block);
block->page.zip.data = (page_zip_t*) data;
@@ -5418,7 +5416,7 @@ buf_page_init_for_read(
control block (bpage), in order to avoid the
invocation of buf_buddy_relocate_block() on
uninitialized data. */
- data = buf_buddy_alloc(buf_pool, page_size.physical(), &lru);
+ data = buf_buddy_alloc(buf_pool, zip_size, &lru);
rw_lock_x_lock(hash_lock);
@@ -5436,8 +5434,7 @@ buf_page_init_for_read(
/* The block was added by some other thread. */
rw_lock_x_unlock(hash_lock);
watch_page = NULL;
- buf_buddy_free(buf_pool, data,
- page_size.physical());
+ buf_buddy_free(buf_pool, data, zip_size);
bpage = NULL;
goto func_exit;
@@ -5450,13 +5447,11 @@ buf_page_init_for_read(
bpage->buf_pool_index = buf_pool_index(buf_pool);
page_zip_des_init(&bpage->zip);
- page_zip_set_size(&bpage->zip, page_size.physical());
+ page_zip_set_size(&bpage->zip, zip_size);
bpage->zip.data = (page_zip_t*) data;
- bpage->size.copy_from(page_size);
-
mutex_enter(&buf_pool->zip_mutex);
- UNIV_MEM_DESC(bpage->zip.data, bpage->size.physical());
+ UNIV_MEM_DESC(bpage->zip.data, zip_size);
buf_page_init_low(bpage);
@@ -5520,18 +5515,18 @@ func_exit:
return(bpage);
}
-/** Initializes a page to the buffer buf_pool. The page is usually not read
+/** Initialize a page in the buffer pool. The page is usually not read
from a file even if it cannot be found in the buffer buf_pool. This is one
of the functions which perform to a block a state transition NOT_USED =>
FILE_PAGE (the other is buf_page_get_gen).
@param[in] page_id page id
-@param[in] page_size page size
-@param[in] mtr mini-transaction
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in,out] mtr mini-transaction
@return pointer to the block, page bufferfixed */
buf_block_t*
buf_page_create(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
mtr_t* mtr)
{
buf_frame_t* frame;
@@ -5541,7 +5536,7 @@ buf_page_create(
rw_lock_t* hash_lock;
ut_ad(mtr->is_active());
- ut_ad(page_id.space() != 0 || !page_size.is_compressed());
+ ut_ad(page_id.space() != 0 || !zip_size);
free_block = buf_LRU_get_free_block(buf_pool);
@@ -5568,7 +5563,7 @@ buf_page_create(
buf_block_free(free_block);
- return(buf_page_get_with_no_latch(page_id, page_size, mtr));
+ return buf_page_get_with_no_latch(page_id, zip_size, mtr);
}
/* If we get here, the page was not in buf_pool: init it there */
@@ -5580,7 +5575,7 @@ buf_page_create(
buf_page_mutex_enter(block);
- buf_page_init(buf_pool, page_id, page_size, block);
+ buf_page_init(buf_pool, page_id, zip_size, block);
rw_lock_x_unlock(hash_lock);
@@ -5590,7 +5585,7 @@ buf_page_create(
buf_block_buf_fix_inc(block, __FILE__, __LINE__);
buf_pool->stat.n_pages_created++;
- if (page_size.is_compressed()) {
+ if (zip_size) {
void* data;
bool lru;
@@ -5608,7 +5603,7 @@ buf_page_create(
the reacquisition of buf_pool->mutex. We also must
defer this operation until after the block descriptor
has been added to buf_pool->LRU and buf_pool->page_hash. */
- data = buf_buddy_alloc(buf_pool, page_size.physical(), &lru);
+ data = buf_buddy_alloc(buf_pool, zip_size, &lru);
buf_page_mutex_enter(block);
block->page.zip.data = (page_zip_t*) data;
@@ -5634,7 +5629,7 @@ buf_page_create(
/* Delete possible entries for the page from the insert buffer:
such can exist if the page belonged to an index which was dropped */
- ibuf_merge_or_delete_for_page(NULL, page_id, &page_size, TRUE);
+ ibuf_merge_or_delete_for_page(NULL, page_id, zip_size, true);
frame = block->frame;
@@ -5844,13 +5839,14 @@ static dberr_t buf_page_check_corrupt(buf_page_t* bpage, fil_space_t* space)
&& space->crypt_data
&& space->crypt_data->type != CRYPT_SCHEME_UNENCRYPTED
&& !bpage->encrypted
- && fil_space_verify_crypt_checksum(dst_frame, bpage->size);
+ && fil_space_verify_crypt_checksum(dst_frame,
+ bpage->zip_size());
if (!still_encrypted) {
/* If traditional checksums match, we assume that page is
not anymore encrypted. */
corrupted = buf_page_is_corrupted(
- true, dst_frame, bpage->size, space);
+ true, dst_frame, bpage->zip_size(), space);
if (!corrupted) {
bpage->encrypted = false;
@@ -5921,7 +5917,7 @@ buf_page_io_complete(buf_page_t* bpage, bool dblwr, bool evict)
io_type = buf_page_get_io_fix(bpage);
ut_ad(io_type == BUF_IO_READ || io_type == BUF_IO_WRITE);
- ut_ad(bpage->size.is_compressed() == (bpage->zip.data != NULL));
+ ut_ad(!!bpage->zip.ssize == (bpage->zip.data != NULL));
ut_ad(uncompressed || bpage->zip.data);
if (io_type == BUF_IO_READ) {
@@ -6021,7 +6017,7 @@ database_corrupted:
<< ". You may have to recover from "
<< "a backup.";
- buf_page_print(frame, bpage->size);
+ buf_page_print(frame, bpage->zip_size());
ib::info()
<< "It is also possible that your"
@@ -6085,7 +6081,7 @@ database_corrupted:
ibuf_merge_or_delete_for_page(
(buf_block_t*) bpage, bpage->id,
- &bpage->size, TRUE);
+ bpage->zip_size(), true);
}
}
@@ -7314,7 +7310,7 @@ buf_page_encrypt_before_write(
return src_frame;
}
- ut_ad(!bpage->size.is_compressed() || !page_compressed);
+ ut_ad(!bpage->zip_size() || !page_compressed);
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
/* Find free slot from temporary memory array */
buf_tmp_buffer_t* slot = buf_pool_reserve_tmp_slot(buf_pool);
@@ -7382,7 +7378,7 @@ bool
buf_page_should_punch_hole(
const buf_page_t* bpage)
{
- return (bpage->real_size != bpage->size.physical());
+ return bpage->real_size != bpage->physical_size();
}
/**
@@ -7395,6 +7391,6 @@ buf_page_get_trim_length(
const buf_page_t* bpage,
ulint write_length)
{
- return (bpage->size.physical() - write_length);
+ return bpage->physical_size() - write_length;
}
#endif /* !UNIV_INNOCHECKSUM */
diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc
index 0eaa746deb8..502aed20343 100644
--- a/storage/innobase/buf/buf0dblwr.cc
+++ b/storage/innobase/buf/buf0dblwr.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2018, MariaDB Corporation.
+Copyright (c) 2013, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -85,7 +85,7 @@ buf_dblwr_get(
buf_block_t* block;
block = buf_page_get(page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO),
- univ_page_size, RW_X_LATCH, mtr);
+ 0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
@@ -580,12 +580,13 @@ buf_dblwr_process()
continue;
}
- const page_size_t page_size(space->flags);
- ut_ad(!buf_page_is_zeroes(page, page_size.physical()));
+ const ulint physical_size = space->physical_size();
+ const ulint zip_size = space->zip_size();
+ ut_ad(!buf_page_is_zeroes(page, physical_size));
/* We want to ensure that for partial reads the
unread portion of the page is NUL. */
- memset(read_buf, 0x0, page_size.physical());
+ memset(read_buf, 0x0, physical_size);
IORequest request;
@@ -594,8 +595,8 @@ buf_dblwr_process()
/* Read in the actual page from the file */
dberr_t err = fil_io(
request, true,
- page_id, page_size,
- 0, page_size.physical(), read_buf, NULL);
+ page_id, zip_size,
+ 0, physical_size, read_buf, NULL);
if (err != DB_SUCCESS) {
ib::warn()
@@ -605,7 +606,7 @@ buf_dblwr_process()
}
const bool is_all_zero = buf_page_is_zeroes(
- read_buf, page_size.physical());
+ read_buf, physical_size);
const bool expect_encrypted = space->crypt_data
&& space->crypt_data->type != CRYPT_SCHEME_UNENCRYPTED;
@@ -618,8 +619,7 @@ buf_dblwr_process()
/* Decompress the page before
validating the checksum. */
ulint decomp = fil_page_decompress(buf, read_buf);
- if (!decomp || (decomp != srv_page_size
- && page_size.is_compressed())) {
+ if (!decomp || (zip_size && decomp != srv_page_size)) {
goto bad;
}
@@ -627,9 +627,9 @@ buf_dblwr_process()
read_buf
+ FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION)
? fil_space_verify_crypt_checksum(read_buf,
- page_size)
+ zip_size)
: !buf_page_is_corrupted(true, read_buf,
- page_size, space)) {
+ zip_size, space)) {
/* The page is good; there is no need
to consult the doublewrite buffer. */
continue;
@@ -644,15 +644,14 @@ bad:
}
ulint decomp = fil_page_decompress(buf, page);
- if (!decomp || (decomp != srv_page_size
- && page_size.is_compressed())) {
+ if (!decomp || (zip_size && decomp != srv_page_size)) {
goto bad_doublewrite;
}
if (expect_encrypted && mach_read_from_4(
page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION)
- ? !fil_space_verify_crypt_checksum(page, page_size)
- : buf_page_is_corrupted(true, page, page_size, space)) {
+ ? !fil_space_verify_crypt_checksum(page, zip_size)
+ : buf_page_is_corrupted(true, page, zip_size, space)) {
if (!is_all_zero) {
bad_doublewrite:
ib::warn() << "A doublewrite copy of page "
@@ -686,8 +685,8 @@ bad_doublewrite:
IORequest write_request(IORequest::WRITE);
- fil_io(write_request, true, page_id, page_size,
- 0, page_size.physical(),
+ fil_io(write_request, true, page_id, zip_size,
+ 0, physical_size,
const_cast<byte*>(page), NULL);
ib::info() << "Recovered page " << page_id
@@ -834,7 +833,7 @@ buf_dblwr_assert_on_corrupt_block(
/*==============================*/
const buf_block_t* block) /*!< in: block to check */
{
- buf_page_print(block->frame, univ_page_size);
+ buf_page_print(block->frame);
ib::fatal() << "Apparent corruption of an index page "
<< block->page.id
@@ -924,14 +923,14 @@ buf_dblwr_write_block_to_datafile(
void * frame = buf_page_get_frame(bpage);
if (bpage->zip.data != NULL) {
- ut_ad(bpage->size.is_compressed());
+ ut_ad(bpage->zip_size());
- fil_io(request, sync, bpage->id, bpage->size, 0,
- bpage->size.physical(),
+ fil_io(request, sync, bpage->id, bpage->zip_size(), 0,
+ bpage->zip_size(),
(void*) frame,
(void*) bpage);
} else {
- ut_ad(!bpage->size.is_compressed());
+ ut_ad(!bpage->zip_size());
/* Our IO API is common for both reads and writes and is
therefore geared towards a non-const parameter. */
@@ -943,8 +942,8 @@ buf_dblwr_write_block_to_datafile(
buf_dblwr_check_page_lsn(block->frame);
fil_io(request,
- sync, bpage->id, bpage->size, 0, bpage->real_size,
- frame, block);
+ sync, bpage->id, bpage->zip_size(), 0, bpage->real_size,
+ frame, block);
}
}
@@ -1045,7 +1044,7 @@ try_again:
buf_dblwr->first_free) << srv_page_size_shift;
fil_io(IORequestWrite, true,
- page_id_t(TRX_SYS_SPACE, buf_dblwr->block1), univ_page_size,
+ page_id_t(TRX_SYS_SPACE, buf_dblwr->block1), 0,
0, len, (void*) write_buf, NULL);
if (buf_dblwr->first_free <= TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
@@ -1061,7 +1060,7 @@ try_again:
+ (TRX_SYS_DOUBLEWRITE_BLOCK_SIZE << srv_page_size_shift);
fil_io(IORequestWrite, true,
- page_id_t(TRX_SYS_SPACE, buf_dblwr->block2), univ_page_size,
+ page_id_t(TRX_SYS_SPACE, buf_dblwr->block2), 0,
0, len, (void*) write_buf, NULL);
flush:
@@ -1146,21 +1145,16 @@ try_again:
encryption and/or page compression */
void * frame = buf_page_get_frame(bpage);
- if (bpage->size.is_compressed()) {
- UNIV_MEM_ASSERT_RW(bpage->zip.data, bpage->size.physical());
+ if (auto zip_size = bpage->zip_size()) {
+ UNIV_MEM_ASSERT_RW(bpage->zip.data, zip_size);
/* Copy the compressed page and clear the rest. */
-
- memcpy(p, frame, bpage->size.physical());
-
- memset(p + bpage->size.physical(), 0x0,
- srv_page_size - bpage->size.physical());
+ memcpy(p, frame, zip_size);
+ memset(p + zip_size, 0x0, srv_page_size - zip_size);
} else {
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
- UNIV_MEM_ASSERT_RW(frame,
- bpage->size.logical());
-
- memcpy(p, frame, bpage->size.logical());
+ UNIV_MEM_ASSERT_RW(frame, srv_page_size);
+ memcpy(p, frame, srv_page_size);
}
buf_dblwr->buf_block_arr[buf_dblwr->first_free] = bpage;
@@ -1282,18 +1276,18 @@ retry:
encryption and/or page compression */
void * frame = buf_page_get_frame(bpage);
- if (bpage->size.is_compressed()) {
+ if (auto zip_size = bpage->zip_size()) {
memcpy(buf_dblwr->write_buf + srv_page_size * i,
- frame, bpage->size.physical());
+ frame, zip_size);
memset(buf_dblwr->write_buf + srv_page_size * i
- + bpage->size.physical(), 0x0,
- srv_page_size - bpage->size.physical());
+ + zip_size, 0x0,
+ srv_page_size - zip_size);
fil_io(IORequestWrite,
true,
page_id_t(TRX_SYS_SPACE, offset),
- univ_page_size,
+ 0,
0,
srv_page_size,
(void *)(buf_dblwr->write_buf + srv_page_size * i),
@@ -1304,7 +1298,7 @@ retry:
fil_io(IORequestWrite,
true,
page_id_t(TRX_SYS_SPACE, offset),
- univ_page_size,
+ 0,
0,
srv_page_size,
(void*) frame,
diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc
index 2747a6fa338..2fc700307ab 100644
--- a/storage/innobase/buf/buf0dump.cc
+++ b/storage/innobase/buf/buf0dump.cc
@@ -672,7 +672,7 @@ buf_load()
so all pages from a given tablespace are consecutive. */
ulint cur_space_id = BUF_DUMP_SPACE(dump[0]);
fil_space_t* space = fil_space_acquire_silent(cur_space_id);
- page_size_t page_size(space ? space->flags : 0);
+ ulint zip_size = space ? space->zip_size() : 0;
/* JAN: TODO: MySQL 5.7 PSI
#ifdef HAVE_PSI_STAGE_INTERFACE
@@ -703,9 +703,7 @@ buf_load()
space = fil_space_acquire_silent(cur_space_id);
if (space != NULL) {
- const page_size_t cur_page_size(
- space->flags);
- page_size.copy_from(cur_page_size);
+ zip_size = space->zip_size();
}
}
@@ -720,7 +718,7 @@ buf_load()
buf_read_page_background(
page_id_t(this_space_id, BUF_DUMP_PAGE(dump[i])),
- page_size, true);
+ zip_size, true);
if (i % 64 == 63) {
os_aio_simulated_wake_handler_threads();
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index ac8dd98dbe1..f1d6398e772 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -211,7 +211,7 @@ incr_flush_list_size_in_bytes(
{
ut_ad(buf_flush_list_mutex_own(buf_pool));
- buf_pool->stat.flush_list_bytes += block->page.size.physical();
+ buf_pool->stat.flush_list_bytes += block->physical_size();
ut_ad(buf_pool->stat.flush_list_bytes <= buf_pool->curr_pool_size);
}
@@ -433,7 +433,7 @@ buf_flush_insert_into_flush_list(
block->page.oldest_modification = lsn;
UNIV_MEM_ASSERT_RW(block->page.zip.data
? block->page.zip.data : block->frame,
- block->page.size.physical());
+ block->physical_size());
incr_flush_list_size_in_bytes(block, buf_pool);
if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) {
@@ -601,7 +601,7 @@ buf_flush_remove(
because we assert on in_flush_list in comparison function. */
ut_d(bpage->in_flush_list = FALSE);
- buf_pool->stat.flush_list_bytes -= bpage->size.physical();
+ buf_pool->stat.flush_list_bytes -= bpage->physical_size();
bpage->oldest_modification = 0;
@@ -977,7 +977,7 @@ buf_flush_write_block_low(
mach_write_to_8(frame + FIL_PAGE_LSN,
bpage->newest_modification);
- ut_a(page_zip_verify_checksum(frame, bpage->size.physical()));
+ ut_a(page_zip_verify_checksum(frame, bpage->zip_size()));
break;
case BUF_BLOCK_FILE_PAGE:
frame = bpage->zip.data;
@@ -1004,7 +1004,8 @@ buf_flush_write_block_low(
/* TODO: pass the tablespace to fil_io() */
fil_io(request,
- sync, bpage->id, bpage->size, 0, bpage->size.physical(),
+ sync, bpage->id, bpage->zip_size(), 0,
+ bpage->physical_size(),
frame, bpage);
} else {
ut_ad(!srv_read_only_mode);
diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc
index 9baa299910a..e0acd1cfeed 100644
--- a/storage/innobase/buf/buf0lru.cc
+++ b/storage/innobase/buf/buf0lru.cc
@@ -166,7 +166,7 @@ incr_LRU_size_in_bytes(
{
ut_ad(buf_pool_mutex_own(buf_pool));
- buf_pool->stat.LRU_bytes += bpage->size.physical();
+ buf_pool->stat.LRU_bytes += bpage->physical_size();
ut_ad(buf_pool->stat.LRU_bytes <= buf_pool->curr_pool_size);
}
@@ -1389,7 +1389,7 @@ buf_LRU_remove_block(
UT_LIST_REMOVE(buf_pool->LRU, bpage);
ut_d(bpage->in_LRU_list = FALSE);
- buf_pool->stat.LRU_bytes -= bpage->size.physical();
+ buf_pool->stat.LRU_bytes -= bpage->physical_size();
buf_unzip_LRU_remove_block_if_needed(bpage);
@@ -1661,9 +1661,9 @@ func_exit:
? BUF_BLOCK_ZIP_DIRTY
: BUF_BLOCK_ZIP_PAGE;
- ut_ad(b->size.is_compressed());
+ ut_ad(b->zip_size());
- UNIV_MEM_DESC(b->zip.data, b->size.physical());
+ UNIV_MEM_DESC(b->zip.data, b->zip_size());
/* The fields in_page_hash and in_LRU_list of
the to-be-freed block descriptor should have
@@ -1742,10 +1742,6 @@ func_exit:
page_zip_set_size(&bpage->zip, 0);
- bpage->size.copy_from(page_size_t(bpage->size.logical(),
- bpage->size.logical(),
- false));
-
mutex_exit(block_mutex);
/* Prevent buf_page_get_gen() from
@@ -1785,11 +1781,11 @@ func_exit:
buf_pool->page_hash, thus inaccessible by any
other thread. */
- ut_ad(b->size.is_compressed());
+ ut_ad(b->zip_size());
const uint32_t checksum = page_zip_calc_checksum(
b->zip.data,
- b->size.physical(),
+ b->zip_size(),
static_cast<srv_checksum_algorithm_t>(
srv_checksum_algorithm));
@@ -1856,19 +1852,14 @@ buf_LRU_block_free_non_file_page(
buf_page_mutex_exit(block);
buf_pool_mutex_exit_forbid(buf_pool);
- ut_ad(block->page.size.is_compressed());
+ ut_ad(block->zip_size());
- buf_buddy_free(buf_pool, data, block->page.size.physical());
+ buf_buddy_free(buf_pool, data, block->zip_size());
buf_pool_mutex_exit_allow(buf_pool);
buf_page_mutex_enter(block);
page_zip_set_size(&block->page.zip, 0);
-
- block->page.size.copy_from(
- page_size_t(block->page.size.logical(),
- block->page.size.logical(),
- false));
}
if (buf_pool->curr_size < buf_pool->old_size
@@ -1939,7 +1930,7 @@ buf_LRU_block_remove_hashed(
const page_t* page = ((buf_block_t*) bpage)->frame;
ut_a(!zip || bpage->oldest_modification == 0);
- ut_ad(bpage->size.is_compressed());
+ ut_ad(bpage->zip_size());
switch (fil_page_get_type(page)) {
case FIL_PAGE_TYPE_ALLOCATED:
@@ -1954,7 +1945,7 @@ buf_LRU_block_remove_hashed(
to the compressed page, which will
be preserved. */
memcpy(bpage->zip.data, page,
- bpage->size.physical());
+ bpage->zip_size());
}
break;
case FIL_PAGE_TYPE_ZBLOB:
@@ -1971,14 +1962,13 @@ buf_LRU_block_remove_hashed(
default:
ib::error() << "The compressed page to be"
" evicted seems corrupt:";
- ut_print_buf(stderr, page,
- bpage->size.logical());
+ ut_print_buf(stderr, page, srv_page_size);
ib::error() << "Possibly older version of"
" the page:";
ut_print_buf(stderr, bpage->zip.data,
- bpage->size.physical());
+ bpage->zip_size());
putc('\n', stderr);
ut_error;
}
@@ -1988,10 +1978,7 @@ buf_LRU_block_remove_hashed(
/* fall through */
case BUF_BLOCK_ZIP_PAGE:
ut_a(bpage->oldest_modification == 0);
- if (bpage->size.is_compressed()) {
- UNIV_MEM_ASSERT_W(bpage->zip.data,
- bpage->size.physical());
- }
+ UNIV_MEM_ASSERT_W(bpage->zip.data, bpage->zip_size());
break;
case BUF_BLOCK_POOL_WATCH:
case BUF_BLOCK_ZIP_DIRTY:
@@ -2007,25 +1994,16 @@ buf_LRU_block_remove_hashed(
if (bpage != hashed_bpage) {
ib::error() << "Page " << bpage->id
<< " not found in the hash table";
-
-#ifdef UNIV_DEBUG
-
-
ib::error()
+#ifdef UNIV_DEBUG
<< "in_page_hash:" << bpage->in_page_hash
<< " in_zip_hash:" << bpage->in_zip_hash
- // << " in_free_list:"<< bpage->in_fee_list
<< " in_flush_list:" << bpage->in_flush_list
<< " in_LRU_list:" << bpage->in_LRU_list
+#endif
<< " zip.data:" << bpage->zip.data
- << " zip_size:" << bpage->size.logical()
- << " page_state:" << buf_page_get_state(bpage);
-#else
- ib::error()
- << " zip.data:" << bpage->zip.data
- << " zip_size:" << bpage->size.logical()
+ << " zip_size:" << bpage->zip_size()
<< " page_state:" << buf_page_get_state(bpage);
-#endif
if (hashed_bpage) {
@@ -2059,7 +2037,7 @@ buf_LRU_block_remove_hashed(
ut_ad(!bpage->in_flush_list);
ut_ad(!bpage->in_LRU_list);
ut_a(bpage->zip.data);
- ut_a(bpage->size.is_compressed());
+ ut_a(bpage->zip.ssize);
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
UT_LIST_REMOVE(buf_pool->zip_clean, bpage);
@@ -2069,8 +2047,7 @@ buf_LRU_block_remove_hashed(
rw_lock_x_unlock(hash_lock);
buf_pool_mutex_exit_forbid(buf_pool);
- buf_buddy_free(buf_pool, bpage->zip.data,
- bpage->size.physical());
+ buf_buddy_free(buf_pool, bpage->zip.data, bpage->zip_size());
buf_pool_mutex_exit_allow(buf_pool);
buf_page_free_descriptor(bpage);
@@ -2117,16 +2094,11 @@ buf_LRU_block_remove_hashed(
ut_ad(!bpage->in_LRU_list);
buf_pool_mutex_exit_forbid(buf_pool);
- buf_buddy_free(buf_pool, data, bpage->size.physical());
+ buf_buddy_free(buf_pool, data, bpage->zip_size());
buf_pool_mutex_exit_allow(buf_pool);
page_zip_set_size(&bpage->zip, 0);
-
- bpage->size.copy_from(
- page_size_t(bpage->size.logical(),
- bpage->size.logical(),
- false));
}
return(true);
@@ -2484,7 +2456,7 @@ buf_LRU_print_instance(
fprintf(stderr, "\ntype %u size " ULINTPF
" index id " IB_ID_FMT "\n",
fil_page_get_type(frame),
- bpage->size.physical(),
+ bpage->zip_size(),
btr_page_get_index_id(frame));
break;
diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc
index 9454b57f59e..f4271c8d738 100644
--- a/storage/innobase/buf/buf0rea.cc
+++ b/storage/innobase/buf/buf0rea.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, 2018, MariaDB Corporation.
+Copyright (c) 2015, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -102,6 +102,7 @@ flag is cleared and the x-lock released by an i/o-handler thread.
@param[in] type IO type, SIMULATED, IGNORE_MISSING
@param[in] mode BUF_READ_IBUF_PAGES_ONLY, ...,
@param[in] page_id page id
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] unzip true=request uncompressed page
@param[in] ignore_missing_space true=ignore missing space when reading
@return 1 if a read request was queued, 0 if the page already resided
@@ -116,7 +117,7 @@ buf_read_page_low(
ulint type,
ulint mode,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
bool unzip,
bool ignore_missing_space = false)
{
@@ -132,7 +133,7 @@ buf_read_page_low(
return(0);
}
- if (ibuf_bitmap_page(page_id, page_size) || trx_sys_hdr_page(page_id)) {
+ if (ibuf_bitmap_page(page_id, zip_size) || trx_sys_hdr_page(page_id)) {
/* Trx sys header is so low in the latching order that we play
safe and do not leave the i/o-completion to an asynchronous
@@ -147,7 +148,7 @@ buf_read_page_low(
or is being dropped; if we succeed in initing the page in the buffer
pool for read, then DISCARD cannot proceed until the read has
completed */
- bpage = buf_page_init_for_read(err, mode, page_id, page_size, unzip);
+ bpage = buf_page_init_for_read(err, mode, page_id, zip_size, unzip);
if (bpage == NULL) {
@@ -155,7 +156,7 @@ buf_read_page_low(
}
DBUG_LOG("ib_buf",
- "read page " << page_id << " size=" << page_size.physical()
+ "read page " << page_id << " zip_size=" << zip_size
<< " unzip=" << unzip << ',' << (sync ? "sync" : "async"));
ut_ad(buf_page_in_file(bpage));
@@ -166,7 +167,7 @@ buf_read_page_low(
void* dst;
- if (page_size.is_compressed()) {
+ if (zip_size) {
dst = bpage->zip.data;
} else {
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
@@ -177,7 +178,8 @@ buf_read_page_low(
IORequest request(type | IORequest::READ);
*err = fil_io(
- request, sync, page_id, page_size, 0, page_size.physical(),
+ request, sync, page_id, zip_size, 0,
+ zip_size ? zip_size : srv_page_size,
dst, bpage, ignore_missing_space);
if (sync) {
@@ -218,16 +220,13 @@ performed by ibuf routines, a situation which could result in a deadlock if
the OS does not support asynchronous i/o.
@param[in] page_id page id of a page which the current thread
wants to access
-@param[in] page_size page size
-@param[in] inside_ibuf TRUE if we are inside ibuf routine
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in] ibuf whether we are inside ibuf routine
@return number of page read requests issued; NOTE that if we read ibuf
pages, it may happen that the page at the given page number does not
get read even if we return a positive value! */
ulint
-buf_read_ahead_random(
- const page_id_t page_id,
- const page_size_t& page_size,
- ibool inside_ibuf)
+buf_read_ahead_random(const page_id_t page_id, ulint zip_size, bool ibuf)
{
buf_pool_t* buf_pool = buf_pool_get(page_id);
ulint recent_blocks = 0;
@@ -249,7 +248,7 @@ buf_read_ahead_random(
return(0);
}
- if (ibuf_bitmap_page(page_id, page_size) || trx_sys_hdr_page(page_id)) {
+ if (ibuf_bitmap_page(page_id, zip_size) || trx_sys_hdr_page(page_id)) {
/* If it is an ibuf bitmap page or trx sys hdr, we do
no read-ahead, as that could break the ibuf page access
@@ -264,14 +263,14 @@ buf_read_ahead_random(
high = (page_id.page_no() / buf_read_ahead_random_area + 1)
* buf_read_ahead_random_area;
- /* Remember the tablespace version before we ask the tablespace size
- below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we
+ /* If DISCARD + IMPORT changes the actual .ibd file meanwhile, we
do not try to read outside the bounds of the tablespace! */
if (fil_space_t* space = fil_space_acquire(page_id.space())) {
#ifdef UNIV_DEBUG
if (srv_file_per_table) {
ulint size = 0;
+ const ulint physical_size = space->physical_size();
for (const fil_node_t* node =
UT_LIST_GET_FIRST(space->chain);
@@ -279,7 +278,7 @@ buf_read_ahead_random(
node = UT_LIST_GET_NEXT(chain, node)) {
size += ulint(os_file_get_size(node->handle)
- / page_size.physical());
+ / physical_size);
}
ut_ad(size == space->size);
@@ -332,12 +331,7 @@ buf_read_ahead_random(
read_ahead:
/* Read all the suitable blocks within the area */
- if (inside_ibuf) {
- ibuf_mode = BUF_READ_IBUF_PAGES_ONLY;
- } else {
- ibuf_mode = BUF_READ_ANY_PAGE;
- }
-
+ ibuf_mode = ibuf ? BUF_READ_IBUF_PAGES_ONLY : BUF_READ_ANY_PAGE;
count = 0;
for (i = low; i < high; i++) {
@@ -346,12 +340,12 @@ read_ahead:
const page_id_t cur_page_id(page_id.space(), i);
- if (!ibuf_bitmap_page(cur_page_id, page_size)) {
+ if (!ibuf_bitmap_page(cur_page_id, zip_size)) {
count += buf_read_page_low(
&err, false,
IORequest::DO_NOT_WAKE,
ibuf_mode,
- cur_page_id, page_size, false);
+ cur_page_id, zip_size, false);
switch (err) {
case DB_SUCCESS:
@@ -396,16 +390,13 @@ buffer buf_pool if it is not already there. Sets the io_fix flag and sets
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
released by the i/o-handler thread.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@retval DB_SUCCESS if the page was read and is not corrupted,
@retval DB_PAGE_CORRUPTED if page based on checksum check is corrupted,
@retval DB_DECRYPTION_FAILED if page post encryption checksum matches but
after decryption normal page checksum does not match.
@retval DB_TABLESPACE_DELETED if tablespace .ibd file is missing */
-dberr_t
-buf_read_page(
- const page_id_t page_id,
- const page_size_t& page_size)
+dberr_t buf_read_page(const page_id_t page_id, ulint zip_size)
{
ulint count;
dberr_t err = DB_SUCCESS;
@@ -418,7 +409,7 @@ buf_read_page(
count = buf_read_page_low(
&err, true,
- 0, BUF_READ_ANY_PAGE, page_id, page_size, false);
+ 0, BUF_READ_ANY_PAGE, page_id, zip_size, false);
srv_stats.buf_pool_reads.add(count);
@@ -438,13 +429,10 @@ buffer buf_pool if it is not already there. Sets the io_fix flag and sets
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
released by the i/o-handler thread.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] sync true if synchronous aio is desired */
void
-buf_read_page_background(
- const page_id_t page_id,
- const page_size_t& page_size,
- bool sync)
+buf_read_page_background(const page_id_t page_id, ulint zip_size, bool sync)
{
ulint count;
dberr_t err;
@@ -453,7 +441,7 @@ buf_read_page_background(
&err, sync,
IORequest::DO_NOT_WAKE | IORequest::IGNORE_MISSING,
BUF_READ_ANY_PAGE,
- page_id, page_size, false);
+ page_id, zip_size, false);
switch (err) {
case DB_SUCCESS:
@@ -508,14 +496,11 @@ NOTE 3: the calling thread must want access to the page given: this rule is
set to prevent unintended read-aheads performed by ibuf routines, a situation
which could result in a deadlock if the OS does not support asynchronous io.
@param[in] page_id page id; see NOTE 3 above
-@param[in] page_size page size
-@param[in] inside_ibuf TRUE if we are inside ibuf routine
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in] ibuf whether if we are inside ibuf routine
@return number of page read requests issued */
ulint
-buf_read_ahead_linear(
- const page_id_t page_id,
- const page_size_t& page_size,
- ibool inside_ibuf)
+buf_read_ahead_linear(const page_id_t page_id, ulint zip_size, bool ibuf)
{
buf_pool_t* buf_pool = buf_pool_get(page_id);
buf_page_t* bpage;
@@ -554,7 +539,7 @@ buf_read_ahead_linear(
return(0);
}
- if (ibuf_bitmap_page(page_id, page_size) || trx_sys_hdr_page(page_id)) {
+ if (ibuf_bitmap_page(page_id, zip_size) || trx_sys_hdr_page(page_id)) {
/* If it is an ibuf bitmap page or trx sys hdr, we do
no read-ahead, as that could break the ibuf page access
@@ -715,9 +700,7 @@ buf_read_ahead_linear(
/* If we got this far, read-ahead can be sensible: do it */
- ulint ibuf_mode;
-
- ibuf_mode = inside_ibuf ? BUF_READ_IBUF_PAGES_ONLY : BUF_READ_ANY_PAGE;
+ ulint ibuf_mode = ibuf ? BUF_READ_IBUF_PAGES_ONLY : BUF_READ_ANY_PAGE;
/* Since Windows XP seems to schedule the i/o handler thread
very eagerly, and consequently it does not wait for the
@@ -731,11 +714,11 @@ buf_read_ahead_linear(
const page_id_t cur_page_id(page_id.space(), i);
- if (!ibuf_bitmap_page(cur_page_id, page_size)) {
+ if (!ibuf_bitmap_page(cur_page_id, zip_size)) {
count += buf_read_page_low(
&err, false,
IORequest::DO_NOT_WAKE,
- ibuf_mode, cur_page_id, page_size, false);
+ ibuf_mode, cur_page_id, zip_size, false);
switch (err) {
case DB_SUCCESS:
@@ -801,11 +784,8 @@ buf_read_ibuf_merge_pages(
#endif
for (ulint i = 0; i < n_stored; i++) {
- bool found;
- const page_size_t page_size(fil_space_get_page_size(
- space_ids[i], &found));
-
- if (!found) {
+ fil_space_t* s = fil_space_acquire_for_io(space_ids[i]);
+ if (!s) {
tablespace_deleted:
/* The tablespace was not found: remove all
entries for it */
@@ -817,6 +797,9 @@ tablespace_deleted:
continue;
}
+ const ulint zip_size = s->zip_size();
+ s->release_for_io();
+
const page_id_t page_id(space_ids[i], page_nos[i]);
buf_pool_t* buf_pool = buf_pool_get(page_id);
@@ -831,7 +814,7 @@ tablespace_deleted:
buf_read_page_low(&err,
sync && (i + 1 == n_stored),
0,
- BUF_READ_ANY_PAGE, page_id, page_size,
+ BUF_READ_ANY_PAGE, page_id, zip_size,
true, true /* ignore_missing_space */);
switch(err) {
@@ -882,7 +865,7 @@ buf_read_recv_pages(
fil_space_open_if_needed(space);
- const page_size_t page_size(space->flags);
+ const ulint zip_size = space->zip_size();
for (ulint i = 0; i < n_stored; i++) {
buf_pool_t* buf_pool;
@@ -915,13 +898,13 @@ buf_read_recv_pages(
&err, true,
0,
BUF_READ_ANY_PAGE,
- cur_page_id, page_size, true);
+ cur_page_id, zip_size, true);
} else {
buf_read_page_low(
&err, false,
IORequest::DO_NOT_WAKE,
BUF_READ_ANY_PAGE,
- cur_page_id, page_size, true);
+ cur_page_id, zip_size, true);
}
if (err == DB_DECRYPTION_FAILED || err == DB_PAGE_CORRUPTED) {
diff --git a/storage/innobase/data/data0data.cc b/storage/innobase/data/data0data.cc
index 9474b9bd18b..a95b56d2247 100644
--- a/storage/innobase/data/data0data.cc
+++ b/storage/innobase/data/data0data.cc
@@ -610,6 +610,12 @@ dtuple_convert_big_rec(
return(NULL);
}
+ if (!index->table->space) {
+ return NULL;
+ }
+
+ const auto zip_size = index->table->space->zip_size();
+
ut_ad(index->n_uniq > 0);
ut_a(dtuple_check_typed_no_assert(entry));
@@ -660,7 +666,7 @@ dtuple_convert_big_rec(
*n_ext),
index->table->not_redundant(),
dict_index_get_n_fields(index),
- dict_table_page_size(index->table))) {
+ zip_size)) {
longest_i = 0;
for (ulint i = index->first_user_field(), longest = 0;
i + mblob < entry->n_fields; i++) {
diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc
index 7a9b8556c1a..2a80def7335 100644
--- a/storage/innobase/dict/dict0boot.cc
+++ b/storage/innobase/dict/dict0boot.cc
@@ -47,7 +47,7 @@ dict_hdr_get(
dict_hdr_t* header;
block = buf_page_get(page_id_t(DICT_HDR_SPACE, DICT_HDR_PAGE_NO),
- univ_page_size, RW_X_LATCH, mtr);
+ 0, RW_X_LATCH, mtr);
header = DICT_HDR + buf_block_get_frame(block);
buf_block_dbg_add_level(block, SYNC_DICT_HEADER);
diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc
index b1ddb7032ab..d8b9bcdaf39 100644
--- a/storage/innobase/dict/dict0crea.cc
+++ b/storage/innobase/dict/dict0crea.cc
@@ -960,21 +960,19 @@ dict_drop_index_tree(
ut_ad(len == 8);
- bool found;
- const page_size_t page_size(fil_space_get_page_size(space,
- &found));
-
- if (!found) {
- /* It is a single table tablespace and the .ibd file is
- missing: do nothing */
-
- return(false);
+ if (fil_space_t* s = fil_space_acquire_silent(space)) {
+ /* Ensure that the tablespace file exists
+ in order to avoid a crash in buf_page_get_gen(). */
+ if (s->size || fil_space_get_size(space)) {
+ btr_free_if_exists(page_id_t(space, root_page_no),
+ s->zip_size(),
+ mach_read_from_8(ptr), mtr);
+ }
+ s->release();
+ return true;
}
- btr_free_if_exists(page_id_t(space, root_page_no), page_size,
- mach_read_from_8(ptr), mtr);
-
- return(true);
+ return false;
}
/*******************************************************************//**
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index 4ea5a5b30e9..7664bc2064d 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -2118,10 +2118,9 @@ dict_index_too_big_for_tree(
comp = dict_table_is_comp(table);
- const page_size_t page_size(dict_tf_get_page_size(table->flags));
+ const ulint zip_size = dict_tf_get_zip_size(table->flags);
- if (page_size.is_compressed()
- && page_size.physical() < srv_page_size) {
+ if (zip_size && zip_size < srv_page_size) {
/* On a compressed page, two records must fit in the
uncompressed page modification log. On compressed pages
with size.physical() == srv_page_size,
@@ -2132,7 +2131,7 @@ dict_index_too_big_for_tree(
number in the page modification log. The maximum
allowed node pointer size is half that. */
page_rec_max = page_zip_empty_size(new_index->n_fields,
- page_size.physical());
+ zip_size);
if (page_rec_max) {
page_rec_max--;
}
@@ -7073,52 +7072,3 @@ dict_space_get_id(
return(id);
}
-
-/** Determine the extent size (in pages) for the given table
-@param[in] table the table whose extent size is being
- calculated.
-@return extent size in pages (256, 128 or 64) */
-ulint
-dict_table_extent_size(
- const dict_table_t* table)
-{
- const ulint mb_1 = 1024 * 1024;
- const ulint mb_2 = 2 * mb_1;
- const ulint mb_4 = 4 * mb_1;
-
- page_size_t page_size = dict_table_page_size(table);
- ulint pages_in_extent = FSP_EXTENT_SIZE;
-
- if (page_size.is_compressed()) {
-
- ulint disk_page_size = page_size.physical();
-
- switch (disk_page_size) {
- case 1024:
- pages_in_extent = mb_1/1024;
- break;
- case 2048:
- pages_in_extent = mb_1/2048;
- break;
- case 4096:
- pages_in_extent = mb_1/4096;
- break;
- case 8192:
- pages_in_extent = mb_1/8192;
- break;
- case 16384:
- pages_in_extent = mb_1/16384;
- break;
- case 32768:
- pages_in_extent = mb_2/32768;
- break;
- case 65536:
- pages_in_extent = mb_4/65536;
- break;
- default:
- ut_ad(0);
- }
- }
-
- return(pages_in_extent);
-}
diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc
index f236d2edadf..f4b05766e79 100644
--- a/storage/innobase/dict/dict0stats.cc
+++ b/storage/innobase/dict/dict0stats.cc
@@ -1505,7 +1505,7 @@ dict_stats_analyze_index_below_cur(
page_id_t page_id(index->table->space_id,
btr_node_ptr_get_child_page_no(
rec, offsets_rec));
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
/* assume no external pages by default - in case we quit from this
function without analyzing any leaf pages */
@@ -1518,7 +1518,7 @@ dict_stats_analyze_index_below_cur(
dberr_t err = DB_SUCCESS;
- block = buf_page_get_gen(page_id, page_size, RW_S_LATCH,
+ block = buf_page_get_gen(page_id, zip_size, RW_S_LATCH,
NULL /* no guessed block */,
BUF_GET, __FILE__, __LINE__, &mtr, &err);
diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc
index a30be6c5aed..b49bd5cc04d 100644
--- a/storage/innobase/fil/fil0crypt.cc
+++ b/storage/innobase/fil/fil0crypt.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (C) 2013, 2015, Google Inc. All Rights Reserved.
-Copyright (c) 2014, 2018, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 2014, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -274,16 +274,14 @@ fil_space_merge_crypt_data(
}
/** Initialize encryption parameters from a tablespace header page.
-@param[in] page_size page size of the tablespace
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] page first page of the tablespace
@return crypt data from page 0
@retval NULL if not present or not valid */
-UNIV_INTERN
-fil_space_crypt_t*
-fil_space_read_crypt_data(const page_size_t& page_size, const byte* page)
+fil_space_crypt_t* fil_space_read_crypt_data(ulint zip_size, const byte* page)
{
const ulint offset = FSP_HEADER_OFFSET
- + fsp_header_get_encryption_offset(page_size);
+ + fsp_header_get_encryption_offset(zip_size);
if (memcmp(page + offset, CRYPT_MAGIC, MAGIC_SZ) != 0) {
/* Crypt data is not stored. */
@@ -371,7 +369,7 @@ fil_space_crypt_t::write_page0(
ut_ad(this == space->crypt_data);
const uint len = sizeof(iv);
const ulint offset = FSP_HEADER_OFFSET
- + fsp_header_get_encryption_offset(page_size_t(space->flags));
+ + fsp_header_get_encryption_offset(space->zip_size());
page0_offset = offset;
/*
@@ -545,7 +543,7 @@ fil_parse_write_crypt_data(
@param[in] offset Page offset
@param[in] lsn Log sequence number
@param[in] src_frame Page to encrypt
-@param[in] page_size Page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] dst_frame Output buffer
@return encrypted buffer or NULL */
UNIV_INTERN
@@ -556,10 +554,10 @@ fil_encrypt_buf(
ulint offset,
lsn_t lsn,
const byte* src_frame,
- const page_size_t& page_size,
+ ulint zip_size,
byte* dst_frame)
{
- uint size = uint(page_size.physical());
+ uint size = uint(zip_size ? zip_size : srv_page_size);
uint key_version = fil_crypt_get_latest_key_version(crypt_data);
ut_a(key_version != ENCRYPTION_KEY_VERSION_INVALID);
@@ -601,24 +599,24 @@ fil_encrypt_buf(
to sector boundary is written. */
if (!page_compressed) {
/* FIL page trailer is also not encrypted */
- memcpy(dst_frame + page_size.physical() - FIL_PAGE_DATA_END,
- src_frame + page_size.physical() - FIL_PAGE_DATA_END,
+ memcpy(dst_frame + size - FIL_PAGE_DATA_END,
+ src_frame + size - FIL_PAGE_DATA_END,
FIL_PAGE_DATA_END);
} else {
/* Clean up rest of buffer */
memset(dst_frame+header_len+srclen, 0,
- page_size.physical() - (header_len + srclen));
+ size - (header_len + srclen));
}
/* handle post encryption checksum */
ib_uint32_t checksum = 0;
- checksum = fil_crypt_calculate_checksum(page_size, dst_frame);
+ checksum = fil_crypt_calculate_checksum(zip_size, dst_frame);
// store the post-encryption checksum after the key-version
mach_write_to_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4, checksum);
- ut_ad(fil_space_verify_crypt_checksum(dst_frame, page_size));
+ ut_ad(fil_space_verify_crypt_checksum(dst_frame, zip_size));
srv_stats.pages_encrypted.inc();
@@ -657,10 +655,10 @@ fil_space_encrypt(
}
fil_space_crypt_t* crypt_data = space->crypt_data;
- const page_size_t page_size(space->flags);
+ const ulint zip_size = space->zip_size();
ut_ad(space->pending_io());
byte* tmp = fil_encrypt_buf(crypt_data, space->id, offset, lsn,
- src_frame, page_size, dst_frame);
+ src_frame, zip_size, dst_frame);
#ifdef UNIV_DEBUG
if (tmp) {
@@ -681,8 +679,9 @@ fil_space_encrypt(
}
}
- ut_ad(!buf_page_is_corrupted(true, src, page_size, space));
- ut_ad(fil_space_decrypt(crypt_data, tmp_mem, page_size, tmp,
+ ut_ad(!buf_page_is_corrupted(true, src, zip_size, space));
+ ut_ad(fil_space_decrypt(crypt_data, tmp_mem,
+ space->physical_size(), tmp,
&err));
ut_ad(err == DB_SUCCESS);
@@ -696,7 +695,7 @@ fil_space_encrypt(
memcpy(tmp_mem + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
src + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 8);
- ut_ad(!memcmp(src, tmp_mem, page_size.physical()));
+ ut_ad(!memcmp(src, tmp_mem, space->physical_size()));
}
#endif /* UNIV_DEBUG */
@@ -706,7 +705,7 @@ fil_space_encrypt(
/** Decrypt a page.
@param[in] crypt_data crypt_data
@param[in] tmp_frame Temporary buffer
-@param[in] page_size Page size
+@param[in] physical_size page size
@param[in,out] src_frame Page to decrypt
@param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED
@return true if page decrypted, false if not.*/
@@ -715,7 +714,7 @@ bool
fil_space_decrypt(
fil_space_crypt_t* crypt_data,
byte* tmp_frame,
- const page_size_t& page_size,
+ ulint physical_size,
byte* src_frame,
dberr_t* err)
{
@@ -748,8 +747,7 @@ fil_space_decrypt(
const byte* src = src_frame + header_len;
byte* dst = tmp_frame + header_len;
uint32 dstlen = 0;
- uint srclen = uint(page_size.physical())
- - header_len - FIL_PAGE_DATA_END;
+ uint srclen = uint(physical_size) - header_len - FIL_PAGE_DATA_END;
if (page_compressed) {
srclen = mach_read_from_2(src_frame + FIL_PAGE_DATA);
@@ -779,8 +777,8 @@ fil_space_decrypt(
to sector boundary is written. */
if (!page_compressed) {
/* Copy FIL trailer */
- memcpy(tmp_frame + page_size.physical() - FIL_PAGE_DATA_END,
- src_frame + page_size.physical() - FIL_PAGE_DATA_END,
+ memcpy(tmp_frame + physical_size - FIL_PAGE_DATA_END,
+ src_frame + physical_size - FIL_PAGE_DATA_END,
FIL_PAGE_DATA_END);
}
@@ -807,21 +805,21 @@ fil_space_decrypt(
{
dberr_t err = DB_SUCCESS;
byte* res = NULL;
- const page_size_t page_size(space->flags);
+ const ulint physical_size = space->physical_size();
*decrypted = false;
ut_ad(space->crypt_data != NULL && space->crypt_data->is_encrypted());
ut_ad(space->pending_io());
bool encrypted = fil_space_decrypt(space->crypt_data, tmp_frame,
- page_size, src_frame, &err);
+ physical_size, src_frame, &err);
if (err == DB_SUCCESS) {
if (encrypted) {
*decrypted = true;
/* Copy the decrypted page back to page buffer, not
really any other options. */
- memcpy(src_frame, tmp_frame, page_size.physical());
+ memcpy(src_frame, tmp_frame, physical_size);
}
res = src_frame;
@@ -830,21 +828,18 @@ fil_space_decrypt(
return res;
}
-/******************************************************************
+/**
Calculate post encryption checksum
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] dst_frame Block where checksum is calculated
@return page checksum
not needed. */
-UNIV_INTERN
uint32_t
-fil_crypt_calculate_checksum(
- const page_size_t& page_size,
- const byte* dst_frame)
+fil_crypt_calculate_checksum(ulint zip_size, const byte* dst_frame)
{
/* For encrypted tables we use only crc32 and strict_crc32 */
- return page_size.is_compressed()
- ? page_zip_calc_checksum(dst_frame, page_size.physical(),
+ return zip_size
+ ? page_zip_calc_checksum(dst_frame, zip_size,
SRV_CHECKSUM_ALGORITHM_CRC32)
: buf_calc_page_crc32(dst_frame);
}
@@ -952,15 +947,15 @@ fil_crypt_read_crypt_data(fil_space_t* space)
return;
}
- const page_size_t page_size(space->flags);
+ const ulint zip_size = space->zip_size();
mtr_t mtr;
mtr.start();
if (buf_block_t* block = buf_page_get(page_id_t(space->id, 0),
- page_size, RW_S_LATCH, &mtr)) {
+ zip_size, RW_S_LATCH, &mtr)) {
mutex_enter(&fil_system.mutex);
if (!space->crypt_data) {
space->crypt_data = fil_space_read_crypt_data(
- page_size, block->frame);
+ zip_size, block->frame);
}
mutex_exit(&fil_system.mutex);
}
@@ -1034,7 +1029,7 @@ fil_crypt_start_encrypting_space(
/* 2 - get page 0 */
dberr_t err = DB_SUCCESS;
buf_block_t* block = buf_page_get_gen(
- page_id_t(space->id, 0), page_size_t(space->flags),
+ page_id_t(space->id, 0), space->zip_size(),
RW_X_LATCH, NULL, BUF_GET,
__FILE__, __LINE__,
&mtr, &err);
@@ -1623,7 +1618,7 @@ fil_crypt_get_page_throttle_func(
unsigned line)
{
fil_space_t* space = state->space;
- const page_size_t page_size = page_size_t(space->flags);
+ const ulint zip_size = space->zip_size();
const page_id_t page_id(space->id, offset);
ut_ad(space->referenced());
@@ -1634,7 +1629,7 @@ fil_crypt_get_page_throttle_func(
}
dberr_t err = DB_SUCCESS;
- buf_block_t* block = buf_page_get_gen(page_id, page_size, RW_X_LATCH,
+ buf_block_t* block = buf_page_get_gen(page_id, zip_size, RW_X_LATCH,
NULL,
BUF_PEEK_IF_IN_POOL, file, line,
mtr, &err);
@@ -1651,7 +1646,7 @@ fil_crypt_get_page_throttle_func(
state->crypt_stat.pages_read_from_disk++;
uintmax_t start = ut_time_us(NULL);
- block = buf_page_get_gen(page_id, page_size,
+ block = buf_page_get_gen(page_id, zip_size,
RW_X_LATCH,
NULL, BUF_GET_POSSIBLY_FREED,
file, line, mtr, &err);
@@ -2020,7 +2015,7 @@ fil_crypt_flush_space(
dberr_t err;
if (buf_block_t* block = buf_page_get_gen(
- page_id_t(space->id, 0), page_size_t(space->flags),
+ page_id_t(space->id, 0), space->zip_size(),
RW_X_LATCH, NULL, BUF_GET,
__FILE__, __LINE__, &mtr, &err)) {
mtr.set_named_space(space);
@@ -2527,10 +2522,9 @@ calculated checksum as if it does page could be valid unencrypted,
encrypted, or corrupted.
@param[in,out] page page frame (checksum is temporarily modified)
-@param[in] page_size page size
-@return whether the encrypted page is OK */
-bool
-fil_space_verify_crypt_checksum(const byte* page, const page_size_t& page_size)
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@return true if page is encrypted AND OK, false otherwise */
+bool fil_space_verify_crypt_checksum(const byte* page, ulint zip_size)
{
ut_ad(mach_read_from_4(page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION));
@@ -2551,10 +2545,9 @@ fil_space_verify_crypt_checksum(const byte* page, const page_size_t& page_size)
switch (srv_checksum_algorithm_t(srv_checksum_algorithm)) {
case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
- if (page_size.is_compressed()) {
+ if (zip_size) {
return checksum == page_zip_calc_checksum(
- page, page_size.physical(),
- SRV_CHECKSUM_ALGORITHM_CRC32);
+ page, zip_size, SRV_CHECKSUM_ALGORITHM_CRC32);
}
return checksum == buf_calc_page_crc32(page);
@@ -2575,12 +2568,12 @@ fil_space_verify_crypt_checksum(const byte* page, const page_size_t& page_size)
if (checksum == BUF_NO_CHECKSUM_MAGIC) {
return true;
}
- if (page_size.is_compressed()) {
+ if (zip_size) {
return checksum == page_zip_calc_checksum(
- page, page_size.physical(),
+ page, zip_size,
SRV_CHECKSUM_ALGORITHM_CRC32)
|| checksum == page_zip_calc_checksum(
- page, page_size.physical(),
+ page, zip_size,
SRV_CHECKSUM_ALGORITHM_INNODB);
}
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index e891c5bcdf8..0a35e183e06 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -261,7 +261,7 @@ fil_node_complete_io(fil_node_t* node, const IORequest& type);
blocks at the end of file are ignored: they are not taken into account when
calculating the byte offset within a space.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] byte_offset remainder of offset in bytes; in aio this
must be divisible by the OS block size
@param[in] len how many bytes to read; this must not cross a
@@ -274,12 +274,12 @@ UNIV_INLINE
dberr_t
fil_read(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint byte_offset,
ulint len,
void* buf)
{
- return(fil_io(IORequestRead, true, page_id, page_size,
+ return(fil_io(IORequestRead, true, page_id, zip_size,
byte_offset, len, buf, NULL));
}
@@ -287,7 +287,7 @@ fil_read(
blocks at the end of file are ignored: they are not taken into account when
calculating the byte offset within a space.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] byte_offset remainder of offset in bytes; in aio this
must be divisible by the OS block size
@param[in] len how many bytes to write; this must not cross
@@ -300,14 +300,14 @@ UNIV_INLINE
dberr_t
fil_write(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint byte_offset,
ulint len,
void* buf)
{
ut_ad(!srv_read_only_mode);
- return(fil_io(IORequestWrite, true, page_id, page_size,
+ return(fil_io(IORequestWrite, true, page_id, zip_size,
byte_offset, len, buf, NULL));
}
@@ -389,8 +389,7 @@ void fil_space_t::set_imported()
const fil_node_t* node = UT_LIST_GET_FIRST(chain);
atomic_write_supported = node->atomic_write
&& srv_use_atomic_writes
- && my_test_if_atomic_write(node->handle,
- int(page_size_t(flags).physical()));
+ && my_test_if_atomic_write(node->handle, physical_size());
purpose = FIL_TYPE_TABLESPACE;
}
@@ -477,8 +476,7 @@ bool fil_node_t::read_page0(bool first)
{
ut_ad(mutex_own(&fil_system.mutex));
ut_a(space->purpose != FIL_TYPE_LOG);
- const page_size_t page_size(space->flags);
- const ulint psize = page_size.physical();
+ const ulint psize = space->physical_size();
os_offset_t size_bytes = os_file_get_size(handle);
ut_a(size_bytes != (os_offset_t) -1);
@@ -507,12 +505,6 @@ bool fil_node_t::read_page0(bool first)
const ulint free_limit = fsp_header_get_field(page, FSP_FREE_LIMIT);
const ulint free_len = flst_get_len(FSP_HEADER_OFFSET + FSP_FREE
+ page);
- /* Try to read crypt_data from page 0 if it is not yet read. */
- if (!space->crypt_data) {
- space->crypt_data = fil_space_read_crypt_data(page_size, page);
- }
- ut_free(buf2);
-
if (!fsp_flags_is_valid(flags, space->id)) {
ulint cflags = fsp_flags_convert_from_101(flags);
if (cflags == ULINT_UNDEFINED
@@ -522,12 +514,20 @@ bool fil_node_t::read_page0(bool first)
<< ib::hex(space->flags)
<< " but found " << ib::hex(flags)
<< " in the file " << name;
+ ut_free(buf2);
return false;
}
flags = cflags;
}
+ /* Try to read crypt_data from page 0 if it is not yet read. */
+ if (!space->crypt_data) {
+ space->crypt_data = fil_space_read_crypt_data(
+ fil_space_t::zip_size(flags), page);
+ }
+ ut_free(buf2);
+
if (UNIV_UNLIKELY(space_id != space->id)) {
ib::error() << "Expected tablespace id " << space->id
<< " but found " << space_id
@@ -647,9 +647,7 @@ retry:
|| (node->atomic_write
&& srv_use_atomic_writes
&& my_test_if_atomic_write(
- node->handle,
- int(page_size_t(space->flags)
- .physical())));
+ node->handle, space->physical_size()));
}
ut_a(success);
@@ -921,8 +919,7 @@ fil_space_extend_must_retry(
node->handle, node->name);
}
- const page_size_t pageSize(space->flags);
- const ulint page_size = pageSize.physical();
+ const ulint page_size = space->physical_size();
/* fil_read_first_page() expects srv_page_size bytes.
fil_node_open_file() expects at least 4 * srv_page_size bytes.*/
@@ -982,7 +979,6 @@ fil_space_extend_must_retry(
srv_tmp_space.set_last_file_size(pages_in_MiB);
return(false);
}
-
}
/*******************************************************************//**
@@ -1637,28 +1633,6 @@ void fil_space_t::close()
mutex_exit(&fil_system.mutex);
}
-/** Returns the page size of the space and whether it is compressed or not.
-The tablespace must be cached in the memory cache.
-@param[in] id space id
-@param[out] found true if tablespace was found
-@return page size */
-const page_size_t
-fil_space_get_page_size(
- ulint id,
- bool* found)
-{
- const ulint flags = fil_space_get_flags(id);
-
- if (flags == ULINT_UNDEFINED) {
- *found = false;
- return(univ_page_size);
- }
-
- *found = true;
-
- return(page_size_t(flags));
-}
-
void fil_system_t::create(ulint hash_size)
{
ut_ad(this == &fil_system);
@@ -1896,13 +1870,11 @@ fil_write_flushed_lsn(
const page_id_t page_id(TRX_SYS_SPACE, 0);
- err = fil_read(page_id, univ_page_size, 0, srv_page_size,
- buf);
+ err = fil_read(page_id, 0, 0, srv_page_size, buf);
if (err == DB_SUCCESS) {
mach_write_to_8(buf + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, lsn);
- err = fil_write(page_id, univ_page_size, 0,
- srv_page_size, buf);
+ err = fil_write(page_id, 0, 0, srv_page_size, buf);
fil_flush_file_spaces(FIL_TYPE_TABLESPACE);
}
@@ -3050,18 +3022,9 @@ err_exit:
fsp_header_init_fields(page, space_id, flags);
mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id);
- const page_size_t page_size(flags);
- IORequest request(IORequest::WRITE);
-
- if (!page_size.is_compressed()) {
-
- buf_flush_init_for_writing(NULL, page, NULL, 0);
-
- *err = os_file_write(
- request, path, file, page, 0, page_size.physical());
- } else {
+ if (ulint zip_size = fil_space_t::zip_size(flags)) {
page_zip_des_t page_zip;
- page_zip_set_size(&page_zip, page_size.physical());
+ page_zip_set_size(&page_zip, zip_size);
page_zip.data = page + srv_page_size;
#ifdef UNIV_DEBUG
page_zip.m_start =
@@ -3072,8 +3035,12 @@ err_exit:
buf_flush_init_for_writing(NULL, page, &page_zip, 0);
*err = os_file_write(
- request, path, file, page_zip.data, 0,
- page_size.physical());
+ IORequestWrite, path, file, page_zip.data, 0, zip_size);
+ } else {
+ buf_flush_init_for_writing(NULL, page, NULL, 0);
+
+ *err = os_file_write(
+ IORequestWrite, path, file, page, 0, srv_page_size);
}
ut_free(buf2);
@@ -3487,7 +3454,8 @@ skip_validate:
df_remote.get_first_page();
fil_space_crypt_t* crypt_data = first_page
- ? fil_space_read_crypt_data(page_size_t(flags), first_page)
+ ? fil_space_read_crypt_data(fil_space_t::zip_size(flags),
+ first_page)
: NULL;
fil_space_t* space = fil_space_create(
@@ -3835,7 +3803,8 @@ fil_ibd_load(
const byte* first_page = file.get_first_page();
fil_space_crypt_t* crypt_data = first_page
- ? fil_space_read_crypt_data(page_size_t(flags), first_page)
+ ? fil_space_read_crypt_data(fil_space_t::zip_size(flags),
+ first_page)
: NULL;
space = fil_space_create(
file.name(), space_id, flags, FIL_TYPE_TABLESPACE, crypt_data);
@@ -3909,7 +3878,7 @@ void fsp_flags_try_adjust(fil_space_t* space, ulint flags)
mtr_t mtr;
mtr.start();
if (buf_block_t* b = buf_page_get(
- page_id_t(space->id, 0), page_size_t(flags),
+ page_id_t(space->id, 0), space->zip_size(),
RW_X_LATCH, &mtr)) {
ulint f = fsp_header_get_flags(b->frame);
/* Suppress the message if only the DATA_DIR flag to differs. */
@@ -4110,7 +4079,7 @@ fil_report_invalid_page_access(
@param[in,out] type IO context
@param[in] sync true if synchronous aio is desired
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] byte_offset remainder of offset in bytes; in aio this
must be divisible by the OS block size
@param[in] len how many bytes to read or write; this must
@@ -4129,7 +4098,7 @@ fil_io(
const IORequest& type,
bool sync,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint byte_offset,
ulint len,
void* buf,
@@ -4143,7 +4112,7 @@ fil_io(
ut_ad(len > 0);
ut_ad(byte_offset < srv_page_size);
- ut_ad(!page_size.is_compressed() || byte_offset == 0);
+ ut_ad(!zip_size || byte_offset == 0);
ut_ad(srv_page_size == 1UL << srv_page_size_shift);
compile_time_assert((1U << UNIV_PAGE_SIZE_SHIFT_MAX)
== UNIV_PAGE_SIZE_MAX);
@@ -4154,7 +4123,7 @@ fil_io(
/* ibuf bitmap pages must be read in the sync AIO mode: */
ut_ad(recv_no_ibuf_operations
|| req_type.is_write()
- || !ibuf_bitmap_page(page_id, page_size)
+ || !ibuf_bitmap_page(page_id, zip_size)
|| sync
|| req_type.is_log());
@@ -4170,7 +4139,7 @@ fil_io(
} else if (req_type.is_read()
&& !recv_no_ibuf_operations
- && ibuf_page(page_id, page_size, NULL)) {
+ && ibuf_page(page_id, zip_size, NULL)) {
mode = OS_AIO_IBUF;
@@ -4312,37 +4281,10 @@ fil_io(
/* Now we have made the changes in the data structures of fil_system */
mutex_exit(&fil_system.mutex);
- /* Calculate the low 32 bits and the high 32 bits of the file offset */
-
- if (!page_size.is_compressed()) {
+ if (!zip_size) zip_size = srv_page_size;
- offset = ((os_offset_t) cur_page_no
- << srv_page_size_shift) + byte_offset;
-
- ut_a(node->size - cur_page_no
- >= ((byte_offset + len + (srv_page_size - 1))
- >> srv_page_size_shift));
- } else {
- ulint size_shift;
-
- switch (page_size.physical()) {
- case 1024: size_shift = 10; break;
- case 2048: size_shift = 11; break;
- case 4096: size_shift = 12; break;
- case 8192: size_shift = 13; break;
- case 16384: size_shift = 14; break;
- case 32768: size_shift = 15; break;
- case 65536: size_shift = 16; break;
- default: ut_error;
- }
-
- offset = ((os_offset_t) cur_page_no << size_shift)
- + byte_offset;
-
- ut_a(node->size - cur_page_no
- >= (len + (page_size.physical() - 1))
- / page_size.physical());
- }
+ offset = os_offset_t(cur_page_no) * zip_size + byte_offset;
+ ut_ad(node->size - cur_page_no >= (len + (zip_size - 1)) / zip_size);
/* Do AIO */
diff --git a/storage/innobase/fil/fil0pagecompress.cc b/storage/innobase/fil/fil0pagecompress.cc
index 57bb736d230..adb41709027 100644
--- a/storage/innobase/fil/fil0pagecompress.cc
+++ b/storage/innobase/fil/fil0pagecompress.cc
@@ -250,8 +250,7 @@ success:
page_t page[UNIV_PAGE_SIZE_MAX];
memcpy(page, out_buf, srv_page_size);
ut_ad(fil_page_decompress(tmp_buf, page));
- ut_ad(!buf_page_is_corrupted(false, page, univ_page_size,
- NULL));
+ ut_ad(!buf_page_is_corrupted(false, page, 0, NULL));
}
#endif /* UNIV_DEBUG */
diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc
index 3070f989c04..fdcb4070894 100644
--- a/storage/innobase/fsp/fsp0file.cc
+++ b/storage/innobase/fsp/fsp0file.cc
@@ -356,8 +356,14 @@ Datafile::read_first_page(bool read_only_mode)
}
}
- const page_size_t ps(m_flags);
- if (ps.physical() > page_size) {
+ ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(m_flags);
+ if (!ssize) ssize = UNIV_PAGE_SSIZE_ORIG;
+ const ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(m_flags);
+ const size_t logical_size = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize);
+ const size_t physical_size = zip_ssize
+ ? (UNIV_ZIP_SIZE_MIN >> 1) << zip_ssize : logical_size;
+
+ if (physical_size > page_size) {
ib::error() << "File " << m_filepath
<< " should be longer than "
<< page_size << " bytes";
@@ -543,13 +549,13 @@ err_exit:
goto err_exit;
}
- const page_size_t page_size(m_flags);
+ ulint logical_size = fil_space_t::logical_size(m_flags);
- if (srv_page_size != page_size.logical()) {
+ if (srv_page_size != logical_size) {
/* Logical size must be innodb_page_size. */
ib::error()
<< "Data file '" << m_filepath << "' uses page size "
- << page_size.logical() << ", but the innodb_page_size"
+ << logical_size << ", but the innodb_page_size"
" start-up parameter is "
<< srv_page_size;
free_first_page();
@@ -568,7 +574,8 @@ err_exit:
goto err_exit;
}
- if (buf_page_is_corrupted(false, m_first_page, page_size)) {
+ if (buf_page_is_corrupted(false, m_first_page,
+ fil_space_t::zip_size(m_flags))) {
/* Look for checksum and other corruptions. */
error_txt = "Checksum mismatch";
goto err_exit;
@@ -630,7 +637,6 @@ Datafile::find_space_id()
for (ulint page_size = UNIV_ZIP_SIZE_MIN;
page_size <= UNIV_PAGE_SIZE_MAX;
page_size <<= 1) {
-
/* map[space_id] = count of pages */
typedef std::map<
ulint,
@@ -681,27 +687,16 @@ Datafile::find_space_id()
equal to srv_page_size. */
if (page_size == srv_page_size) {
noncompressed_ok = !buf_page_is_corrupted(
- false, page, univ_page_size, NULL);
+ false, page, 0, NULL);
}
bool compressed_ok = false;
- /* file-per-table tablespaces can be compressed with
- the same physical and logical page size. General
- tablespaces must have different physical and logical
- page sizes in order to be compressed. For this check,
- assume the page is compressed if univ_page_size.
- logical() is equal to or less than 16k and the
- page_size we are checking is equal to or less than
- srv_page_size. */
if (srv_page_size <= UNIV_PAGE_SIZE_DEF
&& page_size <= srv_page_size) {
- const page_size_t compr_page_size(
- page_size, srv_page_size,
- true);
-
compressed_ok = !buf_page_is_corrupted(
- false, page, compr_page_size, NULL);
+ false, page,
+ page_size, NULL);
}
if (noncompressed_ok || compressed_ok) {
@@ -801,21 +796,21 @@ Datafile::restore_from_doublewrite()
/* The flags on the page should be converted later. */
}
- const page_size_t page_size(flags);
+ ulint physical_size = fil_space_t::physical_size(flags);
ut_a(page_get_page_no(page) == page_id.page_no());
ib::info() << "Restoring page " << page_id
<< " of datafile '" << m_filepath
<< "' from the doublewrite buffer. Writing "
- << page_size.physical() << " bytes into file '"
+ << physical_size << " bytes into file '"
<< m_filepath << "'";
IORequest request(IORequest::WRITE);
return(os_file_write(
request,
- m_filepath, m_handle, page, 0, page_size.physical())
+ m_filepath, m_handle, page, 0, physical_size)
!= DB_SUCCESS);
}
diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc
index 9e92646556c..cd0454d0cca 100644
--- a/storage/innobase/fsp/fsp0fsp.cc
+++ b/storage/innobase/fsp/fsp0fsp.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2018, MariaDB Corporation.
+Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -50,7 +50,6 @@ typedef ulint page_no_t;
/** Return an extent to the free list of a space.
@param[in,out] space tablespace
@param[in] offset page number in the extent
-@param[in] page_size page size
@param[in,out] mtr mini-transaction */
MY_ATTRIBUTE((nonnull))
static
@@ -58,7 +57,6 @@ void
fsp_free_extent(
fil_space_t* space,
page_no_t offset,
- const page_size_t& page_size,
mtr_t* mtr);
/********************************************************************//**
@@ -78,7 +76,6 @@ We think of the extent lists of the segment catenated in the order
FSEG_FULL -> FSEG_NOT_FULL -> FSEG_FREE.
@param[in] inode segment inode
@param[in] space tablespace
-@param[in] page_size page size
@param[in,out] mtr mini-transaction
@return the first extent descriptor, or NULL if none */
MY_ATTRIBUTE((nonnull, warn_unused_result))
@@ -87,7 +84,6 @@ xdes_t*
fseg_get_first_extent(
fseg_inode_t* inode,
const fil_space_t* space,
- const page_size_t& page_size,
mtr_t* mtr);
/** Put new extents to the free list if there are free extents above the free
@@ -111,7 +107,6 @@ fsp_fill_free_list(
This function implements the intelligent allocation strategy which tries
to minimize file space fragmentation.
@param[in,out] space tablespace
-@param[in] page_size page size
@param[in,out] seg_inode segment inode
@param[in] hint hint of which page would be desirable
@param[in] direction if the new page is needed because of
@@ -132,7 +127,6 @@ static
buf_block_t*
fseg_alloc_free_page_low(
fil_space_t* space,
- const page_size_t& page_size,
fseg_inode_t* seg_inode,
ulint hint,
byte direction,
@@ -147,24 +141,16 @@ fseg_alloc_free_page_low(
/** Gets a pointer to the space header and x-locks its page.
@param[in] space tablespace
-@param[in] page_size page size
@param[in,out] mtr mini-transaction
@return pointer to the space header, page x-locked */
-UNIV_INLINE
-fsp_header_t*
-fsp_get_space_header(
- const fil_space_t* space,
- const page_size_t& page_size,
- mtr_t* mtr)
+inline fsp_header_t* fsp_get_space_header(const fil_space_t* space, mtr_t* mtr)
{
buf_block_t* block;
fsp_header_t* header;
ut_ad(space->purpose != FIL_TYPE_LOG);
- ut_ad(!FSP_FLAGS_GET_ZIP_SSIZE(space->flags)
- == !page_size.is_compressed());
- block = buf_page_get(page_id_t(space->id, 0), page_size,
+ block = buf_page_get(page_id_t(space->id, 0), space->zip_size(),
RW_SX_LATCH, mtr);
header = FSP_HEADER_OFFSET + buf_block_get_frame(block);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
@@ -427,9 +413,9 @@ xdes_get_descriptor_with_space_hdr(
return(NULL);
}
- const page_size_t page_size(space->flags);
+ const ulint zip_size = space->zip_size();
- descr_page_no = xdes_calc_descriptor_page(page_size, offset);
+ descr_page_no = xdes_calc_descriptor_page(zip_size, offset);
buf_block_t* block;
@@ -440,7 +426,7 @@ xdes_get_descriptor_with_space_hdr(
block = NULL;
} else {
block = buf_page_get(
- page_id_t(space->id, descr_page_no), page_size,
+ page_id_t(space->id, descr_page_no), zip_size,
RW_SX_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
@@ -453,7 +439,7 @@ xdes_get_descriptor_with_space_hdr(
}
return(descr_page + XDES_ARR_OFFSET
- + XDES_SIZE * xdes_calc_descriptor_index(page_size, offset));
+ + XDES_SIZE * xdes_calc_descriptor_index(zip_size, offset));
}
/** Get the extent descriptor of a page.
@@ -465,22 +451,17 @@ defined, as they are uninitialized above the free limit.
@param[in] space tablespace
@param[in] offset page offset; if equal to the free limit, we
try to add new extents to the space free list
-@param[in] page_size page size
@param[in,out] mtr mini-transaction
@return the extent descriptor */
MY_ATTRIBUTE((warn_unused_result))
static
xdes_t*
-xdes_get_descriptor(
- const fil_space_t* space,
- page_no_t offset,
- const page_size_t& page_size,
- mtr_t* mtr)
+xdes_get_descriptor(const fil_space_t* space, page_no_t offset, mtr_t* mtr)
{
buf_block_t* block;
fsp_header_t* sp_header;
- block = buf_page_get(page_id_t(space->id, 0), page_size,
+ block = buf_page_get(page_id_t(space->id, 0), space->zip_size(),
RW_SX_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
@@ -499,7 +480,6 @@ defined, as they are uninitialized above the free limit.
@param[in] space tablespace
@param[in] page descriptor page offset
@param[in] offset page offset
-@param[in] page_size page size
@param[in,out] mtr mini-transaction
@return the extent descriptor
@retval NULL if the descriptor is not available */
@@ -510,15 +490,16 @@ xdes_get_descriptor_const(
const fil_space_t* space,
page_no_t page,
page_no_t offset,
- const page_size_t& page_size,
mtr_t* mtr)
{
ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_S_LOCK));
ut_ad(offset < space->free_limit);
ut_ad(offset < space->size_in_header);
+ const ulint zip_size = space->zip_size();
+
if (buf_block_t* block = buf_page_get(page_id_t(space->id, page),
- page_size, RW_S_LATCH, mtr)) {
+ zip_size, RW_S_LATCH, mtr)) {
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
ut_ad(page != 0 || space->free_limit == mach_read_from_4(
@@ -529,7 +510,7 @@ xdes_get_descriptor_const(
+ block->frame));
return(block->frame + XDES_ARR_OFFSET + XDES_SIZE
- * xdes_calc_descriptor_index(page_size, offset));
+ * xdes_calc_descriptor_index(zip_size, offset));
}
return(NULL);
@@ -538,7 +519,6 @@ xdes_get_descriptor_const(
/** Get a pointer to the extent descriptor. The page where the
extent descriptor resides is x-locked.
@param[in] space tablespace
-@param[in] page_size page size
@param[in] lst_node file address of the list node
contained in the descriptor
@param[in,out] mtr mini-transaction
@@ -548,14 +528,13 @@ UNIV_INLINE
xdes_t*
xdes_lst_get_descriptor(
const fil_space_t* space,
- const page_size_t& page_size,
fil_addr_t lst_node,
mtr_t* mtr)
{
ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK));
- ut_ad(page_size.equals_to(page_size_t(space->flags)));
- return(fut_get_ptr(space->id, page_size, lst_node, RW_SX_LATCH, mtr)
- - XDES_FLST_NODE);
+ return fut_get_ptr(space->id, space->zip_size(),
+ lst_node, RW_SX_LATCH, mtr)
+ - XDES_FLST_NODE;
}
/********************************************************************//**
@@ -706,12 +685,12 @@ fsp_header_init_fields(
@param[in,out] mtr mini-transaction */
void fsp_header_init(fil_space_t* space, ulint size, mtr_t* mtr)
{
- const page_id_t page_id(space->id, 0);
- const page_size_t page_size(space->flags);
+ const page_id_t page_id(space->id, 0);
+ const ulint zip_size = space->zip_size();
mtr_x_lock(&space->latch, mtr);
- buf_block_t* block = buf_page_create(page_id, page_size, mtr);
- buf_page_get(page_id, page_size, RW_SX_LATCH, mtr);
+ buf_block_t* block = buf_page_create(page_id, zip_size, mtr);
+ buf_page_get(page_id, zip_size, RW_SX_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
space->size_in_header = size;
@@ -820,6 +799,44 @@ fsp_try_extend_data_file_with_pages(
return(success);
}
+/** Calculate the number of physical pages in an extent for this file.
+@param[in] physical_size page_size of the datafile
+@return number of pages in an extent for this file */
+inline ulint fsp_get_extent_size_in_pages(ulint physical_size)
+{
+ return (FSP_EXTENT_SIZE << srv_page_size_shift) / physical_size;
+}
+
+
+/** Calculate the number of pages to extend a datafile.
+We extend single-table tablespaces first one extent at a time,
+but 4 at a time for bigger tablespaces. It is not enough to extend always
+by one extent, because we need to add at least one extent to FSP_FREE.
+A single extent descriptor page will track many extents. And the extent
+that uses its extent descriptor page is put onto the FSP_FREE_FRAG list.
+Extents that do not use their extent descriptor page are added to FSP_FREE.
+The physical page size is used to determine how many extents are tracked
+on one extent descriptor page. See xdes_calc_descriptor_page().
+@param[in] physical_size page size in data file
+@param[in] size current number of pages in the datafile
+@return number of pages to extend the file. */
+static ulint fsp_get_pages_to_extend_ibd(ulint physical_size, ulint size)
+{
+ ulint extent_size = fsp_get_extent_size_in_pages(physical_size);
+ /* The threshold is set at 32MiB except when the physical page
+ size is small enough that it must be done sooner. */
+ ulint threshold = std::min(32 * extent_size, physical_size);
+
+ if (size >= threshold) {
+ /* Below in fsp_fill_free_list() we assume
+ that we add at most FSP_FREE_ADD extents at
+ a time */
+ extent_size *= FSP_FREE_ADD;
+ }
+
+ return extent_size;
+}
+
/** Try to extend the last data file of a tablespace if it is auto-extending.
@param[in,out] space tablespace
@param[in,out] header tablespace header
@@ -872,8 +889,7 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr)
size = mach_read_from_4(header + FSP_SIZE);
ut_ad(size == space->size_in_header);
- const page_size_t page_size(
- mach_read_from_4(header + FSP_SPACE_FLAGS));
+ const ulint ps = space->physical_size();
switch (space->id) {
case TRX_SYS_SPACE:
@@ -883,8 +899,7 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr)
size_increase = srv_tmp_space.get_increment();
break;
default:
- ulint extent_pages
- = fsp_get_extent_size_in_pages(page_size);
+ ulint extent_pages = fsp_get_extent_size_in_pages(ps);
if (size < extent_pages) {
/* Let us first extend the file to extent_size */
if (!fsp_try_extend_data_file_with_pages(
@@ -895,7 +910,7 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr)
size = extent_pages;
}
- size_increase = fsp_get_pages_to_extend_ibd(page_size, size);
+ size_increase = fsp_get_pages_to_extend_ibd(ps, size);
}
if (size_increase == 0) {
@@ -910,7 +925,7 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr)
to the space header */
space->size_in_header = ut_calc_align_down(
- space->size, (1024 * 1024) / page_size.physical());
+ space->size, (1024 * 1024) / ps);
mlog_write_ulint(
header + FSP_SIZE, space->size_in_header, MLOG_4BYTES, mtr);
@@ -918,47 +933,6 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr)
return(size_increase);
}
-/** Calculate the number of pages to extend a datafile.
-We extend single-table tablespaces first one extent at a time,
-but 4 at a time for bigger tablespaces. It is not enough to extend always
-by one extent, because we need to add at least one extent to FSP_FREE.
-A single extent descriptor page will track many extents. And the extent
-that uses its extent descriptor page is put onto the FSP_FREE_FRAG list.
-Extents that do not use their extent descriptor page are added to FSP_FREE.
-The physical page size is used to determine how many extents are tracked
-on one extent descriptor page. See xdes_calc_descriptor_page().
-@param[in] page_size page_size of the datafile
-@param[in] size current number of pages in the datafile
-@return number of pages to extend the file. */
-ulint
-fsp_get_pages_to_extend_ibd(
- const page_size_t& page_size,
- ulint size)
-{
- ulint size_increase; /* number of pages to extend this file */
- ulint extent_size; /* one megabyte, in pages */
- ulint threshold; /* The size of the tablespace (in number
- of pages) where we start allocating more
- than one extent at a time. */
-
- extent_size = fsp_get_extent_size_in_pages(page_size);
-
- /* The threshold is set at 32MiB except when the physical page
- size is small enough that it must be done sooner. */
- threshold = ut_min(32 * extent_size, page_size.physical());
-
- if (size < threshold) {
- size_increase = extent_size;
- } else {
- /* Below in fsp_fill_free_list() we assume
- that we add at most FSP_FREE_ADD extents at
- a time */
- size_increase = FSP_FREE_ADD * extent_size;
- }
-
- return(size_increase);
-}
-
/** Reset the page type.
Data files created before MySQL 5.1.48 may contain garbage in FIL_PAGE_TYPE.
In MySQL 3.23.53, only undo log pages and index pages were tagged.
@@ -1009,7 +983,7 @@ fsp_fill_free_list(
ut_ad(size == space->size_in_header);
ut_ad(limit == space->free_limit);
- const page_size_t page_size(space->flags);
+ const ulint zip_size = space->zip_size();
if (size < limit + FSP_EXTENT_SIZE * FSP_FREE_ADD) {
bool skip_resize = init_space;
@@ -1034,7 +1008,7 @@ fsp_fill_free_list(
|| ((i + FSP_EXTENT_SIZE <= size) && (count < FSP_FREE_ADD))) {
bool init_xdes
- = (ut_2pow_remainder(i, page_size.physical()) == 0);
+ = (ut_2pow_remainder(i, space->physical_size()) == 0);
space->free_limit = i + FSP_EXTENT_SIZE;
mlog_write_ulint(header + FSP_FREE_LIMIT, i + FSP_EXTENT_SIZE,
@@ -1052,10 +1026,10 @@ fsp_fill_free_list(
const page_id_t page_id(space->id, i);
block = buf_page_create(
- page_id, page_size, mtr);
+ page_id, zip_size, mtr);
buf_page_get(
- page_id, page_size, RW_SX_LATCH, mtr);
+ page_id, zip_size, RW_SX_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
@@ -1082,18 +1056,18 @@ fsp_fill_free_list(
i + FSP_IBUF_BITMAP_OFFSET);
block = buf_page_create(
- page_id, page_size, &ibuf_mtr);
+ page_id, zip_size, &ibuf_mtr);
buf_page_get(
- page_id, page_size, RW_SX_LATCH,
+ page_id, zip_size, RW_SX_LATCH,
&ibuf_mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
fsp_init_file_page(space, block, &ibuf_mtr);
-
- ibuf_bitmap_page_init(block, &ibuf_mtr);
-
+ mlog_write_ulint(block->frame + FIL_PAGE_TYPE,
+ FIL_PAGE_IBUF_BITMAP,
+ MLOG_2BYTES, &ibuf_mtr);
mtr_commit(&ibuf_mtr);
}
}
@@ -1138,7 +1112,6 @@ fsp_fill_free_list(
/** Allocates a new free extent.
@param[in,out] space tablespace
-@param[in] page_size page size
@param[in] hint hint of which extent would be desirable: any
page offset in the extent goes; the hint must not be > FSP_FREE_LIMIT
@param[in,out] mtr mini-transaction
@@ -1147,7 +1120,6 @@ static
xdes_t*
fsp_alloc_free_extent(
fil_space_t* space,
- const page_size_t& page_size,
ulint hint,
mtr_t* mtr)
{
@@ -1156,7 +1128,7 @@ fsp_alloc_free_extent(
xdes_t* descr;
buf_block_t* desc_block = NULL;
- header = fsp_get_space_header(space, page_size, mtr);
+ header = fsp_get_space_header(space, mtr);
descr = xdes_get_descriptor_with_space_hdr(
header, space, hint, mtr, false, &desc_block);
@@ -1182,8 +1154,7 @@ fsp_alloc_free_extent(
return(NULL); /* No free extents left */
}
- descr = xdes_lst_get_descriptor(
- space, page_size, first, mtr);
+ descr = xdes_lst_get_descriptor(space, first, mtr);
}
flst_remove(header + FSP_FREE, descr + XDES_FLST_NODE, mtr);
@@ -1234,7 +1205,6 @@ not previously x-latched. It is assumed that the block has been
x-latched only by mtr, and freed in mtr in that case.
@param[in,out] space tablespace
@param[in] offset page number of the allocated page
-@param[in] page_size page size of the allocated page
@param[in] rw_latch RW_SX_LATCH, RW_X_LATCH
@param[in,out] mtr mini-transaction of the allocation
@param[in,out] init_mtr mini-transaction for initializing the page
@@ -1245,15 +1215,12 @@ buf_block_t*
fsp_page_create(
fil_space_t* space,
page_no_t offset,
- const page_size_t& page_size,
rw_lock_type_t rw_latch,
mtr_t* mtr,
mtr_t* init_mtr)
{
- ut_ad(page_size.equals_to(page_size_t(space->flags)));
-
buf_block_t* block = buf_page_create(page_id_t(space->id, offset),
- page_size, init_mtr);
+ space->zip_size(), init_mtr);
ut_d(bool latched = mtr_memo_contains_flagged(mtr, block,
MTR_MEMO_PAGE_X_FIX
@@ -1293,7 +1260,6 @@ fsp_page_create(
/** Allocates a single free page from a space.
The page is marked as used.
@param[in,out] space tablespace
-@param[in] page_size page size
@param[in] hint hint of which page would be desirable
@param[in] rw_latch RW_SX_LATCH, RW_X_LATCH
@param[in,out] mtr mini-transaction
@@ -1307,7 +1273,6 @@ static MY_ATTRIBUTE((warn_unused_result, nonnull))
buf_block_t*
fsp_alloc_free_page(
fil_space_t* space,
- const page_size_t& page_size,
ulint hint,
rw_lock_type_t rw_latch,
mtr_t* mtr,
@@ -1320,7 +1285,7 @@ fsp_alloc_free_page(
const ulint space_id = space->id;
ut_d(fsp_space_modify_check(space, mtr));
- header = fsp_get_space_header(space, page_size, mtr);
+ header = fsp_get_space_header(space, mtr);
/* Get the hinted descriptor */
descr = xdes_get_descriptor_with_space_hdr(header, space, hint, mtr);
@@ -1339,8 +1304,7 @@ fsp_alloc_free_page(
FREE_FRAG list. But we will allocate our page from the
the free extent anyway. */
- descr = fsp_alloc_free_extent(space, page_size,
- hint, mtr);
+ descr = fsp_alloc_free_extent(space, hint, mtr);
if (descr == NULL) {
/* No free space left */
@@ -1352,8 +1316,7 @@ fsp_alloc_free_page(
flst_add_last(header + FSP_FREE_FRAG,
descr + XDES_FLST_NODE, mtr);
} else {
- descr = xdes_lst_get_descriptor(space, page_size,
- first, mtr);
+ descr = xdes_lst_get_descriptor(space, first, mtr);
}
/* Reset the hint */
@@ -1401,23 +1364,15 @@ fsp_alloc_free_page(
}
fsp_alloc_from_free_frag(header, descr, free, mtr);
- return(fsp_page_create(space, page_no, page_size, rw_latch,
- mtr, init_mtr));
+ return fsp_page_create(space, page_no, rw_latch, mtr, init_mtr);
}
/** Frees a single page of a space.
The page is marked as free and clean.
@param[in,out] space tablespace
-@param[in] page_id page id
-@param[in] page_size page size
+@param[in] offset page number
@param[in,out] mtr mini-transaction */
-static
-void
-fsp_free_page(
- fil_space_t* space,
- ulint offset,
- const page_size_t& page_size,
- mtr_t* mtr)
+static void fsp_free_page(fil_space_t* space, page_no_t offset, mtr_t* mtr)
{
fsp_header_t* header;
xdes_t* descr;
@@ -1429,7 +1384,7 @@ fsp_free_page(
/* fprintf(stderr, "Freeing page %lu in space %lu\n", page, space); */
- header = fsp_get_space_header(space, page_size, mtr);
+ header = fsp_get_space_header(space, mtr);
descr = xdes_get_descriptor_with_space_hdr(
header, space, offset, mtr);
@@ -1498,29 +1453,22 @@ fsp_free_page(
/* The extent has become free: move it to another list */
flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
mtr);
- fsp_free_extent(space, offset, page_size, mtr);
+ fsp_free_extent(space, offset, mtr);
}
}
/** Return an extent to the free list of a space.
@param[in,out] space tablespace
@param[in] offset page number in the extent
-@param[in] page_size page size
@param[in,out] mtr mini-transaction */
-static
-void
-fsp_free_extent(
- fil_space_t* space,
- page_no_t offset,
- const page_size_t& page_size,
- mtr_t* mtr)
+static void fsp_free_extent(fil_space_t* space, page_no_t offset, mtr_t* mtr)
{
fsp_header_t* header;
xdes_t* descr;
ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK));
- header = fsp_get_space_header(space, page_size, mtr);
+ header = fsp_get_space_header(space, mtr);
descr = xdes_get_descriptor_with_space_hdr(
header, space, offset, mtr);
@@ -1533,10 +1481,16 @@ fsp_free_extent(
space->free_len++;
}
+/** @return Number of segment inodes which fit on a single page */
+inline ulint FSP_SEG_INODES_PER_PAGE(ulint physical_size)
+{
+ return (physical_size - FSEG_ARR_OFFSET - 10) / FSEG_INODE_SIZE;
+}
+
/** Returns the nth inode slot on an inode page.
@param[in] page segment inode page
@param[in] i inode index on page
-@param[in] page_size page size
+@param[in] physical_size page size
@param[in,out] mtr mini-transaction
@return segment inode */
UNIV_INLINE
@@ -1544,10 +1498,10 @@ fseg_inode_t*
fsp_seg_inode_page_get_nth_inode(
page_t* page,
ulint i,
- const page_size_t& page_size,
+ ulint physical_size,
mtr_t* mtr)
{
- ut_ad(i < FSP_SEG_INODES_PER_PAGE(page_size));
+ ut_ad(i < FSP_SEG_INODES_PER_PAGE(physical_size));
ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_SX_FIX));
return(page + FSEG_ARR_OFFSET + FSEG_INODE_SIZE * i);
@@ -1555,23 +1509,23 @@ fsp_seg_inode_page_get_nth_inode(
/** Looks for a used segment inode on a segment inode page.
@param[in] page segment inode page
-@param[in] page_size page size
+@param[in] physical_size page size
@param[in,out] mtr mini-transaction
@return segment inode index, or ULINT_UNDEFINED if not found */
static
ulint
fsp_seg_inode_page_find_used(
page_t* page,
- const page_size_t& page_size,
+ ulint physical_size,
mtr_t* mtr)
{
ulint i;
fseg_inode_t* inode;
- for (i = 0; i < FSP_SEG_INODES_PER_PAGE(page_size); i++) {
+ for (i = 0; i < FSP_SEG_INODES_PER_PAGE(physical_size); i++) {
inode = fsp_seg_inode_page_get_nth_inode(
- page, i, page_size, mtr);
+ page, i, physical_size, mtr);
if (mach_read_from_8(inode + FSEG_ID)) {
/* This is used */
@@ -1588,7 +1542,7 @@ fsp_seg_inode_page_find_used(
/** Looks for an unused segment inode on a segment inode page.
@param[in] page segment inode page
@param[in] i search forward starting from this index
-@param[in] page_size page size
+@param[in] physical_size page size
@param[in,out] mtr mini-transaction
@return segment inode index, or ULINT_UNDEFINED if not found */
static
@@ -1596,15 +1550,15 @@ ulint
fsp_seg_inode_page_find_free(
page_t* page,
ulint i,
- const page_size_t& page_size,
+ ulint physical_size,
mtr_t* mtr)
{
- for (; i < FSP_SEG_INODES_PER_PAGE(page_size); i++) {
+ for (; i < FSP_SEG_INODES_PER_PAGE(physical_size); i++) {
fseg_inode_t* inode;
inode = fsp_seg_inode_page_get_nth_inode(
- page, i, page_size, mtr);
+ page, i, physical_size, mtr);
if (!mach_read_from_8(inode + FSEG_ID)) {
/* This is unused */
@@ -1638,10 +1592,7 @@ fsp_alloc_seg_inode_page(
ut_ad(page_offset(space_header) == FSP_HEADER_OFFSET);
ut_ad(page_get_space_id(page_align(space_header)) == space->id);
- const page_size_t page_size(space->flags);
-
- block = fsp_alloc_free_page(
- space, page_size, 0, RW_SX_LATCH, mtr, mtr);
+ block = fsp_alloc_free_page(space, 0, RW_SX_LATCH, mtr, mtr);
if (block == NULL) {
@@ -1656,10 +1607,12 @@ fsp_alloc_seg_inode_page(
mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_INODE,
MLOG_2BYTES, mtr);
- for (ulint i = 0; i < FSP_SEG_INODES_PER_PAGE(page_size); i++) {
+ const ulint physical_size = space->physical_size();
+
+ for (ulint i = 0; i < FSP_SEG_INODES_PER_PAGE(physical_size); i++) {
inode = fsp_seg_inode_page_get_nth_inode(
- page, i, page_size, mtr);
+ page, i, physical_size, mtr);
mlog_write_ull(inode + FSEG_ID, 0, mtr);
}
@@ -1697,25 +1650,27 @@ fsp_alloc_seg_inode(
&& !fsp_alloc_seg_inode_page(space, space_header, mtr)) {
return(NULL);
}
- const page_size_t page_size(space->flags);
const page_id_t page_id(
space->id,
flst_get_first(space_header + FSP_SEG_INODES_FREE, mtr).page);
- block = buf_page_get(page_id, page_size, RW_SX_LATCH, mtr);
+ block = buf_page_get(page_id, space->zip_size(), RW_SX_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
fil_block_check_type(*block, FIL_PAGE_INODE, mtr);
page = buf_block_get_frame(block);
- n = fsp_seg_inode_page_find_free(page, 0, page_size, mtr);
+ const ulint physical_size = space->physical_size();
+
+ n = fsp_seg_inode_page_find_free(page, 0, physical_size, mtr);
ut_a(n != ULINT_UNDEFINED);
- inode = fsp_seg_inode_page_get_nth_inode(page, n, page_size, mtr);
+ inode = fsp_seg_inode_page_get_nth_inode(page, n, physical_size, mtr);
if (ULINT_UNDEFINED == fsp_seg_inode_page_find_free(page, n + 1,
- page_size, mtr)) {
+ physical_size,
+ mtr)) {
/* There are no other unused headers left on the page: move it
to another list */
@@ -1733,14 +1688,10 @@ fsp_alloc_seg_inode(
/** Frees a file segment inode.
@param[in,out] space tablespace
-@param[in] page_size page size
@param[in,out] inode segment inode
@param[in,out] mtr mini-transaction */
-static
-void
-fsp_free_seg_inode(
+static void fsp_free_seg_inode(
fil_space_t* space,
- const page_size_t& page_size,
fseg_inode_t* inode,
mtr_t* mtr)
{
@@ -1751,12 +1702,14 @@ fsp_free_seg_inode(
page = page_align(inode);
- space_header = fsp_get_space_header(space, page_size, mtr);
+ space_header = fsp_get_space_header(space, mtr);
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
+ const ulint physical_size = space->physical_size();
+
if (ULINT_UNDEFINED
- == fsp_seg_inode_page_find_free(page, 0, page_size, mtr)) {
+ == fsp_seg_inode_page_find_free(page, 0, physical_size, mtr)) {
/* Move the page to another list */
@@ -1771,21 +1724,21 @@ fsp_free_seg_inode(
mlog_write_ulint(inode + FSEG_MAGIC_N, 0xfa051ce3, MLOG_4BYTES, mtr);
if (ULINT_UNDEFINED
- == fsp_seg_inode_page_find_used(page, page_size, mtr)) {
+ == fsp_seg_inode_page_find_used(page, physical_size, mtr)) {
/* There are no other used headers left on the page: free it */
flst_remove(space_header + FSP_SEG_INODES_FREE,
page + FSEG_INODE_PAGE_NODE, mtr);
- fsp_free_page(space, page_get_page_no(page), page_size, mtr);
+ fsp_free_page(space, page_get_page_no(page), mtr);
}
}
/** Returns the file segment inode, page x-latched.
@param[in] header segment header
@param[in] space space id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] mtr mini-transaction
@param[out] block inode block, or NULL to ignore
@return segment inode, page x-latched; NULL if the inode is free */
@@ -1794,7 +1747,7 @@ fseg_inode_t*
fseg_inode_try_get(
fseg_header_t* header,
ulint space,
- const page_size_t& page_size,
+ ulint zip_size,
mtr_t* mtr,
buf_block_t** block)
{
@@ -1805,7 +1758,7 @@ fseg_inode_try_get(
inode_addr.boffset = mach_read_from_2(header + FSEG_HDR_OFFSET);
ut_ad(space == mach_read_from_4(header + FSEG_HDR_SPACE));
- inode = fut_get_ptr(space, page_size, inode_addr, RW_SX_LATCH, mtr,
+ inode = fut_get_ptr(space, zip_size, inode_addr, RW_SX_LATCH, mtr,
block);
if (UNIV_UNLIKELY(!mach_read_from_8(inode + FSEG_ID))) {
@@ -1822,7 +1775,7 @@ fseg_inode_try_get(
/** Returns the file segment inode, page x-latched.
@param[in] header segment header
@param[in] space space id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] mtr mini-transaction
@param[out] block inode block
@return segment inode, page x-latched */
@@ -1831,12 +1784,12 @@ fseg_inode_t*
fseg_inode_get(
fseg_header_t* header,
ulint space,
- const page_size_t& page_size,
+ ulint zip_size,
mtr_t* mtr,
buf_block_t** block = NULL)
{
fseg_inode_t* inode
- = fseg_inode_try_get(header, space, page_size, mtr, block);
+ = fseg_inode_try_get(header, space, zip_size, mtr, block);
ut_a(inode);
return(inode);
}
@@ -1996,11 +1949,11 @@ fseg_create(
<= srv_page_size - FIL_PAGE_DATA_END);
mtr_x_lock(&space->latch, mtr);
- const page_size_t page_size(space->flags);
ut_d(fsp_space_modify_check(space, mtr));
if (page != 0) {
- block = buf_page_get(page_id_t(space->id, page), page_size,
+ block = buf_page_get(page_id_t(space->id, page),
+ space->zip_size(),
RW_SX_LATCH, mtr);
header = byte_offset + buf_block_get_frame(block);
@@ -2019,7 +1972,7 @@ fseg_create(
DBUG_RETURN(NULL);
}
- space_header = fsp_get_space_header(space, page_size, mtr);
+ space_header = fsp_get_space_header(space, mtr);
inode = fsp_alloc_seg_inode(space, space_header, mtr);
@@ -2048,7 +2001,7 @@ fseg_create(
}
if (page == 0) {
- block = fseg_alloc_free_page_low(space, page_size,
+ block = fseg_alloc_free_page_low(space,
inode, 0, FSP_UP, RW_SX_LATCH,
mtr, mtr
#ifdef UNIV_DEBUG
@@ -2061,9 +2014,7 @@ fseg_create(
ut_ad(!has_done_reservation || block != NULL);
if (block == NULL) {
-
- fsp_free_seg_inode(space, page_size, inode, mtr);
-
+ fsp_free_seg_inode(space, inode, mtr);
goto funct_exit;
}
@@ -2140,9 +2091,7 @@ fseg_n_reserved_pages(
space_id = page_get_space_id(page_align(header));
space = mtr_x_lock_space(space_id, mtr);
- const page_size_t page_size(space->flags);
-
- inode = fseg_inode_get(header, space_id, page_size, mtr);
+ inode = fseg_inode_get(header, space_id, space->zip_size(), mtr);
ret = fseg_n_reserved_pages_low(inode, used, mtr);
@@ -2155,7 +2104,6 @@ the free list is empty, and the extents can be allocated consecutively from
the hint onward.
@param[in] inode segment inode
@param[in] space tablespace
-@param[in] page_size page size
@param[in] hint hint which extent would be good as the first
extent
@param[in,out] mtr mini-transaction */
@@ -2164,7 +2112,6 @@ void
fseg_fill_free_list(
fseg_inode_t* inode,
fil_space_t* space,
- const page_size_t& page_size,
ulint hint,
mtr_t* mtr)
{
@@ -2194,7 +2141,7 @@ fseg_fill_free_list(
}
for (i = 0; i < FSEG_FREE_LIST_MAX_LEN; i++) {
- descr = xdes_get_descriptor(space, hint, page_size, mtr);
+ descr = xdes_get_descriptor(space, hint, mtr);
if ((descr == NULL)
|| (XDES_FREE != xdes_get_state(descr, mtr))) {
@@ -2204,7 +2151,7 @@ fseg_fill_free_list(
return;
}
- descr = fsp_alloc_free_extent(space, page_size, hint, mtr);
+ descr = fsp_alloc_free_extent(space, hint, mtr);
xdes_set_state(descr, XDES_FSEG, mtr);
@@ -2224,7 +2171,6 @@ NOTE that the extent returned still resides in the segment free list, it is
not yet taken off it!
@param[in] inode segment inode
@param[in,out] space tablespace
-@param[in] page_size page size
@param[in,out] mtr mini-transaction
@retval NULL if no page could be allocated
@retval block rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
@@ -2235,7 +2181,6 @@ xdes_t*
fseg_alloc_free_extent(
fseg_inode_t* inode,
fil_space_t* space,
- const page_size_t& page_size,
mtr_t* mtr)
{
xdes_t* descr;
@@ -2251,10 +2196,10 @@ fseg_alloc_free_extent(
first = flst_get_first(inode + FSEG_FREE, mtr);
- descr = xdes_lst_get_descriptor(space, page_size, first, mtr);
+ descr = xdes_lst_get_descriptor(space, first, mtr);
} else {
/* Segment free list was empty, allocate from space */
- descr = fsp_alloc_free_extent(space, page_size, 0, mtr);
+ descr = fsp_alloc_free_extent(space, 0, mtr);
if (descr == NULL) {
@@ -2268,7 +2213,7 @@ fseg_alloc_free_extent(
flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
/* Try to fill the segment free list */
- fseg_fill_free_list(inode, space, page_size,
+ fseg_fill_free_list(inode, space,
xdes_get_offset(descr) + FSP_EXTENT_SIZE,
mtr);
}
@@ -2280,7 +2225,6 @@ fseg_alloc_free_extent(
This function implements the intelligent allocation strategy which tries to
minimize file space fragmentation.
@param[in,out] space tablespace
-@param[in] page_size page size
@param[in,out] seg_inode segment inode
@param[in] hint hint of which page would be desirable
@param[in] direction if the new page is needed because of
@@ -2301,7 +2245,6 @@ static
buf_block_t*
fseg_alloc_free_page_low(
fil_space_t* space,
- const page_size_t& page_size,
fseg_inode_t* seg_inode,
ulint hint,
byte direction,
@@ -2336,7 +2279,7 @@ fseg_alloc_free_page_low(
reserved = fseg_n_reserved_pages_low(seg_inode, &used, mtr);
- space_header = fsp_get_space_header(space, page_size, mtr);
+ space_header = fsp_get_space_header(space, mtr);
descr = xdes_get_descriptor_with_space_hdr(space_header, space,
hint, mtr);
@@ -2345,7 +2288,7 @@ fseg_alloc_free_page_low(
hint */
/* The file space header page is always allocated. */
hint = 0;
- descr = xdes_get_descriptor(space, hint, page_size, mtr);
+ descr = xdes_get_descriptor(space, hint, mtr);
}
/* In the big if-else below we look for ret_page and ret_descr */
@@ -2372,7 +2315,7 @@ take_hinted_page:
=========================================================
the hinted page
===============*/
- ret_descr = fsp_alloc_free_extent(space, page_size, hint, mtr);
+ ret_descr = fsp_alloc_free_extent(space, hint, mtr);
ut_a(ret_descr == descr);
@@ -2382,7 +2325,7 @@ take_hinted_page:
ret_descr + XDES_FLST_NODE, mtr);
/* Try to fill the segment free list */
- fseg_fill_free_list(seg_inode, space, page_size,
+ fseg_fill_free_list(seg_inode, space,
hint + FSP_EXTENT_SIZE, mtr);
goto take_hinted_page;
/*-----------------------------------------------------------*/
@@ -2390,8 +2333,7 @@ take_hinted_page:
&& ((reserved - used) < reserved / FSEG_FILLFACTOR)
&& (used >= FSEG_FRAG_LIMIT)
&& (!!(ret_descr
- = fseg_alloc_free_extent(
- seg_inode, space, page_size, mtr)))) {
+ = fseg_alloc_free_extent(seg_inode, space, mtr)))) {
/* 3. We take any free extent (which was already assigned above
===============================================================
@@ -2437,8 +2379,7 @@ take_hinted_page:
return(NULL);
}
- ret_descr = xdes_lst_get_descriptor(space, page_size,
- first, mtr);
+ ret_descr = xdes_lst_get_descriptor(space, first, mtr);
ret_page = xdes_get_offset(ret_descr)
+ xdes_find_bit(ret_descr, XDES_FREE_BIT, TRUE,
0, mtr);
@@ -2448,7 +2389,7 @@ take_hinted_page:
/* 6. We allocate an individual page from the space
===================================================*/
buf_block_t* block = fsp_alloc_free_page(
- space, page_size, hint, rw_latch, mtr, init_mtr);
+ space, hint, rw_latch, mtr, init_mtr);
ut_ad(!has_done_reservation || block != NULL);
@@ -2470,8 +2411,7 @@ take_hinted_page:
} else {
/* 7. We allocate a new extent and take its first page
======================================================*/
- ret_descr = fseg_alloc_free_extent(seg_inode,
- space, page_size, mtr);
+ ret_descr = fseg_alloc_free_extent(seg_inode, space, mtr);
if (ret_descr == NULL) {
ret_page = FIL_NULL;
@@ -2519,8 +2459,7 @@ got_hinted_page:
The extent is still in the appropriate list (FSEG_NOT_FULL
or FSEG_FREE), and the page is not yet marked as used. */
- ut_ad(xdes_get_descriptor(space, ret_page, page_size, mtr)
- == ret_descr);
+ ut_ad(xdes_get_descriptor(space, ret_page, mtr) == ret_descr);
ut_ad(xdes_mtr_get_bit(
ret_descr, XDES_FREE_BIT,
@@ -2529,8 +2468,7 @@ got_hinted_page:
fseg_mark_page_used(seg_inode, ret_page, ret_descr, mtr);
}
- return(fsp_page_create(space, ret_page, page_size, rw_latch,
- mtr, init_mtr));
+ return fsp_page_create(space, ret_page, rw_latch, mtr, init_mtr);
}
/**********************************************************************//**
@@ -2572,9 +2510,8 @@ fseg_alloc_free_page_general(
space_id = page_get_space_id(page_align(seg_header));
space = mtr_x_lock_space(space_id, mtr);
- const page_size_t page_size(space->flags);
-
- inode = fseg_inode_get(seg_header, space_id, page_size, mtr, &iblock);
+ inode = fseg_inode_get(seg_header, space_id, space->zip_size(),
+ mtr, &iblock);
fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
if (!has_done_reservation
@@ -2583,7 +2520,7 @@ fseg_alloc_free_page_general(
return(NULL);
}
- block = fseg_alloc_free_page_low(space, page_size,
+ block = fseg_alloc_free_page_low(space,
inode, hint, direction,
RW_X_LATCH, mtr, init_mtr
#ifdef UNIV_DEBUG
@@ -2701,9 +2638,9 @@ fsp_reserve_free_extents(
*n_reserved = n_ext;
mtr_x_lock(&space->latch, mtr);
- const page_size_t page_size(space->flags);
+ const ulint physical_size = space->physical_size();
- space_header = fsp_get_space_header(space, page_size, mtr);
+ space_header = fsp_get_space_header(space, mtr);
try_again:
size = mach_read_from_4(space_header + FSP_SIZE);
ut_ad(size == space->size_in_header);
@@ -2735,8 +2672,7 @@ try_again:
if (n_free_up > 0) {
n_free_up--;
- n_free_up -= n_free_up / (page_size.physical()
- / FSP_EXTENT_SIZE);
+ n_free_up -= n_free_up / (physical_size / FSP_EXTENT_SIZE);
}
n_free = n_free_list_ext + n_free_up;
@@ -2844,7 +2780,6 @@ fseg_mark_page_used(
@param[in] seg_inode segment inode
@param[in,out] space tablespace
@param[in] offset page number
-@param[in] page_size page size
@param[in] ahi whether we may need to drop the adaptive
hash index
@param[in,out] mtr mini-transaction */
@@ -2854,7 +2789,6 @@ fseg_free_page_low(
fseg_inode_t* seg_inode,
fil_space_t* space,
page_no_t offset,
- const page_size_t& page_size,
#ifdef BTR_CUR_HASH_ADAPT
bool ahi,
#endif /* BTR_CUR_HASH_ADAPT */
@@ -2883,7 +2817,7 @@ fseg_free_page_low(
}
#endif /* BTR_CUR_HASH_ADAPT */
- descr = xdes_get_descriptor(space, offset, page_size, mtr);
+ descr = xdes_get_descriptor(space, offset, mtr);
if (xdes_mtr_get_bit(descr, XDES_FREE_BIT,
offset % FSP_EXTENT_SIZE, mtr)) {
@@ -2911,8 +2845,7 @@ fseg_free_page_low(
}
}
- fsp_free_page(space, offset, page_size, mtr);
-
+ fsp_free_page(space, offset, mtr);
return;
}
@@ -2962,13 +2895,13 @@ fseg_free_page_low(
/* The extent has become free: free it to space */
flst_remove(seg_inode + FSEG_NOT_FULL,
descr + XDES_FLST_NODE, mtr);
- fsp_free_extent(space, offset, page_size, mtr);
+ fsp_free_extent(space, offset, mtr);
}
}
#ifndef BTR_CUR_HASH_ADAPT
-# define fseg_free_page_low(inode, space, offset, page_size, ahi, mtr) \
- fseg_free_page_low(inode, space, offset, page_size, mtr)
+# define fseg_free_page_low(inode, space, offset, ahi, mtr) \
+ fseg_free_page_low(inode, space, offset, mtr)
#endif /* !BTR_CUR_HASH_ADAPT */
/**********************************************************************//**
@@ -2988,16 +2921,16 @@ fseg_free_page_func(
fseg_inode_t* seg_inode;
buf_block_t* iblock;
fil_space_t* space = mtr_x_lock_space(space_id, mtr);
- const page_size_t page_size(space->flags);
DBUG_LOG("fseg_free_page", "space_id: " << space_id
<< ", page_no: " << page);
- seg_inode = fseg_inode_get(seg_header, space_id, page_size, mtr,
+ seg_inode = fseg_inode_get(seg_header, space_id, space->zip_size(),
+ mtr,
&iblock);
fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
- fseg_free_page_low(seg_inode, space, page, page_size, ahi, mtr);
+ fseg_free_page_low(seg_inode, space, page, ahi, mtr);
ut_d(buf_page_set_file_page_was_freed(page_id_t(space_id, page)));
@@ -3013,8 +2946,8 @@ fseg_page_is_free(fil_space_t* space, unsigned page)
{
bool is_free;
mtr_t mtr;
- page_size_t page_size(space->flags);
- page_no_t dpage = xdes_calc_descriptor_page(page_size, page);
+ page_no_t dpage = xdes_calc_descriptor_page(space->zip_size(),
+ page);
mtr.start();
mtr_s_lock(&space->latch, &mtr);
@@ -3022,7 +2955,7 @@ fseg_page_is_free(fil_space_t* space, unsigned page)
if (page >= space->free_limit || page >= space->size_in_header) {
is_free = true;
} else if (const xdes_t* descr = xdes_get_descriptor_const(
- space, dpage, page, page_size, &mtr)) {
+ space, dpage, page, &mtr)) {
is_free = xdes_get_bit(descr, XDES_FREE_BIT,
page % FSP_EXTENT_SIZE);
} else {
@@ -3036,7 +2969,6 @@ fseg_page_is_free(fil_space_t* space, unsigned page)
/** Free an extent of a segment to the space free list.
@param[in,out] seg_inode segment inode
@param[in,out] space tablespace
-@param[in] page_size page size
@param[in] page page number in the extent
@param[in] ahi whether we may need to drop
the adaptive hash index
@@ -3047,7 +2979,6 @@ void
fseg_free_extent(
fseg_inode_t* seg_inode,
fil_space_t* space,
- const page_size_t& page_size,
ulint page,
#ifdef BTR_CUR_HASH_ADAPT
bool ahi,
@@ -3062,7 +2993,7 @@ fseg_free_extent(
ut_ad(mtr != NULL);
- descr = xdes_get_descriptor(space, page, page_size, mtr);
+ descr = xdes_get_descriptor(space, page, mtr);
ut_a(xdes_get_state(descr, mtr) == XDES_FSEG);
ut_a(!memcmp(descr + XDES_ID, seg_inode + FSEG_ID, 8));
@@ -3109,7 +3040,7 @@ fseg_free_extent(
MLOG_4BYTES, mtr);
}
- fsp_free_extent(space, page, page_size, mtr);
+ fsp_free_extent(space, page, mtr);
#ifdef UNIV_DEBUG
for (i = 0; i < FSP_EXTENT_SIZE; i++) {
@@ -3121,8 +3052,8 @@ fseg_free_extent(
}
#ifndef BTR_CUR_HASH_ADAPT
-# define fseg_free_extent(inode, space, page_size, page, ahi, mtr) \
- fseg_free_extent(inode, space, page_size, page, mtr)
+# define fseg_free_extent(inode, space, page, ahi, mtr) \
+ fseg_free_extent(inode, space, page, mtr)
#endif /* !BTR_CUR_HASH_ADAPT */
/**********************************************************************//**
@@ -3156,9 +3087,8 @@ fseg_free_step_func(
header_page = page_get_page_no(page_align(header));
fil_space_t* space = mtr_x_lock_space(space_id, mtr);
- const page_size_t page_size(space->flags);
- descr = xdes_get_descriptor(space, header_page, page_size, mtr);
+ descr = xdes_get_descriptor(space, header_page, mtr);
/* Check that the header resides on a page which has not been
freed yet */
@@ -3166,8 +3096,8 @@ fseg_free_step_func(
ut_a(xdes_mtr_get_bit(descr, XDES_FREE_BIT,
header_page % FSP_EXTENT_SIZE, mtr) == FALSE);
buf_block_t* iblock;
-
- inode = fseg_inode_try_get(header, space_id, page_size, mtr, &iblock);
+ const ulint zip_size = space->zip_size();
+ inode = fseg_inode_try_get(header, space_id, zip_size, mtr, &iblock);
if (inode == NULL) {
ib::info() << "Double free of inode from "
@@ -3176,14 +3106,12 @@ fseg_free_step_func(
}
fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
- descr = fseg_get_first_extent(inode, space, page_size, mtr);
+ descr = fseg_get_first_extent(inode, space, mtr);
if (descr != NULL) {
/* Free the extent held by the segment */
page = xdes_get_offset(descr);
-
- fseg_free_extent(inode, space, page_size, page, ahi, mtr);
-
+ fseg_free_extent(inode, space, page, ahi, mtr);
DBUG_RETURN(FALSE);
}
@@ -3192,7 +3120,7 @@ fseg_free_step_func(
if (n == ULINT_UNDEFINED) {
/* Freeing completed: free the segment inode */
- fsp_free_seg_inode(space, page_size, inode, mtr);
+ fsp_free_seg_inode(space, inode, mtr);
DBUG_RETURN(TRUE);
}
@@ -3200,13 +3128,13 @@ fseg_free_step_func(
fseg_free_page_low(
inode, space,
fseg_get_nth_frag_page_no(inode, n, mtr),
- page_size, ahi, mtr);
+ ahi, mtr);
n = fseg_find_last_used_frag_page_slot(inode, mtr);
if (n == ULINT_UNDEFINED) {
/* Freeing completed: free the segment inode */
- fsp_free_seg_inode(space, page_size, inode, mtr);
+ fsp_free_seg_inode(space, inode, mtr);
DBUG_RETURN(TRUE);
}
@@ -3239,19 +3167,19 @@ fseg_free_step_not_header_func(
ut_ad(mtr->is_named_space(space_id));
fil_space_t* space = mtr_x_lock_space(space_id, mtr);
- const page_size_t page_size(space->flags);
buf_block_t* iblock;
- inode = fseg_inode_get(header, space_id, page_size, mtr, &iblock);
+ inode = fseg_inode_get(header, space_id, space->zip_size(), mtr,
+ &iblock);
fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
- descr = fseg_get_first_extent(inode, space, page_size, mtr);
+ descr = fseg_get_first_extent(inode, space, mtr);
if (descr != NULL) {
/* Free the extent held by the segment */
page = xdes_get_offset(descr);
- fseg_free_extent(inode, space, page_size, page, ahi, mtr);
+ fseg_free_extent(inode, space, page, ahi, mtr);
return(FALSE);
}
@@ -3271,7 +3199,7 @@ fseg_free_step_not_header_func(
return(TRUE);
}
- fseg_free_page_low(inode, space, page_no, page_size, ahi, mtr);
+ fseg_free_page_low(inode, space, page_no, ahi, mtr);
return(FALSE);
}
@@ -3281,7 +3209,6 @@ We think of the extent lists of the segment catenated in the order
FSEG_FULL -> FSEG_NOT_FULL -> FSEG_FREE.
@param[in] inode segment inode
@param[in] space tablespace
-@param[in] page_size page size
@param[in,out] mtr mini-transaction
@return the first extent descriptor, or NULL if none */
MY_ATTRIBUTE((nonnull, warn_unused_result))
@@ -3290,7 +3217,6 @@ xdes_t*
fseg_get_first_extent(
fseg_inode_t* inode,
const fil_space_t* space,
- const page_size_t& page_size,
mtr_t* mtr)
{
fil_addr_t first;
@@ -3316,7 +3242,7 @@ fseg_get_first_extent(
ut_ad(first.page != FIL_NULL);
return(first.page == FIL_NULL ? NULL
- : xdes_lst_get_descriptor(space, page_size, first, mtr));
+ : xdes_lst_get_descriptor(space, first, mtr));
}
#ifdef UNIV_BTR_PRINT
@@ -3380,9 +3306,8 @@ fseg_print(
space_id = page_get_space_id(page_align(header));
const fil_space_t* space = mtr_x_lock_space(space_id, mtr);
- const page_size_t page_size(space->flags);
- inode = fseg_inode_get(header, space_id, page_size, mtr);
+ inode = fseg_inode_get(header, space_id, space->zip_size(), mtr);
fseg_print_low(inode, mtr);
}
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index d5ce2f30ab4..d7695b7e9cc 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -3273,7 +3273,7 @@ fts_fetch_doc_from_rec(
doc->text.f_str =
btr_rec_copy_externally_stored_field(
clust_rec, offsets,
- btr_pcur_get_block(pcur)->page.size,
+ btr_pcur_get_block(pcur)->zip_size(),
clust_pos, &doc->text.f_len,
static_cast<mem_heap_t*>(
doc->self_heap->arg));
@@ -7456,7 +7456,7 @@ fts_init_recover_doc(
doc.text.f_str = btr_copy_externally_stored_field(
&doc.text.f_len,
static_cast<byte*>(dfield_get_data(dfield)),
- dict_table_page_size(table), len,
+ table->space->zip_size(), len,
static_cast<mem_heap_t*>(doc.self_heap->arg));
} else {
doc.text.f_str = static_cast<byte*>(
diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc
index 00f3b9aedf0..bf7e262ac98 100644
--- a/storage/innobase/fts/fts0que.cc
+++ b/storage/innobase/fts/fts0que.cc
@@ -206,7 +206,7 @@ struct fts_phrase_t {
distance(0),
charset(NULL),
heap(NULL),
- page_size(dict_table_page_size(table)),
+ zip_size(table->space->zip_size()),
proximity_pos(NULL),
parser(NULL)
{
@@ -230,8 +230,8 @@ struct fts_phrase_t {
/** Heap for word processing */
mem_heap_t* heap;
- /** Row page size */
- const page_size_t page_size;
+ /** ROW_FORMAT=COMPRESSED page size, or 0 */
+ const ulint zip_size;
/** Position info for proximity search verification. Records the
min and max position of words matched */
@@ -2013,7 +2013,7 @@ fts_query_fetch_document(
if (dfield_is_ext(dfield)) {
data = btr_copy_externally_stored_field(
- &cur_len, data, phrase->page_size,
+ &cur_len, data, phrase->zip_size,
dfield_get_len(dfield), phrase->heap);
} else {
cur_len = dfield_get_len(dfield);
diff --git a/storage/innobase/fut/fut0lst.cc b/storage/innobase/fut/fut0lst.cc
index 05474b02cbd..66e35c6e2c4 100644
--- a/storage/innobase/fut/fut0lst.cc
+++ b/storage/innobase/fut/fut0lst.cc
@@ -120,13 +120,11 @@ flst_add_last(
if (last_addr.page == node_addr.page) {
last_node = page_align(node) + last_addr.boffset;
} else {
- bool found;
- const page_size_t& page_size
- = fil_space_get_page_size(space, &found);
+ fil_space_t* s = fil_space_acquire_silent(space);
+ ulint zip_size = s ? s->zip_size() : 0;
+ if (s) s->release();
- ut_ad(found);
-
- last_node = fut_get_ptr(space, page_size, last_addr,
+ last_node = fut_get_ptr(space, zip_size, last_addr,
RW_SX_LATCH, mtr);
}
@@ -170,13 +168,11 @@ flst_add_first(
if (first_addr.page == node_addr.page) {
first_node = page_align(node) + first_addr.boffset;
} else {
- bool found;
- const page_size_t& page_size
- = fil_space_get_page_size(space, &found);
-
- ut_ad(found);
+ fil_space_t* s = fil_space_acquire_silent(space);
+ ulint zip_size = s ? s->zip_size() : 0;
+ if (s) s->release();
- first_node = fut_get_ptr(space, page_size, first_addr,
+ first_node = fut_get_ptr(space, zip_size, first_addr,
RW_SX_LATCH, mtr);
}
@@ -230,13 +226,11 @@ flst_insert_after(
if (!fil_addr_is_null(node3_addr)) {
/* Update prev field of node3 */
- bool found;
- const page_size_t& page_size
- = fil_space_get_page_size(space, &found);
-
- ut_ad(found);
+ fil_space_t* s = fil_space_acquire_silent(space);
+ ulint zip_size = s ? s->zip_size() : 0;
+ if (s) s->release();
- node3 = fut_get_ptr(space, page_size,
+ node3 = fut_get_ptr(space, zip_size,
node3_addr, RW_SX_LATCH, mtr);
flst_write_addr(node3 + FLST_PREV, node2_addr, mtr);
} else {
@@ -294,14 +288,12 @@ flst_insert_before(
flst_write_addr(node2 + FLST_NEXT, node3_addr, mtr);
if (!fil_addr_is_null(node1_addr)) {
- bool found;
- const page_size_t& page_size
- = fil_space_get_page_size(space, &found);
-
- ut_ad(found);
+ fil_space_t* s = fil_space_acquire_silent(space);
+ ulint zip_size = s ? s->zip_size() : 0;
+ if (s) s->release();
/* Update next field of node1 */
- node1 = fut_get_ptr(space, page_size, node1_addr,
+ node1 = fut_get_ptr(space, zip_size, node1_addr,
RW_SX_LATCH, mtr);
flst_write_addr(node1 + FLST_NEXT, node2_addr, mtr);
} else {
@@ -344,11 +336,9 @@ flst_remove(
buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
- bool found;
- const page_size_t& page_size = fil_space_get_page_size(space,
- &found);
-
- ut_ad(found);
+ fil_space_t* s = fil_space_acquire_silent(space);
+ ulint zip_size = s ? s->zip_size() : 0;
+ if (s) s->release();
node1_addr = flst_get_prev_addr(node2, mtr);
node3_addr = flst_get_next_addr(node2, mtr);
@@ -361,7 +351,7 @@ flst_remove(
node1 = page_align(node2) + node1_addr.boffset;
} else {
- node1 = fut_get_ptr(space, page_size,
+ node1 = fut_get_ptr(space, zip_size,
node1_addr, RW_SX_LATCH, mtr);
}
@@ -380,7 +370,7 @@ flst_remove(
node3 = page_align(node2) + node3_addr.boffset;
} else {
- node3 = fut_get_ptr(space, page_size,
+ node3 = fut_get_ptr(space, zip_size,
node3_addr, RW_SX_LATCH, mtr);
}
@@ -431,11 +421,9 @@ flst_validate(
/* Find out the space id */
buf_ptr_get_fsp_addr(base, &space, &base_addr);
- bool found;
- const page_size_t& page_size = fil_space_get_page_size(space,
- &found);
-
- ut_ad(found);
+ fil_space_t* s = fil_space_acquire_silent(space);
+ ulint zip_size = s ? s->zip_size() : 0;
+ if (s) s->release();
len = flst_get_len(base);
node_addr = flst_get_first(base, mtr1);
@@ -443,7 +431,7 @@ flst_validate(
for (i = 0; i < len; i++) {
mtr_start(&mtr2);
- node = fut_get_ptr(space, page_size,
+ node = fut_get_ptr(space, zip_size,
node_addr, RW_SX_LATCH, &mtr2);
node_addr = flst_get_next_addr(node, &mtr2);
@@ -458,7 +446,7 @@ flst_validate(
for (i = 0; i < len; i++) {
mtr_start(&mtr2);
- node = fut_get_ptr(space, page_size,
+ node = fut_get_ptr(space, zip_size,
node_addr, RW_SX_LATCH, &mtr2);
node_addr = flst_get_prev_addr(node, &mtr2);
diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc
index 9c10108a3f3..d77e29d308e 100644
--- a/storage/innobase/gis/gis0rtree.cc
+++ b/storage/innobase/gis/gis0rtree.cc
@@ -746,14 +746,14 @@ rtr_adjust_upper_level(
prev_page_no = btr_page_get_prev(page, mtr);
next_page_no = btr_page_get_next(page, mtr);
space = block->page.id.space();
- ut_ad(block->page.size.equals_to(dict_table_page_size(index->table)));
+ ut_ad(block->zip_size() == index->table->space->zip_size());
/* Update page links of the level */
if (prev_page_no != FIL_NULL) {
page_id_t prev_page_id(space, prev_page_no);
buf_block_t* prev_block = btr_block_get(
- prev_page_id, block->page.size, RW_X_LATCH,
+ prev_page_id, block->zip_size(), RW_X_LATCH,
index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(prev_block->frame) == page_is_comp(page));
@@ -770,7 +770,7 @@ rtr_adjust_upper_level(
page_id_t next_page_id(space, next_page_no);
buf_block_t* next_block = btr_block_get(
- next_page_id, block->page.size, RW_X_LATCH,
+ next_page_id, block->zip_size(), RW_X_LATCH,
index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(next_block->frame) == page_is_comp(page));
@@ -1875,7 +1875,7 @@ rtr_estimate_n_rows_in_range(
buf_block_t* block = btr_block_get(
page_id_t(index->table->space_id, index->page),
- page_size_t(index->table->space->flags),
+ index->table->space->zip_size(),
RW_S_LATCH, index, &mtr);
const page_t* page = buf_block_get_frame(block);
const unsigned n_recs = page_header_get_field(page, PAGE_N_RECS);
diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc
index a406acabf6e..84d07b5ac52 100644
--- a/storage/innobase/gis/gis0sea.cc
+++ b/storage/innobase/gis/gis0sea.cc
@@ -145,7 +145,7 @@ rtr_pcur_getnext_from_path(
| MTR_MEMO_X_LOCK));
}
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
/* Pop each node/page to be searched from "path" structure
and do a search on it. Please note, any pages that are in
@@ -269,7 +269,7 @@ rtr_pcur_getnext_from_path(
block = buf_page_get_gen(
page_id_t(index->table->space_id,
- next_rec.page_no), page_size,
+ next_rec.page_no), zip_size,
rw_latch, NULL, BUF_GET, __FILE__, __LINE__, mtr, &err);
if (block == NULL) {
@@ -424,7 +424,7 @@ rtr_pcur_getnext_from_path(
block,
page_id_t(index->table->space_id,
block->page.id.page_no()),
- page_size, BTR_MODIFY_TREE,
+ zip_size, BTR_MODIFY_TREE,
btr_cur, mtr);
}
@@ -1344,8 +1344,7 @@ rtr_cur_restore_position(
page_cur_t* page_cursor;
node_visit_t* node = rtr_get_parent_node(btr_cur, level, false);
node_seq_t path_ssn = node->seq_no;
- const page_size_t page_size(index->table->space->flags);
-
+ const ulint zip_size = index->table->space->zip_size();
ulint page_no = node->page_no;
heap = mem_heap_create(256);
@@ -1361,7 +1360,7 @@ search_again:
block = buf_page_get_gen(
page_id_t(index->table->space_id, page_no),
- page_size, RW_X_LATCH, NULL,
+ zip_size, RW_X_LATCH, NULL,
BUF_GET, __FILE__, __LINE__, mtr, &err);
ut_ad(block);
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 153390dbc2d..ee986d55f77 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -4,7 +4,7 @@ Copyright (c) 2000, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2013, 2018, MariaDB Corporation.
+Copyright (c) 2013, 2019, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -3842,11 +3842,6 @@ static int innodb_init_params()
DBUG_RETURN(HA_ERR_INITIALIZATION);
}
- /* This is the first time univ_page_size is used.
- It was initialized to 16k pages before srv_page_size was set */
- univ_page_size.copy_from(
- page_size_t(srv_page_size, srv_page_size, false));
-
srv_sys_space.set_space_id(TRX_SYS_SPACE);
srv_sys_space.set_flags(FSP_FLAGS_PAGE_SSIZE());
srv_sys_space.set_name("innodb_system");
@@ -12722,10 +12717,7 @@ ha_innobase::discard_or_import_tablespace(
DBUG_RETURN(HA_ERR_TABLE_READONLY);
}
- dict_table_t* dict_table = m_prebuilt->table;
-
- if (dict_table->is_temporary()) {
-
+ if (m_prebuilt->table->is_temporary()) {
ib_senderrf(
m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
ER_CANNOT_DISCARD_TEMPORARY_TABLE);
@@ -12733,11 +12725,11 @@ ha_innobase::discard_or_import_tablespace(
DBUG_RETURN(HA_ERR_TABLE_NEEDS_UPGRADE);
}
- if (dict_table->space == fil_system.sys_space) {
+ if (m_prebuilt->table->space == fil_system.sys_space) {
ib_senderrf(
m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
ER_TABLE_IN_SYSTEM_TABLESPACE,
- dict_table->name.m_name);
+ m_prebuilt->table->name.m_name);
DBUG_RETURN(HA_ERR_TABLE_NEEDS_UPGRADE);
}
@@ -12746,7 +12738,7 @@ ha_innobase::discard_or_import_tablespace(
/* Obtain an exclusive lock on the table. */
dberr_t err = row_mysql_lock_table(
- m_prebuilt->trx, dict_table, LOCK_X,
+ m_prebuilt->trx, m_prebuilt->table, LOCK_X,
discard ? "setting table lock for DISCARD TABLESPACE"
: "setting table lock for IMPORT TABLESPACE");
@@ -12759,32 +12751,32 @@ ha_innobase::discard_or_import_tablespace(
user may want to set the DISCARD flag in order to IMPORT
a new tablespace. */
- if (!dict_table->is_readable()) {
+ if (!m_prebuilt->table->is_readable()) {
ib_senderrf(
m_prebuilt->trx->mysql_thd,
IB_LOG_LEVEL_WARN, ER_TABLESPACE_MISSING,
- dict_table->name.m_name);
+ m_prebuilt->table->name.m_name);
}
err = row_discard_tablespace_for_mysql(
- dict_table->name.m_name, m_prebuilt->trx);
+ m_prebuilt->table->name.m_name, m_prebuilt->trx);
- } else if (dict_table->is_readable()) {
+ } else if (m_prebuilt->table->is_readable()) {
/* Commit the transaction in order to
release the table lock. */
trx_commit_for_mysql(m_prebuilt->trx);
ib::error() << "Unable to import tablespace "
- << dict_table->name << " because it already"
+ << m_prebuilt->table->name << " because it already"
" exists. Please DISCARD the tablespace"
" before IMPORT.";
ib_senderrf(
m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
- ER_TABLESPACE_EXISTS, dict_table->name.m_name);
+ ER_TABLESPACE_EXISTS, m_prebuilt->table->name.m_name);
DBUG_RETURN(HA_ERR_TABLE_EXIST);
} else {
- err = row_import_for_mysql(dict_table, m_prebuilt);
+ err = row_import_for_mysql(m_prebuilt->table, m_prebuilt);
if (err == DB_SUCCESS) {
@@ -12800,12 +12792,35 @@ ha_innobase::discard_or_import_tablespace(
/* Commit the transaction in order to release the table lock. */
trx_commit_for_mysql(m_prebuilt->trx);
- if (err == DB_SUCCESS && !discard
- && dict_stats_is_persistent_enabled(dict_table)) {
+ if (discard || err != DB_SUCCESS) {
+ DBUG_RETURN(convert_error_code_to_mysql(
+ err, m_prebuilt->table->flags, NULL));
+ }
+
+ /* Evict and reload the table definition in order to invoke
+ btr_cur_instant_init(). */
+ table_id_t id = m_prebuilt->table->id;
+ ut_ad(id);
+ mutex_enter(&dict_sys->mutex);
+ dict_table_close(m_prebuilt->table, TRUE, FALSE);
+ dict_table_remove_from_cache(m_prebuilt->table);
+ m_prebuilt->table = dict_table_open_on_id(id, TRUE,
+ DICT_TABLE_OP_NORMAL);
+ mutex_exit(&dict_sys->mutex);
+ if (!m_prebuilt->table) {
+ err = DB_TABLE_NOT_FOUND;
+ } else {
+ if (const Field* ai = table->found_next_number_field) {
+ initialize_auto_increment(m_prebuilt->table, ai);
+ }
+ dict_stats_init(m_prebuilt->table);
+ }
+
+ if (dict_stats_is_persistent_enabled(m_prebuilt->table)) {
dberr_t ret;
/* Adjust the persistent statistics. */
- ret = dict_stats_update(dict_table,
+ ret = dict_stats_update(m_prebuilt->table,
DICT_STATS_RECALC_PERSISTENT);
if (ret != DB_SUCCESS) {
@@ -12815,11 +12830,12 @@ ha_innobase::discard_or_import_tablespace(
ER_ALTER_INFO,
"Error updating stats for table '%s'"
" after table rebuild: %s",
- dict_table->name.m_name, ut_strerr(ret));
+ m_prebuilt->table->name.m_name,
+ ut_strerr(ret));
}
}
- DBUG_RETURN(convert_error_code_to_mysql(err, dict_table->flags, NULL));
+ DBUG_RETURN(0);
}
/**
@@ -13834,7 +13850,7 @@ fsp_get_available_space_in_free_extents(const fil_space_t& space)
ulint n_free_up =
(size_in_header - space.free_limit) / FSP_EXTENT_SIZE;
- const ulint size = page_size_t(space.flags).physical();
+ const ulint size = space.physical_size();
if (n_free_up > 0) {
n_free_up--;
n_free_up -= n_free_up / (size / FSP_EXTENT_SIZE);
@@ -13984,8 +14000,7 @@ ha_innobase::info_low(
stats.records = (ha_rows) n_rows;
stats.deleted = 0;
if (fil_space_t* space = ib_table->space) {
- const ulint size = page_size_t(space->flags)
- .physical();
+ const ulint size = space->physical_size();
stats.data_file_length
= ulonglong(stat_clustered_index_size)
* size;
@@ -17446,7 +17461,7 @@ innodb_make_page_dirty(THD*, st_mysql_sys_var*, void*, const void* save)
buf_block_t* block = buf_page_get(
page_id_t(space_id, srv_saved_page_number_debug),
- page_size_t(space->flags), RW_X_LATCH, &mtr);
+ space->zip_size(), RW_X_LATCH, &mtr);
if (block != NULL) {
byte* page = block->frame;
@@ -20637,9 +20652,9 @@ innobase_get_computed_value(
dfield_t* field;
ulint len;
- const page_size_t page_size = (old_table == NULL)
- ? dict_table_page_size(index->table)
- : dict_table_page_size(old_table);
+ const ulint zip_size = old_table
+ ? old_table->space->zip_size()
+ : dict_tf_get_zip_size(index->table->flags);
ulint ret = 0;
@@ -20691,7 +20706,7 @@ innobase_get_computed_value(
}
data = btr_copy_externally_stored_field(
- &len, data, page_size,
+ &len, data, zip_size,
dfield_get_len(row_field), *local_heap);
}
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 51d0042e011..4af97951570 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -1465,15 +1465,25 @@ instant_alter_column_possible(
const TABLE* table,
const TABLE* altered_table)
{
- if (!ib_table.supports_instant()) {
- return false;
- }
+ if (ha_alter_info->handler_flags
+ & (ALTER_STORED_COLUMN_ORDER | ALTER_DROP_STORED_COLUMN
+ | ALTER_ADD_STORED_BASE_COLUMN)) {
#if 1 // MDEV-17459: adjust fts_fetch_doc_from_rec() and friends; remove this
- if (ib_table.fts) {
- return false;
- }
+ if (ib_table.fts) return false;
+#endif
+#if 1 // MDEV-17468: fix bugs with indexed virtual columns & remove this
+ for (const dict_index_t* index = ib_table.indexes.start;
+ index; index = index->indexes.next) {
+ if (index->has_virtual()) {
+ ut_ad(ib_table.n_v_cols);
+ return false;
+ }
+ }
#endif
- const dict_index_t* index = ib_table.indexes.start;
+ }
+ const dict_index_t* const pk = ib_table.indexes.start;
+ ut_ad(pk->is_primary());
+ ut_ad(!pk->has_virtual());
if (ha_alter_info->handler_flags & ALTER_ADD_STORED_BASE_COLUMN) {
List_iterator_fast<Create_field> cf_it(
ha_alter_info->alter_info->create_list);
@@ -1481,21 +1491,11 @@ instant_alter_column_possible(
while (const Create_field* cf = cf_it++) {
n_add += !cf->field;
}
- if (index->n_fields >= REC_MAX_N_USER_FIELDS + DATA_N_SYS_COLS
+ if (pk->n_fields >= REC_MAX_N_USER_FIELDS + DATA_N_SYS_COLS
- n_add) {
return false;
}
}
-#if 1 // MDEV-17468: fix bugs with indexed virtual columns & remove this
- ut_ad(index->is_primary());
- ut_ad(!index->has_virtual());
- while ((index = index->indexes.next) != NULL) {
- if (index->has_virtual()) {
- ut_ad(ib_table.n_v_cols);
- return false;
- }
- }
-#endif
// Making table system-versioned instantly is not implemented yet.
if (ha_alter_info->handler_flags & ALTER_ADD_SYSTEM_VERSIONING) {
return false;
@@ -1521,6 +1521,8 @@ instant_alter_column_possible(
&& alter_options_need_rebuild(ha_alter_info, table)) {
return false;
}
+ } else if (!ib_table.supports_instant()) {
+ return false;
}
/* At the moment, we disallow ADD [UNIQUE] INDEX together with
@@ -1560,7 +1562,6 @@ instant_alter_column_possible(
return false;
}
- const dict_index_t* pk = ib_table.indexes.start;
Field** af = altered_table->field;
Field** const end = altered_table->field
+ altered_table->s->fields;
@@ -10217,7 +10218,7 @@ commit_cache_norebuild(
mtr.start();
if (buf_block_t* b = buf_page_get(
page_id_t(space->id, 0),
- page_size_t(space->flags),
+ space->zip_size(),
RW_X_LATCH, &mtr)) {
mtr.set_named_space(space);
mlog_write_ulint(
diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index cedb6e05782..bbbff16796f 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -5978,7 +5978,7 @@ i_s_dict_fill_sys_tables(
ulint compact = DICT_TF_GET_COMPACT(table->flags);
ulint atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(
table->flags);
- const page_size_t& page_size = dict_tf_get_page_size(table->flags);
+ const ulint zip_size = dict_tf_get_zip_size(table->flags);
const char* row_format;
if (!compact) {
@@ -6007,10 +6007,7 @@ i_s_dict_fill_sys_tables(
OK(field_store_string(fields[SYS_TABLES_ROW_FORMAT], row_format));
- OK(fields[SYS_TABLES_ZIP_PAGE_SIZE]->store(
- page_size.is_compressed()
- ? page_size.physical()
- : 0, true));
+ OK(fields[SYS_TABLES_ZIP_PAGE_SIZE]->store(zip_size, true));
OK(field_store_string(fields[SYS_TABLES_SPACE_TYPE],
table->space_id ? "Single" : "System"));
@@ -8003,13 +8000,11 @@ i_s_dict_fill_sys_tablespaces(
DBUG_RETURN(0);
}
- const page_size_t page_size(cflags);
-
OK(fields[SYS_TABLESPACES_PAGE_SIZE]->store(
- page_size.logical(), true));
+ fil_space_t::logical_size(cflags), true));
OK(fields[SYS_TABLESPACES_ZIP_PAGE_SIZE]->store(
- page_size.physical(), true));
+ fil_space_t::physical_size(cflags), true));
char* filepath = NULL;
if (FSP_FLAGS_HAS_DATA_DIR(cflags)) {
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index 1c90e8dd5c8..429163528ff 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2016, 2018, MariaDB Corporation.
+Copyright (c) 2016, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -363,8 +363,7 @@ ibuf_header_page_get(
block = buf_page_get(
page_id_t(IBUF_SPACE_ID, FSP_IBUF_HEADER_PAGE_NO),
- univ_page_size, RW_X_LATCH, mtr);
-
+ 0, RW_X_LATCH, mtr);
if (!block->page.encrypted) {
buf_block_dbg_add_level(block, SYNC_IBUF_HEADER);
@@ -395,7 +394,7 @@ ibuf_tree_root_get(
/* only segment list access is exclusive each other */
block = buf_page_get(
page_id_t(IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO),
- univ_page_size, RW_SX_LATCH, mtr);
+ 0, RW_SX_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
@@ -539,7 +538,7 @@ ibuf_init_at_db_start(void)
block = buf_page_get(
page_id_t(IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO),
- univ_page_size, RW_X_LATCH, &mtr);
+ 0, RW_X_LATCH, &mtr);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
@@ -585,13 +584,8 @@ ibuf_max_size_update(
}
-/*********************************************************************//**
-Initializes an ibuf bitmap page. */
-void
-ibuf_bitmap_page_init(
-/*==================*/
- buf_block_t* block, /*!< in: bitmap page */
- mtr_t* mtr) /*!< in: mtr */
+/** Apply MLOG_IBUF_BITMAP_INIT when crash-upgrading */
+ATTRIBUTE_COLD void ibuf_bitmap_init_apply(buf_block_t* block)
{
page_t* page;
ulint byte_offset;
@@ -602,65 +596,41 @@ ibuf_bitmap_page_init(
/* Write all zeros to the bitmap */
compile_time_assert(!(IBUF_BITS_PER_PAGE % 2));
- byte_offset = UT_BITS_IN_BYTES(block->page.size.physical()
+ byte_offset = UT_BITS_IN_BYTES(block->physical_size()
* IBUF_BITS_PER_PAGE);
memset(page + IBUF_BITMAP, 0, byte_offset);
-
- /* The remaining area (up to the page trailer) is uninitialized. */
- mlog_write_initial_log_record(page, MLOG_IBUF_BITMAP_INIT, mtr);
-}
-
-/*********************************************************************//**
-Parses a redo log record of an ibuf bitmap page init.
-@return end of log record or NULL */
-byte*
-ibuf_parse_bitmap_init(
-/*===================*/
- byte* ptr, /*!< in: buffer */
- byte* end_ptr MY_ATTRIBUTE((unused)), /*!< in: buffer end */
- buf_block_t* block, /*!< in: block or NULL */
- mtr_t* mtr) /*!< in: mtr or NULL */
-{
- ut_ad(ptr != NULL);
- ut_ad(end_ptr != NULL);
-
- if (block) {
- ibuf_bitmap_page_init(block, mtr);
- }
-
- return(ptr);
}
# ifdef UNIV_DEBUG
/** Gets the desired bits for a given page from a bitmap page.
@param[in] page bitmap page
@param[in] page_id page id whose bits to get
-@param[in] page_size page id whose bits to get
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] bit IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ...
@param[in,out] mtr mini-transaction holding an x-latch on the
bitmap page
@return value of bits */
-# define ibuf_bitmap_page_get_bits(page, page_id, page_size, bit, mtr) \
- ibuf_bitmap_page_get_bits_low(page, page_id, page_size, \
+# define ibuf_bitmap_page_get_bits(page, page_id, zip_size, bit, mtr) \
+ ibuf_bitmap_page_get_bits_low(page, page_id, zip_size, \
MTR_MEMO_PAGE_X_FIX, mtr, bit)
# else /* UNIV_DEBUG */
/** Gets the desired bits for a given page from a bitmap page.
@param[in] page bitmap page
@param[in] page_id page id whose bits to get
-@param[in] page_size page id whose bits to get
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] bit IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ...
@param[in,out] mtr mini-transaction holding an x-latch on the
bitmap page
@return value of bits */
-# define ibuf_bitmap_page_get_bits(page, page_id, page_size, bit, mtr) \
- ibuf_bitmap_page_get_bits_low(page, page_id, page_size, bit)
+# define ibuf_bitmap_page_get_bits(page, page_id, zip_size, bit, mtr) \
+ ibuf_bitmap_page_get_bits_low(page, page_id, zip_size, bit)
# endif /* UNIV_DEBUG */
/** Gets the desired bits for a given page from a bitmap page.
@param[in] page bitmap page
@param[in] page_id page id whose bits to get
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] latch_type MTR_MEMO_PAGE_X_FIX, MTR_MEMO_BUF_FIX, ...
@param[in,out] mtr mini-transaction holding latch_type on the
bitmap page
@@ -671,7 +641,7 @@ ulint
ibuf_bitmap_page_get_bits_low(
const page_t* page,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
#ifdef UNIV_DEBUG
ulint latch_type,
mtr_t* mtr,
@@ -682,12 +652,14 @@ ibuf_bitmap_page_get_bits_low(
ulint bit_offset;
ulint map_byte;
ulint value;
+ const ulint size = zip_size ? zip_size : srv_page_size;
+ ut_ad(ut_is_2pow(zip_size));
ut_ad(bit < IBUF_BITS_PER_PAGE);
compile_time_assert(!(IBUF_BITS_PER_PAGE % 2));
ut_ad(mtr_memo_contains_page(mtr, page, latch_type));
- bit_offset = (page_id.page_no() % page_size.physical())
+ bit_offset = (page_id.page_no() & (size - 1))
* IBUF_BITS_PER_PAGE + bit;
byte_offset = bit_offset / 8;
@@ -711,7 +683,7 @@ ibuf_bitmap_page_get_bits_low(
/** Sets the desired bit for a given page in a bitmap page.
@param[in,out] page bitmap page
@param[in] page_id page id whose bits to set
-@param[in] page_size page size
+@param[in] physical_size page size
@param[in] bit IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ...
@param[in] val value to set
@param[in,out] mtr mtr containing an x-latch to the bitmap page */
@@ -720,7 +692,7 @@ void
ibuf_bitmap_page_set_bits(
page_t* page,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint physical_size,
ulint bit,
ulint val,
mtr_t* mtr)
@@ -738,7 +710,7 @@ ibuf_bitmap_page_set_bits(
|| (0 == ibuf_count_get(page_id)));
#endif
- bit_offset = (page_id.page_no() % page_size.physical())
+ bit_offset = (page_id.page_no() % physical_size)
* IBUF_BITS_PER_PAGE + bit;
byte_offset = bit_offset / 8;
@@ -765,26 +737,20 @@ ibuf_bitmap_page_set_bits(
/** Calculates the bitmap page number for a given page number.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] size page size
@return the bitmap page id where the file page is mapped */
-UNIV_INLINE
-const page_id_t
-ibuf_bitmap_page_no_calc(
- const page_id_t page_id,
- const page_size_t& page_size)
+inline page_id_t ibuf_bitmap_page_no_calc(const page_id_t page_id, ulint size)
{
- ulint bitmap_page_no;
-
- bitmap_page_no = FSP_IBUF_BITMAP_OFFSET
- + (page_id.page_no() & ~(page_size.physical() - 1));
+ if (!size) size = srv_page_size;
- return(page_id_t(page_id.space(), bitmap_page_no));
+ return page_id_t(page_id.space(), FSP_IBUF_BITMAP_OFFSET
+ + (page_id.page_no() & ~(size - 1)));
}
/** Gets the ibuf bitmap page where the bits describing a given file page are
stored.
@param[in] page_id page id of the file page
-@param[in] page_size page size of the file page
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] file file name
@param[in] line line where called
@param[in,out] mtr mini-transaction
@@ -795,7 +761,7 @@ static
page_t*
ibuf_bitmap_get_map_page_func(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
const char* file,
unsigned line,
mtr_t* mtr)
@@ -803,8 +769,8 @@ ibuf_bitmap_get_map_page_func(
buf_block_t* block = NULL;
dberr_t err = DB_SUCCESS;
- block = buf_page_get_gen(ibuf_bitmap_page_no_calc(page_id, page_size),
- page_size, RW_X_LATCH, NULL, BUF_GET,
+ block = buf_page_get_gen(ibuf_bitmap_page_no_calc(page_id, zip_size),
+ zip_size, RW_X_LATCH, NULL, BUF_GET,
file, line, mtr, &err);
if (err != DB_SUCCESS) {
@@ -820,13 +786,13 @@ ibuf_bitmap_get_map_page_func(
/** Gets the ibuf bitmap page where the bits describing a given file page are
stored.
@param[in] page_id page id of the file page
-@param[in] page_size page size of the file page
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] mtr mini-transaction
@return bitmap page where the file page is mapped, that is, the bitmap
page containing the descriptor bits for the file page; the bitmap page
is x-latched */
-#define ibuf_bitmap_get_map_page(page_id, page_size, mtr) \
- ibuf_bitmap_get_map_page_func(page_id, page_size, \
+#define ibuf_bitmap_get_map_page(page_id, zip_size, mtr) \
+ ibuf_bitmap_get_map_page_func(page_id, zip_size, \
__FILE__, __LINE__, mtr)
/************************************************************************//**
@@ -860,14 +826,14 @@ ibuf_set_free_bits_low(
}
bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
- block->page.size, mtr);
+ block->zip_size(), mtr);
#ifdef UNIV_IBUF_DEBUG
ut_a(val <= ibuf_index_page_calc_free(block));
#endif /* UNIV_IBUF_DEBUG */
ibuf_bitmap_page_set_bits(
- bitmap_page, block->page.id, block->page.size,
+ bitmap_page, block->page.id, block->physical_size(),
IBUF_BITMAP_FREE, val, mtr);
}
@@ -904,7 +870,7 @@ ibuf_set_free_bits_func(
block->page.id.space());
bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
- block->page.size, &mtr);
+ block->zip_size(), &mtr);
switch (space->purpose) {
case FIL_TYPE_LOG:
@@ -946,7 +912,7 @@ ibuf_set_free_bits_func(
#endif /* UNIV_IBUF_DEBUG */
ibuf_bitmap_page_set_bits(
- bitmap_page, block->page.id, block->page.size,
+ bitmap_page, block->page.id, block->physical_size(),
IBUF_BITMAP_FREE, val, &mtr);
mtr_commit(&mtr);
@@ -996,7 +962,7 @@ ibuf_update_free_bits_low(
ut_a(!buf_block_get_page_zip(block));
ut_ad(mtr->is_named_space(block->page.id.space()));
- before = ibuf_index_page_calc_free_bits(block->page.size.logical(),
+ before = ibuf_index_page_calc_free_bits(srv_page_size,
max_ins_size);
after = ibuf_index_page_calc_free(block);
@@ -1031,10 +997,10 @@ ibuf_update_free_bits_zip(
buf_frame_t* frame = buf_block_get_frame(block);
ut_a(frame);
ut_a(page_is_leaf(frame));
- ut_a(block->page.size.is_compressed());
+ ut_a(block->zip_size());
bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
- block->page.size, mtr);
+ block->zip_size(), mtr);
after = ibuf_index_page_calc_free_zip(block);
@@ -1048,7 +1014,7 @@ ibuf_update_free_bits_zip(
}
ibuf_bitmap_page_set_bits(
- bitmap_page, block->page.id, block->page.size,
+ bitmap_page, block->page.id, block->physical_size(),
IBUF_BITMAP_FREE, after, mtr);
}
@@ -1090,23 +1056,19 @@ ibuf_update_free_bits_for_two_pages_low(
/** Returns TRUE if the page is one of the fixed address ibuf pages.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@return TRUE if a fixed address ibuf i/o page */
-UNIV_INLINE
-ibool
-ibuf_fixed_addr_page(
- const page_id_t page_id,
- const page_size_t& page_size)
+inline bool ibuf_fixed_addr_page(const page_id_t page_id, ulint zip_size)
{
return((page_id.space() == IBUF_SPACE_ID
&& page_id.page_no() == IBUF_TREE_ROOT_PAGE_NO)
- || ibuf_bitmap_page(page_id, page_size));
+ || ibuf_bitmap_page(page_id, zip_size));
}
/** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages.
Must not be called when recv_no_ibuf_operations==true.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] x_latch FALSE if relaxed check (avoid latching the
bitmap page)
@param[in] file file name
@@ -1115,12 +1077,12 @@ bitmap page)
bitmap page if the page is not one of the fixed address ibuf pages, or NULL,
in which case a new transaction is created.
@return TRUE if level 2 or level 3 page */
-ibool
+bool
ibuf_page_low(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
#ifdef UNIV_DEBUG
- ibool x_latch,
+ bool x_latch,
#endif /* UNIV_DEBUG */
const char* file,
unsigned line,
@@ -1133,12 +1095,10 @@ ibuf_page_low(
ut_ad(!recv_no_ibuf_operations);
ut_ad(x_latch || mtr == NULL);
- if (ibuf_fixed_addr_page(page_id, page_size)) {
-
- return(TRUE);
+ if (ibuf_fixed_addr_page(page_id, zip_size)) {
+ return(true);
} else if (page_id.space() != IBUF_SPACE_ID) {
-
- return(FALSE);
+ return(false);
}
compile_time_assert(IBUF_SPACE_ID == 0);
@@ -1161,14 +1121,14 @@ ibuf_page_low(
dberr_t err = DB_SUCCESS;
buf_block_t* block = buf_page_get_gen(
- ibuf_bitmap_page_no_calc(page_id, page_size),
- page_size, RW_NO_LATCH, NULL, BUF_GET_NO_LATCH,
- file, line, &local_mtr, &err);
+ ibuf_bitmap_page_no_calc(page_id, zip_size),
+ zip_size, RW_NO_LATCH, NULL, BUF_GET_NO_LATCH,
+ file, line, &local_mtr, &err);
bitmap_page = buf_block_get_frame(block);
ret = ibuf_bitmap_page_get_bits_low(
- bitmap_page, page_id, page_size,
+ bitmap_page, page_id, zip_size,
MTR_MEMO_BUF_FIX, &local_mtr, IBUF_BITMAP_IBUF);
mtr_commit(&local_mtr);
@@ -1181,10 +1141,10 @@ ibuf_page_low(
mtr_start(mtr);
}
- bitmap_page = ibuf_bitmap_get_map_page_func(page_id, page_size,
+ bitmap_page = ibuf_bitmap_get_map_page_func(page_id, zip_size,
file, line, mtr);
- ret = ibuf_bitmap_page_get_bits(bitmap_page, page_id, page_size,
+ ret = ibuf_bitmap_page_get_bits(bitmap_page, page_id, zip_size,
IBUF_BITMAP_IBUF, mtr);
if (mtr == &local_mtr) {
@@ -2057,11 +2017,11 @@ ibuf_add_free_page(void)
(level 2 page) */
const page_id_t page_id(IBUF_SPACE_ID, block->page.id.page_no());
- bitmap_page = ibuf_bitmap_get_map_page(page_id, univ_page_size, &mtr);
+ bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr);
mutex_exit(&ibuf_mutex);
- ibuf_bitmap_page_set_bits(bitmap_page, page_id, univ_page_size,
+ ibuf_bitmap_page_set_bits(bitmap_page, page_id, srv_page_size,
IBUF_BITMAP_IBUF, TRUE, &mtr);
ibuf_mtr_commit(&mtr);
@@ -2149,7 +2109,7 @@ ibuf_remove_free_page(void)
{
buf_block_t* block;
- block = buf_page_get(page_id, univ_page_size, RW_X_LATCH, &mtr);
+ block = buf_page_get(page_id, 0, RW_X_LATCH, &mtr);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
@@ -2169,13 +2129,13 @@ ibuf_remove_free_page(void)
/* Set the bit indicating that this page is no more an ibuf tree page
(level 2 page) */
- bitmap_page = ibuf_bitmap_get_map_page(page_id, univ_page_size, &mtr);
+ bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr);
mutex_exit(&ibuf_mutex);
ibuf_bitmap_page_set_bits(
- bitmap_page, page_id, univ_page_size, IBUF_BITMAP_IBUF, FALSE,
- &mtr);
+ bitmap_page, page_id, srv_page_size,
+ IBUF_BITMAP_IBUF, FALSE, &mtr);
ut_d(buf_page_set_file_page_was_freed(page_id));
@@ -3025,7 +2985,7 @@ ibuf_get_volume_buffered(
block = buf_page_get(
page_id_t(IBUF_SPACE_ID, prev_page_no),
- univ_page_size, RW_X_LATCH, mtr);
+ 0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
@@ -3097,7 +3057,7 @@ count_later:
block = buf_page_get(
page_id_t(IBUF_SPACE_ID, next_page_no),
- univ_page_size, RW_X_LATCH, mtr);
+ 0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
@@ -3310,6 +3270,24 @@ ibuf_get_entry_counter_func(
}
}
+
+/** Translates the ibuf free bits to the free space on a page in bytes.
+@param[in] physical_size page_size
+@param[in] bits value for ibuf bitmap bits
+@return maximum insert size after reorganize for the page */
+inline ulint
+ibuf_index_page_calc_free_from_bits(ulint physical_size, ulint bits)
+{
+ ut_ad(bits < 4);
+ ut_ad(physical_size > IBUF_PAGE_SIZE_PER_FREE_SPACE);
+
+ if (bits == 3) {
+ bits = 4;
+ }
+
+ return bits * physical_size / IBUF_PAGE_SIZE_PER_FREE_SPACE;
+}
+
/** Buffer an operation in the insert/delete buffer, instead of doing it
directly to the disk page, if this is possible.
@param[in] mode BTR_MODIFY_PREV or BTR_MODIFY_TREE
@@ -3321,7 +3299,7 @@ buffering
@param[in,out] index index where to insert; must not be unique
or clustered
@param[in] page_id page id where to insert
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] thr query thread
@return DB_SUCCESS, DB_STRONG_FAIL or other error */
static MY_ATTRIBUTE((warn_unused_result))
@@ -3334,7 +3312,7 @@ ibuf_insert_low(
ulint entry_size,
dict_index_t* index,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
que_thr_t* thr)
{
big_rec_t* dummy_big_rec;
@@ -3444,6 +3422,8 @@ ibuf_insert_low(
? &min_n_recs
: NULL, &mtr);
+ const ulint physical_size = zip_size ? zip_size : srv_page_size;
+
if (op == IBUF_OP_DELETE
&& (min_n_recs < 2 || buf_pool_watch_occurred(page_id))) {
/* The page could become empty after the record is
@@ -3488,8 +3468,7 @@ fail_exit:
ibuf_mtr_start(&bitmap_mtr);
index->set_modified(bitmap_mtr);
- bitmap_page = ibuf_bitmap_get_map_page(page_id, page_size,
- &bitmap_mtr);
+ bitmap_page = ibuf_bitmap_get_map_page(page_id, zip_size, &bitmap_mtr);
/* We check if the index page is suitable for buffered entries */
@@ -3503,11 +3482,12 @@ fail_exit:
if (op == IBUF_OP_INSERT) {
ulint bits = ibuf_bitmap_page_get_bits(
- bitmap_page, page_id, page_size, IBUF_BITMAP_FREE,
+ bitmap_page, page_id, physical_size, IBUF_BITMAP_FREE,
&bitmap_mtr);
if (buffered + entry_size + page_dir_calc_reserved_space(1)
- > ibuf_index_page_calc_free_from_bits(page_size, bits)) {
+ > ibuf_index_page_calc_free_from_bits(physical_size,
+ bits)) {
/* Release the bitmap page latch early. */
ibuf_mtr_commit(&bitmap_mtr);
@@ -3550,11 +3530,11 @@ fail_exit:
buffered entries for this index page, if the bit is not set yet */
old_bit_value = ibuf_bitmap_page_get_bits(
- bitmap_page, page_id, page_size,
+ bitmap_page, page_id, physical_size,
IBUF_BITMAP_BUFFERED, &bitmap_mtr);
if (!old_bit_value) {
- ibuf_bitmap_page_set_bits(bitmap_page, page_id, page_size,
+ ibuf_bitmap_page_set_bits(bitmap_page, page_id, physical_size,
IBUF_BITMAP_BUFFERED, TRUE,
&bitmap_mtr);
}
@@ -3659,23 +3639,23 @@ func_exit:
return(err);
}
-/** Buffer an operation in the insert/delete buffer, instead of doing it
-directly to the disk page, if this is possible. Does not do it if the index
+/** Buffer an operation in the change buffer, instead of applying it
+directly to the file page, if this is possible. Does not do it if the index
is clustered or unique.
@param[in] op operation type
@param[in] entry index entry to insert
@param[in,out] index index where to insert
@param[in] page_id page id where to insert
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] thr query thread
-@return TRUE if success */
-ibool
+@return true if success */
+bool
ibuf_insert(
ibuf_op_t op,
const dtuple_t* entry,
dict_index_t* index,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
que_thr_t* thr)
{
dberr_t err;
@@ -3703,7 +3683,7 @@ ibuf_insert(
case IBUF_USE_NONE:
case IBUF_USE_DELETE:
case IBUF_USE_DELETE_MARK:
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(false);
case IBUF_USE_INSERT:
case IBUF_USE_INSERT_DELETE_MARK:
case IBUF_USE_ALL:
@@ -3714,7 +3694,7 @@ ibuf_insert(
switch (use) {
case IBUF_USE_NONE:
case IBUF_USE_INSERT:
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(false);
case IBUF_USE_DELETE_MARK:
case IBUF_USE_DELETE:
case IBUF_USE_INSERT_DELETE_MARK:
@@ -3728,7 +3708,7 @@ ibuf_insert(
case IBUF_USE_NONE:
case IBUF_USE_INSERT:
case IBUF_USE_INSERT_DELETE_MARK:
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(false);
case IBUF_USE_DELETE_MARK:
case IBUF_USE_DELETE:
case IBUF_USE_ALL:
@@ -3768,7 +3748,7 @@ check_watch:
is being buffered, have this request executed
directly on the page in the buffer pool after the
buffered entries for this page have been merged. */
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(false);
}
}
@@ -3779,30 +3759,22 @@ skip_watch:
>= page_get_free_space_of_empty(dict_table_is_comp(index->table))
/ 2) {
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(false);
}
err = ibuf_insert_low(BTR_MODIFY_PREV, op, no_counter,
entry, entry_size,
- index, page_id, page_size, thr);
+ index, page_id, zip_size, thr);
if (err == DB_FAIL) {
err = ibuf_insert_low(BTR_MODIFY_TREE | BTR_LATCH_FOR_INSERT,
op, no_counter, entry, entry_size,
- index, page_id, page_size, thr);
+ index, page_id, zip_size, thr);
}
- if (err == DB_SUCCESS) {
-#ifdef UNIV_IBUF_DEBUG
- /* fprintf(stderr, "Ibuf insert for page no %lu of index %s\n",
- page_no, index->name); */
-#endif
- DBUG_RETURN(TRUE);
-
- } else {
- ut_a(err == DB_STRONG_FAIL || err == DB_TOO_BIG_RECORD);
+ ut_a(err == DB_SUCCESS || err == DB_STRONG_FAIL
+ || err == DB_TOO_BIG_RECORD);
- DBUG_RETURN(FALSE);
- }
+ DBUG_RETURN(err == DB_SUCCESS);
}
/********************************************************************//**
@@ -3866,13 +3838,13 @@ ibuf_insert_to_index_page_low(
"InnoDB: that table.\n", stderr);
bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
- block->page.size, mtr);
+ block->zip_size(), mtr);
old_bits = ibuf_bitmap_page_get_bits(
- bitmap_page, block->page.id, block->page.size,
+ bitmap_page, block->page.id, block->zip_size(),
IBUF_BITMAP_FREE, mtr);
ib::error() << "page " << block->page.id << ", size "
- << block->page.size.physical() << ", bitmap bits " << old_bits;
+ << block->physical_size() << ", bitmap bits " << old_bits;
ib::error() << BUG_REPORT_MSG;
@@ -4398,15 +4370,16 @@ subsequently was dropped.
@param[in,out] block if page has been read from disk,
pointer to the page x-latched, else NULL
@param[in] page_id page id of the index page
-@param[in] update_ibuf_bitmap normally this is set to TRUE, but
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in] update_ibuf_bitmap normally this is set, but
if we have deleted or are deleting the tablespace, then we naturally do not
want to update a non-existent bitmap page */
void
ibuf_merge_or_delete_for_page(
buf_block_t* block,
const page_id_t page_id,
- const page_size_t* page_size,
- ibool update_ibuf_bitmap)
+ ulint zip_size,
+ bool update_ibuf_bitmap)
{
mem_heap_t* heap;
btr_pcur_t pcur;
@@ -4431,38 +4404,23 @@ ibuf_merge_or_delete_for_page(
return;
}
- /* We cannot refer to page_size in the following, because it is passed
- as NULL (it is unknown) when buf_read_ibuf_merge_pages() is merging
- (discarding) changes for a dropped tablespace. When block != NULL or
- update_ibuf_bitmap is specified, then page_size must be known.
- That is why we will repeat the check below, with page_size in
- place of univ_page_size. Passing univ_page_size assumes that the
- uncompressed page size always is a power-of-2 multiple of the
- compressed page size. */
-
- if (ibuf_fixed_addr_page(page_id, univ_page_size)
- || fsp_descr_page(page_id, univ_page_size)) {
+ const ulint physical_size = zip_size ? zip_size : srv_page_size;
+
+ if (ibuf_fixed_addr_page(page_id, physical_size)
+ || fsp_descr_page(page_id, physical_size)) {
return;
}
fil_space_t* space;
if (update_ibuf_bitmap) {
-
- ut_ad(page_size != NULL);
-
- if (ibuf_fixed_addr_page(page_id, *page_size)
- || fsp_descr_page(page_id, *page_size)) {
- return;
- }
-
space = fil_space_acquire_silent(page_id.space());
if (UNIV_UNLIKELY(!space)) {
/* Do not try to read the bitmap page from the
non-existent tablespace, delete the ibuf records */
block = NULL;
- update_ibuf_bitmap = FALSE;
+ update_ibuf_bitmap = false;
} else {
page_t* bitmap_page = NULL;
ulint bitmap_bits = 0;
@@ -4470,12 +4428,12 @@ ibuf_merge_or_delete_for_page(
ibuf_mtr_start(&mtr);
bitmap_page = ibuf_bitmap_get_map_page(
- page_id, *page_size, &mtr);
+ page_id, zip_size, &mtr);
if (bitmap_page &&
fil_page_get_type(bitmap_page) != FIL_PAGE_TYPE_ALLOCATED) {
bitmap_bits = ibuf_bitmap_page_get_bits(
- bitmap_page, page_id, *page_size,
+ bitmap_page, page_id, zip_size,
IBUF_BITMAP_BUFFERED, &mtr);
}
@@ -4489,8 +4447,8 @@ ibuf_merge_or_delete_for_page(
}
}
} else if (block != NULL
- && (ibuf_fixed_addr_page(page_id, *page_size)
- || fsp_descr_page(page_id, *page_size))) {
+ && (ibuf_fixed_addr_page(page_id, physical_size)
+ || fsp_descr_page(page_id, physical_size))) {
return;
} else {
@@ -4723,23 +4681,23 @@ reset_bit:
if (update_ibuf_bitmap) {
page_t* bitmap_page;
- bitmap_page = ibuf_bitmap_get_map_page(page_id, *page_size,
+ bitmap_page = ibuf_bitmap_get_map_page(page_id, zip_size,
&mtr);
ibuf_bitmap_page_set_bits(
- bitmap_page, page_id, *page_size,
+ bitmap_page, page_id, physical_size,
IBUF_BITMAP_BUFFERED, FALSE, &mtr);
if (block != NULL) {
ulint old_bits = ibuf_bitmap_page_get_bits(
- bitmap_page, page_id, *page_size,
+ bitmap_page, page_id, zip_size,
IBUF_BITMAP_FREE, &mtr);
ulint new_bits = ibuf_index_page_calc_free(block);
if (old_bits != new_bits) {
ibuf_bitmap_page_set_bits(
- bitmap_page, page_id, *page_size,
+ bitmap_page, page_id, physical_size,
IBUF_BITMAP_FREE, new_bits, &mtr);
}
}
@@ -4922,9 +4880,9 @@ ibuf_print(
@param[in] read_buf database page
@param[in] size page size
@return whether the page is all zeroes */
-static bool buf_page_is_zeroes(const byte* read_buf, const page_size_t& size)
+static bool buf_page_is_zeroes(const byte* read_buf, ulint size)
{
- for (ulint i = 0; i < size.physical(); i++) {
+ for (ulint i = 0; i < size; i++) {
if (read_buf[i] != 0) {
return false;
}
@@ -4941,7 +4899,9 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
ulint page_no;
ut_ad(trx->mysql_thd);
ut_ad(space->purpose == FIL_TYPE_IMPORT);
- const page_size_t page_size(space->flags);
+
+ const ulint zip_size = space->zip_size();
+ const ulint physical_size = space->physical_size();
/* fil_space_t::size and fil_space_t::free_limit would still be 0
at this point. So, we will have to read page 0. */
ut_ad(!space->free_limit);
@@ -4950,7 +4910,8 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
mtr_t mtr;
ulint size;
mtr.start();
- if (buf_block_t* sp = buf_page_get(page_id_t(space->id, 0), page_size,
+ if (buf_block_t* sp = buf_page_get(page_id_t(space->id, 0),
+ zip_size,
RW_S_LATCH, &mtr)) {
size = std::min(
mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT
@@ -4974,7 +4935,7 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
below page_no is measured in number of pages since the beginning of
the space, as usual. */
- for (page_no = 0; page_no < size; page_no += page_size.physical()) {
+ for (page_no = 0; page_no < size; page_no += physical_size) {
page_t* bitmap_page;
ulint i;
@@ -4990,21 +4951,21 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
ibuf_enter(&mtr);
bitmap_page = ibuf_bitmap_get_map_page(
- page_id_t(space->id, page_no), page_size, &mtr);
+ page_id_t(space->id, page_no), zip_size, &mtr);
- if (buf_page_is_zeroes(bitmap_page, page_size)) {
+ if (buf_page_is_zeroes(bitmap_page, physical_size)) {
/* This means we got all-zero page instead of
ibuf bitmap page. The subsequent page should be
all-zero pages. */
#ifdef UNIV_DEBUG
for (ulint curr_page = page_no + 1;
- curr_page < page_size.physical(); curr_page++) {
+ curr_page < physical_size; curr_page++) {
buf_block_t* block = buf_page_get(
page_id_t(space->id, curr_page),
- page_size, RW_S_LATCH, &mtr);
+ zip_size, RW_S_LATCH, &mtr);
page_t* page = buf_block_get_frame(block);
- ut_ad(buf_page_is_zeroes(page, page_size));
+ ut_ad(buf_page_is_zeroes(page, physical_size));
}
#endif /* UNIV_DEBUG */
ibuf_exit(&mtr);
@@ -5017,17 +4978,13 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
return DB_CORRUPTION;
}
- for (i = FSP_IBUF_BITMAP_OFFSET + 1;
- i < page_size.physical();
- i++) {
-
+ for (i = FSP_IBUF_BITMAP_OFFSET + 1; i < physical_size; i++) {
const ulint offset = page_no + i;
-
const page_id_t cur_page_id(space->id, offset);
if (ibuf_bitmap_page_get_bits(
- bitmap_page, cur_page_id, page_size,
- IBUF_BITMAP_IBUF, &mtr)) {
+ bitmap_page, cur_page_id, zip_size,
+ IBUF_BITMAP_IBUF, &mtr)) {
mutex_exit(&ibuf_mutex);
ibuf_exit(&mtr);
@@ -5044,7 +5001,7 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
}
if (ibuf_bitmap_page_get_bits(
- bitmap_page, cur_page_id, page_size,
+ bitmap_page, cur_page_id, zip_size,
IBUF_BITMAP_BUFFERED, &mtr)) {
ib_errf(trx->mysql_thd,
@@ -5059,7 +5016,8 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
slightly corrupted tables can be
imported and dumped. Clear the bit. */
ibuf_bitmap_page_set_bits(
- bitmap_page, cur_page_id, page_size,
+ bitmap_page, cur_page_id,
+ physical_size,
IBUF_BITMAP_BUFFERED, FALSE, &mtr);
}
}
@@ -5089,18 +5047,18 @@ ibuf_set_bitmap_for_bulk_load(
free_val = ibuf_index_page_calc_free(block);
mtr_start(&mtr);
- mtr.set_named_space_id(block->page.id.space());
+ fil_space_t* space = mtr.set_named_space_id(block->page.id.space());
bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
- block->page.size, &mtr);
+ space->zip_size(), &mtr);
free_val = reset ? 0 : ibuf_index_page_calc_free(block);
ibuf_bitmap_page_set_bits(
- bitmap_page, block->page.id, block->page.size,
+ bitmap_page, block->page.id, block->physical_size(),
IBUF_BITMAP_FREE, free_val, &mtr);
ibuf_bitmap_page_set_bits(
- bitmap_page, block->page.id, block->page.size,
+ bitmap_page, block->page.id, block->physical_size(),
IBUF_BITMAP_BUFFERED, FALSE, &mtr);
mtr_commit(&mtr);
diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h
index 42d7cb3d32b..5d8dd93d655 100644
--- a/storage/innobase/include/btr0btr.h
+++ b/storage/innobase/include/btr0btr.h
@@ -2,7 +2,7 @@
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2014, 2018, MariaDB Corporation.
+Copyright (c) 2014, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -219,6 +219,7 @@ btr_height_get(
/** Gets a buffer page and declares its latching order level.
@param[in] page_id page id
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] mode latch mode
@param[in] file file name
@param[in] line line where called
@@ -230,7 +231,7 @@ UNIV_INLINE
buf_block_t*
btr_block_get_func(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint mode,
const char* file,
unsigned line,
@@ -240,28 +241,28 @@ btr_block_get_func(
# ifdef UNIV_DEBUG
/** Gets a buffer page and declares its latching order level.
@param page_id tablespace/page identifier
-@param page_size page size
+@param zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param mode latch mode
@param index index tree, may be NULL if not the insert buffer tree
@param mtr mini-transaction handle
@return the block descriptor */
-# define btr_block_get(page_id, page_size, mode, index, mtr) \
- btr_block_get_func(page_id, page_size, mode, \
+# define btr_block_get(page_id, zip_size, mode, index, mtr) \
+ btr_block_get_func(page_id, zip_size, mode, \
__FILE__, __LINE__, (dict_index_t*)index, mtr)
# else /* UNIV_DEBUG */
/** Gets a buffer page and declares its latching order level.
@param page_id tablespace/page identifier
-@param page_size page size
+@param zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param mode latch mode
@param index index tree, may be NULL if not the insert buffer tree
@param mtr mini-transaction handle
@return the block descriptor */
-# define btr_block_get(page_id, page_size, mode, index, mtr) \
- btr_block_get_func(page_id, page_size, mode, __FILE__, __LINE__, (dict_index_t*)index, mtr)
+# define btr_block_get(page_id, zip_size, mode, index, mtr) \
+ btr_block_get_func(page_id, zip_size, mode, __FILE__, __LINE__, (dict_index_t*)index, mtr)
# endif /* UNIV_DEBUG */
/** Gets a buffer page and declares its latching order level.
@param page_id tablespace/page identifier
-@param page_size page size
+@param zip_size compressed page size in bytes or 0 for uncompressed pages
@param mode latch mode
@param index index tree, may be NULL if not the insert buffer tree
@param mtr mini-transaction handle
@@ -269,9 +270,8 @@ btr_block_get_func(
UNIV_INLINE
page_t*
btr_page_get(
-/*=========*/
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint mode,
dict_index_t* index,
mtr_t* mtr)
@@ -367,23 +367,19 @@ btr_create(
/** Free a persistent index tree if it exists.
@param[in] page_id root page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] index_id PAGE_INDEX_ID contents
@param[in,out] mtr mini-transaction */
void
btr_free_if_exists(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
index_id_t index_id,
mtr_t* mtr);
-/** Free an index tree in a temporary tablespace or during TRUNCATE TABLE.
-@param[in] page_id root page id
-@param[in] page_size page size */
-void
-btr_free(
- const page_id_t page_id,
- const page_size_t& page_size);
+/** Free an index tree in a temporary tablespace.
+@param[in] page_id root page id */
+void btr_free(const page_id_t page_id);
/** Read the last used AUTO_INCREMENT value from PAGE_ROOT_AUTO_INC.
@param[in,out] index clustered index
@@ -807,17 +803,20 @@ btr_validate_index(
const trx_t* trx) /*!< in: transaction or 0 */
MY_ATTRIBUTE((warn_unused_result));
-/*************************************************************//**
-Removes a page from the level list of pages. */
-UNIV_INTERN
+/** Remove a page from the level list of pages.
+@param[in] space space where removed
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in,out] page page to remove
+@param[in] index index tree
+@param[in,out] mtr mini-transaction */
void
btr_level_list_remove_func(
-/*=======================*/
- ulint space, /*!< in: space where removed */
- const page_size_t& page_size,/*!< in: page size */
- page_t* page, /*!< in/out: page to remove */
- dict_index_t* index, /*!< in: index tree */
- mtr_t* mtr); /*!< in/out: mini-transaction */
+ ulint space,
+ ulint zip_size,
+ page_t* page,
+ dict_index_t* index,
+ mtr_t* mtr);
+
/*************************************************************//**
Removes a page from the level list of pages.
@param space in: space where removed
diff --git a/storage/innobase/include/btr0btr.ic b/storage/innobase/include/btr0btr.ic
index 2669611a9e6..3cdf279f25f 100644
--- a/storage/innobase/include/btr0btr.ic
+++ b/storage/innobase/include/btr0btr.ic
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, 2017, MariaDB Corporation.
+Copyright (c) 2015, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -31,6 +31,7 @@ Created 6/2/1994 Heikki Tuuri
/** Gets a buffer page and declares its latching order level.
@param[in] page_id page id
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] mode latch mode
@param[in] file file name
@param[in] line line where called
@@ -42,7 +43,7 @@ UNIV_INLINE
buf_block_t*
btr_block_get_func(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint mode,
const char* file,
unsigned line,
@@ -53,7 +54,7 @@ btr_block_get_func(
dberr_t err=DB_SUCCESS;
block = buf_page_get_gen(
- page_id, page_size, mode, NULL, BUF_GET, file, line, mtr, &err);
+ page_id, zip_size, mode, NULL, BUF_GET, file, line, mtr, &err);
if (err == DB_DECRYPTION_FAILED) {
if (index && index->table) {
@@ -96,7 +97,7 @@ btr_page_set_index_id(
}
/** Gets a buffer page and declares its latching order level.
-@param space tablespace identifier
+@param page_id tablespace/page identifier
@param zip_size compressed page size in bytes or 0 for uncompressed pages
@param page_no page number
@param mode latch mode
@@ -106,9 +107,8 @@ btr_page_set_index_id(
UNIV_INLINE
page_t*
btr_page_get(
-/*=========*/
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint mode,
dict_index_t* index,
mtr_t* mtr)
@@ -116,7 +116,7 @@ btr_page_get(
buf_block_t* block=NULL;
buf_frame_t* frame=NULL;
- block = btr_block_get(page_id, page_size, mode, index, mtr);
+ block = btr_block_get(page_id, zip_size, mode, index, mtr);
if (block) {
frame = buf_block_get_frame(block);
diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h
index 358f394c5b4..44b679bd07b 100644
--- a/storage/innobase/include/btr0cur.h
+++ b/storage/innobase/include/btr0cur.h
@@ -723,11 +723,12 @@ btr_free_externally_stored_field(
ignored if rec == NULL */
bool rollback, /*!< in: performing rollback? */
mtr_t* local_mtr); /*!< in: mtr containing the latch */
+
/** Copies the prefix of an externally stored field of a record.
The clustered index record must be protected by a lock or a page latch.
@param[out] buf the field, or a prefix of it
@param[in] len length of buf, in bytes
-@param[in] page_size BLOB page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] data 'internally' stored part of the field
containing also the reference to the external part; must be protected by
a lock or a page latch
@@ -738,7 +739,7 @@ ulint
btr_copy_externally_stored_field_prefix(
byte* buf,
ulint len,
- const page_size_t& page_size,
+ ulint zip_size,
const byte* data,
ulint local_len);
@@ -748,7 +749,7 @@ The clustered index record must be protected by a lock or a page latch.
@param[in] data 'internally' stored part of the field
containing also the reference to the external part; must be protected by
a lock or a page latch
-@param[in] page_size BLOB page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] local_len length of data
@param[in,out] heap mem heap
@return the whole field copied to heap */
@@ -756,7 +757,7 @@ byte*
btr_copy_externally_stored_field(
ulint* len,
const byte* data,
- const page_size_t& page_size,
+ ulint zip_size,
ulint local_len,
mem_heap_t* heap);
@@ -764,7 +765,7 @@ btr_copy_externally_stored_field(
@param[in] rec record in a clustered index; must be
protected by a lock or a page latch
@param[in] offset array returned by rec_get_offsets()
-@param[in] page_size BLOB page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] no field number
@param[out] len length of the field
@param[in,out] heap mem heap
@@ -773,7 +774,7 @@ byte*
btr_rec_copy_externally_stored_field(
const rec_t* rec,
const ulint* offsets,
- const page_size_t& page_size,
+ ulint zip_size,
ulint no,
ulint* len,
mem_heap_t* heap);
@@ -816,6 +817,7 @@ btr_rec_set_deleted_flag(
/** Latches the leaf page or pages requested.
@param[in] block leaf page where the search converged
@param[in] page_id page id of the leaf
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] latch_mode BTR_SEARCH_LEAF, ...
@param[in] cursor cursor
@param[in] mtr mini-transaction
@@ -824,7 +826,7 @@ btr_latch_leaves_t
btr_cur_latch_leaves(
buf_block_t* block,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint latch_mode,
btr_cur_t* cursor,
mtr_t* mtr);
diff --git a/storage/innobase/include/btr0types.h b/storage/innobase/include/btr0types.h
index fa59275dbff..0eb89f28de1 100644
--- a/storage/innobase/include/btr0types.h
+++ b/storage/innobase/include/btr0types.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2018, MariaDB Corporation.
+Copyright (c) 2018, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -28,7 +28,6 @@ Created 2/17/1996 Heikki Tuuri
#define btr0types_h
#include "page0types.h"
-#include "page0size.h"
#include "rem0types.h"
/** Persistent cursor */
@@ -50,10 +49,17 @@ extern ulong btr_ahi_parts;
/** The size of a reference to data stored on a different page.
The reference is stored at the end of the prefix of the field
in the index record. */
+#define FIELD_REF_SIZE 20U
#define BTR_EXTERN_FIELD_REF_SIZE FIELD_REF_SIZE
/** If the data don't exceed the size, the data are stored locally. */
#define BTR_EXTERN_LOCAL_STORED_MAX_SIZE \
(BTR_EXTERN_FIELD_REF_SIZE * 2)
+/** A field reference full of zero, for use in assertions and checks,
+and dummy default values of instantly dropped columns.
+Initially, BLOB field references are set to zero, in
+dtuple_convert_big_rec(). */
+extern const byte field_ref_zero[UNIV_PAGE_SIZE_MAX];
+
#endif
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index e888cd64a0a..381b9f8f049 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2018, MariaDB Corporation.
+Copyright (c) 2013, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -488,15 +488,13 @@ be implemented at a higher level. In other words, all possible
accesses to a given page through this function must be protected by
the same set of mutexes or latches.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size
@return pointer to the block */
-buf_page_t*
-buf_page_get_zip(
- const page_id_t page_id,
- const page_size_t& page_size);
+buf_page_t* buf_page_get_zip(const page_id_t page_id, ulint zip_size);
/** This is the general function used to get access to a database page.
@param[in] page_id page id
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH
@param[in] guess guessed block or NULL
@param[in] mode BUF_GET, BUF_GET_IF_IN_POOL,
@@ -509,7 +507,7 @@ BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH, or BUF_GET_IF_IN_POOL_OR_WATCH
buf_block_t*
buf_page_get_gen(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint rw_latch,
buf_block_t* guess,
ulint mode,
@@ -518,18 +516,18 @@ buf_page_get_gen(
mtr_t* mtr,
dberr_t* err);
-/** Initializes a page to the buffer buf_pool. The page is usually not read
+/** Initialize a page in the buffer pool. The page is usually not read
from a file even if it cannot be found in the buffer buf_pool. This is one
of the functions which perform to a block a state transition NOT_USED =>
FILE_PAGE (the other is buf_page_get_gen).
@param[in] page_id page id
-@param[in] page_size page size
-@param[in] mtr mini-transaction
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in,out] mtr mini-transaction
@return pointer to the block, page bufferfixed */
buf_block_t*
buf_page_create(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
mtr_t* mtr);
/********************************************************************//**
@@ -719,14 +717,14 @@ buf_page_is_checksum_valid_none(
/** Check if a page is corrupt.
@param[in] check_lsn whether the LSN should be checked
@param[in] read_buf database page
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] space tablespace
@return whether the page is corrupted */
bool
buf_page_is_corrupted(
bool check_lsn,
const byte* read_buf,
- const page_size_t& page_size,
+ ulint zip_size,
#ifndef UNIV_INNOCHECKSUM
const fil_space_t* space = NULL)
#else
@@ -795,10 +793,8 @@ buf_print(void);
/** Dump a page to stderr.
@param[in] read_buf database page
-@param[in] page_size page size */
-UNIV_INTERN
-void
-buf_page_print(const byte* read_buf, const page_size_t& page_size)
+@param[in] zip_size compressed page size, or 0 */
+void buf_page_print(const byte* read_buf, ulint zip_size = 0)
ATTRIBUTE_COLD __attribute__((nonnull));
/********************************************************************//**
Decompress a block.
@@ -1157,6 +1153,7 @@ and the lock released later.
@param[out] err DB_SUCCESS or DB_TABLESPACE_DELETED
@param[in] mode BUF_READ_IBUF_PAGES_ONLY, ...
@param[in] page_id page id
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] unzip whether the uncompressed page is
requested (for ROW_FORMAT=COMPRESSED)
@return pointer to the block
@@ -1166,7 +1163,7 @@ buf_page_init_for_read(
dberr_t* err,
ulint mode,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
bool unzip);
/** Complete a read or write request of a file page to or from the buffer pool.
@@ -1458,9 +1455,6 @@ public:
buf_pool->page_hash or
buf_pool->zip_hash */
- /** Page size. Protected by buf_pool mutex. */
- page_size_t size;
-
/** Count of how manyfold this block is currently bufferfixed. */
Atomic_counter<uint32_t> buf_fix_count;
@@ -1622,6 +1616,19 @@ public:
ut_ad(count != 0);
return count - 1;
}
+
+ /** @return the physical size, in bytes */
+ ulint physical_size() const
+ {
+ return zip.ssize ? (UNIV_ZIP_SIZE_MIN >> 1) << zip.ssize : srv_page_size;
+ }
+
+ /** @return the ROW_FORMAT=COMPRESSED physical size, in bytes
+ @retval 0 if not compressed */
+ ulint zip_size() const
+ {
+ return zip.ssize ? (UNIV_ZIP_SIZE_MIN >> 1) << zip.ssize : 0;
+ }
};
/** The buffer control block structure */
@@ -1788,6 +1795,13 @@ struct buf_block_t{
void fix() { page.fix(); }
uint32_t unfix() { return page.unfix(); }
+
+ /** @return the physical size, in bytes */
+ ulint physical_size() const { return page.physical_size(); }
+
+ /** @return the ROW_FORMAT=COMPRESSED physical size, in bytes
+ @retval 0 if not compressed */
+ ulint zip_size() const { return page.zip_size(); }
};
/** Check if a buf_block_t object is in a valid state
diff --git a/storage/innobase/include/buf0rea.h b/storage/innobase/include/buf0rea.h
index c32b0d3637e..057ce7711f5 100644
--- a/storage/innobase/include/buf0rea.h
+++ b/storage/innobase/include/buf0rea.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, 2017, MariaDB Corporation.
+Copyright (c) 2015, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -34,30 +34,23 @@ buffer buf_pool if it is not already there. Sets the io_fix flag and sets
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
released by the i/o-handler thread.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@retval DB_SUCCESS if the page was read and is not corrupted,
@retval DB_PAGE_CORRUPTED if page based on checksum check is corrupted,
@retval DB_DECRYPTION_FAILED if page post encryption checksum matches but
after decryption normal page checksum does not match.
@retval DB_TABLESPACE_DELETED if tablespace .ibd file is missing */
-dberr_t
-buf_read_page(
- const page_id_t page_id,
- const page_size_t& page_size);
+dberr_t buf_read_page(const page_id_t page_id, ulint zip_size);
-/********************************************************************//**
-High-level function which reads a page asynchronously from a file to the
+/** High-level function which reads a page asynchronously from a file to the
buffer buf_pool if it is not already there. Sets the io_fix flag and sets
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
released by the i/o-handler thread.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] sync true if synchronous aio is desired */
void
-buf_read_page_background(
- const page_id_t page_id,
- const page_size_t& page_size,
- bool sync);
+buf_read_page_background(const page_id_t page_id, ulint zip_size, bool sync);
/** Applies a random read-ahead in buf_pool if there are at least a threshold
value of accessed pages from the random read-ahead area. Does not read any
@@ -70,16 +63,13 @@ performed by ibuf routines, a situation which could result in a deadlock if
the OS does not support asynchronous i/o.
@param[in] page_id page id of a page which the current thread
wants to access
-@param[in] page_size page size
-@param[in] inside_ibuf TRUE if we are inside ibuf routine
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in] ibuf whether we are inside ibuf routine
@return number of page read requests issued; NOTE that if we read ibuf
pages, it may happen that the page at the given page number does not
get read even if we return a positive value! */
ulint
-buf_read_ahead_random(
- const page_id_t page_id,
- const page_size_t& page_size,
- ibool inside_ibuf);
+buf_read_ahead_random(const page_id_t page_id, ulint zip_size, bool ibuf);
/** Applies linear read-ahead if in the buf_pool the page is a border page of
a linear read-ahead area and all the pages in the area have been accessed.
@@ -104,14 +94,11 @@ NOTE 3: the calling thread must want access to the page given: this rule is
set to prevent unintended read-aheads performed by ibuf routines, a situation
which could result in a deadlock if the OS does not support asynchronous io.
@param[in] page_id page id; see NOTE 3 above
-@param[in] page_size page size
-@param[in] inside_ibuf TRUE if we are inside ibuf routine
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in] ibuf whether if we are inside ibuf routine
@return number of page read requests issued */
ulint
-buf_read_ahead_linear(
- const page_id_t page_id,
- const page_size_t& page_size,
- ibool inside_ibuf);
+buf_read_ahead_linear(const page_id_t page_id, ulint zip_size, bool ibuf);
/********************************************************************//**
Issues read requests for pages which the ibuf module wants to read in, in
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index e602a81ed27..202d56365b7 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -2,7 +2,7 @@
Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2013, 2018, MariaDB Corporation.
+Copyright (c) 2013, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -887,25 +887,33 @@ ulint
dict_tf_to_fsp_flags(ulint table_flags)
MY_ATTRIBUTE((const));
-/** Extract the page size from table flags.
+
+/** Extract the ROW_FORMAT=COMPRESSED page size from table flags.
@param[in] flags flags
-@return compressed page size, or 0 if not compressed */
-UNIV_INLINE
-const page_size_t
-dict_tf_get_page_size(
- ulint flags)
-MY_ATTRIBUTE((const));
+@return ROW_FORMAT=COMPRESSED page size
+@retval 0 if not compressed */
+inline ulint dict_tf_get_zip_size(ulint flags)
+{
+ flags &= DICT_TF_MASK_ZIP_SSIZE;
+ return flags
+ ? (UNIV_ZIP_SIZE_MIN >> 1)
+ << (FSP_FLAGS_GET_ZIP_SSIZE(flags >> DICT_TF_POS_ZIP_SSIZE
+ << FSP_FLAGS_POS_ZIP_SSIZE))
+ : 0;
+}
/** Determine the extent size (in pages) for the given table
@param[in] table the table whose extent size is being
calculated.
@return extent size in pages (256, 128 or 64) */
-ulint
-dict_table_extent_size(
- const dict_table_t* table);
+inline ulint dict_table_extent_size(const dict_table_t* table)
+{
+ if (ulint zip_size = table->space->zip_size()) {
+ return (1ULL << 20) / zip_size;
+ }
-/** Get the table page size. */
-#define dict_table_page_size(table) page_size_t(table->space->flags)
+ return FSP_EXTENT_SIZE;
+}
/*********************************************************************//**
Obtain exclusive locks on all index trees of the table. This is to prevent
diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic
index b970eaf0861..e0824469606 100644
--- a/storage/innobase/include/dict0dict.ic
+++ b/storage/innobase/include/dict0dict.ic
@@ -711,28 +711,6 @@ dict_tf_to_sys_tables_type(
return(type);
}
-/** Extract the page size info from table flags.
-@param[in] flags flags
-@return a structure containing the compressed and uncompressed
-page sizes and a boolean indicating if the page is compressed. */
-UNIV_INLINE
-const page_size_t
-dict_tf_get_page_size(
- ulint flags)
-{
- const ulint zip_ssize = DICT_TF_GET_ZIP_SSIZE(flags);
-
- if (zip_ssize == 0) {
- return(univ_page_size);
- }
-
- const ulint zip_size = (UNIV_ZIP_SIZE_MIN >> 1) << zip_ssize;
-
- ut_ad(zip_size <= UNIV_ZIP_SIZE_MAX);
-
- return(page_size_t(zip_size, srv_page_size, true));
-}
-
/*********************************************************************//**
Obtain exclusive locks on all index trees of the table. This is to prevent
accessing index trees while InnoDB is updating internal metadata for
diff --git a/storage/innobase/include/fil0crypt.h b/storage/innobase/include/fil0crypt.h
index e520f189d63..f278aa8fecb 100644
--- a/storage/innobase/include/fil0crypt.h
+++ b/storage/innobase/include/fil0crypt.h
@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (C) 2013, 2015, Google Inc. All Rights Reserved.
-Copyright (c) 2015, 2018, MariaDB Corporation.
+Copyright (c) 2015, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -273,13 +273,11 @@ fil_space_merge_crypt_data(
const fil_space_crypt_t* src);
/** Initialize encryption parameters from a tablespace header page.
-@param[in] page_size page size of the tablespace
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] page first page of the tablespace
@return crypt data from page 0
@retval NULL if not present or not valid */
-UNIV_INTERN
-fil_space_crypt_t*
-fil_space_read_crypt_data(const page_size_t& page_size, const byte* page)
+fil_space_crypt_t* fil_space_read_crypt_data(ulint zip_size, const byte* page)
MY_ATTRIBUTE((nonnull, warn_unused_result));
/**
@@ -310,9 +308,10 @@ fil_parse_write_crypt_data(
@param[in] offset Page offset
@param[in] lsn Log sequence number
@param[in] src_frame Page to encrypt
-@param[in] page_size Page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] dst_frame Output buffer
@return encrypted buffer or NULL */
+UNIV_INTERN
byte*
fil_encrypt_buf(
fil_space_crypt_t* crypt_data,
@@ -320,7 +319,7 @@ fil_encrypt_buf(
ulint offset,
lsn_t lsn,
const byte* src_frame,
- const page_size_t& page_size,
+ ulint zip_size,
byte* dst_frame)
MY_ATTRIBUTE((warn_unused_result));
@@ -343,20 +342,20 @@ fil_space_encrypt(
byte* dst_frame)
MY_ATTRIBUTE((warn_unused_result));
-/**
-Decrypt a page.
-@param[in,out] crypt_data crypt_data
+
+/** Decrypt a page.
+@param[in] crypt_data crypt_data
@param[in] tmp_frame Temporary buffer
-@param[in] page_size Page size
+@param[in] physical_size page size
@param[in,out] src_frame Page to decrypt
-@param[out] err DB_SUCCESS or error
+@param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED
@return true if page decrypted, false if not.*/
UNIV_INTERN
bool
fil_space_decrypt(
fil_space_crypt_t* crypt_data,
byte* tmp_frame,
- const page_size_t& page_size,
+ ulint physical_size,
byte* src_frame,
dberr_t* err);
@@ -377,17 +376,14 @@ fil_space_decrypt(
bool* decrypted)
MY_ATTRIBUTE((warn_unused_result));
-/******************************************************************
+/**
Calculate post encryption checksum
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] dst_frame Block where checksum is calculated
-@return page checksum or BUF_NO_CHECKSUM_MAGIC
+@return page checksum
not needed. */
-UNIV_INTERN
uint32_t
-fil_crypt_calculate_checksum(
- const page_size_t& page_size,
- const byte* dst_frame)
+fil_crypt_calculate_checksum(ulint zip_size, const byte* dst_frame)
MY_ATTRIBUTE((warn_unused_result));
/*********************************************************************
@@ -485,10 +481,9 @@ calculated checksum as if it does page could be valid unencrypted,
encrypted, or corrupted.
@param[in,out] page page frame (checksum is temporarily modified)
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@return true if page is encrypted AND OK, false otherwise */
-bool
-fil_space_verify_crypt_checksum(const byte* page, const page_size_t& page_size)
+bool fil_space_verify_crypt_checksum(const byte* page, ulint zip_size)
MY_ATTRIBUTE((warn_unused_result));
#endif /* fil0crypt_h */
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index c7278368368..5f17de80ab3 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2018, MariaDB Corporation.
+Copyright (c) 2013, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -27,7 +27,7 @@ Created 10/25/1995 Heikki Tuuri
#ifndef fil0fil_h
#define fil0fil_h
-#include "page0size.h"
+#include "fsp0types.h"
#ifndef UNIV_INNOCHECKSUM
@@ -120,8 +120,7 @@ struct fil_space_t {
or if the size change was implemented */
ulint flags; /*!< FSP_SPACE_FLAGS and FSP_FLAGS_MEM_ flags;
see fsp0types.h,
- fsp_flags_is_valid(),
- page_size_t(ulint) (constructor) */
+ fsp_flags_is_valid() */
ulint n_reserved_extents;
/*!< number of reserved free extents for
ongoing operations like B-tree page split */
@@ -256,6 +255,44 @@ struct fil_space_t {
void release_for_io() { ut_ad(pending_io()); n_pending_ios--; }
/** @return whether I/O is pending */
bool pending_io() const { return n_pending_ios; }
+
+ /** Determine the logical page size.
+ @param flags tablespace flags (FSP_FLAGS)
+ @return the logical page size
+ @retval 0 if the flags are invalid */
+ static ulint logical_size(ulint flags) {
+ switch (FSP_FLAGS_GET_PAGE_SSIZE(flags)) {
+ case 3: return 4096;
+ case 4: return 8192;
+ case 0: return 16384;
+ case 6: return 32768;
+ case 7: return 65536;
+ default: return 0;
+ }
+ }
+ /** Determine the ROW_FORMAT=COMPRESSED page size.
+ @param flags tablespace flags (FSP_FLAGS)
+ @return the ROW_FORMAT=COMPRESSED page size
+ @retval 0 if ROW_FORMAT=COMPRESSED is not used */
+ static ulint zip_size(ulint flags) {
+ ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(flags);
+ return zip_ssize
+ ? (UNIV_ZIP_SIZE_MIN >> 1) << zip_ssize : 0;
+ }
+ /** Determine the physical page size.
+ @param flags tablespace flags (FSP_FLAGS)
+ @return the physical page size */
+ static ulint physical_size(ulint flags) {
+ ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(flags);
+ return zip_ssize
+ ? (UNIV_ZIP_SIZE_MIN >> 1) << zip_ssize
+ : srv_page_size;
+ }
+ /** @return the ROW_FORMAT=COMPRESSED page size
+ @retval 0 if ROW_FORMAT=COMPRESSED is not used */
+ ulint zip_size() const { return zip_size(flags); }
+ /** @return the physical page size */
+ ulint physical_size() const { return physical_size(flags); }
};
/** Value of fil_space_t::magic_n */
@@ -688,16 +725,6 @@ fil_space_get_flags(
/*================*/
ulint id); /*!< in: space id */
-/** Returns the page size of the space and whether it is compressed or not.
-The tablespace must be cached in the memory cache.
-@param[in] id space id
-@param[out] found true if tablespace was found
-@return page size */
-const page_size_t
-fil_space_get_page_size(
- ulint id,
- bool* found);
-
/*******************************************************************//**
Opens all log files and system tablespace data files. They stay open until the
database server shutdown. This should be called at a server startup after the
@@ -1033,7 +1060,7 @@ fil_space_extend(
@param[in] type IO context
@param[in] sync true if synchronous aio is desired
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] byte_offset remainder of offset in bytes; in aio this
must be divisible by the OS block size
@param[in] len how many bytes to read or write; this must
@@ -1052,7 +1079,7 @@ fil_io(
const IORequest& type,
bool sync,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint byte_offset,
ulint len,
void* buf,
diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h
index 9b502f1f546..38ffc9bf4ae 100644
--- a/storage/innobase/include/fsp0fsp.h
+++ b/storage/innobase/include/fsp0fsp.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2018, MariaDB Corporation.
+Copyright (c) 2013, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -201,11 +201,6 @@ typedef byte fseg_inode_t;
(16 + 3 * FLST_BASE_NODE_SIZE \
+ FSEG_FRAG_ARR_N_SLOTS * FSEG_FRAG_SLOT_SIZE)
-#define FSP_SEG_INODES_PER_PAGE(page_size) \
- ((page_size.physical() - FSEG_ARR_OFFSET - 10) / FSEG_INODE_SIZE)
- /* Number of segment inodes which fit on a
- single page */
-
#define FSEG_MAGIC_N_VALUE 97937874
#define FSEG_FILLFACTOR 8 /* If this value is x, then if
@@ -290,33 +285,6 @@ the extent are free and which contain old tuple version to clean. */
#ifndef UNIV_INNOCHECKSUM
/* @} */
-/** Calculate the number of pages to extend a datafile.
-We extend single-table tablespaces first one extent at a time,
-but 4 at a time for bigger tablespaces. It is not enough to extend always
-by one extent, because we need to add at least one extent to FSP_FREE.
-A single extent descriptor page will track many extents. And the extent
-that uses its extent descriptor page is put onto the FSP_FREE_FRAG list.
-Extents that do not use their extent descriptor page are added to FSP_FREE.
-The physical page size is used to determine how many extents are tracked
-on one extent descriptor page. See xdes_calc_descriptor_page().
-@param[in] page_size page_size of the datafile
-@param[in] size current number of pages in the datafile
-@return number of pages to extend the file. */
-ulint
-fsp_get_pages_to_extend_ibd(
- const page_size_t& page_size,
- ulint size);
-
-/** Calculate the number of physical pages in an extent for this file.
-@param[in] page_size page_size of the datafile
-@return number of pages in an extent for this file. */
-UNIV_INLINE
-ulint
-fsp_get_extent_size_in_pages(const page_size_t& page_size)
-{
- return (FSP_EXTENT_SIZE << srv_page_size_shift) / page_size.physical();
-}
-
/**********************************************************************//**
Reads the space id from the first page of a tablespace.
@return space id, ULINT UNDEFINED if error */
@@ -347,13 +315,15 @@ fsp_header_get_flags(const page_t* page)
}
/** Get the byte offset of encryption information in page 0.
-@param[in] ps page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@return byte offset relative to FSP_HEADER_OFFSET */
inline MY_ATTRIBUTE((pure, warn_unused_result))
-ulint
-fsp_header_get_encryption_offset(const page_size_t& ps)
+ulint fsp_header_get_encryption_offset(ulint zip_size)
{
- return XDES_ARR_OFFSET + XDES_SIZE * ps.physical() / FSP_EXTENT_SIZE;
+ return zip_size
+ ? XDES_ARR_OFFSET + XDES_SIZE * zip_size / FSP_EXTENT_SIZE
+ : XDES_ARR_OFFSET + (XDES_SIZE << srv_page_size_shift)
+ / FSP_EXTENT_SIZE;
}
/** Check the encryption key from the first page of a tablespace.
@@ -619,13 +589,12 @@ fil_block_check_type(
/** Checks if a page address is an extent descriptor page address.
@param[in] page_id page id
-@param[in] page_size page size
-@return TRUE if a descriptor page */
-UNIV_INLINE
-ibool
-fsp_descr_page(
- const page_id_t page_id,
- const page_size_t& page_size);
+@param[in] physical_size page size
+@return whether a descriptor page */
+inline bool fsp_descr_page(const page_id_t page_id, ulint physical_size)
+{
+ return (page_id.page_no() & (physical_size - 1)) == FSP_XDES_OFFSET;
+}
/***********************************************************//**
Parses a redo log record of a file page init.
@@ -776,16 +745,6 @@ fsp_flags_match(ulint expected, ulint actual)
return(actual == expected);
}
-/** Calculates the descriptor index within a descriptor page.
-@param[in] page_size page size
-@param[in] offset page offset
-@return descriptor index */
-UNIV_INLINE
-ulint
-xdes_calc_descriptor_index(
- const page_size_t& page_size,
- ulint offset);
-
/**********************************************************************//**
Gets a descriptor bit of a page.
@return TRUE if free */
@@ -798,15 +757,40 @@ xdes_get_bit(
ulint offset);/*!< in: page offset within extent:
0 ... FSP_EXTENT_SIZE - 1 */
-/** Calculates the page where the descriptor of a page resides.
-@param[in] page_size page size
+/** Determine the descriptor index within a descriptor page.
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in] offset page offset
+@return descriptor index */
+inline ulint xdes_calc_descriptor_index(ulint zip_size, ulint offset)
+{
+ return(ut_2pow_remainder(offset, zip_size ? zip_size : srv_page_size)
+ / FSP_EXTENT_SIZE);
+}
+
+/** Determine the descriptor page number for a page.
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] offset page offset
@return descriptor page offset */
-UNIV_INLINE
-ulint
-xdes_calc_descriptor_page(
- const page_size_t& page_size,
- ulint offset);
+inline ulint xdes_calc_descriptor_page(ulint zip_size, ulint offset)
+{
+ compile_time_assert(UNIV_PAGE_SIZE_MAX > XDES_ARR_OFFSET
+ + (UNIV_PAGE_SIZE_MAX / FSP_EXTENT_SIZE_MAX)
+ * XDES_SIZE_MAX);
+ compile_time_assert(UNIV_PAGE_SIZE_MIN > XDES_ARR_OFFSET
+ + (UNIV_PAGE_SIZE_MIN / FSP_EXTENT_SIZE_MIN)
+ * XDES_SIZE_MIN);
+
+ ut_ad(srv_page_size > XDES_ARR_OFFSET
+ + (srv_page_size / FSP_EXTENT_SIZE)
+ * XDES_SIZE);
+ ut_ad(UNIV_ZIP_SIZE_MIN > XDES_ARR_OFFSET
+ + (UNIV_ZIP_SIZE_MIN / FSP_EXTENT_SIZE)
+ * XDES_SIZE);
+ ut_ad(!zip_size
+ || zip_size > XDES_ARR_OFFSET
+ + (zip_size / FSP_EXTENT_SIZE) * XDES_SIZE);
+ return ut_2pow_round(offset, zip_size ? zip_size : srv_page_size);
+}
#endif /* UNIV_INNOCHECKSUM */
diff --git a/storage/innobase/include/fsp0fsp.ic b/storage/innobase/include/fsp0fsp.ic
index 3258704615a..5977a954aea 100644
--- a/storage/innobase/include/fsp0fsp.ic
+++ b/storage/innobase/include/fsp0fsp.ic
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2017, MariaDB Corporation.
+Copyright (c) 2013, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -24,37 +24,6 @@ File space management
Created 12/18/1995 Heikki Tuuri
*******************************************************/
-#ifndef UNIV_INNOCHECKSUM
-
-/** Checks if a page address is an extent descriptor page address.
-@param[in] page_id page id
-@param[in] page_size page size
-@return TRUE if a descriptor page */
-UNIV_INLINE
-ibool
-fsp_descr_page(
- const page_id_t page_id,
- const page_size_t& page_size)
-{
- return((page_id.page_no() & (page_size.physical() - 1))
- == FSP_XDES_OFFSET);
-}
-
-/** Calculates the descriptor index within a descriptor page.
-@param[in] page_size page size
-@param[in] offset page offset
-@return descriptor index */
-UNIV_INLINE
-ulint
-xdes_calc_descriptor_index(
- const page_size_t& page_size,
- ulint offset)
-{
- return(ut_2pow_remainder(offset, page_size.physical())
- / FSP_EXTENT_SIZE);
-}
-#endif /*!UNIV_INNOCHECKSUM */
-
/**********************************************************************//**
Gets a descriptor bit of a page.
@return TRUE if free */
@@ -80,39 +49,3 @@ xdes_get_bit(
MLOG_1BYTE),
bit_index));
}
-
-#ifndef UNIV_INNOCHECKSUM
-/** Calculates the page where the descriptor of a page resides.
-@param[in] page_size page size
-@param[in] offset page offset
-@return descriptor page offset */
-UNIV_INLINE
-ulint
-xdes_calc_descriptor_page(
- const page_size_t& page_size,
- ulint offset)
-{
- compile_time_assert(UNIV_PAGE_SIZE_MAX > XDES_ARR_OFFSET
- + (UNIV_PAGE_SIZE_MAX / FSP_EXTENT_SIZE_MAX)
- * XDES_SIZE_MAX);
- compile_time_assert(UNIV_PAGE_SIZE_MIN > XDES_ARR_OFFSET
- + (UNIV_PAGE_SIZE_MIN / FSP_EXTENT_SIZE_MIN)
- * XDES_SIZE_MIN);
-
- ut_ad(srv_page_size > XDES_ARR_OFFSET
- + (srv_page_size / FSP_EXTENT_SIZE)
- * XDES_SIZE);
- ut_ad(UNIV_ZIP_SIZE_MIN > XDES_ARR_OFFSET
- + (UNIV_ZIP_SIZE_MIN / FSP_EXTENT_SIZE)
- * XDES_SIZE);
-
-#ifdef UNIV_DEBUG
- if (page_size.is_compressed()) {
- ut_a(page_size.physical() > XDES_ARR_OFFSET
- + (page_size.physical() / FSP_EXTENT_SIZE) * XDES_SIZE);
- }
-#endif /* UNIV_DEBUG */
-
- return(ut_2pow_round(offset, page_size.physical()));
-}
-#endif /* !UNIV_INNOCHECKSUM */
diff --git a/storage/innobase/include/fut0fut.h b/storage/innobase/include/fut0fut.h
index d8072708089..e06fc3c5e92 100644
--- a/storage/innobase/include/fut0fut.h
+++ b/storage/innobase/include/fut0fut.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -31,7 +32,7 @@ Created 12/13/1995 Heikki Tuuri
/** Gets a pointer to a file address and latches the page.
@param[in] space space id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] addr file address
@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_SX_LATCH
@param[out] ptr_block file page
@@ -42,13 +43,32 @@ UNIV_INLINE
byte*
fut_get_ptr(
ulint space,
- const page_size_t& page_size,
+ ulint zip_size,
fil_addr_t addr,
rw_lock_type_t rw_latch,
mtr_t* mtr,
buf_block_t** ptr_block = NULL)
- MY_ATTRIBUTE((warn_unused_result));
+{
+ buf_block_t* block;
+ byte* ptr = NULL;
-#include "fut0fut.ic"
+ ut_ad(addr.boffset < srv_page_size);
+ ut_ad((rw_latch == RW_S_LATCH)
+ || (rw_latch == RW_X_LATCH)
+ || (rw_latch == RW_SX_LATCH));
+
+ block = buf_page_get(page_id_t(space, addr.page), zip_size,
+ rw_latch, mtr);
+
+ ptr = buf_block_get_frame(block) + addr.boffset;
+
+ buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
+
+ if (ptr_block != NULL) {
+ *ptr_block = block;
+ }
+
+ return(ptr);
+}
#endif /* fut0fut_h */
diff --git a/storage/innobase/include/fut0fut.ic b/storage/innobase/include/fut0fut.ic
deleted file mode 100644
index 56be971f233..00000000000
--- a/storage/innobase/include/fut0fut.ic
+++ /dev/null
@@ -1,68 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
-
-*****************************************************************************/
-
-/******************************************************************//**
-@file include/fut0fut.ic
-File-based utilities
-
-Created 12/13/1995 Heikki Tuuri
-***********************************************************************/
-
-#include "sync0rw.h"
-#include "buf0buf.h"
-
-/** Gets a pointer to a file address and latches the page.
-@param[in] space space id
-@param[in] page_size page size
-@param[in] addr file address
-@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_SX_LATCH
-@param[in,out] mtr mini-transaction
-@param[out] ptr_block file page
-@return pointer to a byte in (*ptr_block)->frame; the *ptr_block is
-bufferfixed and latched */
-UNIV_INLINE
-byte*
-fut_get_ptr(
- ulint space,
- const page_size_t& page_size,
- fil_addr_t addr,
- rw_lock_type_t rw_latch,
- mtr_t* mtr,
- buf_block_t** ptr_block)
-{
- buf_block_t* block;
- byte* ptr = NULL;
-
- ut_ad(addr.boffset < srv_page_size);
- ut_ad((rw_latch == RW_S_LATCH)
- || (rw_latch == RW_X_LATCH)
- || (rw_latch == RW_SX_LATCH));
-
- block = buf_page_get(page_id_t(space, addr.page), page_size,
- rw_latch, mtr);
-
- ptr = buf_block_get_frame(block) + addr.boffset;
-
- buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
-
- if (ptr_block != NULL) {
- *ptr_block = block;
- }
-
- return(ptr);
-}
diff --git a/storage/innobase/include/ibuf0ibuf.h b/storage/innobase/include/ibuf0ibuf.h
index 72b9e291fca..c0c19eedab9 100644
--- a/storage/innobase/include/ibuf0ibuf.h
+++ b/storage/innobase/include/ibuf0ibuf.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2016, 2018, MariaDB Corporation.
+Copyright (c) 2016, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -119,13 +119,6 @@ ibuf_mtr_commit(
/*============*/
mtr_t* mtr) /*!< in/out: mini-transaction */
MY_ATTRIBUTE((nonnull));
-/*********************************************************************//**
-Initializes an ibuf bitmap page. */
-void
-ibuf_bitmap_page_init(
-/*==================*/
- buf_block_t* block, /*!< in: bitmap page */
- mtr_t* mtr); /*!< in: mtr */
/************************************************************************//**
Resets the free bits of the page in the ibuf bitmap. This is done in a
separate mini-transaction, hence this operation does not restrict
@@ -241,18 +234,19 @@ ibuf_inside(
/** Checks if a page address is an ibuf bitmap page (level 3 page) address.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@return TRUE if a bitmap page */
-UNIV_INLINE
-ibool
-ibuf_bitmap_page(
- const page_id_t page_id,
- const page_size_t& page_size);
+inline bool ibuf_bitmap_page(const page_id_t page_id, ulint zip_size)
+{
+ ut_ad(ut_is_2pow(zip_size));
+ ulint size = zip_size ? zip_size : srv_page_size;
+ return (page_id.page_no() & (size - 1)) == FSP_IBUF_BITMAP_OFFSET;
+}
/** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages.
Must not be called when recv_no_ibuf_operations==true.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] x_latch FALSE if relaxed check (avoid latching the
bitmap page)
@param[in] file file name
@@ -260,13 +254,13 @@ bitmap page)
@param[in,out] mtr mtr which will contain an x-latch to the
bitmap page if the page is not one of the fixed address ibuf pages, or NULL,
in which case a new transaction is created.
-@return TRUE if level 2 or level 3 page */
-ibool
+@return true if level 2 or level 3 page */
+bool
ibuf_page_low(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
#ifdef UNIV_DEBUG
- ibool x_latch,
+ bool x_latch,
#endif /* UNIV_DEBUG */
const char* file,
unsigned line,
@@ -278,22 +272,22 @@ ibuf_page_low(
/** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages.
Must not be called when recv_no_ibuf_operations==true.
@param[in] page_id tablespace/page identifier
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] mtr mini-transaction or NULL
@return TRUE if level 2 or level 3 page */
-# define ibuf_page(page_id, page_size, mtr) \
- ibuf_page_low(page_id, page_size, TRUE, __FILE__, __LINE__, mtr)
+# define ibuf_page(page_id, zip_size, mtr) \
+ ibuf_page_low(page_id, zip_size, true, __FILE__, __LINE__, mtr)
#else /* UVIV_DEBUG */
/** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages.
Must not be called when recv_no_ibuf_operations==true.
@param[in] page_id tablespace/page identifier
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] mtr mini-transaction or NULL
@return TRUE if level 2 or level 3 page */
-# define ibuf_page(page_id, page_size, mtr) \
- ibuf_page_low(page_id, page_size, __FILE__, __LINE__, mtr)
+# define ibuf_page(page_id, zip_size, mtr) \
+ ibuf_page_low(page_id, zip_size, __FILE__, __LINE__, mtr)
#endif /* UVIV_DEBUG */
/***********************************************************************//**
@@ -304,23 +298,23 @@ void
ibuf_free_excess_pages(void);
/*========================*/
-/** Buffer an operation in the insert/delete buffer, instead of doing it
-directly to the disk page, if this is possible. Does not do it if the index
+/** Buffer an operation in the change buffer, instead of applying it
+directly to the file page, if this is possible. Does not do it if the index
is clustered or unique.
@param[in] op operation type
@param[in] entry index entry to insert
@param[in,out] index index where to insert
@param[in] page_id page id where to insert
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] thr query thread
-@return TRUE if success */
-ibool
+@return true if success */
+bool
ibuf_insert(
ibuf_op_t op,
const dtuple_t* entry,
dict_index_t* index,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
que_thr_t* thr);
/** When an index page is read from a disk to the buffer pool, this function
@@ -332,15 +326,16 @@ subsequently was dropped.
@param[in,out] block if page has been read from disk,
pointer to the page x-latched, else NULL
@param[in] page_id page id of the index page
-@param[in] update_ibuf_bitmap normally this is set to TRUE, but
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in] update_ibuf_bitmap normally this is set, but
if we have deleted or are deleting the tablespace, then we naturally do not
want to update a non-existent bitmap page */
void
ibuf_merge_or_delete_for_page(
buf_block_t* block,
const page_id_t page_id,
- const page_size_t* page_size,
- ibool update_ibuf_bitmap);
+ ulint zip_size,
+ bool update_ibuf_bitmap);
/*********************************************************************//**
Deletes all entries in the insert buffer for a given space id. This is used
@@ -370,16 +365,8 @@ ibuf_merge_space(
/*=============*/
ulint space); /*!< in: space id */
-/*********************************************************************//**
-Parses a redo log record of an ibuf bitmap page init.
-@return end of log record or NULL */
-byte*
-ibuf_parse_bitmap_init(
-/*===================*/
- byte* ptr, /*!< in: buffer */
- byte* end_ptr,/*!< in: buffer end */
- buf_block_t* block, /*!< in: block or NULL */
- mtr_t* mtr); /*!< in: mtr or NULL */
+/** Apply MLOG_IBUF_BITMAP_INIT when crash-upgrading */
+ATTRIBUTE_COLD void ibuf_bitmap_init_apply(buf_block_t* block);
#ifdef UNIV_IBUF_COUNT_DEBUG
/** Gets the ibuf count for a given page.
diff --git a/storage/innobase/include/ibuf0ibuf.ic b/storage/innobase/include/ibuf0ibuf.ic
index e35b8a252a7..5be9569290b 100644
--- a/storage/innobase/include/ibuf0ibuf.ic
+++ b/storage/innobase/include/ibuf0ibuf.ic
@@ -150,20 +150,6 @@ ibuf_inside(
return(mtr->is_inside_ibuf());
}
-/** Checks if a page address is an ibuf bitmap page (level 3 page) address.
-@param[in] page_id page id
-@param[in] page_size page size
-@return TRUE if a bitmap page */
-UNIV_INLINE
-ibool
-ibuf_bitmap_page(
- const page_id_t page_id,
- const page_size_t& page_size)
-{
- return((page_id.page_no() & (page_size.physical() - 1))
- == FSP_IBUF_BITMAP_OFFSET);
-}
-
/** Translates the free space on a page to a value in the ibuf bitmap.
@param[in] page_size page size in bytes
@param[in] max_ins_size maximum insert size after reorganize for
@@ -192,29 +178,6 @@ ibuf_index_page_calc_free_bits(
return(n);
}
-/** Translates the ibuf free bits to the free space on a page in bytes.
-@param[in] page_size page_size
-@param[in] bits value for ibuf bitmap bits
-@return maximum insert size after reorganize for the page */
-UNIV_INLINE
-ulint
-ibuf_index_page_calc_free_from_bits(
- const page_size_t& page_size,
- ulint bits)
-{
- ut_ad(bits < 4);
- ut_ad(!page_size.is_compressed()
- || page_size.physical() > IBUF_PAGE_SIZE_PER_FREE_SPACE);
-
- if (bits == 3) {
- return(4 * page_size.physical()
- / IBUF_PAGE_SIZE_PER_FREE_SPACE);
- }
-
- return(bits * (page_size.physical()
- / IBUF_PAGE_SIZE_PER_FREE_SPACE));
-}
-
/*********************************************************************//**
Translates the free space on a compressed page to a value in the ibuf bitmap.
@return value for ibuf bitmap bits */
@@ -228,7 +191,7 @@ ibuf_index_page_calc_free_zip(
const page_zip_des_t* page_zip;
lint zip_max_ins;
- ut_ad(block->page.size.is_compressed());
+ ut_ad(block->page.zip.data);
/* Consider the maximum insert size on the uncompressed page
without reorganizing the page. We must not assume anything
@@ -251,7 +214,7 @@ ibuf_index_page_calc_free_zip(
max_ins_size = (ulint) zip_max_ins;
}
- return(ibuf_index_page_calc_free_bits(block->page.size.physical(),
+ return(ibuf_index_page_calc_free_bits(block->physical_size(),
max_ins_size));
}
@@ -264,14 +227,14 @@ ibuf_index_page_calc_free(
/*======================*/
const buf_block_t* block) /*!< in: buffer block */
{
- if (!block->page.size.is_compressed()) {
+ if (!block->page.zip.data) {
ulint max_ins_size;
max_ins_size = page_get_max_insert_size_after_reorganize(
buf_block_get_frame(block), 1);
return(ibuf_index_page_calc_free_bits(
- block->page.size.physical(), max_ins_size));
+ block->physical_size(), max_ins_size));
} else {
return(ibuf_index_page_calc_free_zip(block));
}
@@ -312,12 +275,12 @@ ibuf_update_free_bits_if_full(
ut_ad(buf_block_get_page_zip(block) == NULL);
before = ibuf_index_page_calc_free_bits(
- block->page.size.physical(), max_ins_size);
+ srv_page_size, max_ins_size);
if (max_ins_size >= increase) {
compile_time_assert(ULINT32_UNDEFINED > UNIV_PAGE_SIZE_MAX);
after = ibuf_index_page_calc_free_bits(
- block->page.size.physical(), max_ins_size - increase);
+ srv_page_size, max_ins_size - increase);
#ifdef UNIV_IBUF_DEBUG
ut_a(after <= ibuf_index_page_calc_free(block));
#endif
diff --git a/storage/innobase/include/mem0mem.ic b/storage/innobase/include/mem0mem.ic
index 8a8d141ce11..bfe3a3afd51 100644
--- a/storage/innobase/include/mem0mem.ic
+++ b/storage/innobase/include/mem0mem.ic
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation.
+Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -212,7 +212,7 @@ mem_heap_alloc(
mem_block_set_free(block, free + MEM_SPACE_NEEDED(n));
- UNIV_MEM_ALLOC(buf, n);
+ TRASH_ALLOC(buf, n);
return(buf);
}
diff --git a/storage/innobase/include/mtr0types.h b/storage/innobase/include/mtr0types.h
index 39ed707267d..af42010f415 100644
--- a/storage/innobase/include/mtr0types.h
+++ b/storage/innobase/include/mtr0types.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2018, MariaDB Corporation.
+Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -118,7 +118,7 @@ enum mlog_id_t {
/** mark an index record as the predefined minimum record */
MLOG_REC_MIN_MARK = 26,
- /** initialize an ibuf bitmap page */
+ /** initialize an ibuf bitmap page (used in MariaDB 10.2 and 10.3) */
MLOG_IBUF_BITMAP_INIT = 27,
#ifdef UNIV_LOG_LSN_DEBUG
@@ -231,8 +231,11 @@ enum mlog_id_t {
/** initialize a page with a string of identical bytes */
MLOG_MEMSET = 63,
+ /** Zero-fill a page that is not allocated. */
+ MLOG_INIT_FREE_PAGE = 64,
+
/** biggest value (used in assertions) */
- MLOG_BIGGEST_TYPE = MLOG_MEMSET,
+ MLOG_BIGGEST_TYPE = MLOG_INIT_FREE_PAGE,
/** log record for writing/updating crypt data of
a tablespace */
diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h
index 71da751ad25..2c11e447952 100644
--- a/storage/innobase/include/os0file.h
+++ b/storage/innobase/include/os0file.h
@@ -36,7 +36,7 @@ Created 10/21/1995 Heikki Tuuri
#ifndef os0file_h
#define os0file_h
-#include "page0size.h"
+#include "fsp0types.h"
#include "os0api.h"
#ifndef _WIN32
diff --git a/storage/innobase/include/page0size.h b/storage/innobase/include/page0size.h
deleted file mode 100644
index 08d072822bf..00000000000
--- a/storage/innobase/include/page0size.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file include/page0size.h
-A class describing a page size.
-
-Created Nov 14, 2013 Vasil Dimov
-*******************************************************/
-
-#ifndef page0size_t
-#define page0size_t
-
-#include "fsp0types.h"
-
-#define FIELD_REF_SIZE 20U
-
-/** A BLOB field reference full of zero, for use in assertions and
-tests.Initially, BLOB field references are set to zero, in
-dtuple_convert_big_rec(). */
-extern const byte field_ref_zero[UNIV_PAGE_SIZE_MAX];
-
-#define PAGE_SIZE_T_SIZE_BITS 17
-
-/** Page size descriptor. Contains the physical and logical page size, as well
-as whether the page is compressed or not. */
-class page_size_t {
-public:
- /** Constructor from (physical, logical, is_compressed).
- @param[in] physical physical (on-disk/zipped) page size
- @param[in] logical logical (in-memory/unzipped) page size
- @param[in] is_compressed whether the page is compressed */
- page_size_t(ulint physical, ulint logical, bool is_compressed)
- {
- if (physical == 0) {
- physical = UNIV_PAGE_SIZE_ORIG;
- }
- if (logical == 0) {
- logical = UNIV_PAGE_SIZE_ORIG;
- }
-
- m_physical = static_cast<unsigned>(physical);
- m_logical = static_cast<unsigned>(logical);
- m_is_compressed = static_cast<unsigned>(is_compressed);
-
- ut_ad(physical <= (1 << PAGE_SIZE_T_SIZE_BITS));
- ut_ad(logical <= (1 << PAGE_SIZE_T_SIZE_BITS));
-
- ut_ad(ut_is_2pow(physical));
- ut_ad(ut_is_2pow(logical));
-
- ut_ad(logical <= UNIV_PAGE_SIZE_MAX);
- ut_ad(logical >= physical);
- ut_ad(!is_compressed || physical <= UNIV_ZIP_SIZE_MAX);
- }
-
- /** Constructor from (fsp_flags).
- @param[in] fsp_flags filespace flags */
- explicit page_size_t(ulint fsp_flags)
- {
- ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(fsp_flags);
-
- /* If the logical page size is zero in fsp_flags, then use the
- legacy 16k page size. */
- ssize = (0 == ssize) ? UNIV_PAGE_SSIZE_ORIG : ssize;
-
- /* Convert from a 'log2 minus 9' to a page size in bytes. */
- const unsigned size = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize);
-
- ut_ad(size <= UNIV_PAGE_SIZE_MAX);
- ut_ad(size <= (1 << PAGE_SIZE_T_SIZE_BITS));
-
- m_logical = size;
-
- ssize = FSP_FLAGS_GET_ZIP_SSIZE(fsp_flags);
-
- /* If the fsp_flags have zero in the zip_ssize field, then it means
- that the tablespace does not have compressed pages and the physical
- page size is the same as the logical page size. */
- if (ssize == 0) {
- m_is_compressed = false;
- m_physical = m_logical;
- } else {
- m_is_compressed = true;
-
- /* Convert from a 'log2 minus 9' to a page size
- in bytes. */
- const unsigned phy
- = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize);
-
- ut_ad(phy <= UNIV_ZIP_SIZE_MAX);
- ut_ad(phy <= (1 << PAGE_SIZE_T_SIZE_BITS));
-
- m_physical = phy;
- }
- }
-
- /** Retrieve the physical page size (on-disk).
- @return physical page size in bytes */
- inline ulint physical() const
- {
- ut_ad(m_physical > 0);
-
- return(m_physical);
- }
-
- /** Retrieve the logical page size (in-memory).
- @return logical page size in bytes */
- inline ulint logical() const
- {
- ut_ad(m_logical > 0);
- return(m_logical);
- }
-
- /** Check whether the page is compressed on disk.
- @return true if compressed */
- inline bool is_compressed() const
- {
- return(m_is_compressed);
- }
-
- /** Copy the values from a given page_size_t object.
- @param[in] src page size object whose values to fetch */
- inline void copy_from(const page_size_t& src)
- {
- *this = src;
- }
-
- /** Check if a given page_size_t object is equal to the current one.
- @param[in] a page_size_t object to compare
- @return true if equal */
- inline bool equals_to(const page_size_t& a) const
- {
- return(a.physical() == m_physical
- && a.logical() == m_logical
- && a.is_compressed() == m_is_compressed);
- }
-
-private:
-
- /* For non compressed tablespaces, physical page size is equal to
- the logical page size and the data is stored in buf_page_t::frame
- (and is also always equal to univ_page_size (--innodb-page-size=)).
-
- For compressed tablespaces, physical page size is the compressed
- page size as stored on disk and in buf_page_t::zip::data. The logical
- page size is the uncompressed page size in memory - the size of
- buf_page_t::frame (currently also always equal to univ_page_size
- (--innodb-page-size=)). */
-
- /** Physical page size. */
- unsigned m_physical:PAGE_SIZE_T_SIZE_BITS;
-
- /** Logical page size. */
- unsigned m_logical:PAGE_SIZE_T_SIZE_BITS;
-
- /** Flag designating whether the physical page is compressed, which is
- true IFF the whole tablespace where the page belongs is compressed. */
- unsigned m_is_compressed:1;
-};
-
-/* Overloading the global output operator to conveniently print an object
-of type the page_size_t.
-@param[in,out] out the output stream
-@param[in] obj an object of type page_size_t to be printed
-@retval the output stream */
-inline
-std::ostream&
-operator<<(
- std::ostream& out,
- const page_size_t& obj)
-{
- out << "[page size: physical=" << obj.physical()
- << ", logical=" << obj.logical()
- << ", compressed=" << obj.is_compressed() << "]";
- return(out);
-}
-
-extern page_size_t univ_page_size;
-
-#endif /* page0size_t */
diff --git a/storage/innobase/include/page0zip.h b/storage/innobase/include/page0zip.h
index 1e11897482f..42432d08ad9 100644
--- a/storage/innobase/include/page0zip.h
+++ b/storage/innobase/include/page0zip.h
@@ -2,7 +2,7 @@
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2017, 2018, MariaDB Corporation.
+Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -86,15 +86,10 @@ page_zip_set_size(
@param[in] comp nonzero=compact format
@param[in] n_fields number of fields in the record; ignored if
tablespace is not compressed
-@param[in] page_size page size
-@return FALSE if the entire record can be stored locally on the page */
-UNIV_INLINE
-ibool
-page_zip_rec_needs_ext(
- ulint rec_size,
- ulint comp,
- ulint n_fields,
- const page_size_t& page_size)
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@return false if the entire record can be stored locally on the page */
+inline bool page_zip_rec_needs_ext(ulint rec_size, ulint comp, ulint n_fields,
+ ulint zip_size)
MY_ATTRIBUTE((warn_unused_result));
/**********************************************************************//**
diff --git a/storage/innobase/include/page0zip.ic b/storage/innobase/include/page0zip.ic
index 10a311089dc..a187f7e0111 100644
--- a/storage/innobase/include/page0zip.ic
+++ b/storage/innobase/include/page0zip.ic
@@ -2,7 +2,7 @@
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2017, MariaDB Corporation.
+Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -149,19 +149,14 @@ page_zip_set_size(
@param[in] comp nonzero=compact format
@param[in] n_fields number of fields in the record; ignored if
tablespace is not compressed
-@param[in] page_size page size
-@return FALSE if the entire record can be stored locally on the page */
-UNIV_INLINE
-ibool
-page_zip_rec_needs_ext(
- ulint rec_size,
- ulint comp,
- ulint n_fields,
- const page_size_t& page_size)
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@return false if the entire record can be stored locally on the page */
+inline bool page_zip_rec_needs_ext(ulint rec_size, ulint comp, ulint n_fields,
+ ulint zip_size)
{
ut_ad(rec_size
> ulint(comp ? REC_N_NEW_EXTRA_BYTES : REC_N_OLD_EXTRA_BYTES));
- ut_ad(comp || !page_size.is_compressed());
+ ut_ad(comp || !zip_size);
#if UNIV_PAGE_SIZE_MAX > COMPRESSED_REC_MAX_DATA_SIZE
if (comp ? rec_size >= COMPRESSED_REC_MAX_DATA_SIZE :
@@ -170,7 +165,7 @@ page_zip_rec_needs_ext(
}
#endif
- if (page_size.is_compressed()) {
+ if (zip_size) {
ut_ad(comp);
/* On a compressed page, there is a two-byte entry in
the dense page directory for every record. But there
@@ -179,7 +174,7 @@ page_zip_rec_needs_ext(
the encoded heap number. Check also the available space
on the uncompressed page. */
return(rec_size - (REC_N_NEW_EXTRA_BYTES - 2 - 1)
- >= page_zip_empty_size(n_fields, page_size.physical())
+ >= page_zip_empty_size(n_fields, zip_size)
|| rec_size >= page_get_free_space_of_empty(TRUE) / 2);
}
diff --git a/storage/innobase/include/row0ext.h b/storage/innobase/include/row0ext.h
index fe4bd710156..651dab9f6e3 100644
--- a/storage/innobase/include/row0ext.h
+++ b/storage/innobase/include/row0ext.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2006, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -29,7 +30,7 @@ Created September 2006 Marko Makela
#include "data0types.h"
#include "mem0mem.h"
#include "dict0types.h"
-#include "page0size.h"
+#include "fsp0types.h"
#include "row0types.h"
/********************************************************************//**
@@ -43,7 +44,7 @@ row_ext_create(
in the InnoDB table object, as reported by
dict_col_get_no(); NOT relative to the records
in the clustered index */
- ulint flags, /*!< in: table->flags */
+ const dict_table_t& table, /*!< in: table */
const dtuple_t* tuple, /*!< in: data tuple containing the field
references of the externally stored
columns; must be indexed by col_no;
@@ -91,9 +92,7 @@ struct row_ext_t{
REC_ANTELOPE_MAX_INDEX_COL_LEN or
REC_VERSION_56_MAX_INDEX_COL_LEN depending
on row format */
- page_size_t page_size;
- /*!< page size of the externally stored
- columns */
+ ulint zip_size;/*!< ROW_FORMAT=COMPRESSED page size, or 0 */
ulint len[1]; /*!< prefix lengths; 0 if not cached */
};
diff --git a/storage/innobase/include/trx0rseg.ic b/storage/innobase/include/trx0rseg.ic
index 9edfe897155..1257ffcb391 100644
--- a/storage/innobase/include/trx0rseg.ic
+++ b/storage/innobase/include/trx0rseg.ic
@@ -41,7 +41,7 @@ trx_rsegf_get(fil_space_t* space, ulint page_no, mtr_t* mtr)
|| !srv_was_started);
buf_block_t* block = buf_page_get(page_id_t(space->id, page_no),
- univ_page_size, RW_X_LATCH, mtr);
+ 0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_RSEG_HEADER);
@@ -67,8 +67,7 @@ trx_rsegf_get_new(
|| !srv_was_started);
ut_ad(space <= TRX_SYS_MAX_UNDO_SPACES || space == SRV_TMP_SPACE_ID);
- block = buf_page_get(
- page_id_t(space, page_no), univ_page_size, RW_X_LATCH, mtr);
+ block = buf_page_get(page_id_t(space, page_no), 0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW);
diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h
index 92f24d036ae..205a28033a7 100644
--- a/storage/innobase/include/trx0sys.h
+++ b/storage/innobase/include/trx0sys.h
@@ -74,7 +74,7 @@ trx_sysf_get(mtr_t* mtr, bool rw = true)
{
buf_block_t* block = buf_page_get(
page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO),
- univ_page_size, rw ? RW_X_LATCH : RW_S_LATCH, mtr);
+ 0, rw ? RW_X_LATCH : RW_S_LATCH, mtr);
if (block) {
buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER);
}
diff --git a/storage/innobase/include/trx0undo.ic b/storage/innobase/include/trx0undo.ic
index f6106ffddfa..b54f73cdda6 100644
--- a/storage/innobase/include/trx0undo.ic
+++ b/storage/innobase/include/trx0undo.ic
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2018, MariaDB Corporation.
+Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -111,8 +111,7 @@ UNIV_INLINE
page_t*
trx_undo_page_get(const page_id_t page_id, mtr_t* mtr)
{
- buf_block_t* block = buf_page_get(page_id, univ_page_size,
- RW_X_LATCH, mtr);
+ buf_block_t* block = buf_page_get(page_id, 0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
@@ -127,8 +126,7 @@ UNIV_INLINE
page_t*
trx_undo_page_get_s_latched(const page_id_t page_id, mtr_t* mtr)
{
- buf_block_t* block = buf_page_get(page_id, univ_page_size,
- RW_S_LATCH, mtr);
+ buf_block_t* block = buf_page_get(page_id, 0, RW_S_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index a8877ab8a33..0433a04e6f8 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -5176,7 +5176,7 @@ lock_rec_block_validate(
block = buf_page_get_gen(
page_id_t(space_id, page_no),
- page_size_t(space->flags),
+ space->zip_size(),
RW_X_LATCH, NULL,
BUF_GET_POSSIBLY_FREED,
__FILE__, __LINE__, &mtr, &err);
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index 720bb94f012..a39b46b53be 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -719,7 +719,7 @@ log_file_header_flush(
fil_io(IORequestLogWrite, true,
page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no),
- univ_page_size,
+ 0,
ulint(dest_offset & (srv_page_size - 1)),
OS_FILE_LOG_BLOCK_SIZE, buf, NULL);
@@ -838,7 +838,7 @@ loop:
fil_io(IORequestLogWrite, true,
page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no),
- univ_page_size,
+ 0,
ulint(next_offset & (srv_page_size - 1)), write_len, buf, NULL);
srv_stats.os_log_pending_writes.dec();
@@ -1341,7 +1341,7 @@ log_group_checkpoint(lsn_t end_lsn)
fil_io(IORequestLogWrite, false,
page_id_t(SRV_LOG_SPACE_FIRST_ID, 0),
- univ_page_size,
+ 0,
(log_sys.next_checkpoint_no & 1)
? LOG_CHECKPOINT_2 : LOG_CHECKPOINT_1,
OS_FILE_LOG_BLOCK_SIZE,
@@ -1361,7 +1361,7 @@ void log_header_read(ulint header)
fil_io(IORequestLogRead, true,
page_id_t(SRV_LOG_SPACE_FIRST_ID,
header >> srv_page_size_shift),
- univ_page_size, header & (srv_page_size - 1),
+ 0, header & (srv_page_size - 1),
OS_FILE_LOG_BLOCK_SIZE, log_sys.checkpoint_buf, NULL);
}
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index 9f6b9243070..f59bee021a1 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -780,7 +780,7 @@ loop:
fil_io(IORequestLogRead, true,
page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no),
- univ_page_size,
+ 0,
ulint(source_offset & (srv_page_size - 1)),
len, buf, NULL);
@@ -997,7 +997,7 @@ static dberr_t recv_log_format_0_recover(lsn_t lsn, bool crypt)
fil_io(IORequestLogRead, true,
page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no),
- univ_page_size,
+ 0,
ulint((source_offset & ~(OS_FILE_LOG_BLOCK_SIZE - 1))
& (srv_page_size - 1)),
OS_FILE_LOG_BLOCK_SIZE, buf, NULL);
@@ -1516,12 +1516,17 @@ parse_log:
break;
case MLOG_IBUF_BITMAP_INIT:
/* Allow anything in page_type when creating a page. */
- ptr = ibuf_parse_bitmap_init(ptr, end_ptr, block, mtr);
+ if (block) ibuf_bitmap_init_apply(block);
break;
case MLOG_INIT_FILE_PAGE2:
/* Allow anything in page_type when creating a page. */
ptr = fsp_parse_init_file_page(ptr, end_ptr, block);
break;
+ case MLOG_INIT_FREE_PAGE:
+ /* The page can be zero-filled and its previous
+ contents can be ignored. We do not write or apply
+ this record yet. */
+ break;
case MLOG_WRITE_STRING:
ptr = mlog_parse_string(ptr, end_ptr, page, page_zip);
break;
@@ -2081,19 +2086,21 @@ void recv_apply_hashed_log_recs(bool last_batch)
if (recv_addr->state == RECV_DISCARDED
|| !UT_LIST_GET_LEN(recv_addr->rec_list)) {
+not_found:
ut_a(recv_sys->n_addrs);
recv_sys->n_addrs--;
continue;
}
+ fil_space_t* space = fil_space_acquire_for_io(
+ recv_addr->space);
+ if (!space) {
+ goto not_found;
+ }
+
const page_id_t page_id(recv_addr->space,
recv_addr->page_no);
- bool found;
- const page_size_t& page_size
- = fil_space_get_page_size(recv_addr->space,
- &found);
-
- ut_ad(found);
+ const ulint zip_size = space->zip_size();
if (recv_addr->state == RECV_NOT_PROCESSED) {
mutex_exit(&recv_sys->mutex);
@@ -2103,7 +2110,7 @@ void recv_apply_hashed_log_recs(bool last_batch)
mtr.start();
buf_block_t* block = buf_page_get(
- page_id, page_size,
+ page_id, zip_size,
RW_X_LATCH, &mtr);
buf_block_dbg_add_level(
@@ -2117,6 +2124,8 @@ void recv_apply_hashed_log_recs(bool last_batch)
mutex_enter(&recv_sys->mutex);
}
+
+ space->release_for_io();
}
}
@@ -3857,6 +3866,9 @@ static const char* get_mlog_string(mlog_id_t type)
case MLOG_MEMSET:
return("MLOG_MEMSET");
+ case MLOG_INIT_FREE_PAGE:
+ return("MLOG_INIT_FREE_PAGE");
+
case MLOG_FILE_WRITE_CRYPT_DATA:
return("MLOG_FILE_WRITE_CRYPT_DATA");
}
diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc
index 13934546448..5c15e8238d2 100644
--- a/storage/innobase/mtr/mtr0mtr.cc
+++ b/storage/innobase/mtr/mtr0mtr.cc
@@ -142,7 +142,7 @@ struct FindPage
slot->object);
if (m_ptr < block->frame
- || m_ptr >= block->frame + block->page.size.logical()) {
+ || m_ptr >= block->frame + srv_page_size) {
return(true);
}
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index f7a436ed68e..bb51123617d 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -3511,8 +3511,6 @@ static WinIoInit win_io_init;
/** Free storage space associated with a section of the file.
@param[in] fh Open file handle
-@param[in] page_size Tablespace page size
-@param[in] block_size File system block size
@param[in] off Starting offset (SEEK_SET)
@param[in] len Size of the hole
@return 0 on success or errno */
diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc
index 96f5603853b..6c213f28c12 100644
--- a/storage/innobase/page/page0zip.cc
+++ b/storage/innobase/page/page0zip.cc
@@ -26,19 +26,19 @@ Created June 2005 by Marko Makela
*******************************************************/
#include "page0zip.h"
-#include "page0size.h"
+#include "fsp0types.h"
#include "page0page.h"
#include "buf0checksum.h"
+#include "ut0crc32.h"
+#include "zlib.h"
+
+#ifndef UNIV_INNOCHECKSUM
/** A BLOB field reference full of zero, for use in assertions and tests.
Initially, BLOB field references are set to zero, in
dtuple_convert_big_rec(). */
const byte field_ref_zero[UNIV_PAGE_SIZE_MAX] = { 0, };
-#include "ut0crc32.h"
-#include "zlib.h"
-
-#ifndef UNIV_INNOCHECKSUM
#include "mtr0log.h"
#include "dict0dict.h"
#include "btr0cur.h"
@@ -170,18 +170,17 @@ page_zip_is_too_big(
const dict_index_t* index,
const dtuple_t* entry)
{
- const page_size_t& page_size =
- dict_table_page_size(index->table);
+ const ulint zip_size = index->table->space->zip_size();
/* Estimate the free space of an empty compressed page.
Subtract one byte for the encoded heap_no in the
modification log. */
ulint free_space_zip = page_zip_empty_size(
- index->n_fields, page_size.physical());
+ index->n_fields, zip_size);
ulint n_uniq = dict_index_get_n_unique_in_tree(index);
ut_ad(dict_table_is_comp(index->table));
- ut_ad(page_size.is_compressed());
+ ut_ad(zip_size);
if (free_space_zip == 0) {
return(true);
diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc
index 19764318c1a..c76bf3429b9 100644
--- a/storage/innobase/rem/rem0rec.cc
+++ b/storage/innobase/rem/rem0rec.cc
@@ -612,7 +612,13 @@ rec_init_offsets(
ulint i = 0;
ulint offs;
- ut_ad(index->n_core_null_bytes <= UT_BITS_IN_BYTES(index->n_nullable));
+ /* This assertion was relaxed for the btr_cur_open_at_index_side()
+ call in btr_cur_instant_init_low(). We cannot invoke
+ index->is_instant(), because the same assertion would fail there
+ until btr_cur_instant_init_low() has invoked
+ dict_table_t::deserialise_columns(). */
+ ut_ad(index->n_core_null_bytes <= UT_BITS_IN_BYTES(index->n_nullable)
+ || (!leaf && index->n_core_fields != index->n_fields));
ut_d(offsets[2] = ulint(rec));
ut_d(offsets[3] = ulint(index));
diff --git a/storage/innobase/row/row0ext.cc b/storage/innobase/row/row0ext.cc
index 503f7d0d3e7..6973fe758d9 100644
--- a/storage/innobase/row/row0ext.cc
+++ b/storage/innobase/row/row0ext.cc
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2006, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -29,14 +30,14 @@ Created September 2006 Marko Makela
/** Fills the column prefix cache of an externally stored column.
@param[in,out] ext column prefix cache
@param[in] i index of ext->ext[]
-@param[in] page_size page size
+@param[in] space tablespace
@param[in] dfield data field */
static
void
row_ext_cache_fill(
row_ext_t* ext,
ulint i,
- const page_size_t& page_size,
+ fil_space_t* space,
const dfield_t* dfield)
{
const byte* field = static_cast<const byte*>(
@@ -75,7 +76,8 @@ row_ext_cache_fill(
crashed during the execution of
btr_free_externally_stored_field(). */
ext->len[i] = btr_copy_externally_stored_field_prefix(
- buf, ext->max_len, page_size, field, f_len);
+ buf, ext->max_len, ext->zip_size,
+ field, f_len);
}
}
}
@@ -91,7 +93,7 @@ row_ext_create(
in the InnoDB table object, as reported by
dict_col_get_no(); NOT relative to the records
in the clustered index */
- ulint flags, /*!< in: table->flags */
+ const dict_table_t& table, /*!< in: table */
const dtuple_t* tuple, /*!< in: data tuple containing the field
references of the externally stored
columns; must be indexed by col_no;
@@ -100,36 +102,30 @@ row_ext_create(
to prevent deletion (rollback or purge). */
mem_heap_t* heap) /*!< in: heap where created */
{
- ulint i;
- const page_size_t& page_size = dict_tf_get_page_size(flags);
-
- row_ext_t* ret;
+ if (!table.space) {
+ return NULL;
+ }
ut_ad(n_ext > 0);
- ret = static_cast<row_ext_t*>(
+ row_ext_t* ret = static_cast<row_ext_t*>(
mem_heap_alloc(heap,
(sizeof *ret) + (n_ext - 1) * sizeof ret->len));
ret->n_ext = n_ext;
ret->ext = ext;
- ret->max_len = DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags);
- ret->page_size.copy_from(page_size);
+ ret->max_len = DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(table.flags);
+ ret->zip_size = dict_tf_get_zip_size(table.flags);
ret->buf = static_cast<byte*>(
mem_heap_alloc(heap, n_ext * ret->max_len));
-#ifdef UNIV_DEBUG
- memset(ret->buf, 0xaa, n_ext * ret->max_len);
- UNIV_MEM_ALLOC(ret->buf, n_ext * ret->max_len);
-#endif
-
/* Fetch the BLOB prefixes */
- for (i = 0; i < n_ext; i++) {
+ for (ulint i = 0; i < n_ext; i++) {
const dfield_t* dfield;
dfield = dtuple_get_nth_field(tuple, ext[i]);
- row_ext_cache_fill(ret, i, page_size, dfield);
+ row_ext_cache_fill(ret, i, table.space, dfield);
}
return(ret);
diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc
index 19b6dfd0763..4e3a4b0c4c7 100644
--- a/storage/innobase/row/row0ftsort.cc
+++ b/storage/innobase/row/row0ftsort.cc
@@ -808,7 +808,7 @@ DECLARE_THREAD(fts_parallel_tokenization)(
block = psort_info->merge_block;
crypt_block = psort_info->crypt_block;
- const page_size_t& page_size = dict_table_page_size(table);
+ const ulint zip_size = table->space->zip_size();
row_merge_fts_get_next_doc_item(psort_info, &doc_item);
@@ -838,7 +838,7 @@ loop:
doc.text.f_str =
btr_copy_externally_stored_field(
&doc.text.f_len, data,
- page_size, data_len, blob_heap);
+ zip_size, data_len, blob_heap);
} else {
doc.text.f_str = data;
doc.text.f_len = data_len;
diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc
index 4e9f16a502f..ec8d31bc902 100644
--- a/storage/innobase/row/row0import.cc
+++ b/storage/innobase/row/row0import.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, 2018, MariaDB Corporation.
+Copyright (c) 2015, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -53,7 +53,7 @@ Created 2012-02-08 by Sunny Bains.
/** The size of the buffer to use for IO.
@param n physical page size
@return number of pages */
-#define IO_BUFFER_SIZE(n) ((1024 * 1024) / n)
+#define IO_BUFFER_SIZE(n) ((1024 * 1024) / (n))
/** For gathering stats on records during phase I */
struct row_stats_t {
@@ -115,7 +115,7 @@ struct row_import {
m_hostname(NULL),
m_table_name(NULL),
m_autoinc(0),
- m_page_size(0, 0, false),
+ m_zip_size(0),
m_flags(0),
m_n_cols(0),
m_cols(NULL),
@@ -196,7 +196,8 @@ struct row_import {
ib_uint64_t m_autoinc; /*!< Next autoinc value */
- page_size_t m_page_size; /*!< Tablespace page size */
+ ulint m_zip_size; /*!< ROW_FORMAT=COMPRESSED
+ page size, or 0 */
ulint m_flags; /*!< Table flags */
@@ -356,7 +357,7 @@ public:
@param trx covering transaction */
AbstractCallback(trx_t* trx, ulint space_id)
:
- m_page_size(0, 0, false),
+ m_zip_size(0),
m_trx(trx),
m_space(space_id),
m_xdes(),
@@ -380,7 +381,7 @@ public:
/** @return true if compressed table. */
bool is_compressed_table() const UNIV_NOTHROW
{
- return(get_page_size().is_compressed());
+ return get_zip_size();
}
/** @return the tablespace flags */
@@ -400,7 +401,11 @@ public:
m_filepath = filename;
}
- const page_size_t& get_page_size() const { return m_page_size; }
+ ulint get_zip_size() const { return m_zip_size; }
+ ulint physical_size() const
+ {
+ return m_zip_size ? m_zip_size : srv_page_size;
+ }
const char* filename() const { return m_filepath; }
@@ -439,7 +444,7 @@ protected:
{
ulint offset;
- offset = xdes_calc_descriptor_index(get_page_size(), page_no);
+ offset = xdes_calc_descriptor_index(get_zip_size(), page_no);
return(page + XDES_ARR_OFFSET + XDES_SIZE * offset);
}
@@ -467,9 +472,11 @@ protected:
state = mach_read_ulint(xdesc + XDES_STATE, MLOG_4BYTES);
if (state != XDES_FREE) {
+ const ulint physical_size = m_zip_size
+ ? m_zip_size : srv_page_size;
m_xdes = UT_NEW_ARRAY_NOKEY(xdes_t,
- m_page_size.physical());
+ physical_size);
/* Trigger OOM */
DBUG_EXECUTE_IF(
@@ -482,7 +489,7 @@ protected:
return(DB_OUT_OF_MEMORY);
}
- memcpy(m_xdes, page, m_page_size.physical());
+ memcpy(m_xdes, page, physical_size);
}
return(DB_SUCCESS);
@@ -493,7 +500,7 @@ protected:
@return true if the page is marked as free */
bool is_free(ulint page_no) const UNIV_NOTHROW
{
- ut_a(xdes_calc_descriptor_page(get_page_size(), page_no)
+ ut_a(xdes_calc_descriptor_page(get_zip_size(), page_no)
== m_xdes_page_no);
if (m_xdes != 0) {
@@ -508,8 +515,8 @@ protected:
}
protected:
- /** The tablespace page size. */
- page_size_t m_page_size;
+ /** The ROW_FORMAT=COMPRESSED page size, or 0. */
+ ulint m_zip_size;
/** File handle to the tablespace */
pfs_os_file_t m_file;
@@ -568,21 +575,23 @@ AbstractCallback::init(
/* Clear the DATA_DIR flag, which is basically garbage. */
m_space_flags &= ~(1U << FSP_FLAGS_POS_RESERVED);
- m_page_size.copy_from(page_size_t(m_space_flags));
+ m_zip_size = fil_space_t::zip_size(m_space_flags);
+ const ulint logical_size = fil_space_t::logical_size(m_space_flags);
+ const ulint physical_size = fil_space_t::physical_size(m_space_flags);
- if (!is_compressed_table() && !m_page_size.equals_to(univ_page_size)) {
+ if (logical_size != srv_page_size) {
- ib::error() << "Page size " << m_page_size.physical()
+ ib::error() << "Page size " << logical_size
<< " of ibd file is not the same as the server page"
" size " << srv_page_size;
return(DB_CORRUPTION);
- } else if (file_size % m_page_size.physical() != 0) {
+ } else if (file_size & (physical_size - 1)) {
ib::error() << "File size " << file_size << " is not a"
" multiple of the page size "
- << m_page_size.physical();
+ << physical_size;
return(DB_CORRUPTION);
}
@@ -694,7 +703,7 @@ FetchIndexRootPages::build_row_import(row_import* cfg) const UNIV_NOTHROW
Indexes::const_iterator end = m_indexes.end();
ut_a(cfg->m_table == m_table);
- cfg->m_page_size.copy_from(m_page_size);
+ cfg->m_zip_size = m_zip_size;
cfg->m_n_indexes = m_indexes.size();
if (cfg->m_n_indexes == 0) {
@@ -1820,13 +1829,39 @@ PageConverter::update_index_page(
if (dict_index_is_clust(m_index->m_srv_index)) {
if (page_is_root(page)) {
+ dict_index_t* index = const_cast<dict_index_t*>(
+ m_index->m_srv_index);
/* Preserve the PAGE_ROOT_AUTO_INC. */
- if (m_index->m_srv_index->table->supports_instant()
- && btr_cur_instant_root_init(
- const_cast<dict_index_t*>(
- m_index->m_srv_index),
- page)) {
- return(DB_CORRUPTION);
+ if (index->table->supports_instant()) {
+ if (btr_cur_instant_root_init(index, page)) {
+ return(DB_CORRUPTION);
+ }
+
+ if (index->n_core_fields > index->n_fields) {
+ /* Some columns have been dropped.
+ Refuse to IMPORT TABLESPACE for now.
+
+ NOTE: This is not an accurate check.
+ Columns could have been both
+ added and dropped instantly.
+ For an accurate check, we must read
+ the metadata BLOB page pointed to
+ by the leftmost leaf page.
+
+ But we would have to read
+ those pages in a special way,
+ bypassing the buffer pool! */
+ return DB_UNSUPPORTED;
+ }
+
+ /* Provisionally set all instantly
+ added columns to be DEFAULT NULL. */
+ for (unsigned i = index->n_core_fields;
+ i < index->n_fields; i++) {
+ dict_col_t* col = index->fields[i].col;
+ col->def_val.len = UNIV_SQL_NULL;
+ col->def_val.data = NULL;
+ }
}
} else {
/* Clear PAGE_MAX_TRX_ID so that it can be
@@ -1980,7 +2015,7 @@ dberr_t PageConverter::operator()(buf_block_t* block) UNIV_NOTHROW
/* If we already had an old page with matching number
in the buffer pool, evict it now, because
we no longer evict the pages on DISCARD TABLESPACE. */
- buf_page_get_gen(block->page.id, get_page_size(),
+ buf_page_get_gen(block->page.id, get_zip_size(),
RW_NO_LATCH, NULL, BUF_EVICT_IF_IN_POOL,
__FILE__, __LINE__, NULL, NULL);
@@ -2000,7 +2035,7 @@ dberr_t PageConverter::operator()(buf_block_t* block) UNIV_NOTHROW
/* Calculate and update the checksum of non-index
pages for ROW_FORMAT=COMPRESSED tables. */
buf_flush_update_zip_checksum(
- block->page.zip.data, get_page_size().physical(),
+ block->page.zip.data, block->zip_size(),
m_current_lsn);
}
@@ -2904,10 +2939,7 @@ row_import_read_v1(
cfg->m_flags = mach_read_from_4(ptr);
ptr += sizeof(ib_uint32_t);
- cfg->m_page_size.copy_from(dict_tf_get_page_size(cfg->m_flags));
-
- ut_a(logical_page_size == cfg->m_page_size.logical());
-
+ cfg->m_zip_size = dict_tf_get_zip_size(cfg->m_flags);
cfg->m_n_cols = mach_read_from_4(ptr);
if (!dict_tf_is_valid(cfg->m_flags)) {
@@ -3265,7 +3297,7 @@ fil_iterate(
AbstractCallback& callback)
{
os_offset_t offset;
- const ulint size = callback.get_page_size().physical();
+ const ulint size = callback.physical_size();
ulint n_bytes = iter.n_io_buffers * size;
const ulint buf_size = srv_page_size
@@ -3390,13 +3422,13 @@ not_encrypted:
}
} else {
if (!fil_space_verify_crypt_checksum(
- src, callback.get_page_size())) {
+ src, callback.get_zip_size())) {
goto page_corrupted;
}
decrypted = fil_space_decrypt(
iter.crypt_data, dst,
- callback.get_page_size(), src, &err);
+ callback.physical_size(), src, &err);
if (err != DB_SUCCESS) {
goto func_exit;
@@ -3423,7 +3455,7 @@ not_encrypted:
false,
encrypted && !frame_changed
? dst : src,
- callback.get_page_size(), NULL)) {
+ callback.get_zip_size(), NULL)) {
goto page_corrupted;
}
@@ -3500,7 +3532,7 @@ not_encrypted:
block->page.id.space(),
block->page.id.page_no(),
mach_read_from_8(src + FIL_PAGE_LSN),
- src, callback.get_page_size(), dest);
+ src, block->zip_size(), dest);
if (tmp == src) {
/* TODO: remove unnecessary memcpy's */
@@ -3625,10 +3657,8 @@ fil_tablespace_iterate(
if (err == DB_SUCCESS) {
block->page.id = page_id_t(callback.get_space_id(), 0);
- block->page.size.copy_from(callback.get_page_size());
- if (block->page.size.is_compressed()) {
- page_zip_set_size(&block->page.zip,
- callback.get_page_size().physical());
+ if (ulint zip_size = callback.get_zip_size()) {
+ page_zip_set_size(&block->page.zip, zip_size);
/* ROW_FORMAT=COMPRESSED is not optimised for block IO
for now. We do the IMPORT page by page. */
n_io_buffers = 1;
@@ -3638,7 +3668,7 @@ fil_tablespace_iterate(
/* read (optional) crypt data */
iter.crypt_data = fil_space_read_crypt_data(
- callback.get_page_size(), page);
+ callback.get_zip_size(), page);
/* If tablespace is encrypted, it needs extra buffers */
if (iter.crypt_data && n_io_buffers > 1) {
@@ -3819,12 +3849,12 @@ row_import_for_mysql(
ut_a(err == DB_FAIL);
- cfg.m_page_size.copy_from(univ_page_size);
+ cfg.m_zip_size = 0;
FetchIndexRootPages fetchIndexRootPages(table, trx);
err = fil_tablespace_iterate(
- table, IO_BUFFER_SIZE(cfg.m_page_size.physical()),
+ table, IO_BUFFER_SIZE(srv_page_size),
fetchIndexRootPages);
if (err == DB_SUCCESS) {
@@ -3862,7 +3892,8 @@ row_import_for_mysql(
/* Set the IO buffer size in pages. */
err = fil_tablespace_iterate(
- table, IO_BUFFER_SIZE(cfg.m_page_size.physical()), converter);
+ table, IO_BUFFER_SIZE(cfg.m_zip_size ? cfg.m_zip_size
+ : srv_page_size), converter);
DBUG_EXECUTE_IF("ib_import_reset_space_and_lsn_failure",
err = DB_TOO_MANY_CONCURRENT_TRXS;);
diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc
index 09df80f789d..5701a4af233 100644
--- a/storage/innobase/row/row0log.cc
+++ b/storage/innobase/row/row0log.cc
@@ -1139,7 +1139,7 @@ ALTER TABLE)
table
@param[in] offsets rec_get_offsets(rec)
@param[in] i rec field corresponding to col
-@param[in] page_size page size of the old table
+@param[in] zip_size ROW_FORMAT=COMPRESSED size of the old table
@param[in] max_len maximum length of dfield
@param[in] log row log for the table
@retval DB_INVALID_NULL if a NULL value is encountered
@@ -1153,7 +1153,7 @@ row_log_table_get_pk_col(
const rec_t* rec,
const ulint* offsets,
ulint i,
- const page_size_t& page_size,
+ ulint zip_size,
ulint max_len,
const row_log_t* log)
{
@@ -1192,7 +1192,7 @@ row_log_table_get_pk_col(
mem_heap_alloc(heap, field_len));
len = btr_copy_externally_stored_field_prefix(
- blob_field, field_len, page_size, field, len);
+ blob_field, field_len, zip_size, field, len);
if (len >= max_len + 1) {
return(DB_TOO_BIG_INDEX_COL);
}
@@ -1307,8 +1307,7 @@ row_log_table_get_pk(
const ulint max_len = DICT_MAX_FIELD_LEN_BY_FORMAT(new_table);
- const page_size_t& page_size
- = dict_table_page_size(index->table);
+ const ulint zip_size = index->table->space->zip_size();
for (ulint new_i = 0; new_i < new_n_uniq; new_i++) {
dict_field_t* ifield;
@@ -1335,7 +1334,8 @@ row_log_table_get_pk(
log->error = row_log_table_get_pk_col(
ifield, dfield, *heap,
- rec, offsets, i, page_size, max_len, log);
+ rec, offsets, i, zip_size, max_len,
+ log);
if (log->error != DB_SUCCESS) {
err_exit:
@@ -1602,7 +1602,7 @@ row_log_table_apply_convert_mrec(
data = btr_rec_copy_externally_stored_field(
mrec, offsets,
- dict_table_page_size(index->table),
+ index->table->space->zip_size(),
i, &len, heap);
ut_a(data);
dfield_set_data(dfield, data, len);
@@ -2676,8 +2676,8 @@ ulint
row_log_progress_inc_per_block()
{
/* We must increment the progress once per page (as in
- univ_page_size, usually 16KiB). One block here is srv_sort_buf_size
- (usually 1MiB). */
+ srv_page_size, default = innodb_page_size=16KiB).
+ One block here is srv_sort_buf_size (usually 1MiB). */
const ulint pages_per_block = std::max<ulint>(
ulint(srv_sort_buf_size >> srv_page_size_shift), 1);
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index 50d70b22a5a..f1776dd07ee 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -442,7 +442,7 @@ row_merge_buf_redundant_convert(
const dfield_t* row_field,
dfield_t* field,
ulint len,
- const page_size_t& page_size,
+ ulint zip_size,
mem_heap_t* heap)
{
ut_ad(field->type.mbminlen == 1);
@@ -462,7 +462,7 @@ row_merge_buf_redundant_convert(
field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE));
byte* data = btr_copy_externally_stored_field(
- &ext_len, field_data, page_size, field_len, heap);
+ &ext_len, field_data, zip_size, field_len, heap);
ut_ad(ext_len < len);
@@ -704,7 +704,7 @@ row_merge_buf_add(
if (conv_heap != NULL) {
row_merge_buf_redundant_convert(
row_field, field, col->len,
- dict_table_page_size(old_table),
+ old_table->space->zip_size(),
conv_heap);
} else {
/* Field length mismatch should not
@@ -2036,7 +2036,7 @@ end_of_index:
block = btr_block_get(
page_id_t(block->page.id.space(),
next_page_no),
- block->page.size,
+ block->zip_size(),
BTR_SEARCH_LEAF,
clust_index, &mtr);
@@ -3424,7 +3424,7 @@ void
row_merge_copy_blobs(
const mrec_t* mrec,
const ulint* offsets,
- const page_size_t& page_size,
+ ulint zip_size,
dtuple_t* tuple,
mem_heap_t* heap)
{
@@ -3462,10 +3462,10 @@ row_merge_copy_blobs(
BTR_EXTERN_FIELD_REF_SIZE));
data = btr_copy_externally_stored_field(
- &len, field_data, page_size, field_len, heap);
+ &len, field_data, zip_size, field_len, heap);
} else {
data = btr_rec_copy_externally_stored_field(
- mrec, offsets, page_size, i, &len, heap);
+ mrec, offsets, zip_size, i, &len, heap);
}
/* Because we have locked the table, any records
@@ -3663,8 +3663,7 @@ row_merge_insert_index_tuples(
row_log_table_blob_alloc() and
row_log_table_blob_free(). */
row_merge_copy_blobs(
- mrec, offsets,
- dict_table_page_size(old_table),
+ mrec, offsets, old_table->space->zip_size(),
dtuple, tuple_heap);
}
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 28c6a1abf21..071ef9ffd92 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -3079,13 +3079,14 @@ row_discard_tablespace(
table->flags2 |= DICT_TF2_DISCARDED;
dict_table_change_id_in_cache(table, new_id);
- /* Reset the root page numbers. */
+ dict_index_t* index = UT_LIST_GET_FIRST(table->indexes);
+ if (index) index->clear_instant_alter();
- for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes);
- index != 0;
- index = UT_LIST_GET_NEXT(indexes, index)) {
+ /* Reset the root page numbers. */
+ for (; index; index = UT_LIST_GET_NEXT(indexes, index)) {
index->page = FIL_NULL;
}
+
/* If the tablespace did not already exist or we couldn't
write to it, we treat that as a successful DISCARD. It is
unusable anyway. */
@@ -3361,8 +3362,7 @@ row_drop_table_for_mysql(
for (dict_index_t* index = dict_table_get_first_index(table);
index != NULL;
index = dict_table_get_next_index(index)) {
- btr_free(page_id_t(SRV_TMP_SPACE_ID, index->page),
- univ_page_size);
+ btr_free(page_id_t(SRV_TMP_SPACE_ID, index->page));
}
/* Remove the pointer to this table object from the list
of modified tables by the transaction because the object
diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc
index f0652ed3d54..633fc0f049f 100644
--- a/storage/innobase/row/row0purge.cc
+++ b/storage/innobase/row/row0purge.cc
@@ -992,7 +992,7 @@ skip_secondaries:
block = buf_page_get(
page_id_t(rseg->space->id, page_no),
- univ_page_size, RW_X_LATCH, &mtr);
+ 0, RW_X_LATCH, &mtr);
buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc
index 3c03f8277ae..400faba0d88 100644
--- a/storage/innobase/row/row0row.cc
+++ b/storage/innobase/row/row0row.cc
@@ -151,7 +151,7 @@ static bool row_build_spatial_index_key(
temp_heap = mem_heap_create(1000);
dptr = btr_copy_externally_stored_field(
- &dlen, dptr, ext ? ext->page_size : page_size_t(space->flags),
+ &dlen, dptr, ext ? ext->zip_size : space->zip_size(),
flen, temp_heap);
write_mbr:
@@ -593,7 +593,7 @@ row_build_low(
row_log_table_delete(). */
} else if (j) {
- *ext = row_ext_create(j, ext_cols, index->table->flags, row,
+ *ext = row_ext_create(j, ext_cols, *index->table, row,
heap);
} else {
*ext = NULL;
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index 8d7824bfc56..215ed0fe1e9 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -2,7 +2,7 @@
Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
-Copyright (c) 2015, 2018, MariaDB Corporation.
+Copyright (c) 2015, 2019, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -127,7 +127,7 @@ row_sel_sec_rec_is_for_blob(
}
len = btr_copy_externally_stored_field_prefix(
- buf, prefix_len, page_size_t(table->space->flags),
+ buf, prefix_len, table->space->zip_size(),
clust_field, clust_len);
if (len == 0) {
@@ -308,8 +308,7 @@ row_sel_sec_rec_is_for_clust_rec(
if (rec_offs_nth_extern(clust_offs, clust_pos)) {
dptr = btr_copy_externally_stored_field(
&clust_len, dptr,
- page_size_t(clust_index->table->space
- ->flags),
+ clust_index->table->space->zip_size(),
len, heap);
}
@@ -532,7 +531,7 @@ row_sel_fetch_columns(
data = btr_rec_copy_externally_stored_field(
rec, offsets,
- dict_table_page_size(index->table),
+ index->table->space->zip_size(),
field_no, &len, heap);
/* data == NULL means that the
@@ -1135,7 +1134,7 @@ re_scan:
cur_block = buf_page_get_gen(
page_id_t(index->table->space_id, page_no),
- page_size_t(index->table->space->flags),
+ index->table->space->zip_size(),
RW_X_LATCH, NULL, BUF_GET,
__FILE__, __LINE__, mtr, &err);
} else {
@@ -2933,8 +2932,7 @@ row_sel_store_mysql_field(
causes an assert */
data = btr_rec_copy_externally_stored_field(
- rec, offsets,
- dict_table_page_size(prebuilt->table),
+ rec, offsets, prebuilt->table->space->zip_size(),
field_no, &len, heap);
if (UNIV_UNLIKELY(!data)) {
@@ -3308,7 +3306,7 @@ row_sel_get_clust_rec_for_mysql(
and is it not unsafe to use RW_NO_LATCH here? */
buf_block_t* block = buf_page_get_gen(
btr_pcur_get_block(prebuilt->pcur)->page.id,
- btr_pcur_get_block(prebuilt->pcur)->page.size,
+ btr_pcur_get_block(prebuilt->pcur)->zip_size(),
RW_NO_LATCH, NULL, BUF_GET,
__FILE__, __LINE__, mtr, &err);
mem_heap_t* heap = mem_heap_create(256);
diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc
index e8ee3aeac30..6be66d1d56c 100644
--- a/storage/innobase/row/row0upd.cc
+++ b/storage/innobase/row/row0upd.cc
@@ -1131,7 +1131,7 @@ of the column and must not be poisoned with the new values.
@param[in] data 'internally' stored part of the field
containing also the reference to the external part
@param[in] local_len length of data, in bytes
-@param[in] page_size BLOB page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] len input - length of prefix to
fetch; output: fetched length of the prefix
@param[in,out] heap heap where to allocate
@@ -1141,14 +1141,14 @@ byte*
row_upd_ext_fetch(
const byte* data,
ulint local_len,
- const page_size_t& page_size,
+ ulint zip_size,
ulint* len,
mem_heap_t* heap)
{
byte* buf = static_cast<byte*>(mem_heap_alloc(heap, *len));
*len = btr_copy_externally_stored_field_prefix(
- buf, *len, page_size, data, local_len);
+ buf, *len, zip_size, data, local_len);
/* We should never update records containing a half-deleted BLOB. */
ut_a(*len);
@@ -1164,7 +1164,7 @@ the given index entry field.
@param[in] uf update field
@param[in,out] heap memory heap for allocating and copying
the new value
-@param[in] page_size page size */
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 */
static
void
row_upd_index_replace_new_col_val(
@@ -1173,7 +1173,7 @@ row_upd_index_replace_new_col_val(
const dict_col_t* col,
const upd_field_t* uf,
mem_heap_t* heap,
- const page_size_t& page_size)
+ ulint zip_size)
{
ulint len;
const byte* data;
@@ -1197,7 +1197,7 @@ row_upd_index_replace_new_col_val(
len = field->prefix_len;
- data = row_upd_ext_fetch(data, l, page_size,
+ data = row_upd_ext_fetch(data, l, zip_size,
&len, heap);
}
@@ -1270,7 +1270,7 @@ row_upd_index_replace_metadata(
ut_ad(update->is_alter_metadata());
ut_ad(entry->info_bits == update->info_bits);
ut_ad(entry->n_fields == ulint(index->n_fields) + 1);
- const page_size_t& page_size = dict_table_page_size(index->table);
+ const ulint zip_size = index->table->space->zip_size();
const ulint first = index->first_user_field();
ut_d(bool found_mblob = false);
@@ -1298,7 +1298,7 @@ row_upd_index_replace_metadata(
f -= f > first;
const dict_field_t* field = dict_index_get_nth_field(index, f);
row_upd_index_replace_new_col_val(dfield, field, field->col,
- uf, heap, page_size);
+ uf, heap, zip_size);
}
ut_ad(found_mblob);
@@ -1326,7 +1326,7 @@ row_upd_index_replace_new_col_vals_index_pos(
return;
}
- const page_size_t& page_size = dict_table_page_size(index->table);
+ const ulint zip_size = index->table->space->zip_size();
dtuple_set_info_bits(entry, update->info_bits);
@@ -1352,7 +1352,7 @@ row_upd_index_replace_new_col_vals_index_pos(
if (uf) {
row_upd_index_replace_new_col_val(
dtuple_get_nth_field(entry, i),
- field, col, uf, heap, page_size);
+ field, col, uf, heap, zip_size);
}
}
}
@@ -1378,7 +1378,7 @@ row_upd_index_replace_new_col_vals(
ulint i;
const dict_index_t* clust_index
= dict_table_get_first_index(index->table);
- const page_size_t& page_size = dict_table_page_size(index->table);
+ const ulint zip_size = index->table->space->zip_size();
ut_ad(!index->table->skip_alter_undo);
@@ -1408,7 +1408,7 @@ row_upd_index_replace_new_col_vals(
if (uf) {
row_upd_index_replace_new_col_val(
dtuple_get_nth_field(entry, i),
- field, col, uf, heap, page_size);
+ field, col, uf, heap, zip_size);
}
}
}
@@ -1632,8 +1632,7 @@ row_upd_replace(
}
if (n_ext_cols) {
- *ext = row_ext_create(n_ext_cols, ext_cols, table->flags, row,
- heap);
+ *ext = row_ext_create(n_ext_cols, ext_cols, *table, row, heap);
} else {
*ext = NULL;
}
@@ -1741,11 +1740,9 @@ row_upd_changes_ord_field_binary_func(
mem_heap_t* temp_heap = NULL;
const dfield_t* new_field = &upd_field->new_val;
- const page_size_t page_size
- = (ext != NULL)
- ? ext->page_size
- : dict_table_page_size(
- index->table);
+ const ulint zip_size = ext
+ ? ext->zip_size
+ : index->table->space->zip_size();
ut_ad(dfield->data != NULL
&& dfield->len > GEO_DATA_HEADER_SIZE);
@@ -1762,7 +1759,7 @@ row_upd_changes_ord_field_binary_func(
dptr = btr_copy_externally_stored_field(
&dlen, dptr,
- page_size,
+ zip_size,
flen,
temp_heap);
} else {
@@ -1825,7 +1822,7 @@ row_upd_changes_ord_field_binary_func(
dptr = btr_copy_externally_stored_field(
&dlen, dptr,
- page_size,
+ zip_size,
flen,
temp_heap);
} else {
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index 34638dfda25..3d1415b07c6 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -194,8 +194,6 @@ ulong srv_page_size_shift;
/** innodb_log_write_ahead_size */
ulong srv_log_write_ahead_size;
-page_size_t univ_page_size(0, 0, false);
-
/** innodb_adaptive_flushing; try to flush dirty pages so as to avoid
IO bursts at the checkpoints. */
my_bool srv_adaptive_flushing;
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 108e9182f00..46de5ec812d 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -1887,7 +1887,7 @@ files_checked:
/* New data file(s) were added */
mtr.start();
buf_block_t* block = buf_page_get(
- page_id_t(0, 0), univ_page_size,
+ page_id_t(0, 0), 0,
RW_SX_LATCH, &mtr);
ulint size = mach_read_from_4(
FSP_HEADER_OFFSET + FSP_SIZE
@@ -1911,8 +1911,7 @@ files_checked:
#ifdef UNIV_DEBUG
{
mtr.start();
- buf_block_t* block = buf_page_get(page_id_t(0, 0),
- univ_page_size,
+ buf_block_t* block = buf_page_get(page_id_t(0, 0), 0,
RW_S_LATCH, &mtr);
ut_ad(mach_read_from_4(FSP_SIZE + FSP_HEADER_OFFSET
+ block->frame)
@@ -2075,24 +2074,24 @@ files_checked:
block = buf_page_get(
page_id_t(IBUF_SPACE_ID,
FSP_IBUF_HEADER_PAGE_NO),
- univ_page_size, RW_X_LATCH, &mtr);
+ 0, RW_X_LATCH, &mtr);
fil_block_check_type(*block, FIL_PAGE_TYPE_SYS, &mtr);
/* Already MySQL 3.23.53 initialized
FSP_IBUF_TREE_ROOT_PAGE_NO to
FIL_PAGE_INDEX. No need to reset that one. */
block = buf_page_get(
page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO),
- univ_page_size, RW_X_LATCH, &mtr);
+ 0, RW_X_LATCH, &mtr);
fil_block_check_type(*block, FIL_PAGE_TYPE_TRX_SYS,
&mtr);
block = buf_page_get(
page_id_t(TRX_SYS_SPACE,
FSP_FIRST_RSEG_PAGE_NO),
- univ_page_size, RW_X_LATCH, &mtr);
+ 0, RW_X_LATCH, &mtr);
fil_block_check_type(*block, FIL_PAGE_TYPE_SYS, &mtr);
block = buf_page_get(
page_id_t(TRX_SYS_SPACE, FSP_DICT_HDR_PAGE_NO),
- univ_page_size, RW_X_LATCH, &mtr);
+ 0, RW_X_LATCH, &mtr);
fil_block_check_type(*block, FIL_PAGE_TYPE_SYS, &mtr);
mtr.commit();
}
diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc
index 595c2a15fb3..fdb28fee8c2 100644
--- a/storage/innobase/trx/trx0rec.cc
+++ b/storage/innobase/trx/trx0rec.cc
@@ -718,7 +718,7 @@ trx_undo_rec_skip_row_ref(
log of an update or delete marking of a clustered index record.
@param[out] ext_buf buffer to hold the prefix data and BLOB pointer
@param[in] prefix_len prefix size to store in the undo log
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] field an externally stored column
@param[in,out] len input: length of field; output: used length of
ext_buf
@@ -728,13 +728,13 @@ byte*
trx_undo_page_fetch_ext(
byte* ext_buf,
ulint prefix_len,
- const page_size_t& page_size,
+ ulint zip_size,
const byte* field,
ulint* len)
{
/* Fetch the BLOB. */
ulint ext_len = btr_copy_externally_stored_field_prefix(
- ext_buf, prefix_len, page_size, field, *len);
+ ext_buf, prefix_len, zip_size, field, *len);
/* BLOBs should always be nonempty. */
ut_a(ext_len);
/* Append the BLOB pointer to the prefix. */
@@ -752,7 +752,7 @@ available
size, or NULL when should not fetch a longer
prefix
@param[in] prefix_len prefix size to store in the undo log
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] field the locally stored part of the externally
stored column
@param[in,out] len length of field, in bytes
@@ -765,7 +765,7 @@ trx_undo_page_report_modify_ext(
byte* ptr,
byte* ext_buf,
ulint prefix_len,
- const page_size_t& page_size,
+ ulint zip_size,
const byte** field,
ulint* len,
spatial_status_t spatial_status)
@@ -807,7 +807,7 @@ trx_undo_page_report_modify_ext(
ptr += mach_write_compressed(ptr, *len);
*field = trx_undo_page_fetch_ext(ext_buf, prefix_len,
- page_size, *field, len);
+ zip_size, *field, len);
ptr += mach_write_compressed(ptr, *len + spatial_len);
} else {
@@ -820,7 +820,7 @@ trx_undo_page_report_modify_ext(
/** Get MBR from a Geometry column stored externally
@param[out] mbr MBR to fill
-@param[in] pagesize table pagesize
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] field field contain the geometry data
@param[in,out] len length of field, in bytes
*/
@@ -828,17 +828,17 @@ static
void
trx_undo_get_mbr_from_ext(
/*======================*/
- double* mbr,
- const page_size_t& page_size,
- const byte* field,
- ulint* len)
+ double* mbr,
+ ulint zip_size,
+ const byte* field,
+ ulint* len)
{
uchar* dptr = NULL;
ulint dlen;
mem_heap_t* heap = mem_heap_create(100);
dptr = btr_copy_externally_stored_field(
- &dlen, field, page_size, *len, heap);
+ &dlen, field, zip_size, *len, heap);
if (dlen <= GEO_DATA_HEADER_SIZE) {
for (uint i = 0; i < SPDIMS; ++i) {
@@ -1181,7 +1181,7 @@ write_field:
&& !ignore_prefix
&& flen < REC_ANTELOPE_MAX_INDEX_COL_LEN
? ext_buf : NULL, prefix_len,
- dict_table_page_size(table),
+ table->space->zip_size(),
&field, &flen, SPATIAL_UNKNOWN);
*type_cmpl_ptr |= TRX_UNDO_UPD_EXTERN;
@@ -1335,8 +1335,8 @@ store_len:
table, col);
ut_a(prefix_len < sizeof ext_buf);
- const page_size_t& page_size
- = dict_table_page_size(table);
+ const ulint zip_size
+ = table->space->zip_size();
/* If there is a spatial index on it,
log its MBR */
@@ -1345,7 +1345,7 @@ store_len:
col->mtype));
trx_undo_get_mbr_from_ext(
- mbr, page_size,
+ mbr, zip_size,
field, &flen);
}
@@ -1354,7 +1354,7 @@ store_len:
flen < REC_ANTELOPE_MAX_INDEX_COL_LEN
&& !ignore_prefix
? ext_buf : NULL, prefix_len,
- page_size,
+ zip_size,
&field, &flen,
spatial_status);
} else {
diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc
index 239df440c2b..f57e97b2e57 100644
--- a/storage/innobase/trx/trx0rseg.cc
+++ b/storage/innobase/trx/trx0rseg.cc
@@ -98,6 +98,19 @@ trx_rseg_update_wsrep_checkpoint(
trx_rseg_write_wsrep_checkpoint(rseg_header, xid, mtr);
}
+/** Clear the WSREP XID information from rollback segment header.
+@param[in,out] rseg_header Rollback segment header
+@param[in,out] mtr mini-transaction */
+static void
+trx_rseg_clear_wsrep_checkpoint(
+ trx_rsegf_t* rseg_header,
+ mtr_t* mtr)
+{
+ mlog_memset(rseg_header + TRX_RSEG_WSREP_XID_INFO,
+ TRX_RSEG_WSREP_XID_DATA + XIDDATASIZE
+ - TRX_RSEG_WSREP_XID_INFO, 0, mtr);
+}
+
/** Update WSREP checkpoint XID in first rollback segment header
as part of wsrep_set_SE_checkpoint() when it is guaranteed that there
are no wsrep transactions committing.
@@ -128,10 +141,6 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid)
trx_rseg_update_wsrep_checkpoint(rseg_header, xid, &mtr);
if (must_clear_rsegs) {
- XID null_xid;
- memset(&null_xid, 0, sizeof null_xid);
- null_xid.null();
- memcpy(wsrep_uuid, xid_uuid, sizeof wsrep_uuid);
/* Because the UUID part of the WSREP XID differed
from current_xid_uuid, the WSREP group UUID was
changed, and we must reset the XID in all rollback
@@ -139,11 +148,10 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid)
for (ulint rseg_id = 1; rseg_id < TRX_SYS_N_RSEGS; ++rseg_id) {
if (const trx_rseg_t* rseg =
trx_sys.rseg_array[rseg_id]) {
- trx_rseg_write_wsrep_checkpoint(
+ trx_rseg_clear_wsrep_checkpoint(
trx_rsegf_get(rseg->space,
rseg->page_no,
&mtr),
- &null_xid,
&mtr);
}
}
diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc
index e084b0b67bf..81e0b5a1945 100644
--- a/storage/innobase/trx/trx0undo.cc
+++ b/storage/innobase/trx/trx0undo.cc
@@ -187,7 +187,7 @@ trx_undo_get_prev_rec_from_prev_page(
space = page_get_space_id(undo_page);
buf_block_t* block = buf_page_get(
- page_id_t(space, prev_page_no), univ_page_size,
+ page_id_t(space, prev_page_no), 0,
shared ? RW_S_LATCH : RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
@@ -1340,7 +1340,7 @@ trx_undo_reuse_cached(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** pundo,
buf_block_t* block = buf_page_get(page_id_t(undo->rseg->space->id,
undo->hdr_page_no),
- univ_page_size, RW_X_LATCH, mtr);
+ 0, RW_X_LATCH, mtr);
if (!block) {
return NULL;
}
@@ -1399,7 +1399,7 @@ trx_undo_assign(trx_t* trx, dberr_t* err, mtr_t* mtr)
if (undo) {
return buf_page_get_gen(
page_id_t(undo->rseg->space->id, undo->last_page_no),
- univ_page_size, RW_X_LATCH,
+ 0, RW_X_LATCH,
buf_pool_is_obsolete(undo->withdraw_clock)
? NULL : undo->guess_block,
BUF_GET, __FILE__, __LINE__, mtr, err);
@@ -1455,7 +1455,7 @@ trx_undo_assign_low(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** undo,
if (*undo) {
return buf_page_get_gen(
page_id_t(rseg->space->id, (*undo)->last_page_no),
- univ_page_size, RW_X_LATCH,
+ 0, RW_X_LATCH,
buf_pool_is_obsolete((*undo)->withdraw_clock)
? NULL : (*undo)->guess_block,
BUF_GET, __FILE__, __LINE__, mtr, err);
diff --git a/wsrep-lib b/wsrep-lib
-Subproject 136767ae044eac53e7f3d76909d176cde0dc27a
+Subproject e7d72ae7f6a6995a21d743389426a963429a1ff