summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--VERSION2
-rw-r--r--client/mysqltest.cc32
-rw-r--r--cmake/mysql_version.cmake4
-rw-r--r--extra/innochecksum.c8
-rw-r--r--include/decimal.h9
-rw-r--r--include/my_base.h6
-rw-r--r--libmysql/client_settings.h5
-rw-r--r--mysql-test/include/mtr_check.sql10
-rw-r--r--mysql-test/include/mysqld--help.inc2
-rw-r--r--mysql-test/lib/mtr_cases.pm46
-rwxr-xr-xmysql-test/mysql-test-run.pl6
-rw-r--r--mysql-test/r/auth_rpl.result24
-rw-r--r--mysql-test/r/execution_constants.result2
-rw-r--r--mysql-test/r/func_str.result35
-rw-r--r--mysql-test/r/group_by.result32
-rw-r--r--mysql-test/r/myisampack.result32
-rw-r--r--mysql-test/r/mysqltest.result23
-rw-r--r--mysql-test/r/sp_trans.result46
-rw-r--r--mysql-test/r/type_newdecimal.result11
-rw-r--r--mysql-test/std_data/bug57108.cnf95
-rw-r--r--mysql-test/suite/innodb/r/innodb-index.result98
-rw-r--r--mysql-test/suite/innodb/r/innodb_bug59733.result18
-rw-r--r--mysql-test/suite/innodb/r/innodb_corrupt_bit.result81
-rw-r--r--mysql-test/suite/innodb/t/innodb-index.test93
-rw-r--r--mysql-test/suite/innodb/t/innodb_bug59733.test53
-rw-r--r--mysql-test/suite/innodb/t/innodb_corrupt_bit.test120
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_file_per_table_basic.result27
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_force_load_corrupted_basic.result53
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_large_prefix_basic.result92
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_lock_wait_timeout_basic.result21
-rw-r--r--mysql-test/suite/sys_vars/r/plugin_dir_basic.result10
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_autoinc_lock_mode_basic.test3
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_fast_shutdown_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_file_per_table_basic.test22
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_force_load_corrupted_basic.test102
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_io_capacity_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_large_prefix_basic.test70
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_lock_wait_timeout_basic.test24
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_max_dirty_pages_pct_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/plugin_dir_basic-master.opt1
-rw-r--r--mysql-test/suite/sys_vars/t/plugin_dir_basic.test14
-rw-r--r--mysql-test/t/auth_rpl-master.opt2
-rw-r--r--mysql-test/t/auth_rpl-slave.opt4
-rw-r--r--mysql-test/t/auth_rpl.test66
-rw-r--r--mysql-test/t/execution_constants.test10
-rw-r--r--mysql-test/t/func_str.test19
-rw-r--r--mysql-test/t/group_by.test14
-rw-r--r--mysql-test/t/myisampack.test44
-rw-r--r--mysql-test/t/mysqltest.test38
-rw-r--r--mysql-test/t/sp_trans.test33
-rw-r--r--mysql-test/t/type_newdecimal.test14
-rw-r--r--mysql-test/valgrind.supp43
-rw-r--r--mysys/my_handler_errors.h4
-rw-r--r--plugin/semisync/semisync_master.cc18
-rw-r--r--scripts/CMakeLists.txt12
-rw-r--r--scripts/make_binary_distribution.sh342
-rwxr-xr-xscripts/make_win_bin_dist425
-rw-r--r--scripts/mysql_install_db.pl.in5
-rw-r--r--scripts/mysql_install_db.sh5
-rw-r--r--sql/client_settings.h15
-rw-r--r--sql/filesort.cc16
-rw-r--r--sql/handler.cc7
-rw-r--r--sql/my_decimal.h6
-rw-r--r--sql/share/errmsg-utf8.txt6
-rw-r--r--sql/slave.cc4
-rw-r--r--sql/sql_parse.cc6
-rw-r--r--sql/sql_yacc.yy12
-rw-r--r--storage/innobase/btr/btr0btr.c320
-rw-r--r--storage/innobase/btr/btr0cur.c209
-rw-r--r--storage/innobase/btr/btr0pcur.c9
-rw-r--r--storage/innobase/btr/btr0sea.c3
-rw-r--r--storage/innobase/buf/buf0buddy.c2
-rw-r--r--storage/innobase/buf/buf0buf.c100
-rw-r--r--storage/innobase/buf/buf0lru.c16
-rw-r--r--storage/innobase/dict/dict0crea.c4
-rw-r--r--storage/innobase/dict/dict0dict.c192
-rw-r--r--storage/innobase/dict/dict0load.c94
-rw-r--r--storage/innobase/fsp/fsp0fsp.c234
-rw-r--r--storage/innobase/handler/ha_innodb.cc143
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.c44
-rw-r--r--storage/innobase/include/btr0btr.h66
-rw-r--r--storage/innobase/include/btr0btr.ic10
-rw-r--r--storage/innobase/include/btr0cur.h38
-rw-r--r--storage/innobase/include/buf0buf.h9
-rw-r--r--storage/innobase/include/buf0lru.h11
-rw-r--r--storage/innobase/include/db0err.h4
-rw-r--r--storage/innobase/include/dict0boot.h6
-rw-r--r--storage/innobase/include/dict0dict.h82
-rw-r--r--storage/innobase/include/dict0dict.ic46
-rw-r--r--storage/innobase/include/dict0mem.h14
-rw-r--r--storage/innobase/include/dict0types.h3
-rw-r--r--storage/innobase/include/fsp0fsp.h30
-rw-r--r--storage/innobase/include/mtr0mtr.h13
-rw-r--r--storage/innobase/include/mtr0mtr.ic8
-rw-r--r--storage/innobase/include/page0page.h5
-rw-r--r--storage/innobase/include/row0upd.ic5
-rw-r--r--storage/innobase/include/srv0srv.h4
-rw-r--r--storage/innobase/include/sync0sync.h10
-rw-r--r--storage/innobase/include/sync0sync.ic5
-rw-r--r--storage/innobase/include/trx0undo.h46
-rw-r--r--storage/innobase/mtr/mtr0mtr.c5
-rw-r--r--storage/innobase/pars/pars0opt.c2
-rw-r--r--storage/innobase/row/row0ins.c42
-rw-r--r--storage/innobase/row/row0merge.c5
-rw-r--r--storage/innobase/row/row0mysql.c33
-rw-r--r--storage/innobase/row/row0purge.c33
-rw-r--r--storage/innobase/row/row0row.c27
-rw-r--r--storage/innobase/row/row0sel.c28
-rw-r--r--storage/innobase/row/row0uins.c4
-rw-r--r--storage/innobase/row/row0umod.c25
-rw-r--r--storage/innobase/row/row0upd.c30
-rw-r--r--storage/innobase/sync/sync0sync.c35
-rw-r--r--storage/innobase/trx/trx0rec.c70
-rw-r--r--storage/innobase/trx/trx0undo.c70
-rw-r--r--storage/innobase/ut/ut0ut.c4
-rw-r--r--storage/myisam/ft_boolean_search.c2
-rw-r--r--storage/myisam/ft_nlq_search.c2
-rw-r--r--storage/myisam/mi_check.c4
-rw-r--r--storage/myisam/mi_write.c2
-rw-r--r--strings/decimal.c9
-rw-r--r--strings/dtoa.c7
-rw-r--r--support-files/mysql.spec.sh141
122 files changed, 3217 insertions, 1662 deletions
diff --git a/VERSION b/VERSION
index d9f537cb915..4ef9a31b64d 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
MYSQL_VERSION_MAJOR=5
MYSQL_VERSION_MINOR=5
-MYSQL_VERSION_PATCH=16
+MYSQL_VERSION_PATCH=17
MYSQL_VERSION_EXTRA=
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index cc5dd1f377c..903f6a024f7 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -494,6 +494,7 @@ void str_to_file(const char *fname, char *str, int size);
void str_to_file2(const char *fname, char *str, int size, my_bool append);
void fix_win_paths(const char *val, int len);
+const char *get_errname_from_code (uint error_code);
#ifdef __WIN__
void free_tmp_sh_file();
@@ -2263,6 +2264,7 @@ void var_set_int(const char* name, int value)
void var_set_errno(int sql_errno)
{
var_set_int("$mysql_errno", sql_errno);
+ var_set_string("$mysql_errname", get_errname_from_code(sql_errno));
}
@@ -4670,8 +4672,7 @@ void do_shutdown_server(struct st_command *command)
}
-#if MYSQL_VERSION_ID >= 50000
-/* List of error names to error codes, available from 5.0 */
+/* List of error names to error codes */
typedef struct
{
const char *name;
@@ -4681,6 +4682,7 @@ typedef struct
static st_error global_error_names[] =
{
+ { "<No error>", -1, "" },
#include <mysqld_ername.h>
{ 0, 0, 0 }
};
@@ -4711,16 +4713,28 @@ uint get_errcode_from_name(char *error_name, char *error_end)
die("Unknown SQL error name '%s'", error_name);
DBUG_RETURN(0);
}
-#else
-uint get_errcode_from_name(char *error_name __attribute__((unused)),
- char *error_end __attribute__((unused)))
+
+const char *get_errname_from_code (uint error_code)
{
- abort_not_in_this_version();
- return 0; /* Never reached */
-}
-#endif
+ st_error *e= global_error_names;
+ DBUG_ENTER("get_errname_from_code");
+ DBUG_PRINT("enter", ("error_code: %d", error_code));
+ if (! error_code)
+ {
+ DBUG_RETURN("");
+ }
+ for (; e->name; e++)
+ {
+ if (e->code == error_code)
+ {
+ DBUG_RETURN(e->name);
+ }
+ }
+ /* Apparently, errors without known names may occur */
+ DBUG_RETURN("<Unknown>");
+}
void do_get_errcodes(struct st_command *command)
{
diff --git a/cmake/mysql_version.cmake b/cmake/mysql_version.cmake
index 122f0e63736..f21d29815e6 100644
--- a/cmake/mysql_version.cmake
+++ b/cmake/mysql_version.cmake
@@ -94,8 +94,8 @@ ENDIF()
IF(NOT CPACK_SOURCE_PACKAGE_FILE_NAME)
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "mysql-${VERSION}")
ENDIF()
-SET(CPACK_PACKAGE_CONTACT "MySQL Build Team <build@mysql.com>")
-SET(CPACK_PACKAGE_VENDOR "Sun Microsystems, Inc")
+SET(CPACK_PACKAGE_CONTACT "MySQL Release Engineering <mysql-build@oss.oracle.com>")
+SET(CPACK_PACKAGE_VENDOR "Oracle Corporation")
SET(CPACK_SOURCE_GENERATOR "TGZ")
INCLUDE(cpack_source_ignore_files)
diff --git a/extra/innochecksum.c b/extra/innochecksum.c
index 7ad900d16d3..b55b510b888 100644
--- a/extra/innochecksum.c
+++ b/extra/innochecksum.c
@@ -25,12 +25,7 @@
Published with a permission.
*/
-/* needed to have access to 64 bit file functions */
-#define _LARGEFILE_SOURCE
-#define _LARGEFILE64_SOURCE
-
-#define _XOPEN_SOURCE 500 /* needed to include getopt.h on some platforms. */
-
+#include <my_global.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
@@ -53,7 +48,6 @@
/* another argument to specify page ranges... seek to right spot and go from there */
typedef unsigned long int ulint;
-typedef unsigned char uchar;
/* innodb function in name; modified slightly to not have the ASM version (lots of #ifs that didn't apply) */
ulint mach_read_from_4(uchar *b)
diff --git a/include/decimal.h b/include/decimal.h
index 7a77b6a23da..0257242d865 100644
--- a/include/decimal.h
+++ b/include/decimal.h
@@ -21,6 +21,15 @@ typedef enum
decimal_round_mode;
typedef int32 decimal_digit_t;
+/**
+ intg is the number of *decimal* digits (NOT number of decimal_digit_t's !)
+ before the point
+ frac is the number of decimal digits after the point
+ len is the length of buf (length of allocated space) in decimal_digit_t's,
+ not in bytes
+ sign false means positive, true means negative
+ buf is an array of decimal_digit_t's
+ */
typedef struct st_decimal_t {
int intg, frac, len;
my_bool sign;
diff --git a/include/my_base.h b/include/my_base.h
index f6afc891281..d9f08a3c467 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -446,8 +446,10 @@ enum ha_base_keytype {
#define HA_ERR_FILE_TOO_SHORT 175 /* File too short */
#define HA_ERR_WRONG_CRC 176 /* Wrong CRC on page */
#define HA_ERR_TOO_MANY_CONCURRENT_TRXS 177 /*Too many active concurrent transactions */
-#define HA_ERR_INDEX_COL_TOO_LONG 178 /* Index column length exceeds limit */
-#define HA_ERR_LAST 178 /* Copy of last error nr */
+#define HA_ERR_INDEX_COL_TOO_LONG 178 /* Index column length exceeds limit */
+#define HA_ERR_INDEX_CORRUPT 179 /* Index corrupted */
+#define HA_ERR_UNDO_REC_TOO_BIG 180 /* Undo log record too big */
+#define HA_ERR_LAST 180 /* Copy of last error nr */
/* Number of different errors */
#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)
diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h
index d04d61067f2..ecc9a7773ca 100644
--- a/libmysql/client_settings.h
+++ b/libmysql/client_settings.h
@@ -22,6 +22,11 @@
extern uint mysql_port;
extern char * mysql_unix_port;
+/*
+ Note: CLIENT_CAPABILITIES is also defined in sql/client_settings.h.
+ When adding capabilities here, consider if they should be also added to
+ the server's version.
+*/
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | \
CLIENT_LONG_FLAG | \
CLIENT_TRANSACTIONS | \
diff --git a/mysql-test/include/mtr_check.sql b/mysql-test/include/mtr_check.sql
index 55e346c2007..699a35a1831 100644
--- a/mysql-test/include/mtr_check.sql
+++ b/mysql-test/include/mtr_check.sql
@@ -72,3 +72,13 @@ BEGIN
mysql.user;
END||
+
+--
+-- Procedure used by test case used to force all
+-- servers to restart after testcase and thus skipping
+-- check test case after test
+--
+CREATE DEFINER=root@localhost PROCEDURE force_restart()
+BEGIN
+ SELECT 1 INTO OUTFILE 'force_restart';
+END||
diff --git a/mysql-test/include/mysqld--help.inc b/mysql-test/include/mysqld--help.inc
index 5d20cff2c13..380a7f6c8cf 100644
--- a/mysql-test/include/mysqld--help.inc
+++ b/mysql-test/include/mysqld--help.inc
@@ -26,7 +26,7 @@ perl;
# And substitute the content some environment variables with their
# names:
- @env=qw/MYSQLTEST_VARDIR MYSQL_TEST_DIR MYSQL_LIBDIR MYSQL_CHARSETSDIR MYSQL_SHAREDIR/;
+ @env=qw/MYSQLTEST_VARDIR MYSQL_TEST_DIR MYSQL_CHARSETSDIR MYSQL_SHAREDIR/;
$re1=join('|', @skipvars, @plugins);
$re2=join('|', @plugins);
diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm
index 044ebb1f176..c8381e16061 100644
--- a/mysql-test/lib/mtr_cases.pm
+++ b/mysql-test/lib/mtr_cases.pm
@@ -337,17 +337,41 @@ sub collect_one_suite($)
for my $skip (@disabled_collection)
{
if ( open(DISABLED, $skip ) )
- {
- while ( <DISABLED> )
- {
- chomp;
- if ( /^\s*(\S+)\s*:\s*(.*?)\s*$/ )
- {
- $disabled{$1}= $2 if not exists $disabled{$1};
- }
- }
- close DISABLED;
- }
+ {
+ # $^O on Windows considered not generic enough
+ my $plat= (IS_WINDOWS) ? 'windows' : $^O;
+
+ while ( <DISABLED> )
+ {
+ chomp;
+ #diasble the test case if platform matches
+ if ( /\@/ )
+ {
+ if ( /\@$plat/ )
+ {
+ /^\s*(\S+)\s*\@$plat.*:\s*(.*?)\s*$/ ;
+ $disabled{$1}= $2 if not exists $disabled{$1};
+ }
+ elsif ( /\@!(\S*)/ )
+ {
+ if ( $1 ne $plat)
+ {
+ /^\s*(\S+)\s*\@!.*:\s*(.*?)\s*$/ ;
+ $disabled{$1}= $2 if not exists $disabled{$1};
+ }
+ }
+ }
+ elsif ( /^\s*(\S+)\s*:\s*(.*?)\s*$/ )
+ {
+ chomp;
+ if ( /^\s*(\S+)\s*:\s*(.*?)\s*$/ )
+ {
+ $disabled{$1}= $2 if not exists $disabled{$1};
+ }
+ }
+ }
+ close DISABLED;
+ }
}
# Read suite.opt file
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 1f02a5fb08e..1954d2798ed 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -2298,12 +2298,6 @@ sub environment_setup {
$ENV{'DEFAULT_MASTER_PORT'}= $mysqld_variables{'port'};
$ENV{'MYSQL_TMP_DIR'}= $opt_tmpdir;
$ENV{'MYSQLTEST_VARDIR'}= $opt_vardir;
- # Used for guessing default plugin dir, we can't really know for sure
- $ENV{'MYSQL_LIBDIR'}= "$basedir/lib";
- # Override if this does not exist, but lib64 does (best effort)
- if (! -d "$basedir/lib" && -d "$basedir/lib64") {
- $ENV{'MYSQL_LIBDIR'}= "$basedir/lib64";
- }
$ENV{'MYSQL_BINDIR'}= "$bindir";
$ENV{'MYSQL_SHAREDIR'}= $path_language;
$ENV{'MYSQL_CHARSETSDIR'}= $path_charsetsdir;
diff --git a/mysql-test/r/auth_rpl.result b/mysql-test/r/auth_rpl.result
new file mode 100644
index 00000000000..70626b02b2b
--- /dev/null
+++ b/mysql-test/r/auth_rpl.result
@@ -0,0 +1,24 @@
+include/master-slave.inc
+[connection master]
+[connection slave]
+include/stop_slave.inc
+[connection master]
+CREATE USER 'plug_user' IDENTIFIED WITH 'test_plugin_server' AS 'plug_user';
+GRANT REPLICATION SLAVE ON *.* TO plug_user;
+FLUSH PRIVILEGES;
+[connection slave]
+CHANGE MASTER TO
+MASTER_USER= 'plug_user',
+MASTER_PASSWORD= 'plug_user';
+include/start_slave.inc
+# Slave in-sync with master now.
+SELECT user, plugin, authentication_string FROM mysql.user WHERE user LIKE 'plug_user';
+user plugin authentication_string
+plug_user test_plugin_server plug_user
+# Cleanup (on slave).
+include/stop_slave.inc
+CHANGE MASTER TO MASTER_USER='root';
+DROP USER 'plug_user';
+# Cleanup (on master).
+DROP USER 'plug_user';
+include/rpl_end.inc
diff --git a/mysql-test/r/execution_constants.result b/mysql-test/r/execution_constants.result
index 293c88dc506..86eed447b83 100644
--- a/mysql-test/r/execution_constants.result
+++ b/mysql-test/r/execution_constants.result
@@ -7,6 +7,6 @@ PRIMARY KEY (`ID_MEMBER`,`ID_BOARD`),
KEY `logTime` (`logTime`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 COLLATE=cp1251_bulgarian_ci;
INSERT INTO `t_bug21476` VALUES (2,2,1154870939,0),(1,2,1154870957,0),(2,183,1154941362,0),(2,84,1154904301,0),(1,84,1154905867,0),(2,13,1154947484,10271),(3,84,1154880549,0),(1,6,1154892183,0),(2,25,1154947581,10271),(3,25,1154904760,0),(1,25,1154947373,10271),(1,179,1154899992,0),(2,179,1154899410,0),(5,25,1154901666,0),(2,329,1154902026,0),(3,329,1154902040,0),(1,329,1154902058,0),(1,13,1154930841,0),(3,85,1154904987,0),(1,183,1154929665,0),(3,13,1154931268,0),(1,85,1154936888,0),(1,169,1154937959,0),(2,169,1154941717,0),(3,183,1154939810,0),(3,169,1154941734,0);
-Assertion: mysql_errno 1436 == 1436
+Assertion: mysql_errname ER_STACK_OVERRUN_NEED_MORE == ER_STACK_OVERRUN_NEED_MORE
DROP TABLE `t_bug21476`;
End of 5.0 tests.
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 81fe2413725..755763e6994 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -2785,5 +2785,40 @@ format(123,2,'no_NO')
123,00
DROP TABLE t1;
#
+# Bug#12985030 SIMPLE QUERY WITH DECIMAL NUMBERS LEAKS MEMORY
+#
+SELECT (rpad(1.0,2048,1)) IS NOT FALSE;
+(rpad(1.0,2048,1)) IS NOT FALSE
+1
+SELECT ((+0) IN
+((0b111111111111111111111111111111111111111111111111111),(rpad(1.0,2048,1)),
+(32767.1)));
+((+0) IN
+((0b111111111111111111111111111111111111111111111111111),(rpad(1.0,2048,1)),
+(32767.1)))
+0
+SELECT ((rpad(1.0,2048,1)) = ('4(') ^ (0.1));
+((rpad(1.0,2048,1)) = ('4(') ^ (0.1))
+0
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: '4('
+SELECT
+pow((rpad(1.0,2048,1)),(b'1111111111111111111111111111111111111111111'));
+ERROR 22003: DOUBLE value is out of range in 'pow(rpad(1.0,2048,1),0x07ffffffffff)'
+SELECT ((rpad(1.0,2048,1)) + (0) ^ ('../'));
+((rpad(1.0,2048,1)) + (0) ^ ('../'))
+1.011111111111111
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: '../'
+SELECT stddev_samp(rpad(1.0,2048,1));
+stddev_samp(rpad(1.0,2048,1))
+NULL
+SELECT ((127.1) not in ((rpad(1.0,2048,1)),(''),(-1.1)));
+((127.1) not in ((rpad(1.0,2048,1)),(''),(-1.1)))
+1
+SELECT ((0xf3) * (rpad(1.0,2048,1)) << (0xcc));
+((0xf3) * (rpad(1.0,2048,1)) << (0xcc))
+0
+#
# End of 5.5 tests
#
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 2a52d63e1d7..950de54b815 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -1892,6 +1892,38 @@ a AVG(t1.b) t11c t12c
1 4.0000 6 6
2 2.0000 7 7
DROP TABLE t1;
+#
+# Bug#11765254 (58200): Assertion failed: param.sort_length when grouping
+# by functions
+#
+SET SQL_BIG_TABLES=1;
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES (0),(0);
+SELECT 1 FROM t1 GROUP BY IF(`a`,'','');
+1
+1
+SELECT 1 FROM t1 GROUP BY TRIM(LEADING RAND() FROM '');
+1
+1
+SELECT 1 FROM t1 GROUP BY SUBSTRING('',SLEEP(0),'');
+1
+1
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: ''
+Warning 1292 Truncated incorrect INTEGER value: ''
+Warning 1292 Truncated incorrect INTEGER value: ''
+SELECT 1 FROM t1 GROUP BY SUBSTRING(SYSDATE() FROM 'K' FOR 'jxW<');
+1
+1
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: 'K'
+Warning 1292 Truncated incorrect INTEGER value: 'jxW<'
+Warning 1292 Truncated incorrect INTEGER value: 'K'
+Warning 1292 Truncated incorrect INTEGER value: 'jxW<'
+Warning 1292 Truncated incorrect INTEGER value: 'K'
+Warning 1292 Truncated incorrect INTEGER value: 'jxW<'
+DROP TABLE t1;
+SET SQL_BIG_TABLES=0;
# End of 5.1 tests
#
# Bug#49771: Incorrect MIN (date) when minimum value is 0000-00-00
diff --git a/mysql-test/r/myisampack.result b/mysql-test/r/myisampack.result
index 91700701139..56f61ccdf47 100644
--- a/mysql-test/r/myisampack.result
+++ b/mysql-test/r/myisampack.result
@@ -118,3 +118,35 @@ Aborted: file is not compressed
DROP TABLE t1,t2,t3;
DROP TABLE mysql_db1.t1;
DROP DATABASE mysql_db1;
+#
+# BUG#11761180 - 53646: MYISAMPACK CORRUPTS TABLES WITH FULLTEXT INDEXES
+#
+CREATE TABLE t1(a CHAR(4), FULLTEXT(a));
+INSERT INTO t1 VALUES('aaaa'),('bbbb'),('cccc');
+FLUSH TABLE t1;
+CHECK TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+SELECT * FROM t1 WHERE MATCH(a) AGAINST('aaaa' IN BOOLEAN MODE);
+a
+aaaa
+SELECT * FROM t1 WHERE MATCH(a) AGAINST('aaaa');
+a
+aaaa
+DROP TABLE t1;
+# Test table with key_reflength > rec_reflength
+CREATE TABLE t1(a CHAR(30), FULLTEXT(a));
+# Populating a table, so it's index file exceeds 65K
+# Populating a table, so index file has second level fulltext tree
+FLUSH TABLE t1;
+# Compressing table
+# Fixing index (repair by sort)
+CHECK TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+FLUSH TABLE t1;
+# Fixing index (repair with keycache)
+CHECK TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+DROP TABLE t1;
diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result
index 9c8f49c333b..9d000e6f782 100644
--- a/mysql-test/r/mysqltest.result
+++ b/mysql-test/r/mysqltest.result
@@ -1,6 +1,5 @@
-select 0 as "before_use_test" ;
-before_use_test
-0
+-1 before test
+<No error> before test
select otto from (select 1 as otto) as t1;
otto
1
@@ -21,27 +20,32 @@ mysqltest: At line 1: query 'select friedrich from (select 1 as otto) as t1' fai
select otto from (select 1 as otto) as t1;
otto
1
+
select 0 as "after_successful_stmt_errno" ;
after_successful_stmt_errno
0
garbage ;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+ER_PARSE_ERROR
select 1064 as "after_wrong_syntax_errno" ;
after_wrong_syntax_errno
1064
garbage ;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+ER_PARSE_ERROR
select 1064 as "after_let_var_equal_value" ;
after_let_var_equal_value
1064
garbage ;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
set @my_var= 'abc' ;
+
select 0 as "after_set_var_equal_value" ;
after_set_var_equal_value
0
garbage ;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+ER_PARSE_ERROR
select 1064 as "after_disable_warnings_command" ;
after_disable_warnings_command
1064
@@ -49,6 +53,7 @@ drop table if exists t1 ;
garbage ;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
drop table if exists t1 ;
+
select 0 as "after_disable_warnings" ;
after_disable_warnings
0
@@ -56,6 +61,7 @@ garbage ;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
select 3 from t1 ;
ERROR 42S02: Table 'test.t1' doesn't exist
+ER_NO_SUCH_TABLE
select 1146 as "after_minus_masked" ;
after_minus_masked
1146
@@ -63,6 +69,7 @@ garbage ;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
select 3 from t1 ;
ERROR 42S02: Table 'test.t1' doesn't exist
+ER_NO_SUCH_TABLE
select 1146 as "after_!_masked" ;
after_!_masked
1146
@@ -75,6 +82,7 @@ garbage ;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
prepare stmt from "select 3 from t1" ;
ERROR 42S02: Table 'test.t1' doesn't exist
+ER_NO_SUCH_TABLE
select 1146 as "after_failing_prepare" ;
after_failing_prepare
1146
@@ -82,6 +90,7 @@ create table t1 ( f1 char(10));
garbage ;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
prepare stmt from "select 3 from t1" ;
+
select 0 as "after_successful_prepare" ;
after_successful_prepare
0
@@ -89,6 +98,7 @@ garbage ;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
execute stmt;
3
+
select 0 as "after_successful_execute" ;
after_successful_execute
0
@@ -97,6 +107,7 @@ garbage ;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
execute stmt;
ERROR 42S02: Table 'test.t1' doesn't exist
+ER_NO_SUCH_TABLE
select 1146 as "after_failing_execute" ;
after_failing_execute
1146
@@ -104,12 +115,14 @@ garbage ;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
execute __stmt_;
ERROR HY000: Unknown prepared statement handler (__stmt_) given to EXECUTE
+ER_UNKNOWN_STMT_HANDLER
select 1243 as "after_failing_execute" ;
after_failing_execute
1243
garbage ;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
deallocate prepare stmt;
+
select 0 as "after_successful_deallocate" ;
after_successful_deallocate
0
@@ -117,11 +130,13 @@ garbage ;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
deallocate prepare __stmt_;
ERROR HY000: Unknown prepared statement handler (__stmt_) given to DEALLOCATE PREPARE
+ER_UNKNOWN_STMT_HANDLER
select 1243 as "after_failing_deallocate" ;
after_failing_deallocate
1243
garbage ;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+ER_PARSE_ERROR
select 1064 as "after_--disable_abort_on_error" ;
after_--disable_abort_on_error
1064
@@ -131,12 +146,14 @@ select 3 from t1 ;
ERROR 42S02: Table 'test.t1' doesn't exist
select 3 from t1 ;
ERROR 42S02: Table 'test.t1' doesn't exist
+ER_NO_SUCH_TABLE
select 1146 as "after_!errno_masked_error" ;
after_!errno_masked_error
1146
mysqltest: At line 1: query 'select 3 from t1' failed with wrong errno 1146: 'Table 'test.t1' doesn't exist', instead of 1000...
garbage ;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+ER_PARSE_ERROR
select 1064 as "after_--enable_abort_on_error" ;
after_--enable_abort_on_error
1064
diff --git a/mysql-test/r/sp_trans.result b/mysql-test/r/sp_trans.result
index 4163725a196..b91dc898f12 100644
--- a/mysql-test/r/sp_trans.result
+++ b/mysql-test/r/sp_trans.result
@@ -558,6 +558,52 @@ f1 bug13575(f1)
3 ccc
drop function bug13575|
drop table t3|
+SELECT @@GLOBAL.storage_engine INTO @old_engine|
+SET @@GLOBAL.storage_engine=InnoDB|
+SET @@SESSION.storage_engine=InnoDB|
+SHOW GLOBAL VARIABLES LIKE 'storage_engine'|
+Variable_name Value
+storage_engine InnoDB
+SHOW SESSION VARIABLES LIKE 'storage_engine'|
+Variable_name Value
+storage_engine InnoDB
+CREATE PROCEDURE bug11758414()
+BEGIN
+SET @@GLOBAL.storage_engine="MyISAM";
+SET @@SESSION.storage_engine="MyISAM";
+# show defaults at execution time / that setting them worked
+SHOW GLOBAL VARIABLES LIKE 'storage_engine';
+SHOW SESSION VARIABLES LIKE 'storage_engine';
+CREATE TABLE t1 (id int);
+CREATE TABLE t2 (id int) ENGINE=InnoDB;
+# show we're heeding the default (at run-time, not parse-time!)
+ SHOW CREATE TABLE t1;
+ # show that we didn't break explicit override with ENGINE=...
+SHOW CREATE TABLE t2;
+END;
+|
+CALL bug11758414|
+Variable_name Value
+storage_engine MyISAM
+Variable_name Value
+storage_engine MyISAM
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW GLOBAL VARIABLES LIKE 'storage_engine'|
+Variable_name Value
+storage_engine MyISAM
+SHOW SESSION VARIABLES LIKE 'storage_engine'|
+Variable_name Value
+storage_engine MyISAM
+DROP PROCEDURE bug11758414|
+DROP TABLE t1, t2|
+SET @@GLOBAL.storage_engine=@old_engine|
#
# End of 5.1 tests
#
diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result
index c9db73c5f85..30c3c8f6442 100644
--- a/mysql-test/r/type_newdecimal.result
+++ b/mysql-test/r/type_newdecimal.result
@@ -1934,3 +1934,14 @@ f1
0.000000000000000000000000
DROP TABLE IF EXISTS t1;
End of 5.1 tests
+#
+# BUG#12911710 - VALGRIND FAILURE IN
+# ROW-DEBUG:PERFSCHEMA.SOCKET_SUMMARY_BY_INSTANCE_FUNC
+#
+CREATE TABLE t1(d1 DECIMAL(60,0) NOT NULL,
+d2 DECIMAL(60,0) NOT NULL);
+INSERT INTO t1 (d1, d2) VALUES(0.0, 0.0);
+SELECT d1 * d2 FROM t1;
+d1 * d2
+0
+DROP TABLE t1;
diff --git a/mysql-test/std_data/bug57108.cnf b/mysql-test/std_data/bug57108.cnf
deleted file mode 100644
index 5fd8c485cf0..00000000000
--- a/mysql-test/std_data/bug57108.cnf
+++ /dev/null
@@ -1,95 +0,0 @@
-[mysqld]
-open-files-limit=1024
-character-set-server=latin1
-connect-timeout=4711
-log-bin-trust-function-creators=1
-key_buffer_size=1M
-sort_buffer=256K
-max_heap_table_size=1M
-loose-innodb_data_file_path=ibdata1:10M:autoextend
-loose-innodb_buffer_pool_size=8M
-loose-innodb_write_io_threads=2
-loose-innodb_read_io_threads=2
-loose-innodb_log_buffer_size=1M
-loose-innodb_log_file_size=5M
-loose-innodb_additional_mem_pool_size=1M
-loose-innodb_log_files_in_group=2
-slave-net-timeout=120
-log-bin=mysqld-bin
-loose-enable-performance-schema
-loose-performance-schema-max-mutex-instances=10000
-loose-performance-schema-max-rwlock-instances=10000
-loose-performance-schema-max-table-instances=500
-loose-performance-schema-max-table-handles=1000
-binlog-direct-non-transactional-updates
-
-[mysql]
-default-character-set=latin1
-
-[mysqlshow]
-default-character-set=latin1
-
-[mysqlimport]
-default-character-set=latin1
-
-[mysqlcheck]
-default-character-set=latin1
-
-[mysql_upgrade]
-default-character-set=latin1
-tmpdir=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/tmp
-
-[mysqld.1]
-#!run-master-sh
-log-bin=master-bin
-loose-enable-performance-schema
-basedir=/home/bzr/bugs/b57108-5.5-bugteam
-tmpdir=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/tmp/mysqld.1
-character-sets-dir=/home/bzr/bugs/b57108-5.5-bugteam/sql/share/charsets
-lc-messages-dir=/home/bzr/bugs/b57108-5.5-bugteam/sql/share/
-datadir=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/mysqld.1/data
-pid-file=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/run/mysqld.1.pid
-#host=localhost
-port=13000
-socket=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/tmp/mysqld.1.sock
-#log-error=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/log/mysqld.1.err
-general_log=1
-general_log_file=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/mysqld.1/mysqld.log
-slow_query_log=1
-slow_query_log_file=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/mysqld.1/mysqld-slow.log
-#user=root
-#password=
-server-id=1
-secure-file-priv=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var
-ssl-ca=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/std_data/cacert.pem
-ssl-cert=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/std_data/server-cert.pem
-ssl-key=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/std_data/server-key.pem
-
-[mysqlbinlog]
-disable-force-if-open
-character-sets-dir=/home/bzr/bugs/b57108-5.5-bugteam/sql/share/charsets
-
-[ENV]
-MASTER_MYPORT=13000
-MASTER_MYSOCK=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/tmp/mysqld.1.sock
-
-[client]
-password=
-user=root
-port=13000
-host=localhost
-socket=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/tmp/mysqld.1.sock
-
-[mysqltest]
-ssl-ca=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/std_data/cacert.pem
-ssl-cert=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/std_data/client-cert.pem
-ssl-key=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/std_data/client-key.pem
-skip-ssl=1
-
-[client.1]
-password=
-user=root
-port=13000
-host=localhost
-socket=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/tmp/mysqld.1.sock
-
diff --git a/mysql-test/suite/innodb/r/innodb-index.result b/mysql-test/suite/innodb/r/innodb-index.result
index aa03c72022b..a33099661aa 100644
--- a/mysql-test/suite/innodb/r/innodb-index.result
+++ b/mysql-test/suite/innodb/r/innodb-index.result
@@ -39,6 +39,81 @@ DELETE FROM t1_purge;
DELETE FROM t2_purge;
DELETE FROM t3_purge;
DELETE FROM t4_purge;
+SET @r=REPEAT('a',500);
+CREATE TABLE t12637786(a INT,
+v1 VARCHAR(500), v2 VARCHAR(500), v3 VARCHAR(500),
+v4 VARCHAR(500), v5 VARCHAR(500), v6 VARCHAR(500),
+v7 VARCHAR(500), v8 VARCHAR(500), v9 VARCHAR(500),
+v10 VARCHAR(500), v11 VARCHAR(500), v12 VARCHAR(500),
+v13 VARCHAR(500), v14 VARCHAR(500), v15 VARCHAR(500),
+v16 VARCHAR(500), v17 VARCHAR(500), v18 VARCHAR(500)
+) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
+CREATE INDEX idx1 ON t12637786(a,v1);
+INSERT INTO t12637786 VALUES(9,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r);
+UPDATE t12637786 SET a=1000;
+DELETE FROM t12637786;
+create table t12963823(a blob,b blob,c blob,d blob,e blob,f blob,g blob,h blob,
+i blob,j blob,k blob,l blob,m blob,n blob,o blob,p blob)
+engine=innodb row_format=dynamic;
+SET @r = repeat('a', 767);
+insert into t12963823 values (@r,@r,@r,@r, @r,@r,@r,@r, @r,@r,@r,@r, @r,@r,@r,@r);
+create index ndx_a on t12963823 (a(500));
+create index ndx_b on t12963823 (b(500));
+create index ndx_c on t12963823 (c(500));
+create index ndx_d on t12963823 (d(500));
+create index ndx_e on t12963823 (e(500));
+create index ndx_f on t12963823 (f(500));
+create index ndx_k on t12963823 (k(500));
+create index ndx_l on t12963823 (l(500));
+SET @r = repeat('b', 500);
+update t12963823 set a=@r,b=@r,c=@r,d=@r;
+update t12963823 set e=@r,f=@r,g=@r,h=@r;
+update t12963823 set i=@r,j=@r,k=@r,l=@r;
+update t12963823 set m=@r,n=@r,o=@r,p=@r;
+alter table t12963823 drop index ndx_a;
+alter table t12963823 drop index ndx_b;
+create index ndx_g on t12963823 (g(500));
+create index ndx_h on t12963823 (h(500));
+create index ndx_i on t12963823 (i(500));
+create index ndx_j on t12963823 (j(500));
+create index ndx_m on t12963823 (m(500));
+create index ndx_n on t12963823 (n(500));
+create index ndx_o on t12963823 (o(500));
+create index ndx_p on t12963823 (p(500));
+show create table t12963823;
+Table Create Table
+t12963823 CREATE TABLE `t12963823` (
+ `a` blob,
+ `b` blob,
+ `c` blob,
+ `d` blob,
+ `e` blob,
+ `f` blob,
+ `g` blob,
+ `h` blob,
+ `i` blob,
+ `j` blob,
+ `k` blob,
+ `l` blob,
+ `m` blob,
+ `n` blob,
+ `o` blob,
+ `p` blob,
+ KEY `ndx_c` (`c`(500)),
+ KEY `ndx_d` (`d`(500)),
+ KEY `ndx_e` (`e`(500)),
+ KEY `ndx_f` (`f`(500)),
+ KEY `ndx_k` (`k`(500)),
+ KEY `ndx_l` (`l`(500)),
+ KEY `ndx_g` (`g`(500)),
+ KEY `ndx_h` (`h`(500)),
+ KEY `ndx_i` (`i`(500)),
+ KEY `ndx_j` (`j`(500)),
+ KEY `ndx_m` (`m`(500)),
+ KEY `ndx_n` (`n`(500)),
+ KEY `ndx_o` (`o`(500)),
+ KEY `ndx_p` (`p`(500))
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
set global innodb_file_per_table=0;
set global innodb_file_format=Antelope;
create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb;
@@ -961,20 +1036,15 @@ ERROR HY000: Too big row
alter table t1 row_format=compact;
create index t1u on t1 (u(767));
drop table t1;
-SET @r=REPEAT('a',500);
-CREATE TABLE t1(a INT,
-v1 VARCHAR(500), v2 VARCHAR(500), v3 VARCHAR(500),
-v4 VARCHAR(500), v5 VARCHAR(500), v6 VARCHAR(500),
-v7 VARCHAR(500), v8 VARCHAR(500), v9 VARCHAR(500),
-v10 VARCHAR(500), v11 VARCHAR(500), v12 VARCHAR(500),
-v13 VARCHAR(500), v14 VARCHAR(500), v15 VARCHAR(500),
-v16 VARCHAR(500), v17 VARCHAR(500), v18 VARCHAR(500)
+CREATE TABLE bug12547647(
+a INT NOT NULL, b BLOB NOT NULL, c TEXT,
+PRIMARY KEY (b(10), a), INDEX (c(767)), INDEX(b(767))
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
-CREATE INDEX idx1 ON t1(a,v1);
-INSERT INTO t1 VALUES(9,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r);
-UPDATE t1 SET a=1000;
-DELETE FROM t1;
-DROP TABLE t1;
+INSERT INTO bug12547647 VALUES (5,repeat('khdfo5AlOq',1900),repeat('g',7751));
+COMMIT;
+UPDATE bug12547647 SET c = REPEAT('b',16928);
+ERROR HY000: Undo log record is too big.
+DROP TABLE bug12547647;
set global innodb_file_per_table=0;
set global innodb_file_format=Antelope;
set global innodb_file_format_max=Antelope;
@@ -1146,3 +1216,5 @@ SELECT SLEEP(10);
SLEEP(10)
0
DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge;
+DROP TABLE t12637786;
+DROP TABLE t12963823;
diff --git a/mysql-test/suite/innodb/r/innodb_bug59733.result b/mysql-test/suite/innodb/r/innodb_bug59733.result
new file mode 100644
index 00000000000..c962cdfd677
--- /dev/null
+++ b/mysql-test/suite/innodb/r/innodb_bug59733.result
@@ -0,0 +1,18 @@
+CREATE TABLE bug59733(a INT AUTO_INCREMENT PRIMARY KEY,b CHAR(1))ENGINE=InnoDB;
+INSERT INTO bug59733 VALUES(0,'x');
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+CREATE INDEX b ON bug59733 (b);
+DELETE FROM bug59733 WHERE (a%100)=0;
+DROP INDEX b ON bug59733;
+CREATE INDEX b ON bug59733 (b);
+DROP TABLE bug59733;
diff --git a/mysql-test/suite/innodb/r/innodb_corrupt_bit.result b/mysql-test/suite/innodb/r/innodb_corrupt_bit.result
new file mode 100644
index 00000000000..c88e1ed2504
--- /dev/null
+++ b/mysql-test/suite/innodb/r/innodb_corrupt_bit.result
@@ -0,0 +1,81 @@
+set names utf8;
+CREATE TABLE corrupt_bit_test_ā(
+a INT AUTO_INCREMENT PRIMARY KEY,
+b CHAR(100),
+c INT,
+z INT,
+INDEX(b))
+ENGINE=InnoDB;
+INSERT INTO corrupt_bit_test_ā VALUES(0,'x',1, 1);
+CREATE UNIQUE INDEX idxā ON corrupt_bit_test_ā(c, b);
+CREATE UNIQUE INDEX idxē ON corrupt_bit_test_ā(z, b);
+SELECT * FROM corrupt_bit_test_ā;
+a b c z
+1 x 1 1
+select @@unique_checks;
+@@unique_checks
+0
+select @@innodb_change_buffering_debug;
+@@innodb_change_buffering_debug
+1
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+1,z+1 FROM corrupt_bit_test_ā;
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+10,z+10 FROM corrupt_bit_test_ā;
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+20,z+20 FROM corrupt_bit_test_ā;
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+50,z+50 FROM corrupt_bit_test_ā;
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+100,z+100 FROM corrupt_bit_test_ā;
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+200,z+200 FROM corrupt_bit_test_ā;
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+400,z+400 FROM corrupt_bit_test_ā;
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+800,z+800 FROM corrupt_bit_test_ā;
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+1600,z+1600 FROM corrupt_bit_test_ā;
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+4000,z+4000 FROM corrupt_bit_test_ā;
+select count(*) from corrupt_bit_test_ā;
+count(*)
+1024
+CREATE INDEX idx3 ON corrupt_bit_test_ā(b, c);
+INSERT INTO corrupt_bit_test_ā VALUES(13000,'x',1,1);
+CREATE INDEX idx4 ON corrupt_bit_test_ā(b, z);
+check table corrupt_bit_test_ā;
+Table Op Msg_type Msg_text
+test.corrupt_bit_test_ā check Warning InnoDB: The B-tree of index "idxā" is corrupted.
+test.corrupt_bit_test_ā check Warning InnoDB: The B-tree of index "idxē" is corrupted.
+test.corrupt_bit_test_ā check error Corrupt
+select c from corrupt_bit_test_ā;
+ERROR HY000: Incorrect key file for table 'corrupt_bit_test_ā'; try to repair it
+select z from corrupt_bit_test_ā;
+ERROR HY000: Incorrect key file for table 'corrupt_bit_test_ā'; try to repair it
+show warnings;
+Level Code Message
+Warning 179 InnoDB: Index "idxē" for table "test"."corrupt_bit_test_ā" is marked as corrupted
+Error 1034 Incorrect key file for table 'corrupt_bit_test_ā'; try to repair it
+insert into corrupt_bit_test_ā values (10001, "a", 20001, 20001);
+select * from corrupt_bit_test_ā use index(primary) where a = 10001;
+a b c z
+10001 a 20001 20001
+begin;
+insert into corrupt_bit_test_ā values (10002, "a", 20002, 20002);
+delete from corrupt_bit_test_ā where a = 10001;
+insert into corrupt_bit_test_ā values (10001, "a", 20001, 20001);
+rollback;
+drop index idxā on corrupt_bit_test_ā;
+check table corrupt_bit_test_ā;
+Table Op Msg_type Msg_text
+test.corrupt_bit_test_ā check Warning InnoDB: Index "idxē" is marked as corrupted
+test.corrupt_bit_test_ā check error Corrupt
+set names utf8;
+select z from corrupt_bit_test_ā;
+ERROR HY000: Incorrect key file for table 'corrupt_bit_test_ā'; try to repair it
+drop index idxē on corrupt_bit_test_ā;
+select z from corrupt_bit_test_ā limit 10;
+z
+20001
+1
+1
+2
+11
+12
+21
+22
+31
+32
+drop table corrupt_bit_test_ā;
+SET GLOBAL innodb_change_buffering_debug = 0;
diff --git a/mysql-test/suite/innodb/t/innodb-index.test b/mysql-test/suite/innodb/t/innodb-index.test
index fad90e280fc..d52237e02e3 100644
--- a/mysql-test/suite/innodb/t/innodb-index.test
+++ b/mysql-test/suite/innodb/t/innodb-index.test
@@ -9,7 +9,7 @@ let $format=`select @@innodb_file_format`;
set global innodb_file_per_table=on;
set global innodb_file_format='Barracuda';
-# Test an assertion failure on purge.
+# Bug #12429576 - Test an assertion failure on purge.
CREATE TABLE t1_purge (
A INT,
B BLOB, C BLOB, D BLOB, E BLOB,
@@ -59,6 +59,68 @@ DELETE FROM t1_purge;
DELETE FROM t2_purge;
DELETE FROM t3_purge;
DELETE FROM t4_purge;
+# Instead of doing a --sleep 10, wait until the rest of the tests in
+# this file complete before dropping the tables. By then, the purge thread
+# will have delt with the updates above.
+
+# Bug#12637786 - Bad assert by purge thread for records with external data
+# used in secondary indexes.
+SET @r=REPEAT('a',500);
+CREATE TABLE t12637786(a INT,
+ v1 VARCHAR(500), v2 VARCHAR(500), v3 VARCHAR(500),
+ v4 VARCHAR(500), v5 VARCHAR(500), v6 VARCHAR(500),
+ v7 VARCHAR(500), v8 VARCHAR(500), v9 VARCHAR(500),
+ v10 VARCHAR(500), v11 VARCHAR(500), v12 VARCHAR(500),
+ v13 VARCHAR(500), v14 VARCHAR(500), v15 VARCHAR(500),
+ v16 VARCHAR(500), v17 VARCHAR(500), v18 VARCHAR(500)
+) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
+CREATE INDEX idx1 ON t12637786(a,v1);
+INSERT INTO t12637786 VALUES(9,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r);
+UPDATE t12637786 SET a=1000;
+DELETE FROM t12637786;
+# We need to activate the purge thread at this point to make sure it does not
+# assert and is able to clean up the old versions of secondary index entries.
+# But instead of doing a --sleep 10, wait until the rest of the tests in
+# this file complete before dropping the table. By then, the purge thread
+# will have delt with the updates above.
+
+# Bug#12963823 - Test that the purge thread does not crash when
+# the number of indexes has changed since the UNDO record was logged.
+create table t12963823(a blob,b blob,c blob,d blob,e blob,f blob,g blob,h blob,
+ i blob,j blob,k blob,l blob,m blob,n blob,o blob,p blob)
+ engine=innodb row_format=dynamic;
+SET @r = repeat('a', 767);
+insert into t12963823 values (@r,@r,@r,@r, @r,@r,@r,@r, @r,@r,@r,@r, @r,@r,@r,@r);
+create index ndx_a on t12963823 (a(500));
+create index ndx_b on t12963823 (b(500));
+create index ndx_c on t12963823 (c(500));
+create index ndx_d on t12963823 (d(500));
+create index ndx_e on t12963823 (e(500));
+create index ndx_f on t12963823 (f(500));
+create index ndx_k on t12963823 (k(500));
+create index ndx_l on t12963823 (l(500));
+
+SET @r = repeat('b', 500);
+update t12963823 set a=@r,b=@r,c=@r,d=@r;
+update t12963823 set e=@r,f=@r,g=@r,h=@r;
+update t12963823 set i=@r,j=@r,k=@r,l=@r;
+update t12963823 set m=@r,n=@r,o=@r,p=@r;
+alter table t12963823 drop index ndx_a;
+alter table t12963823 drop index ndx_b;
+create index ndx_g on t12963823 (g(500));
+create index ndx_h on t12963823 (h(500));
+create index ndx_i on t12963823 (i(500));
+create index ndx_j on t12963823 (j(500));
+create index ndx_m on t12963823 (m(500));
+create index ndx_n on t12963823 (n(500));
+create index ndx_o on t12963823 (o(500));
+create index ndx_p on t12963823 (p(500));
+show create table t12963823;
+# We need to activate the purge thread at this point to see if it crashes
+# but instead of doing a --sleep 10, wait until the rest of the tests in
+# this file complete before dropping the table. By then, the purge thread
+# will have delt with the updates above.
+
eval set global innodb_file_per_table=$per_table;
eval set global innodb_file_format=$format;
@@ -459,23 +521,18 @@ create index t1u on t1 (u(767));
drop table t1;
-# Bug#12637786
-SET @r=REPEAT('a',500);
-CREATE TABLE t1(a INT,
- v1 VARCHAR(500), v2 VARCHAR(500), v3 VARCHAR(500),
- v4 VARCHAR(500), v5 VARCHAR(500), v6 VARCHAR(500),
- v7 VARCHAR(500), v8 VARCHAR(500), v9 VARCHAR(500),
- v10 VARCHAR(500), v11 VARCHAR(500), v12 VARCHAR(500),
- v13 VARCHAR(500), v14 VARCHAR(500), v15 VARCHAR(500),
- v16 VARCHAR(500), v17 VARCHAR(500), v18 VARCHAR(500)
+# Bug#12547647 UPDATE LOGGING COULD EXCEED LOG PAGE SIZE
+CREATE TABLE bug12547647(
+a INT NOT NULL, b BLOB NOT NULL, c TEXT,
+PRIMARY KEY (b(10), a), INDEX (c(767)), INDEX(b(767))
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
-CREATE INDEX idx1 ON t1(a,v1);
-INSERT INTO t1 VALUES(9,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r);
-UPDATE t1 SET a=1000;
-DELETE FROM t1;
-# Let the purge thread clean up this file.
--- sleep 10
-DROP TABLE t1;
+
+INSERT INTO bug12547647 VALUES (5,repeat('khdfo5AlOq',1900),repeat('g',7751));
+COMMIT;
+# The following used to cause infinite undo log allocation.
+--error ER_UNDO_RECORD_TOO_BIG
+UPDATE bug12547647 SET c = REPEAT('b',16928);
+DROP TABLE bug12547647;
eval set global innodb_file_per_table=$per_table;
eval set global innodb_file_format=$format;
@@ -623,6 +680,8 @@ DROP TABLE t1;
#this delay is needed because 45225_2 is disabled, to allow the purge to run
SELECT SLEEP(10);
DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge;
+DROP TABLE t12637786;
+DROP TABLE t12963823;
#
# restore environment to the state it was before this test execution
diff --git a/mysql-test/suite/innodb/t/innodb_bug59733.test b/mysql-test/suite/innodb/t/innodb_bug59733.test
new file mode 100644
index 00000000000..0b1bff51932
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb_bug59733.test
@@ -0,0 +1,53 @@
+#
+# Bug #59733 Possible deadlock when buffered changes are to be discarded
+# in buf_page_create
+#
+-- source include/have_innodb.inc
+
+-- disable_query_log
+# The flag innodb_change_buffering_debug is only available in debug builds.
+# It instructs InnoDB to try to evict pages from the buffer pool when
+# change buffering is possible, so that the change buffer will be used
+# whenever possible.
+-- error 0,ER_UNKNOWN_SYSTEM_VARIABLE
+SET @innodb_change_buffering_debug_orig = @@innodb_change_buffering_debug;
+-- error 0,ER_UNKNOWN_SYSTEM_VARIABLE
+SET GLOBAL innodb_change_buffering_debug = 1;
+-- enable_query_log
+
+CREATE TABLE bug59733(a INT AUTO_INCREMENT PRIMARY KEY,b CHAR(1))ENGINE=InnoDB;
+
+# Create enough rows for the table, so that the insert buffer will be
+# used. There must be multiple index pages, because changes to the
+# root page are never buffered.
+
+INSERT INTO bug59733 VALUES(0,'x');
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+INSERT INTO bug59733 SELECT 0,b FROM bug59733;
+
+# Create the secondary index for which changes will be buffered.
+CREATE INDEX b ON bug59733 (b);
+
+# This should be buffered, if innodb_change_buffering_debug = 1 is in effect.
+DELETE FROM bug59733 WHERE (a%100)=0;
+
+# Drop the index in order to get free pages with orphaned buffered changes.
+DROP INDEX b ON bug59733;
+
+# Create the index and attempt to reuse pages for which buffered changes exist.
+CREATE INDEX b ON bug59733 (b);
+
+DROP TABLE bug59733;
+
+-- disable_query_log
+-- error 0, ER_UNKNOWN_SYSTEM_VARIABLE
+SET GLOBAL innodb_change_buffering_debug = @innodb_change_buffering_debug_orig;
diff --git a/mysql-test/suite/innodb/t/innodb_corrupt_bit.test b/mysql-test/suite/innodb/t/innodb_corrupt_bit.test
new file mode 100644
index 00000000000..34991362f98
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb_corrupt_bit.test
@@ -0,0 +1,120 @@
+#
+# Test for persistent corrupt bit for corrupted index and table
+#
+-- source include/have_innodb.inc
+
+# This test needs debug server
+--source include/have_debug.inc
+
+-- disable_query_log
+# This test setup is extracted from bug56680.test:
+# The flag innodb_change_buffering_debug is only available in debug builds.
+# It instructs InnoDB to try to evict pages from the buffer pool when
+# change buffering is possible, so that the change buffer will be used
+# whenever possible.
+-- error 0,ER_UNKNOWN_SYSTEM_VARIABLE
+SET @innodb_change_buffering_debug_orig = @@innodb_change_buffering_debug;
+-- error 0,ER_UNKNOWN_SYSTEM_VARIABLE
+SET GLOBAL innodb_change_buffering_debug = 1;
+
+# Turn off Unique Check to create corrupted index with dup key
+SET UNIQUE_CHECKS=0;
+
+-- enable_query_log
+
+set names utf8;
+
+CREATE TABLE corrupt_bit_test_ā(
+ a INT AUTO_INCREMENT PRIMARY KEY,
+ b CHAR(100),
+ c INT,
+ z INT,
+ INDEX(b))
+ENGINE=InnoDB;
+
+INSERT INTO corrupt_bit_test_ā VALUES(0,'x',1, 1);
+
+# This is the first unique index we intend to corrupt
+CREATE UNIQUE INDEX idxā ON corrupt_bit_test_ā(c, b);
+
+# This is the second unique index we intend to corrupt
+CREATE UNIQUE INDEX idxē ON corrupt_bit_test_ā(z, b);
+
+SELECT * FROM corrupt_bit_test_ā;
+
+select @@unique_checks;
+select @@innodb_change_buffering_debug;
+
+# Create enough rows for the table, so that the insert buffer will be
+# used for modifying the secondary index page. There must be multiple
+# index pages, because changes to the root page are never buffered.
+
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+1,z+1 FROM corrupt_bit_test_ā;
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+10,z+10 FROM corrupt_bit_test_ā;
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+20,z+20 FROM corrupt_bit_test_ā;
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+50,z+50 FROM corrupt_bit_test_ā;
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+100,z+100 FROM corrupt_bit_test_ā;
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+200,z+200 FROM corrupt_bit_test_ā;
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+400,z+400 FROM corrupt_bit_test_ā;
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+800,z+800 FROM corrupt_bit_test_ā;
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+1600,z+1600 FROM corrupt_bit_test_ā;
+INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+4000,z+4000 FROM corrupt_bit_test_ā;
+
+select count(*) from corrupt_bit_test_ā;
+
+CREATE INDEX idx3 ON corrupt_bit_test_ā(b, c);
+
+# Create a dup key error on index "idxē" and "idxā" by inserting a dup value
+INSERT INTO corrupt_bit_test_ā VALUES(13000,'x',1,1);
+
+# creating an index should succeed even if other secondary indexes are corrupted
+CREATE INDEX idx4 ON corrupt_bit_test_ā(b, z);
+
+# Check table will find the unique indexes corrupted
+# with dup key
+check table corrupt_bit_test_ā;
+
+# This selection intend to use the corrupted index. Expect to fail
+-- error ER_NOT_KEYFILE
+select c from corrupt_bit_test_ā;
+
+-- error ER_NOT_KEYFILE
+select z from corrupt_bit_test_ā;
+
+show warnings;
+
+# Since corrupted index is a secondary index, we only disable such
+# index and allow other DML to proceed
+insert into corrupt_bit_test_ā values (10001, "a", 20001, 20001);
+
+# This does not use the corrupted index, expect to succeed
+select * from corrupt_bit_test_ā use index(primary) where a = 10001;
+
+# Some more DMLs
+begin;
+insert into corrupt_bit_test_ā values (10002, "a", 20002, 20002);
+delete from corrupt_bit_test_ā where a = 10001;
+insert into corrupt_bit_test_ā values (10001, "a", 20001, 20001);
+rollback;
+
+# Drop one corrupted index before reboot
+drop index idxā on corrupt_bit_test_ā;
+
+check table corrupt_bit_test_ā;
+
+set names utf8;
+
+-- error ER_NOT_KEYFILE
+select z from corrupt_bit_test_ā;
+
+# Drop the corrupted index
+drop index idxē on corrupt_bit_test_ā;
+
+# Now select back to normal
+select z from corrupt_bit_test_ā limit 10;
+
+# Drop table
+drop table corrupt_bit_test_ā;
+
+-- error 0, ER_UNKNOWN_SYSTEM_VARIABLE
+SET GLOBAL innodb_change_buffering_debug = 0;
diff --git a/mysql-test/suite/sys_vars/r/innodb_file_per_table_basic.result b/mysql-test/suite/sys_vars/r/innodb_file_per_table_basic.result
index 163eb31f686..ecf11351cd9 100644
--- a/mysql-test/suite/sys_vars/r/innodb_file_per_table_basic.result
+++ b/mysql-test/suite/sys_vars/r/innodb_file_per_table_basic.result
@@ -1,13 +1,29 @@
+SET @start_global_value = @@global.innodb_file_per_table;
+SELECT @start_global_value;
+@start_global_value
+0
'#---------------------BS_STVARS_028_01----------------------#'
SELECT COUNT(@@GLOBAL.innodb_file_per_table);
COUNT(@@GLOBAL.innodb_file_per_table)
1
1 Expected
'#---------------------BS_STVARS_028_02----------------------#'
-SELECT COUNT(@@GLOBAL.innodb_file_per_table);
-COUNT(@@GLOBAL.innodb_file_per_table)
+SET @@global.innodb_file_per_table = 0;
+SELECT @@global.innodb_file_per_table;
+@@global.innodb_file_per_table
+0
+SET @@global.innodb_file_per_table ='On' ;
+SELECT @@global.innodb_file_per_table;
+@@global.innodb_file_per_table
+1
+SET @@global.innodb_file_per_table ='Off' ;
+SELECT @@global.innodb_file_per_table;
+@@global.innodb_file_per_table
+0
+SET @@global.innodb_file_per_table = 1;
+SELECT @@global.innodb_file_per_table;
+@@global.innodb_file_per_table
1
-1 Expected
'#---------------------BS_STVARS_028_03----------------------#'
SELECT IF(@@GLOBAL.innodb_file_per_table,'ON','OFF') = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
@@ -47,4 +63,7 @@ COUNT(@@GLOBAL.innodb_file_per_table)
1 Expected
SELECT innodb_file_per_table = @@SESSION.innodb_file_per_table;
ERROR 42S22: Unknown column 'innodb_file_per_table' in 'field list'
-Expected error 'Readonly variable'
+SET @@global.innodb_file_per_table = @start_global_value;
+SELECT @@global.innodb_file_per_table;
+@@global.innodb_file_per_table
+0
diff --git a/mysql-test/suite/sys_vars/r/innodb_force_load_corrupted_basic.result b/mysql-test/suite/sys_vars/r/innodb_force_load_corrupted_basic.result
new file mode 100644
index 00000000000..bc9b7019eb8
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/innodb_force_load_corrupted_basic.result
@@ -0,0 +1,53 @@
+'#---------------------BS_STVARS_031_01----------------------#'
+SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted);
+COUNT(@@GLOBAL.innodb_force_load_corrupted)
+1
+1 Expected
+'#---------------------BS_STVARS_031_02----------------------#'
+SET @@GLOBAL.innodb_force_load_corrupted=1;
+ERROR HY000: Variable 'innodb_force_load_corrupted' is a read only variable
+Expected error 'Read only variable'
+SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted);
+COUNT(@@GLOBAL.innodb_force_load_corrupted)
+1
+1 Expected
+'#---------------------BS_STVARS_031_03----------------------#'
+SELECT IF(@@GLOBAL.innodb_force_load_corrupted, "ON", "OFF") = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='innodb_force_load_corrupted';
+IF(@@GLOBAL.innodb_force_load_corrupted, "ON", "OFF") = VARIABLE_VALUE
+1
+1 Expected
+SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted);
+COUNT(@@GLOBAL.innodb_force_load_corrupted)
+1
+1 Expected
+SELECT COUNT(VARIABLE_VALUE)
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='innodb_force_load_corrupted';
+COUNT(VARIABLE_VALUE)
+1
+1 Expected
+'#---------------------BS_STVARS_031_04----------------------#'
+SELECT @@innodb_force_load_corrupted = @@GLOBAL.innodb_force_load_corrupted;
+@@innodb_force_load_corrupted = @@GLOBAL.innodb_force_load_corrupted
+1
+1 Expected
+'#---------------------BS_STVARS_031_05----------------------#'
+SELECT COUNT(@@innodb_force_load_corrupted);
+COUNT(@@innodb_force_load_corrupted)
+1
+1 Expected
+SELECT COUNT(@@local.innodb_force_load_corrupted);
+ERROR HY000: Variable 'innodb_force_load_corrupted' is a GLOBAL variable
+Expected error 'Variable is a GLOBAL variable'
+SELECT COUNT(@@SESSION.innodb_force_load_corrupted);
+ERROR HY000: Variable 'innodb_force_load_corrupted' is a GLOBAL variable
+Expected error 'Variable is a GLOBAL variable'
+SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted);
+COUNT(@@GLOBAL.innodb_force_load_corrupted)
+1
+1 Expected
+SELECT innodb_force_load_corrupted = @@SESSION.innodb_force_load_corrupted;
+ERROR 42S22: Unknown column 'innodb_force_load_corrupted' in 'field list'
+Expected error 'Readonly variable'
diff --git a/mysql-test/suite/sys_vars/r/innodb_large_prefix_basic.result b/mysql-test/suite/sys_vars/r/innodb_large_prefix_basic.result
new file mode 100644
index 00000000000..adb56b347cd
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/innodb_large_prefix_basic.result
@@ -0,0 +1,92 @@
+SET @start_global_value = @@global.innodb_large_prefix;
+SELECT @start_global_value;
+@start_global_value
+0
+Valid values are 'ON' and 'OFF'
+select @@global.innodb_large_prefix in (0, 1);
+@@global.innodb_large_prefix in (0, 1)
+1
+select @@global.innodb_large_prefix;
+@@global.innodb_large_prefix
+0
+select @@session.innodb_large_prefix;
+ERROR HY000: Variable 'innodb_large_prefix' is a GLOBAL variable
+show global variables like 'innodb_large_prefix';
+Variable_name Value
+innodb_large_prefix OFF
+show session variables like 'innodb_large_prefix';
+Variable_name Value
+innodb_large_prefix OFF
+select * from information_schema.global_variables where variable_name='innodb_large_prefix';
+VARIABLE_NAME VARIABLE_VALUE
+INNODB_LARGE_PREFIX OFF
+select * from information_schema.session_variables where variable_name='innodb_large_prefix';
+VARIABLE_NAME VARIABLE_VALUE
+INNODB_LARGE_PREFIX OFF
+set global innodb_large_prefix='OFF';
+select @@global.innodb_large_prefix;
+@@global.innodb_large_prefix
+0
+select * from information_schema.global_variables where variable_name='innodb_large_prefix';
+VARIABLE_NAME VARIABLE_VALUE
+INNODB_LARGE_PREFIX OFF
+select * from information_schema.session_variables where variable_name='innodb_large_prefix';
+VARIABLE_NAME VARIABLE_VALUE
+INNODB_LARGE_PREFIX OFF
+set @@global.innodb_large_prefix=1;
+select @@global.innodb_large_prefix;
+@@global.innodb_large_prefix
+1
+select * from information_schema.global_variables where variable_name='innodb_large_prefix';
+VARIABLE_NAME VARIABLE_VALUE
+INNODB_LARGE_PREFIX ON
+select * from information_schema.session_variables where variable_name='innodb_large_prefix';
+VARIABLE_NAME VARIABLE_VALUE
+INNODB_LARGE_PREFIX ON
+set global innodb_large_prefix=0;
+select @@global.innodb_large_prefix;
+@@global.innodb_large_prefix
+0
+select * from information_schema.global_variables where variable_name='innodb_large_prefix';
+VARIABLE_NAME VARIABLE_VALUE
+INNODB_LARGE_PREFIX OFF
+select * from information_schema.session_variables where variable_name='innodb_large_prefix';
+VARIABLE_NAME VARIABLE_VALUE
+INNODB_LARGE_PREFIX OFF
+set @@global.innodb_large_prefix='ON';
+select @@global.innodb_large_prefix;
+@@global.innodb_large_prefix
+1
+select * from information_schema.global_variables where variable_name='innodb_large_prefix';
+VARIABLE_NAME VARIABLE_VALUE
+INNODB_LARGE_PREFIX ON
+select * from information_schema.session_variables where variable_name='innodb_large_prefix';
+VARIABLE_NAME VARIABLE_VALUE
+INNODB_LARGE_PREFIX ON
+set session innodb_large_prefix='OFF';
+ERROR HY000: Variable 'innodb_large_prefix' is a GLOBAL variable and should be set with SET GLOBAL
+set @@session.innodb_large_prefix='ON';
+ERROR HY000: Variable 'innodb_large_prefix' is a GLOBAL variable and should be set with SET GLOBAL
+set global innodb_large_prefix=1.1;
+ERROR 42000: Incorrect argument type to variable 'innodb_large_prefix'
+set global innodb_large_prefix=1e1;
+ERROR 42000: Incorrect argument type to variable 'innodb_large_prefix'
+set global innodb_large_prefix=2;
+ERROR 42000: Variable 'innodb_large_prefix' can't be set to the value of '2'
+NOTE: The following should fail with ER_WRONG_VALUE_FOR_VAR (BUG#50643)
+set global innodb_large_prefix=-3;
+select @@global.innodb_large_prefix;
+@@global.innodb_large_prefix
+1
+select * from information_schema.global_variables where variable_name='innodb_large_prefix';
+VARIABLE_NAME VARIABLE_VALUE
+INNODB_LARGE_PREFIX ON
+select * from information_schema.session_variables where variable_name='innodb_large_prefix';
+VARIABLE_NAME VARIABLE_VALUE
+INNODB_LARGE_PREFIX ON
+set global innodb_large_prefix='AUTO';
+ERROR 42000: Variable 'innodb_large_prefix' can't be set to the value of 'AUTO'
+SET @@global.innodb_large_prefix = @start_global_value;
+SELECT @@global.innodb_large_prefix;
+@@global.innodb_large_prefix
+0
diff --git a/mysql-test/suite/sys_vars/r/innodb_lock_wait_timeout_basic.result b/mysql-test/suite/sys_vars/r/innodb_lock_wait_timeout_basic.result
index 89960e5860f..1dcc2d554ce 100644
--- a/mysql-test/suite/sys_vars/r/innodb_lock_wait_timeout_basic.result
+++ b/mysql-test/suite/sys_vars/r/innodb_lock_wait_timeout_basic.result
@@ -1,13 +1,21 @@
+SET @start_global_value=@@global.innodb_lock_wait_timeout;
+SELECT @start_global_value;
+@start_global_value
+50
'#---------------------BS_STVARS_032_01----------------------#'
SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
COUNT(@@GLOBAL.innodb_lock_wait_timeout)
1
1 Expected
'#---------------------BS_STVARS_032_02----------------------#'
-SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
-COUNT(@@GLOBAL.innodb_lock_wait_timeout)
-1
-1 Expected
+SET global innodb_lock_wait_timeout=60;
+SELECT @@global.innodb_lock_wait_timeout;
+@@global.innodb_lock_wait_timeout
+60
+SET session innodb_lock_wait_timeout=60;
+SELECT @@session.innodb_lock_wait_timeout;
+@@session.innodb_lock_wait_timeout
+60
'#---------------------BS_STVARS_032_03----------------------#'
SELECT @@GLOBAL.innodb_lock_wait_timeout = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
@@ -47,4 +55,7 @@ COUNT(@@GLOBAL.innodb_lock_wait_timeout)
1 Expected
SELECT innodb_lock_wait_timeout = @@SESSION.innodb_lock_wait_timeout;
ERROR 42S22: Unknown column 'innodb_lock_wait_timeout' in 'field list'
-Expected error 'Readonly variable'
+SET @@global.innodb_lock_wait_timeout = @start_global_value;
+SELECT @@global.innodb_lock_wait_timeout;
+@@global.innodb_lock_wait_timeout
+50
diff --git a/mysql-test/suite/sys_vars/r/plugin_dir_basic.result b/mysql-test/suite/sys_vars/r/plugin_dir_basic.result
index f81cae24dda..a5f36de73fa 100644
--- a/mysql-test/suite/sys_vars/r/plugin_dir_basic.result
+++ b/mysql-test/suite/sys_vars/r/plugin_dir_basic.result
@@ -1,20 +1,20 @@
select @@global.plugin_dir;
@@global.plugin_dir
-MYSQL_LIBDIR/plugin
+MYSQL_TMP_DIR
select @@session.plugin_dir;
ERROR HY000: Variable 'plugin_dir' is a GLOBAL variable
show global variables like 'plugin_dir';
Variable_name Value
-plugin_dir MYSQL_LIBDIR/plugin
+plugin_dir MYSQL_TMP_DIR
show session variables like 'plugin_dir';
Variable_name Value
-plugin_dir MYSQL_LIBDIR/plugin
+plugin_dir MYSQL_TMP_DIR
select * from information_schema.global_variables where variable_name='plugin_dir';
VARIABLE_NAME VARIABLE_VALUE
-PLUGIN_DIR MYSQL_LIBDIR/plugin
+PLUGIN_DIR MYSQL_TMP_DIR
select * from information_schema.session_variables where variable_name='plugin_dir';
VARIABLE_NAME VARIABLE_VALUE
-PLUGIN_DIR MYSQL_LIBDIR/plugin
+PLUGIN_DIR MYSQL_TMP_DIR
set global plugin_dir=1;
ERROR HY000: Variable 'plugin_dir' is a read only variable
set session plugin_dir=1;
diff --git a/mysql-test/suite/sys_vars/t/innodb_autoinc_lock_mode_basic.test b/mysql-test/suite/sys_vars/t/innodb_autoinc_lock_mode_basic.test
index 5b6fa943bbe..e07234a9152 100644
--- a/mysql-test/suite/sys_vars/t/innodb_autoinc_lock_mode_basic.test
+++ b/mysql-test/suite/sys_vars/t/innodb_autoinc_lock_mode_basic.test
@@ -1,8 +1,7 @@
################# mysql-test\t\innodb_autoinc_lock_mode_basic.test ############
# #
# Variable Name: innodb_autoinc_lock_mode #
-# Scope: GLOBAL #
-# Access Type: Dynamic #
+# Access Type: Static #
# Data Type: Numeric #
# Default Value: 1 #
# Range: 0,1,2 #
diff --git a/mysql-test/suite/sys_vars/t/innodb_fast_shutdown_basic.test b/mysql-test/suite/sys_vars/t/innodb_fast_shutdown_basic.test
index 636309a3088..e1b62046313 100644
--- a/mysql-test/suite/sys_vars/t/innodb_fast_shutdown_basic.test
+++ b/mysql-test/suite/sys_vars/t/innodb_fast_shutdown_basic.test
@@ -3,9 +3,9 @@
# Variable Name: innodb_fast_shutdown #
# Scope: GLOBAL #
# Access Type: Dynamic #
-# Data Type: boolean #
+# Data Type: numeric #
# Default Value: 1 #
-# Valid Values: 0,1 #
+# Valid Values: 0,1,2 #
# #
# #
# Creation Date: 2008-02-20 #
diff --git a/mysql-test/suite/sys_vars/t/innodb_file_per_table_basic.test b/mysql-test/suite/sys_vars/t/innodb_file_per_table_basic.test
index 76a50df8879..1478d6df2e9 100644
--- a/mysql-test/suite/sys_vars/t/innodb_file_per_table_basic.test
+++ b/mysql-test/suite/sys_vars/t/innodb_file_per_table_basic.test
@@ -4,7 +4,7 @@
# #
# Variable Name: innodb_file_per_table #
# Scope: Global #
-# Access Type: Static #
+# Access Type: Dynamic #
# Data Type: boolean #
# #
# #
@@ -24,6 +24,10 @@
--source include/have_innodb.inc
+SET @start_global_value = @@global.innodb_file_per_table;
+SELECT @start_global_value;
+
+
--echo '#---------------------BS_STVARS_028_01----------------------#'
####################################################################
# Displaying default value #
@@ -37,11 +41,17 @@ SELECT COUNT(@@GLOBAL.innodb_file_per_table);
# Check if Value can set #
####################################################################
-SELECT COUNT(@@GLOBAL.innodb_file_per_table);
---echo 1 Expected
+SET @@global.innodb_file_per_table = 0;
+SELECT @@global.innodb_file_per_table;
+SET @@global.innodb_file_per_table ='On' ;
+SELECT @@global.innodb_file_per_table;
+SET @@global.innodb_file_per_table ='Off' ;
+SELECT @@global.innodb_file_per_table;
+SET @@global.innodb_file_per_table = 1;
+SELECT @@global.innodb_file_per_table;
--echo '#---------------------BS_STVARS_028_03----------------------#'
#################################################################
@@ -93,6 +103,10 @@ SELECT COUNT(@@GLOBAL.innodb_file_per_table);
--Error ER_BAD_FIELD_ERROR
SELECT innodb_file_per_table = @@SESSION.innodb_file_per_table;
---echo Expected error 'Readonly variable'
+#
+# Cleanup
+#
+SET @@global.innodb_file_per_table = @start_global_value;
+SELECT @@global.innodb_file_per_table;
diff --git a/mysql-test/suite/sys_vars/t/innodb_force_load_corrupted_basic.test b/mysql-test/suite/sys_vars/t/innodb_force_load_corrupted_basic.test
new file mode 100644
index 00000000000..1726b320f47
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/innodb_force_load_corrupted_basic.test
@@ -0,0 +1,102 @@
+
+
+################## mysql-test\t\innodb_force_load_corrupted_basic.test #####
+# #
+# Variable Name: innodb_force_load_corrupted #
+# Scope: Global #
+# Access Type: Static #
+# Data Type: boolean #
+# #
+# #
+# Creation Date: 2008-02-07 #
+# Author : Sharique Abdullah #
+# #
+# #
+# Description:Test Cases of Dynamic System Variable innodb_force_load_corrupted#
+# that checks the behavior of this variable in the following ways #
+# * Value Check #
+# * Scope Check #
+# #
+# Reference: http://dev.mysql.com/doc/refman/5.1/en/ #
+# server-system-variables.html #
+# #
+###############################################################################
+
+--source include/have_innodb.inc
+
+--echo '#---------------------BS_STVARS_031_01----------------------#'
+####################################################################
+# Displaying default value #
+####################################################################
+SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted);
+--echo 1 Expected
+
+
+--echo '#---------------------BS_STVARS_031_02----------------------#'
+####################################################################
+# Check if Value can set #
+####################################################################
+
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SET @@GLOBAL.innodb_force_load_corrupted=1;
+--echo Expected error 'Read only variable'
+
+SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted);
+--echo 1 Expected
+
+
+
+
+--echo '#---------------------BS_STVARS_031_03----------------------#'
+#################################################################
+# Check if the value in GLOBAL Table matches value in variable #
+#################################################################
+
+SELECT IF(@@GLOBAL.innodb_force_load_corrupted, "ON", "OFF") = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='innodb_force_load_corrupted';
+--echo 1 Expected
+
+SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted);
+--echo 1 Expected
+
+SELECT COUNT(VARIABLE_VALUE)
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='innodb_force_load_corrupted';
+--echo 1 Expected
+
+
+
+--echo '#---------------------BS_STVARS_031_04----------------------#'
+################################################################################
+# Check if accessing variable with and without GLOBAL point to same variable #
+################################################################################
+SELECT @@innodb_force_load_corrupted = @@GLOBAL.innodb_force_load_corrupted;
+--echo 1 Expected
+
+
+
+--echo '#---------------------BS_STVARS_031_05----------------------#'
+################################################################################
+# Check if innodb_force_load_corrupted can be accessed with and without @@ sign #
+################################################################################
+
+SELECT COUNT(@@innodb_force_load_corrupted);
+--echo 1 Expected
+
+--Error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT COUNT(@@local.innodb_force_load_corrupted);
+--echo Expected error 'Variable is a GLOBAL variable'
+
+--Error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT COUNT(@@SESSION.innodb_force_load_corrupted);
+--echo Expected error 'Variable is a GLOBAL variable'
+
+SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted);
+--echo 1 Expected
+
+--Error ER_BAD_FIELD_ERROR
+SELECT innodb_force_load_corrupted = @@SESSION.innodb_force_load_corrupted;
+--echo Expected error 'Readonly variable'
+
+
diff --git a/mysql-test/suite/sys_vars/t/innodb_io_capacity_basic.test b/mysql-test/suite/sys_vars/t/innodb_io_capacity_basic.test
index 3f00b50cf08..0ced5800d4b 100644
--- a/mysql-test/suite/sys_vars/t/innodb_io_capacity_basic.test
+++ b/mysql-test/suite/sys_vars/t/innodb_io_capacity_basic.test
@@ -54,5 +54,9 @@ select * from information_schema.global_variables where variable_name='innodb_io
set global innodb_io_capacity=100;
select @@global.innodb_io_capacity;
+#
+# cleanup
+#
+
SET @@global.innodb_io_capacity = @start_global_value;
SELECT @@global.innodb_io_capacity;
diff --git a/mysql-test/suite/sys_vars/t/innodb_large_prefix_basic.test b/mysql-test/suite/sys_vars/t/innodb_large_prefix_basic.test
new file mode 100644
index 00000000000..582e9ffbee8
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/innodb_large_prefix_basic.test
@@ -0,0 +1,70 @@
+
+
+# 2010-01-25 - Added
+#
+
+--source include/have_innodb.inc
+
+SET @start_global_value = @@global.innodb_large_prefix;
+SELECT @start_global_value;
+
+#
+# exists as global only
+#
+--echo Valid values are 'ON' and 'OFF'
+select @@global.innodb_large_prefix in (0, 1);
+select @@global.innodb_large_prefix;
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+select @@session.innodb_large_prefix;
+show global variables like 'innodb_large_prefix';
+show session variables like 'innodb_large_prefix';
+select * from information_schema.global_variables where variable_name='innodb_large_prefix';
+select * from information_schema.session_variables where variable_name='innodb_large_prefix';
+
+#
+# show that it's writable
+#
+set global innodb_large_prefix='OFF';
+select @@global.innodb_large_prefix;
+select * from information_schema.global_variables where variable_name='innodb_large_prefix';
+select * from information_schema.session_variables where variable_name='innodb_large_prefix';
+set @@global.innodb_large_prefix=1;
+select @@global.innodb_large_prefix;
+select * from information_schema.global_variables where variable_name='innodb_large_prefix';
+select * from information_schema.session_variables where variable_name='innodb_large_prefix';
+set global innodb_large_prefix=0;
+select @@global.innodb_large_prefix;
+select * from information_schema.global_variables where variable_name='innodb_large_prefix';
+select * from information_schema.session_variables where variable_name='innodb_large_prefix';
+set @@global.innodb_large_prefix='ON';
+select @@global.innodb_large_prefix;
+select * from information_schema.global_variables where variable_name='innodb_large_prefix';
+select * from information_schema.session_variables where variable_name='innodb_large_prefix';
+--error ER_GLOBAL_VARIABLE
+set session innodb_large_prefix='OFF';
+--error ER_GLOBAL_VARIABLE
+set @@session.innodb_large_prefix='ON';
+
+#
+# incorrect types
+#
+--error ER_WRONG_TYPE_FOR_VAR
+set global innodb_large_prefix=1.1;
+--error ER_WRONG_TYPE_FOR_VAR
+set global innodb_large_prefix=1e1;
+--error ER_WRONG_VALUE_FOR_VAR
+set global innodb_large_prefix=2;
+--echo NOTE: The following should fail with ER_WRONG_VALUE_FOR_VAR (BUG#50643)
+set global innodb_large_prefix=-3;
+select @@global.innodb_large_prefix;
+select * from information_schema.global_variables where variable_name='innodb_large_prefix';
+select * from information_schema.session_variables where variable_name='innodb_large_prefix';
+--error ER_WRONG_VALUE_FOR_VAR
+set global innodb_large_prefix='AUTO';
+
+#
+# Cleanup
+#
+
+SET @@global.innodb_large_prefix = @start_global_value;
+SELECT @@global.innodb_large_prefix;
diff --git a/mysql-test/suite/sys_vars/t/innodb_lock_wait_timeout_basic.test b/mysql-test/suite/sys_vars/t/innodb_lock_wait_timeout_basic.test
index 8cfd23fd6e7..f80b8e48736 100644
--- a/mysql-test/suite/sys_vars/t/innodb_lock_wait_timeout_basic.test
+++ b/mysql-test/suite/sys_vars/t/innodb_lock_wait_timeout_basic.test
@@ -3,13 +3,13 @@
################## mysql-test\t\innodb_lock_wait_timeout_basic.test ###########
# #
# Variable Name: innodb_lock_wait_timeout #
-# Scope: Global #
-# Access Type: Static #
+# Scope: Global , Session #
+# Access Type: Dynamic #
# Data Type: numeric #
# #
# #
# Creation Date: 2008-02-07 #
-# Author : Sharique Abdullah #
+# Author : Sharique Abdullah #
# #
# #
# Description:Test Cases of Dynamic System Variable innodb_lock_wait_timeout #
@@ -24,6 +24,9 @@
--source include/have_innodb.inc
+SET @start_global_value=@@global.innodb_lock_wait_timeout;
+SELECT @start_global_value;
+
--echo '#---------------------BS_STVARS_032_01----------------------#'
####################################################################
# Displaying default value #
@@ -37,11 +40,10 @@ SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
# Check if Value can set #
####################################################################
-SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
---echo 1 Expected
-
-
-
+SET global innodb_lock_wait_timeout=60;
+SELECT @@global.innodb_lock_wait_timeout;
+SET session innodb_lock_wait_timeout=60;
+SELECT @@session.innodb_lock_wait_timeout;
--echo '#---------------------BS_STVARS_032_03----------------------#'
#################################################################
@@ -89,6 +91,10 @@ SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
--Error ER_BAD_FIELD_ERROR
SELECT innodb_lock_wait_timeout = @@SESSION.innodb_lock_wait_timeout;
---echo Expected error 'Readonly variable'
+#
+# Cleanup
+#
+SET @@global.innodb_lock_wait_timeout = @start_global_value;
+SELECT @@global.innodb_lock_wait_timeout;
diff --git a/mysql-test/suite/sys_vars/t/innodb_max_dirty_pages_pct_basic.test b/mysql-test/suite/sys_vars/t/innodb_max_dirty_pages_pct_basic.test
index 38c3acd92a2..7e70ed11351 100644
--- a/mysql-test/suite/sys_vars/t/innodb_max_dirty_pages_pct_basic.test
+++ b/mysql-test/suite/sys_vars/t/innodb_max_dirty_pages_pct_basic.test
@@ -4,8 +4,8 @@
# Scope: GLOBAL #
# Access Type: Dynamic #
# Data Type: Numeric #
-# Default Value: 90 #
-# Range: 0-1000 #
+# Default Value: 75 #
+# Range: 0-99 #
# #
# #
# Creation Date: 2008-02-07 #
diff --git a/mysql-test/suite/sys_vars/t/plugin_dir_basic-master.opt b/mysql-test/suite/sys_vars/t/plugin_dir_basic-master.opt
new file mode 100644
index 00000000000..69a9f0def2a
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/plugin_dir_basic-master.opt
@@ -0,0 +1 @@
+--plugin-dir=$MYSQL_TMP_DIR
diff --git a/mysql-test/suite/sys_vars/t/plugin_dir_basic.test b/mysql-test/suite/sys_vars/t/plugin_dir_basic.test
index d714950c807..59889f7ecb2 100644
--- a/mysql-test/suite/sys_vars/t/plugin_dir_basic.test
+++ b/mysql-test/suite/sys_vars/t/plugin_dir_basic.test
@@ -3,20 +3,20 @@
#
#
-# on windows it's <basedir>/lib/plugin
-# on unix it's <basedir>/lib/mysql/plugin
+# Don't rely on being able to guess the correct default.
+# -master.opt file for this test sets plugin_dir to a known directory
#
---replace_result $MYSQL_LIBDIR MYSQL_LIBDIR /mysql/ /
+--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR /mysql/ /
select @@global.plugin_dir;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
select @@session.plugin_dir;
---replace_result $MYSQL_LIBDIR MYSQL_LIBDIR /mysql/ /
+--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR /mysql/ /
show global variables like 'plugin_dir';
---replace_result $MYSQL_LIBDIR MYSQL_LIBDIR /mysql/ /
+--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR /mysql/ /
show session variables like 'plugin_dir';
---replace_result $MYSQL_LIBDIR MYSQL_LIBDIR /mysql/ /
+--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR /mysql/ /
select * from information_schema.global_variables where variable_name='plugin_dir';
---replace_result $MYSQL_LIBDIR MYSQL_LIBDIR /mysql/ /
+--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR /mysql/ /
select * from information_schema.session_variables where variable_name='plugin_dir';
#
diff --git a/mysql-test/t/auth_rpl-master.opt b/mysql-test/t/auth_rpl-master.opt
new file mode 100644
index 00000000000..3536d102387
--- /dev/null
+++ b/mysql-test/t/auth_rpl-master.opt
@@ -0,0 +1,2 @@
+$PLUGIN_AUTH_OPT
+$PLUGIN_AUTH_LOAD
diff --git a/mysql-test/t/auth_rpl-slave.opt b/mysql-test/t/auth_rpl-slave.opt
new file mode 100644
index 00000000000..3f4af6e59bb
--- /dev/null
+++ b/mysql-test/t/auth_rpl-slave.opt
@@ -0,0 +1,4 @@
+--master-retry-count=1
+$PLUGIN_AUTH_OPT
+$PLUGIN_AUTH_LOAD
+
diff --git a/mysql-test/t/auth_rpl.test b/mysql-test/t/auth_rpl.test
new file mode 100644
index 00000000000..c413a84b53c
--- /dev/null
+++ b/mysql-test/t/auth_rpl.test
@@ -0,0 +1,66 @@
+--source include/have_plugin_auth.inc
+--source include/not_embedded.inc
+--source include/master-slave.inc
+
+#
+# Check that replication slave can connect to master using an account
+# which authenticates with an external authentication plugin (bug#12897501).
+
+#
+# First stop the slave to guarantee that nothing is replicated.
+#
+--connection slave
+--echo [connection slave]
+--source include/stop_slave.inc
+#
+# Create an replication account on the master.
+#
+--connection master
+--echo [connection master]
+CREATE USER 'plug_user' IDENTIFIED WITH 'test_plugin_server' AS 'plug_user';
+GRANT REPLICATION SLAVE ON *.* TO plug_user;
+FLUSH PRIVILEGES;
+
+#
+# Now go to slave and change the replication user.
+#
+--connection slave
+--echo [connection slave]
+--let $master_user= query_get_value(SHOW SLAVE STATUS, Master_User, 1)
+CHANGE MASTER TO
+ MASTER_USER= 'plug_user',
+ MASTER_PASSWORD= 'plug_user';
+
+#
+# Start slave with new replication account - this should trigger connection
+# to the master server.
+#
+--source include/start_slave.inc
+
+# Replicate all statements executed on master, in this case,
+# (creation of the plug_user account).
+#
+--connection master
+--sync_slave_with_master
+--echo # Slave in-sync with master now.
+
+SELECT user, plugin, authentication_string FROM mysql.user WHERE user LIKE 'plug_user';
+
+#
+# Now we can stop the slave and clean up.
+#
+# Note: it is important that slave is stopped at this
+# moment - otherwise master's cleanup statements
+# would be replicated on slave!
+#
+--echo # Cleanup (on slave).
+--source include/stop_slave.inc
+eval CHANGE MASTER TO MASTER_USER='$master_user';
+DROP USER 'plug_user';
+
+--echo # Cleanup (on master).
+--connection master
+DROP USER 'plug_user';
+
+--let $rpl_only_running_threads= 1
+--source include/rpl_end.inc
diff --git a/mysql-test/t/execution_constants.test b/mysql-test/t/execution_constants.test
index 92b1deb9921..285197cd1f4 100644
--- a/mysql-test/t/execution_constants.test
+++ b/mysql-test/t/execution_constants.test
@@ -38,7 +38,7 @@ while ($i)
{
# If we SEGV because the min stack size is exceeded, this would return error
# 2013 .
- error 0,1436 //
+ error 0,ER_STACK_OVERRUN_NEED_MORE //
eval $query_head 0 $query_tail//
if ($mysql_errno)
@@ -48,10 +48,10 @@ while ($i)
# limit, we still have enough space reserved to report an error.
let $i = 1//
- # Check that mysql_errno is 1436
- if ($mysql_errno != 1436)
+ # Check that mysql_errname is ER_STACK_OVERRUN_NEED_MORE
+ if ($mysql_errname != ER_STACK_OVERRUN_NEED_MORE)
{
- die Wrong error triggered, expected 1436 but got $mysql_errno//
+ die Wrong error triggered, expected ER_STACK_OVERRUN_NEED_MORE but got $mysql_errname//
}
}
@@ -76,7 +76,7 @@ while ($i)
enable_result_log//
enable_query_log//
-echo Assertion: mysql_errno 1436 == $mysql_errno//
+echo Assertion: mysql_errname ER_STACK_OVERRUN_NEED_MORE == $mysql_errname//
delimiter ;//
DROP TABLE `t_bug21476`;
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index 9a9a8110a74..2a14648d6f6 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -1437,5 +1437,24 @@ SELECT * FROM t1;
DROP TABLE t1;
--echo #
+--echo # Bug#12985030 SIMPLE QUERY WITH DECIMAL NUMBERS LEAKS MEMORY
+--echo #
+
+SELECT (rpad(1.0,2048,1)) IS NOT FALSE;
+SELECT ((+0) IN
+((0b111111111111111111111111111111111111111111111111111),(rpad(1.0,2048,1)),
+(32767.1)));
+SELECT ((rpad(1.0,2048,1)) = ('4(') ^ (0.1));
+
+--error 1690
+SELECT
+pow((rpad(1.0,2048,1)),(b'1111111111111111111111111111111111111111111'));
+SELECT ((rpad(1.0,2048,1)) + (0) ^ ('../'));
+SELECT stddev_samp(rpad(1.0,2048,1));
+SELECT ((127.1) not in ((rpad(1.0,2048,1)),(''),(-1.1)));
+SELECT ((0xf3) * (rpad(1.0,2048,1)) << (0xcc));
+
+
+--echo #
--echo # End of 5.5 tests
--echo #
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index 0c2da4ae9f4..18034da9a4c 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -1284,6 +1284,20 @@ FROM t1 GROUP BY a;
DROP TABLE t1;
+--echo #
+--echo # Bug#11765254 (58200): Assertion failed: param.sort_length when grouping
+--echo # by functions
+--echo #
+
+SET SQL_BIG_TABLES=1;
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES (0),(0);
+SELECT 1 FROM t1 GROUP BY IF(`a`,'','');
+SELECT 1 FROM t1 GROUP BY TRIM(LEADING RAND() FROM '');
+SELECT 1 FROM t1 GROUP BY SUBSTRING('',SLEEP(0),'');
+SELECT 1 FROM t1 GROUP BY SUBSTRING(SYSDATE() FROM 'K' FOR 'jxW<');
+DROP TABLE t1;
+SET SQL_BIG_TABLES=0;
--echo # End of 5.1 tests
diff --git a/mysql-test/t/myisampack.test b/mysql-test/t/myisampack.test
index 463aa559de2..e0edcab6df7 100644
--- a/mysql-test/t/myisampack.test
+++ b/mysql-test/t/myisampack.test
@@ -221,3 +221,47 @@ DROP TABLE t1,t2,t3;
DROP TABLE mysql_db1.t1;
DROP DATABASE mysql_db1;
+--echo #
+--echo # BUG#11761180 - 53646: MYISAMPACK CORRUPTS TABLES WITH FULLTEXT INDEXES
+--echo #
+CREATE TABLE t1(a CHAR(4), FULLTEXT(a));
+INSERT INTO t1 VALUES('aaaa'),('bbbb'),('cccc');
+FLUSH TABLE t1;
+--exec $MYISAMPACK -sf $MYSQLD_DATADIR/test/t1
+--exec $MYISAMCHK -srq $MYSQLD_DATADIR/test/t1
+CHECK TABLE t1;
+SELECT * FROM t1 WHERE MATCH(a) AGAINST('aaaa' IN BOOLEAN MODE);
+SELECT * FROM t1 WHERE MATCH(a) AGAINST('aaaa');
+DROP TABLE t1;
+
+--echo # Test table with key_reflength > rec_reflength
+CREATE TABLE t1(a CHAR(30), FULLTEXT(a));
+--disable_query_log
+--echo # Populating a table, so it's index file exceeds 65K
+let $1=1700;
+while ($1)
+{
+ eval INSERT INTO t1 VALUES('$1aaaaaaaaaaaaaaaaaaaaaaaaaa');
+ dec $1;
+}
+
+--echo # Populating a table, so index file has second level fulltext tree
+let $1=60;
+while ($1)
+{
+ eval INSERT INTO t1 VALUES('aaaa'),('aaaa'),('aaaa'),('aaaa'),('aaaa');
+ dec $1;
+}
+--enable_query_log
+
+FLUSH TABLE t1;
+--echo # Compressing table
+--exec $MYISAMPACK -sf $MYSQLD_DATADIR/test/t1
+--echo # Fixing index (repair by sort)
+--exec $MYISAMCHK -srnq $MYSQLD_DATADIR/test/t1
+CHECK TABLE t1;
+FLUSH TABLE t1;
+--echo # Fixing index (repair with keycache)
+--exec $MYISAMCHK -soq $MYSQLD_DATADIR/test/t1
+CHECK TABLE t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test
index 9ff92496653..9fa41b9eb51 100644
--- a/mysql-test/t/mysqltest.test
+++ b/mysql-test/t/mysqltest.test
@@ -1,3 +1,14 @@
+# ----------------------------------------------------------------------------
+# $mysql_errno contains the return code of the last command
+# sent to the server.
+# ----------------------------------------------------------------------------
+# get $mysql_errno before the first statement
+# $mysql_errno should be -1
+# get $mysql_errname as well
+
+echo $mysql_errno before test;
+echo $mysql_errname before test;
+
-- source include/have_log_bin.inc
# This test should work in embedded server after mysqltest is fixed
@@ -34,15 +45,6 @@
# ============================================================================
# ----------------------------------------------------------------------------
-# $mysql_errno contains the return code of the last command
-# sent to the server.
-# ----------------------------------------------------------------------------
-# get $mysql_errno before the first statement
-# $mysql_errno should be -1
-eval select $mysql_errno as "before_use_test" ;
-
-
-# ----------------------------------------------------------------------------
# Positive case(statement)
# ----------------------------------------------------------------------------
@@ -134,6 +136,7 @@ select friedrich from (select 1 as otto) as t1;
# check mysql_errno = 0 after successful statement
# ----------------------------------------------------------------------------
select otto from (select 1 as otto) as t1;
+echo $mysql_errname;
eval select $mysql_errno as "after_successful_stmt_errno" ;
#----------------------------------------------------------------------------
@@ -142,6 +145,7 @@ eval select $mysql_errno as "after_successful_stmt_errno" ;
--error ER_PARSE_ERROR
garbage ;
+echo $mysql_errname;
eval select $mysql_errno as "after_wrong_syntax_errno" ;
# ----------------------------------------------------------------------------
@@ -151,6 +155,7 @@ eval select $mysql_errno as "after_wrong_syntax_errno" ;
garbage ;
let $my_var= 'abc' ;
+echo $mysql_errname;
eval select $mysql_errno as "after_let_var_equal_value" ;
# ----------------------------------------------------------------------------
@@ -160,6 +165,7 @@ eval select $mysql_errno as "after_let_var_equal_value" ;
garbage ;
set @my_var= 'abc' ;
+echo $mysql_errname;
eval select $mysql_errno as "after_set_var_equal_value" ;
# ----------------------------------------------------------------------------
@@ -170,6 +176,7 @@ eval select $mysql_errno as "after_set_var_equal_value" ;
garbage ;
--disable_warnings
+echo $mysql_errname;
eval select $mysql_errno as "after_disable_warnings_command" ;
# ----------------------------------------------------------------------------
@@ -182,6 +189,7 @@ drop table if exists t1 ;
garbage ;
drop table if exists t1 ;
+echo $mysql_errname;
eval select $mysql_errno as "after_disable_warnings" ;
--enable_warnings
@@ -194,6 +202,7 @@ garbage ;
--error ER_NO_SUCH_TABLE
select 3 from t1 ;
+echo $mysql_errname;
eval select $mysql_errno as "after_minus_masked" ;
--error ER_PARSE_ERROR
@@ -201,6 +210,7 @@ garbage ;
--error ER_NO_SUCH_TABLE
select 3 from t1 ;
+echo $mysql_errname;
eval select $mysql_errno as "after_!_masked" ;
# ----------------------------------------------------------------------------
@@ -222,6 +232,7 @@ garbage ;
--error ER_NO_SUCH_TABLE
prepare stmt from "select 3 from t1" ;
+echo $mysql_errname;
eval select $mysql_errno as "after_failing_prepare" ;
create table t1 ( f1 char(10));
@@ -230,6 +241,7 @@ create table t1 ( f1 char(10));
garbage ;
prepare stmt from "select 3 from t1" ;
+echo $mysql_errname;
eval select $mysql_errno as "after_successful_prepare" ;
# successful execute
@@ -237,6 +249,7 @@ eval select $mysql_errno as "after_successful_prepare" ;
garbage ;
execute stmt;
+echo $mysql_errname;
eval select $mysql_errno as "after_successful_execute" ;
# failing execute (table has been dropped)
@@ -247,6 +260,7 @@ garbage ;
--error ER_NO_SUCH_TABLE
execute stmt;
+echo $mysql_errname;
eval select $mysql_errno as "after_failing_execute" ;
# failing execute (unknown statement)
@@ -256,6 +270,7 @@ garbage ;
--error ER_UNKNOWN_STMT_HANDLER
execute __stmt_;
+echo $mysql_errname;
eval select $mysql_errno as "after_failing_execute" ;
# successful deallocate
@@ -263,6 +278,7 @@ eval select $mysql_errno as "after_failing_execute" ;
garbage ;
deallocate prepare stmt;
+echo $mysql_errname;
eval select $mysql_errno as "after_successful_deallocate" ;
# failing deallocate ( statement handle does not exist )
@@ -272,6 +288,7 @@ garbage ;
--error ER_UNKNOWN_STMT_HANDLER
deallocate prepare __stmt_;
+echo $mysql_errname;
eval select $mysql_errno as "after_failing_deallocate" ;
@@ -299,6 +316,7 @@ eval select $mysql_errno as "after_failing_deallocate" ;
garbage ;
--disable_abort_on_error
+echo $mysql_errname;
eval select $mysql_errno as "after_--disable_abort_on_error" ;
# ----------------------------------------------------------------------------
@@ -316,6 +334,7 @@ select 3 from t1 ;
--error ER_NO_SUCH_TABLE
select 3 from t1 ;
+echo $mysql_errname;
eval select $mysql_errno as "after_!errno_masked_error" ;
# expected error <> response
# --error 1000
@@ -341,6 +360,7 @@ EOF
garbage ;
--enable_abort_on_error
+echo $mysql_errname;
eval select $mysql_errno as "after_--enable_abort_on_error" ;
# ----------------------------------------------------------------------------
diff --git a/mysql-test/t/sp_trans.test b/mysql-test/t/sp_trans.test
index c114d397e43..39ac086071b 100644
--- a/mysql-test/t/sp_trans.test
+++ b/mysql-test/t/sp_trans.test
@@ -598,6 +598,39 @@ select distinct f1, bug13575(f1) from t3 order by f1|
drop function bug13575|
drop table t3|
+#
+# BUG#11758414: Default storage_engine not honored when set
+# from within a stored procedure
+#
+SELECT @@GLOBAL.storage_engine INTO @old_engine|
+SET @@GLOBAL.storage_engine=InnoDB|
+SET @@SESSION.storage_engine=InnoDB|
+# show defaults at define-time
+SHOW GLOBAL VARIABLES LIKE 'storage_engine'|
+SHOW SESSION VARIABLES LIKE 'storage_engine'|
+CREATE PROCEDURE bug11758414()
+BEGIN
+ SET @@GLOBAL.storage_engine="MyISAM";
+ SET @@SESSION.storage_engine="MyISAM";
+ # show defaults at execution time / that setting them worked
+ SHOW GLOBAL VARIABLES LIKE 'storage_engine';
+ SHOW SESSION VARIABLES LIKE 'storage_engine';
+ CREATE TABLE t1 (id int);
+ CREATE TABLE t2 (id int) ENGINE=InnoDB;
+ # show we're heeding the default (at run-time, not parse-time!)
+ SHOW CREATE TABLE t1;
+ # show that we didn't break explicit override with ENGINE=...
+ SHOW CREATE TABLE t2;
+END;
+|
+CALL bug11758414|
+# show that changing defaults within SP stuck
+SHOW GLOBAL VARIABLES LIKE 'storage_engine'|
+SHOW SESSION VARIABLES LIKE 'storage_engine'|
+DROP PROCEDURE bug11758414|
+DROP TABLE t1, t2|
+SET @@GLOBAL.storage_engine=@old_engine|
+
--echo #
--echo # End of 5.1 tests
--echo #
diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test
index f1eeabbd924..4f4b1962cc3 100644
--- a/mysql-test/t/type_newdecimal.test
+++ b/mysql-test/t/type_newdecimal.test
@@ -1535,3 +1535,17 @@ DROP TABLE IF EXISTS t1;
--echo End of 5.1 tests
+
+--echo #
+--echo # BUG#12911710 - VALGRIND FAILURE IN
+--echo # ROW-DEBUG:PERFSCHEMA.SOCKET_SUMMARY_BY_INSTANCE_FUNC
+--echo #
+
+CREATE TABLE t1(d1 DECIMAL(60,0) NOT NULL,
+ d2 DECIMAL(60,0) NOT NULL);
+
+INSERT INTO t1 (d1, d2) VALUES(0.0, 0.0);
+SELECT d1 * d2 FROM t1;
+
+DROP TABLE t1;
+
diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp
index b2cb4b0dd3e..0ea50c92985 100644
--- a/mysql-test/valgrind.supp
+++ b/mysql-test/valgrind.supp
@@ -876,3 +876,46 @@
fun:buf_buddy_free_low
fun:buf_buddy_free
}
+
+# Note the wildcard in the (mangled) function signatures of
+# write_keys() and find_all_keys().
+# They both return ha_rows, which is platform dependent.
+#
+# The '...' wildcards are for 'fun:inline_mysql_file_write' which *may*
+# be inlined.
+{
+ Bug#12856915 VALGRIND FAILURE IN FILESORT/CREATE_SORT_INDEX / one
+ Memcheck:Param
+ write(buf)
+ obj:*/libpthread*.so
+ fun:my_write
+ ...
+ fun:my_b_flush_io_cache
+ fun:_my_b_write
+ fun:_Z*10write_keysP13st_sort_paramPPhjP11st_io_cacheS4_
+ fun:_Z*13find_all_keysP13st_sort_paramP10SQL_SELECTPPhP11st_io_cacheS6_S6_
+ fun:_Z8filesortP3THDP5TABLEP13st_sort_fieldjP10SQL_SELECTybPy
+}
+
+{
+ Bug#12856915 VALGRIND FAILURE IN FILESORT/CREATE_SORT_INDEX / two
+ Memcheck:Param
+ write(buf)
+ obj:*/libpthread*.so
+ fun:my_write
+ ...
+ fun:my_b_flush_io_cache
+ fun:_Z15merge_many_buffP13st_sort_paramPhP10st_buffpekPjP11st_io_cache
+ fun:_Z8filesortP3THDP5TABLEP13st_sort_fieldjP10SQL_SELECTybPy
+}
+
+{
+ Bug#12856915 VALGRIND FAILURE IN FILESORT/CREATE_SORT_INDEX / three
+ Memcheck:Param
+ write(buf)
+ obj:*/libpthread*.so
+ fun:my_write
+ ...
+ fun:my_b_flush_io_cache
+ fun:_Z8filesortP3THDP5TABLEP13st_sort_fieldjP10SQL_SELECTybPy
+}
diff --git a/mysys/my_handler_errors.h b/mysys/my_handler_errors.h
index 3bd83398e81..3533b633960 100644
--- a/mysys/my_handler_errors.h
+++ b/mysys/my_handler_errors.h
@@ -81,7 +81,9 @@ static const char *handler_error_messages[]=
"File to short; Expected more data in file",
"Read page with wrong checksum",
"Too many active concurrent transactions",
- "Index column length exceeds limit"
+ "Index column length exceeds limit",
+ "Index corrupted",
+ "Undo record too big"
};
extern void my_handler_error_register(void);
diff --git a/plugin/semisync/semisync_master.cc b/plugin/semisync/semisync_master.cc
index 1f92c60913e..1be876d0f1b 100644
--- a/plugin/semisync/semisync_master.cc
+++ b/plugin/semisync/semisync_master.cc
@@ -312,18 +312,18 @@ int ActiveTranx::clear_active_tranx_nodes(const char *log_file_name,
* The most important functions during semi-syn replication listed:
*
* Master:
- * . reportReplyBinlog(): called by the binlog dump thread when it receives
- * the slave's status information.
- * . updateSyncHeader(): based on transaction waiting information, decide
- * whether to request the slave to reply.
- * . writeTraxInBinlog(): called by the transaction thread when it finishes
- * writing all transaction events in binlog.
- * . commitTrx(): transaction thread wait for the slave reply.
+ * . reportReplyBinlog(): called by the binlog dump thread when it receives
+ * the slave's status information.
+ * . updateSyncHeader(): based on transaction waiting information, decide
+ * whether to request the slave to reply.
+ * . writeTranxInBinlog(): called by the transaction thread when it finishes
+ * writing all transaction events in binlog.
+ * . commitTrx(): transaction thread wait for the slave reply.
*
* Slave:
* . slaveReadSyncHeader(): read the semi-sync header from the master, get the
- * sync status and get the payload for events.
- * . slaveReply(): reply to the master about the replication progress.
+ * sync status and get the payload for events.
+ * . slaveReply(): reply to the master about the replication progress.
*
******************************************************************************/
diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt
index 56b7f779bb0..424d92e31e1 100644
--- a/scripts/CMakeLists.txt
+++ b/scripts/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 2011, 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
@@ -65,7 +65,7 @@ ADD_CUSTOM_TARGET(GenFixPrivs
IF(UNIX)
FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/make_binary_distribution
- "cd ${CMAKE_BINARY_DIR} && '${CMAKE_CPACK_COMMAND}' -G TGZ --config CPackConfig.cmake" )
+ "cd ${CMAKE_BINARY_DIR} && '${CMAKE_CPACK_COMMAND}' -G TGZ --config CPackConfig.cmake\n" )
EXECUTE_PROCESS(
COMMAND chmod +x ${CMAKE_CURRENT_BINARY_DIR}/make_binary_distribution
)
@@ -104,11 +104,11 @@ IF(UNIX)
# FIND_PROC and CHECK_PID are used by mysqld_safe
IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
SET (FIND_PROC
- "ps wwwp $PID | grep -v \" grep\" | grep -v mysqld_safe | grep -- \"$MYSQLD\" > /dev/null")
+ "ps wwwp $PID | grep -v mysqld_safe | grep -- $MYSQLD > /dev/null")
ENDIF()
IF(NOT FIND_PROC AND CMAKE_SYSTEM_NAME MATCHES "SunOS")
SET (FIND_PROC
- "ps -p $PID | grep -v \" grep\" | grep -v mysqld_safe | grep -- \"$MYSQLD\" > /dev/null")
+ "ps -p $PID | grep -v mysqld_safe | grep -- $MYSQLD > /dev/null")
ENDIF()
IF(NOT FIND_PROC)
@@ -116,7 +116,7 @@ IF(NOT FIND_PROC)
EXECUTE_PROCESS(COMMAND ps -uaxww OUTPUT_QUIET ERROR_QUIET RESULT_VARIABLE result)
IF(result MATCHES 0)
SET( FIND_PROC
- "ps -uaxww | grep -v \" grep\" | grep -v mysqld_safe | grep -- \"$MYSQLD\" | grep \" $PID \" > /dev/null")
+ "ps -uaxww | grep -v mysqld_safe | grep -- $MYSQLD | grep $PID > /dev/null")
ENDIF()
ENDIF()
@@ -124,7 +124,7 @@ IF(NOT FIND_PROC)
# SysV style
EXECUTE_PROCESS(COMMAND ps -ef OUTPUT_QUIET ERROR_QUIET RESULT_VARIABLE result)
IF(result MATCHES 0)
- SET( FIND_PROC "ps -ef | grep -v \" grep\" | grep -v mysqld_safe | grep -- \"$MYSQLD\" | grep \" $PID \" > /dev/null")
+ SET( FIND_PROC "ps -ef | grep -v mysqld_safe | grep -- $MYSQLD | grep $PID > /dev/null")
ENDIF()
ENDIF()
diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh
deleted file mode 100644
index 5ccdb2b914c..00000000000
--- a/scripts/make_binary_distribution.sh
+++ /dev/null
@@ -1,342 +0,0 @@
-#!/bin/sh
-# Copyright (c) 2000, 2011, 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-
-##############################################################################
-#
-# This is a script to create a TAR or ZIP binary distribution out of a
-# built source tree. The output file will be put at the top level of
-# the source tree, as "mysql-<vsn>....{tar.gz,zip}"
-#
-# Note that the structure created by this script is slightly different from
-# what a normal "make install" would produce. No extra "mysql" sub directory
-# will be created, i.e. no "$prefix/include/mysql", "$prefix/lib/mysql" or
-# "$prefix/share/mysql". This is because the build system explicitly calls
-# make with pkgdatadir=<datadir>, etc.
-#
-# In GNU make/automake terms
-#
-# "pkglibdir" is set to the same as "libdir"
-# "pkgincludedir" is set to the same as "includedir"
-# "pkgdatadir" is set to the same as "datadir"
-# "pkgplugindir" is set to "$pkglibdir/plugin"
-# "pkgsuppdir" is set to "@prefix@/support-files",
-# normally the same as "datadir"
-#
-# The temporary directory path given to "--tmp=<path>" has to be
-# absolute and with no spaces.
-#
-# Note that for best result, the original "make" should be done with
-# the same arguments as used for "make install" below, especially the
-# 'pkglibdir', as the RPATH should to be set correctly.
-#
-##############################################################################
-
-##############################################################################
-#
-# Read the command line arguments that control this script
-#
-##############################################################################
-
-machine=@MACHINE_TYPE@
-system=@SYSTEM_TYPE@
-SOURCE=`pwd`
-CP="cp -p"
-MV="mv"
-
-# There are platforms, notably OS X on Intel (x86 + x86_64),
-# for which "uname" does not provide sufficient information.
-# The value of CFLAGS as used during compilation is the most exact info
-# we can get - after all, we care about _what_ we built, not _where_ we did it.
-cflags="@CFLAGS@"
-
-STRIP=1 # Option ignored
-SILENT=0
-MALLOC_LIB=
-PLATFORM=""
-TMP=/tmp
-NEW_NAME="" # Final top directory and TAR package name
-SUFFIX=""
-SHORT_PRODUCT_TAG="" # If don't want server suffix in package name
-NDBCLUSTER="" # Option ignored
-
-for arg do
- case "$arg" in
- --tmp=*) TMP=`echo "$arg" | sed -e "s;--tmp=;;"` ;;
- --suffix=*) SUFFIX=`echo "$arg" | sed -e "s;--suffix=;;"` ;;
- --short-product-tag=*) SHORT_PRODUCT_TAG=`echo "$arg" | sed -e "s;--short-product-tag=;;"` ;;
- --inject-malloc-lib=*) MALLOC_LIB=`echo "$arg" | sed -e 's;^[^=]*=;;'` ;;
- --no-strip) STRIP=0 ;;
- --machine=*) machine=`echo "$arg" | sed -e "s;--machine=;;"` ;;
- --platform=*) PLATFORM=`echo "$arg" | sed -e "s;--platform=;;"` ;;
- --silent) SILENT=1 ;;
- --with-ndbcluster) NDBCLUSTER=1 ;;
- *)
- echo "Unknown argument '$arg'"
- exit 1
- ;;
- esac
-done
-
-# ----------------------------------------------------------------------
-# Adjust "system" output from "uname" to be more human readable
-# ----------------------------------------------------------------------
-
-if [ x"$PLATFORM" = x"" ] ; then
- # FIXME move this to the build tools
- # Remove vendor from $system
- system=`echo $system | sed -e 's/[a-z]*-\(.*\)/\1/g'`
-
- # Map OS names to "our" OS names (eg. darwin6.8 -> osx10.2)
- system=`echo $system | sed -e 's/darwin6.*/osx10.2/g'`
- system=`echo $system | sed -e 's/darwin7.*/osx10.3/g'`
- system=`echo $system | sed -e 's/darwin8.*/osx10.4/g'`
- system=`echo $system | sed -e 's/darwin9.*/osx10.5/g'`
- system=`echo $system | sed -e 's/\(aix4.3\).*/\1/g'`
- system=`echo $system | sed -e 's/\(aix5.1\).*/\1/g'`
- system=`echo $system | sed -e 's/\(aix5.2\).*/\1/g'`
- system=`echo $system | sed -e 's/\(aix5.3\).*/\1/g'`
- system=`echo $system | sed -e 's/osf5.1b/tru64/g'`
- system=`echo $system | sed -e 's/linux-gnu/linux/g'`
- system=`echo $system | sed -e 's/solaris2.\([0-9]*\)/solaris\1/g'`
- system=`echo $system | sed -e 's/sco3.2v\(.*\)/openserver\1/g'`
-fi
-
-# Get the "machine", which really is the CPU architecture (including the size).
-# The precedence is:
-# 1) use an explicit argument, if given;
-# 2) use platform-specific fixes, if there are any (see bug#37808);
-# 3) stay with the default (determined during "configure", using predefined macros).
-
-if [ x"$MACHINE" != x"" ] ; then
- machine=$MACHINE
-else
- case $system in
- osx* )
- # Extract "XYZ" from CFLAGS "... -arch XYZ ...", or empty!
- cflag_arch=`echo "$cflags" | sed -n -e 's=.* -arch \([^ ]*\) .*=\1=p'`
- case "$cflag_arch" in
- i386 ) case $system in
- osx10.4 ) machine=i686 ;; # Used a different naming
- * ) machine=x86 ;;
- esac ;;
- x86_64 ) machine=x86_64 ;;
- ppc ) ;; # No treatment needed with PPC
- ppc64 ) ;;
- * ) # No matching compiler flag? "--platform" is needed
- if [ x"$PLATFORM" != x"" ] ; then
- : # See below: "$PLATFORM" will take precedence anyway
- elif [ "$system" = "osx10.3" -a -z "$cflag_arch" ] ; then
- : # Special case of OS X 10.3, which is PPC-32 only and doesn't use "-arch"
- else
- echo "On system '$system' only specific '-arch' values are expected."
- echo "It is taken from the 'CFLAGS' whose value is:"
- echo "$cflags"
- echo "'-arch $cflag_arch' is unexpected, and no '--platform' was given: ABORT"
- exit 1
- fi ;;
- esac # "$cflag_arch"
- ;;
- esac # $system
-fi
-
-# Combine OS and CPU to the "platform". Again, an explicit argument takes precedence.
-if [ x"$PLATFORM" != x"" ] ; then
- :
-else
- PLATFORM="$system-$machine"
-fi
-
-# Print the platform name for build logs
-echo "PLATFORM NAME: $PLATFORM"
-
-# Change the distribution to a long descriptive name
-# For the cluster product, concentrate on the second part
-VERSION_NAME=@VERSION@
-case $VERSION_NAME in
- *-ndb-* ) VERSION_NAME=`echo $VERSION_NAME | sed -e 's/[.0-9]*-ndb-//'` ;;
-esac
-if [ x"$SHORT_PRODUCT_TAG" != x"" ] ; then
- NEW_NAME=mysql-$SHORT_PRODUCT_TAG-$VERSION_NAME-$PLATFORM$SUFFIX
-else
- NEW_NAME=mysql@MYSQL_SERVER_SUFFIX@-$VERSION_NAME-$PLATFORM$SUFFIX
-fi
-
-# ----------------------------------------------------------------------
-# Define BASE, and remove the old BASE directory if any
-# ----------------------------------------------------------------------
-BASE=$TMP/my_dist$SUFFIX
-if [ -d $BASE ] ; then
- rm -rf $BASE
-fi
-
-# ----------------------------------------------------------------------
-# Find the TAR to use
-# ----------------------------------------------------------------------
-
-# This is needed to prefer GNU tar over platform tar because that can't
-# always handle long filenames
-
-PATH_DIRS=`echo $PATH | \
- sed -e 's/^:/. /' -e 's/:$/ ./' -e 's/::/ . /g' -e 's/:/ /g' `
-
-which_1 ()
-{
- for cmd
- do
- for d in $PATH_DIRS
- do
- for file in $d/$cmd
- do
- if [ -x $file -a ! -d $file ] ; then
- echo $file
- exit 0
- fi
- done
- done
- done
- exit 1
-}
-
-tar=`which_1 gnutar gtar`
-if [ $? -ne 0 -o x"$tar" = x"" ] ; then
- tar=tar
-fi
-
-
-##############################################################################
-#
-# Handle the Unix/Linux packaging using "make install"
-#
-##############################################################################
-
-# ----------------------------------------------------------------------
-# Terminate on any base level error
-# ----------------------------------------------------------------------
-set -e
-
-# ----------------------------------------------------------------------
-# Really ugly, one script, "mysql_install_db", needs prefix set to ".",
-# i.e. makes access relative the current directory. This matches
-# the documentation, so better not change this. And for another script,
-# "mysql.server", we make some relative, others not.
-# ----------------------------------------------------------------------
-
-cd scripts
-rm -f mysql_install_db
-@MAKE@ mysql_install_db \
- prefix=. \
- bindir=./bin \
- sbindir=./bin \
- scriptdir=./bin \
- libexecdir=./bin \
- pkgdatadir=./share \
- localstatedir=./data
-cd ..
-
-cd support-files
-rm -f mysql.server
-@MAKE@ mysql.server \
- bindir=./bin \
- sbindir=./bin \
- scriptdir=./bin \
- libexecdir=./bin \
- pkgdatadir=@pkgdatadir@
-cd ..
-
-# ----------------------------------------------------------------------
-# Do a install that we later are to pack. Use the same paths as in
-# the build for the relevant directories.
-# ----------------------------------------------------------------------
-@MAKE@ DESTDIR=$BASE install \
- pkglibdir=@pkglibdir@ \
- pkgincludedir=@pkgincludedir@ \
- pkgdatadir=@pkgdatadir@ \
- pkgplugindir=@pkgplugindir@ \
- pkgsuppdir=@pkgsuppdir@ \
- mandir=@mandir@ \
- infodir=@infodir@
-
-# ----------------------------------------------------------------------
-# Rename top directory, and set DEST to the new directory
-# ----------------------------------------------------------------------
-mv $BASE@prefix@ $BASE/$NEW_NAME
-DEST=$BASE/$NEW_NAME
-
-# ----------------------------------------------------------------------
-# If we compiled with gcc, copy libgcc.a to the dist as libmygcc.a
-# ----------------------------------------------------------------------
-if [ x"@GXX@" = x"yes" ] ; then
- gcclib=`@CC@ @CFLAGS@ --print-libgcc-file 2>/dev/null` || true
- if [ -z "$gcclib" ] ; then
- echo "Warning: Compiler doesn't tell libgcc.a!"
- elif [ -f "$gcclib" ] ; then
- $CP $gcclib $DEST/lib/libmygcc.a
- else
- echo "Warning: Compiler result '$gcclib' not found / no file!"
- fi
-fi
-
-# If requested, add a malloc library .so into pkglibdir for use
-# by mysqld_safe
-if [ -n "$MALLOC_LIB" ]; then
- cp "$MALLOC_LIB" "$DEST/lib/"
-fi
-
-# FIXME let this script be in "bin/", where it is in the RPMs?
-# http://dev.mysql.com/doc/refman/5.1/en/mysql-install-db-problems.html
-mkdir $DEST/scripts
-mv $DEST/bin/mysql_install_db $DEST/scripts/
-
-# Note, no legacy "safe_mysqld" link to "mysqld_safe" in 5.1
-
-# Copy readme and license files
-cp README Docs/INSTALL-BINARY $DEST/
-if [ -f COPYING ] ; then
- cp COPYING $DEST/
-elif [ -f LICENSE.mysql ] ; then
- cp LICENSE.mysql $DEST/
-else
- echo "ERROR: no license files found"
- exit 1
-fi
-
-# FIXME should be handled by make file, and to other dir
-mkdir -p $DEST/bin $DEST/support-files
-cp scripts/mysqlaccess.conf $DEST/bin/
-cp support-files/magic $DEST/support-files/
-
-# Create empty data directories, set permission (FIXME why?)
-mkdir $DEST/data $DEST/data/mysql $DEST/data/test
-chmod o-rwx $DEST/data $DEST/data/mysql $DEST/data/test
-
-# ----------------------------------------------------------------------
-# Create the result tar file
-# ----------------------------------------------------------------------
-
-echo "Using $tar to create archive"
-OPT=cvf
-if [ x$SILENT = x1 ] ; then
- OPT=cf
-fi
-
-echo "Creating and compressing archive"
-rm -f $NEW_NAME.tar.gz
-(cd $BASE ; $tar $OPT - $NEW_NAME) | gzip -9 > $NEW_NAME.tar.gz
-echo "$NEW_NAME.tar.gz created"
-
-echo "Removing temporary directory"
-rm -rf $BASE
-exit 0
diff --git a/scripts/make_win_bin_dist b/scripts/make_win_bin_dist
deleted file mode 100755
index 00ef9186d48..00000000000
--- a/scripts/make_win_bin_dist
+++ /dev/null
@@ -1,425 +0,0 @@
-#!/bin/sh
-# Copyright (c) 2006, 2011, 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-
-# Exit if failing to copy, we want exact specifications, not
-# just "what happen to be built".
-set -e
-
-# ----------------------------------------------------------------------
-# Read first argument that is the base name of the resulting TAR file.
-# See usage() function below for a description on the arguments.
-#
-# NOTE: We will read the rest of the command line later on.
-# NOTE: Pattern matching with "{..,..}" can't be used, not portable.
-# ----------------------------------------------------------------------
-
-# FIXME why "libmysql.dll" installed both in "bin" and "lib/opt"?
-
-usage()
-{
- echo <<EOF
-Usage: make_win_bin_dist [ options ] package-base-name [ copy-defs... ]
-
-This is a script to run from the top of a source tree built on Windows.
-The "package-base-name" argument should be something like
-
- mysql-noinstall-5.0.25-win32 (or winx64)
-
-and will become the name of the directory of the unpacked ZIP (stripping
-away the "noinstall" part of the ZIP file name if any) and the base
-for the resulting package name.
-
-Options are
-
- --embedded Pack the embedded server and give error if not built.
- The default is to pack it if it is built.
-
- --no-embedded Don't pack the embedded server even if built
-
- --debug Pack the debug binaries and give error if not built.
- The default is to pack them if they are built.
-
- --no-debug Don't pack the debug binaries even if built
-
- --only-debug The target for this build was "Debug", and we just
- want to replace the normal binaries with debug
- versions, i.e. no separate "debug" directories.
-
- --exe-suffix=SUF Add a suffix to the filename part of the "mysqld" binary.
-
-As you might want to include files of directories from other builds
-(like a "mysqld-max.exe" server), you can instruct this script to copy
-them in for you. This is the "copy-def" arguments, and they are of the
-form
-
- relative-dest-name=source-name .....
-
-i.e. can be something like
-
- bin/mysqld-max.exe=../my-max-build/sql/release/mysqld.exe
-
-If you specify a directory the whole directory will be copied.
-
-EOF
- exit 1
-}
-
-# ----------------------------------------------------------------------
-# We need to be at the top of a source tree, check that we are
-# ----------------------------------------------------------------------
-
-if [ ! -d "sql" ] ; then
- echo "You need to run this script from inside the source tree"
- usage
-fi
-
-# ----------------------------------------------------------------------
-# Actual argument processing, first part
-# ----------------------------------------------------------------------
-
-NOINST_NAME=""
-TARGET="release"
-PACK_EMBEDDED="" # Could be "no", "yes" or empty
-PACK_DEBUG="" # Could be "no", "yes" or empty
-EXE_SUFFIX=""
-
-for arg do
- shift
- case "$arg" in
- --embedded) PACK_EMBEDDED="yes" ;;
- --no-embedded) PACK_EMBEDDED="no" ;;
- --debug) PACK_DEBUG="yes" ;;
- --no-debug) PACK_DEBUG="no" ;;
- --only-debug) TARGET="debug" ; PACK_DEBUG="no" ;;
- --exe-suffix=*) EXE_SUFFIX=`echo "$arg" | sed -e "s,--exe-suffix=,,"` ;;
- -*)
- echo "Unknown argument '$arg'"
- usage
- ;;
- *)
- NOINST_NAME="$arg"
- break
- esac
-done
-
-if [ x"$NOINST_NAME" = x"" ] ; then
- echo "No base package name given"
- usage
-fi
-DESTDIR=`echo $NOINST_NAME | sed 's/-noinstall-/-/'`
-
-if [ -e $DESTDIR ] ; then
- echo "Please remove the old $DESTDIR before running this script"
- usage
-fi
-
-trap 'echo "Cleaning up and exiting..." ; rm -fr $DESTDIR; exit 1' ERR
-
-# ----------------------------------------------------------------------
-# Adjust target name if needed, release with debug info has another name
-# ----------------------------------------------------------------------
-
-if [ x"$TARGET" = x"release" -a -f "client/relwithdebinfo/mysql.exe" ]
-then
- TARGET="relwithdebinfo"
-fi
-
-# ----------------------------------------------------------------------
-# Copy executables, and client DLL
-# ----------------------------------------------------------------------
-
-mkdir $DESTDIR
-mkdir $DESTDIR/bin
-cp client/$TARGET/*.exe $DESTDIR/bin/
-cp extra/$TARGET/*.exe $DESTDIR/bin/
-cp storage/myisam/$TARGET/*.exe $DESTDIR/bin/
-if [ x"$TARGET" != x"release" ] ; then
- cp client/$TARGET/mysql.pdb $DESTDIR/bin/
- cp client/$TARGET/mysqladmin.pdb $DESTDIR/bin/
- cp client/$TARGET/mysqlbinlog.pdb $DESTDIR/bin/
- cp client/$TARGET/mysqldump.pdb $DESTDIR/bin/
- cp client/$TARGET/mysqlimport.pdb $DESTDIR/bin/
- cp client/$TARGET/mysqlshow.pdb $DESTDIR/bin/
-fi
-cp tests/$TARGET/*.exe $DESTDIR/bin/
-cp libmysql/$TARGET/libmysql.dll $DESTDIR/bin/
-
-cp sql/$TARGET/mysqld.exe $DESTDIR/bin/mysqld$EXE_SUFFIX.exe
-if [ x"$TARGET" != x"release" ] ; then
- cp sql/$TARGET/mysqld.pdb $DESTDIR/bin/mysqld$EXE_SUFFIX.pdb
-fi
-
-if [ x"$PACK_DEBUG" = x"" -a -f "sql/debug/mysqld.exe" -o \
- x"$PACK_DEBUG" = x"yes" ] ; then
- cp sql/debug/mysqld.exe $DESTDIR/bin/mysqld-debug.exe
- cp sql/debug/mysqld.pdb $DESTDIR/bin/mysqld-debug.pdb
-fi
-
-# ----------------------------------------------------------------------
-# Copy data directory, readme files etc
-# ----------------------------------------------------------------------
-
-if [ -d win/data ] ; then
- cp -pR win/data $DESTDIR/
-fi
-
-mkdir $DESTDIR/Docs
-cp Docs/INSTALL-BINARY $DESTDIR/Docs/
-cp Docs/manual.chm $DESTDIR/Docs/ || /bin/true
-cp ChangeLog $DESTDIR/Docs/ || /bin/true
-cp support-files/my-*.ini $DESTDIR/
-cp README $DESTDIR/
-
-if [ -f COPYING ] ; then
- cp COPYING $DESTDIR/
- cp COPYING $DESTDIR/Docs/
-fi
-
-# ----------------------------------------------------------------------
-# These will be filled in when we enable embedded. Note that if no
-# argument is given, it is copied if exists, else a check is done.
-# ----------------------------------------------------------------------
-
-copy_embedded()
-{
- mkdir -p $DESTDIR/Embedded/DLL/release \
- $DESTDIR/Embedded/static/release \
- $DESTDIR/include
- cp libmysqld/libmysqld.def $DESTDIR/include/
- cp libmysqld/$TARGET/mysqlserver.lib $DESTDIR/Embedded/static/release/
- cp libmysqld/$TARGET/libmysqld.dll $DESTDIR/Embedded/DLL/release/
- cp libmysqld/$TARGET/libmysqld.exp $DESTDIR/Embedded/DLL/release/
- cp libmysqld/$TARGET/libmysqld.lib $DESTDIR/Embedded/DLL/release/
- if [ x"$TARGET" != x"release" ] ; then
- cp libmysqld/$TARGET/mysqlserver.pdb $DESTDIR/Embedded/static/release/
- cp libmysqld/$TARGET/libmysqld.pdb $DESTDIR/Embedded/DLL/release/
- fi
-
- if [ x"$PACK_DEBUG" = x"" -a -f "libmysqld/debug/libmysqld.lib" -o \
- x"$PACK_DEBUG" = x"yes" ] ; then
- mkdir -p $DESTDIR/Embedded/DLL/debug \
- $DESTDIR/Embedded/static/debug
- cp libmysqld/debug/mysqlserver.lib $DESTDIR/Embedded/static/debug/
- cp libmysqld/debug/mysqlserver.pdb $DESTDIR/Embedded/static/debug/
- cp libmysqld/debug/libmysqld.dll $DESTDIR/Embedded/DLL/debug/
- cp libmysqld/debug/libmysqld.exp $DESTDIR/Embedded/DLL/debug/
- cp libmysqld/debug/libmysqld.lib $DESTDIR/Embedded/DLL/debug/
- cp libmysqld/debug/libmysqld.pdb $DESTDIR/Embedded/DLL/debug/
- fi
-}
-
-if [ x"$PACK_EMBEDDED" = x"" -a \
- -f "libmysqld/$TARGET/mysqlserver.lib" -a \
- -f "libmysqld/$TARGET/libmysqld.lib" -o \
- x"$PACK_EMBEDDED" = x"yes" ] ; then
- copy_embedded
-fi
-
-# ----------------------------------------------------------------------
-# Note: Make sure to sync with include/Makefile.am and WiX installer
-# XML specifications
-# ----------------------------------------------------------------------
-
-mkdir -p $DESTDIR/include
-cp include/mysql.h \
- include/mysql_com.h \
- include/mysql_time.h \
- include/my_list.h \
- include/my_alloc.h \
- include/typelib.h \
- include/my_dbug.h \
- include/m_string.h \
- include/my_sys.h \
- include/my_xml.h \
- include/mysql_embed.h \
- include/my_pthread.h \
- include/my_no_pthread.h \
- include/decimal.h \
- include/errmsg.h \
- include/my_global.h \
- include/my_config.h \
- include/my_net.h \
- include/my_getopt.h \
- include/sslopt-longopts.h \
- include/my_dir.h \
- include/sslopt-vars.h \
- include/sslopt-case.h \
- include/sql_common.h \
- include/keycache.h \
- include/m_ctype.h \
- include/my_attribute.h \
- include/my_compiler.h \
- include/mysqld_error.h \
- include/sql_state.h \
- include/mysqld_ername.h \
- include/mysql_version.h \
- libmysql/libmysql.def \
- $DESTDIR/include/
-
-mkdir -p $DESTDIR/include/mysql
-cp include/mysql/plugin.h $DESTDIR/include/mysql/
-
-# ----------------------------------------------------------------------
-# Client libraries, and other libraries
-# ----------------------------------------------------------------------
-
-mkdir -p $DESTDIR/lib/opt
-mkdir -p $DESTDIR/lib/plugin
-cp sql/$TARGET/mysqld.lib $DESTDIR/lib/
-cp libmysql/$TARGET/libmysql.dll \
- libmysql/$TARGET/libmysql.lib \
- libmysql/$TARGET/mysqlclient.lib \
- mysys/$TARGET/mysys.lib \
- regex/$TARGET/regex.lib \
- strings/$TARGET/strings.lib \
- zlib/$TARGET/zlib.lib $DESTDIR/lib/opt/
-if [ -d storage/innodb_plugin ]; then
- cp storage/innodb_plugin/$TARGET/ha_innodb_plugin.dll \
- $DESTDIR/lib/plugin/
-fi
-if [ -d plugin/semisync ]; then
- cp plugin/semisync/$TARGET/semisync_master.dll \
- plugin/semisync/$TARGET/semisync_slave.dll \
- $DESTDIR/lib/plugin/
-fi
-
-if [ x"$TARGET" != x"release" ] ; then
- cp libmysql/$TARGET/libmysql.pdb \
- libmysql/$TARGET/mysqlclient.pdb \
- mysys/$TARGET/mysys.pdb \
- regex/$TARGET/regex.pdb \
- strings/$TARGET/strings.pdb \
- zlib/$TARGET/zlib.pdb $DESTDIR/lib/opt/
- if [ -d storage/innodb_plugin ]; then
- cp storage/innodb_plugin/$TARGET/ha_innodb_plugin.pdb \
- $DESTDIR/lib/plugin/
- fi
- if [ -d plugin/semisync ]; then
- cp plugin/semisync/$TARGET/semisync_master.pdb \
- plugin/semisync/$TARGET/semisync_slave.pdb \
- $DESTDIR/lib/plugin/
- fi
-fi
-
-
-if [ x"$PACK_DEBUG" = x"" -a -f "libmysql/debug/libmysql.lib" -o \
- x"$PACK_DEBUG" = x"yes" ] ; then
- mkdir -p $DESTDIR/lib/debug
- mkdir -p $DESTDIR/lib/plugin/debug
- cp libmysql/debug/libmysql.dll \
- libmysql/debug/libmysql.lib \
- libmysql/debug/libmysql.pdb \
- libmysql/debug/mysqlclient.lib \
- libmysql/debug/mysqlclient.pdb \
- mysys/debug/mysys.lib \
- mysys/debug/mysys.pdb \
- regex/debug/regex.lib \
- regex/debug/regex.pdb \
- strings/debug/strings.lib \
- strings/debug/strings.pdb \
- zlib/debug/zlib.lib \
- zlib/debug/zlib.pdb $DESTDIR/lib/debug/
- if [ -d storage/innodb_plugin ]; then
- cp storage/innodb_plugin/debug/ha_innodb_plugin.dll \
- storage/innodb_plugin/debug/ha_innodb_plugin.lib \
- storage/innodb_plugin/debug/ha_innodb_plugin.pdb \
- $DESTDIR/lib/plugin/debug/
- fi
- if [ -d plugin/semisync ]; then
- cp plugin/semisync/debug/semisync_master.dll \
- plugin/semisync/debug/semisync_master.lib \
- plugin/semisync/debug/semisync_master.pdb \
- plugin/semisync/debug/semisync_slave.dll \
- plugin/semisync/debug/semisync_slave.lib \
- plugin/semisync/debug/semisync_slave.pdb \
- $DESTDIR/lib/plugin/debug/
- fi
-fi
-
-# ----------------------------------------------------------------------
-# Copy the test directory
-# ----------------------------------------------------------------------
-
-mkdir $DESTDIR/mysql-test
-cp mysql-test/mysql-test-run.pl $DESTDIR/mysql-test/
-cp mysql-test/mysql-stress-test.pl $DESTDIR/mysql-test/
-cp mysql-test/README $DESTDIR/mysql-test/
-cp -R mysql-test/{t,r,include,suite,std_data,lib,collections} $DESTDIR/mysql-test/
-
-# Note that this will not copy "extra" if a soft link
-if [ -d mysql-test/extra ] ; then
- mkdir $DESTDIR/mysql-test/extra
- cp -pR mysql-test/extra/* $DESTDIR/mysql-test/extra/
-fi
-
-# ----------------------------------------------------------------------
-# Copy what could be usable in the "scripts" directory
-# ----------------------------------------------------------------------
-
-mysql_scripts="\
-mysql_config.pl \
-mysql_convert_table_format.pl \
-mysql_install_db.pl \
-mysql_secure_installation.pl \
-mysqld_multi.pl \
-mysqldumpslow.pl \
-mysqlhotcopy.pl \
-"
-
-mkdir -p $DESTDIR/scripts
-
-for i in $mysql_scripts
-do
- cp scripts/$i $DESTDIR/scripts/$i
-done
-
-cp -pR sql/share $DESTDIR/
-cp -pR sql-bench $DESTDIR/
-rm -f $DESTDIR/sql-bench/*.sh $DESTDIR/sql-bench/Makefile*
-
-# The SQL initialisation code is to be in "share"
-cp scripts/*.sql $DESTDIR/share/
-
-# ----------------------------------------------------------------------
-# Clean up from possibly copied SCCS directories
-# ----------------------------------------------------------------------
-
-rm -rf `find $DESTDIR -type d -name SCCS -print`
-
-# ----------------------------------------------------------------------
-# Copy other files specified on command line DEST=SOURCE
-# ----------------------------------------------------------------------
-
-for arg do
- dst=`echo $arg | sed -n 's/=.*$//p'`
- src=`echo $arg | sed -n 's/^.*=//p'`
-
- if [ x"$dst" = x"" -o x"$src" = x"" ] ; then
- echo "Invalid specification of what to copy"
- usage
- fi
-
- mkdir -p `dirname $DESTDIR/$dst`
- cp -pR "$src" $DESTDIR/$dst
-done
-
-# ----------------------------------------------------------------------
-# Finally create the ZIP archive
-# ----------------------------------------------------------------------
-
-rm -f $NOINST_NAME.zip
-zip -r $NOINST_NAME.zip $DESTDIR
-rm -Rf $DESTDIR
diff --git a/scripts/mysql_install_db.pl.in b/scripts/mysql_install_db.pl.in
index 18bd713c041..7bc1e97e7be 100644
--- a/scripts/mysql_install_db.pl.in
+++ b/scripts/mysql_install_db.pl.in
@@ -61,10 +61,15 @@ Usage: $0 [OPTIONS]
--cross-bootstrap For internal use. Used when building the MySQL system
tables on a different host than the target.
--datadir=path The path to the MySQL data directory.
+ --defaults-extra-file=name
+ Read this file after the global files are read.
+ --defaults-file=name Only read default options from the given file name.
--force Causes mysql_install_db to run even if DNS does not
work. In that case, grant table entries that normally
use hostnames will use IP addresses.
+ --help Display this help and exit.
--ldata=path The path to the MySQL data directory. Same as --datadir.
+ --no-defaults Don't read default options from any option file.
--rpm For internal use. This option is used by RPM files
during the MySQL installation process.
--skip-name-resolve Use IP addresses rather than hostnames when creating
diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh
index d8d511b9855..88b0823482f 100644
--- a/scripts/mysql_install_db.sh
+++ b/scripts/mysql_install_db.sh
@@ -46,10 +46,15 @@ Usage: $0 [OPTIONS]
--cross-bootstrap For internal use. Used when building the MySQL system
tables on a different host than the target.
--datadir=path The path to the MySQL data directory.
+ --defaults-extra-file=name
+ Read this file after the global files are read.
+ --defaults-file=name Only read default options from the given file name.
--force Causes mysql_install_db to run even if DNS does not
work. In that case, grant table entries that normally
use hostnames will use IP addresses.
+ --help Display this help and exit.
--ldata=path The path to the MySQL data directory. Same as --datadir.
+ --no-defaults Don't read default options from any option file.
--rpm For internal use. This option is used by RPM files
during the MySQL installation process.
--skip-name-resolve Use IP addresses rather than hostnames when creating
diff --git a/sql/client_settings.h b/sql/client_settings.h
index d9145bcce26..acae7907aa5 100644
--- a/sql/client_settings.h
+++ b/sql/client_settings.h
@@ -23,9 +23,18 @@
#include <thr_alarm.h>
#include <sql_common.h>
-#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \
- CLIENT_SECURE_CONNECTION | CLIENT_TRANSACTIONS | \
- CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION)
+/*
+ Note: CLIENT_CAPABILITIES is also defined in libmysql/client_settings.h.
+ When adding capabilities here, consider if they should be also added to
+ the libmysql version.
+*/
+#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | \
+ CLIENT_LONG_FLAG | \
+ CLIENT_SECURE_CONNECTION | \
+ CLIENT_TRANSACTIONS | \
+ CLIENT_PROTOCOL_41 | \
+ CLIENT_SECURE_CONNECTION | \
+ CLIENT_PLUGIN_AUTH)
#define read_user_name(A) {}
#undef HAVE_SMEM
diff --git a/sql/filesort.cc b/sql/filesort.cc
index c3250b6e699..88e9353abe3 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -147,8 +147,6 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
error= 1;
bzero((char*) &param,sizeof(param));
param.sort_length= sortlength(thd, sortorder, s_length, &multi_byte_charset);
- /* filesort cannot handle zero-length records. */
- DBUG_ASSERT(param.sort_length);
param.ref_length= table->file->ref_length;
param.addon_field= 0;
param.addon_length= 0;
@@ -260,6 +258,9 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
}
else
{
+ /* filesort cannot handle zero-length records during merge. */
+ DBUG_ASSERT(param.sort_length != 0);
+
if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer)
{
my_free(table_sort.buffpek);
@@ -972,21 +973,10 @@ static void make_sortkey(register SORTPARAM *param,
if (addonf->null_bit && field->is_null())
{
nulls[addonf->null_offset]|= addonf->null_bit;
-#ifdef HAVE_purify
- bzero(to, addonf->length);
-#endif
}
else
{
-#ifdef HAVE_purify
- uchar *end= field->pack(to, field->ptr);
- uint length= (uint) ((to + addonf->length) - end);
- DBUG_ASSERT((int) length >= 0);
- if (length)
- bzero(end, length);
-#else
(void) field->pack(to, field->ptr);
-#endif
}
to+= addonf->length;
}
diff --git a/sql/handler.cc b/sql/handler.cc
index 580677242bd..6f7cf2c3456 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -358,6 +358,7 @@ int ha_init_errors(void)
SETMSG(HA_ERR_AUTOINC_ERANGE, ER_DEFAULT(ER_WARN_DATA_OUT_OF_RANGE));
SETMSG(HA_ERR_TOO_MANY_CONCURRENT_TRXS, ER_DEFAULT(ER_TOO_MANY_CONCURRENT_TRXS));
SETMSG(HA_ERR_INDEX_COL_TOO_LONG, ER_DEFAULT(ER_INDEX_COLUMN_TOO_LONG));
+ SETMSG(HA_ERR_INDEX_CORRUPT, ER_DEFAULT(ER_INDEX_CORRUPT));
/* Register the error messages for use with my_error(). */
return my_error_register(get_handler_errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
@@ -2865,6 +2866,12 @@ void handler::print_error(int error, myf errflag)
case HA_ERR_INDEX_COL_TOO_LONG:
textno= ER_INDEX_COLUMN_TOO_LONG;
break;
+ case HA_ERR_INDEX_CORRUPT:
+ textno= ER_INDEX_CORRUPT;
+ break;
+ case HA_ERR_UNDO_REC_TOO_BIG:
+ textno= ER_UNDO_RECORD_TOO_BIG;
+ break;
default:
{
/* The error was "unknown" to this function.
diff --git a/sql/my_decimal.h b/sql/my_decimal.h
index 10fe431f40e..548d5ea3a53 100644
--- a/sql/my_decimal.h
+++ b/sql/my_decimal.h
@@ -124,12 +124,8 @@ public:
{
len= DECIMAL_BUFF_LENGTH;
buf= buffer;
-#if !defined (HAVE_purify) && !defined(DBUG_OFF)
- /* Set buffer to 'random' value to find wrong buffer usage */
- for (uint i= 0; i < DECIMAL_BUFF_LENGTH; i++)
- buffer[i]= i;
-#endif
}
+
my_decimal()
{
init();
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 6f4edac285d..c04106025a7 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -6415,6 +6415,12 @@ ER_ERROR_IN_TRIGGER_BODY
ER_ERROR_IN_UNKNOWN_TRIGGER_BODY
eng "Unknown trigger has an error in its body: '%-.256s'"
+ER_INDEX_CORRUPT
+ eng "Index %s is corrupted"
+
+ER_UNDO_RECORD_TOO_BIG
+ eng "Undo log record is too big."
+
ER_PLUGIN_NO_UNINSTALL
eng "Plugin '%s' is marked as not dynamically uninstallable. You have to stop the server to uninstall it."
diff --git a/sql/slave.cc b/sql/slave.cc
index d0b123c5c6f..7a3eee952c3 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -4204,6 +4204,10 @@ static int connect_to_master(THD* thd, MYSQL* mysql, Master_info* mi,
/* This one is not strictly needed but we have it here for completeness */
mysql_options(mysql, MYSQL_SET_CHARSET_DIR, (char *) charsets_dir);
+ /* Set MYSQL_PLUGIN_DIR in case master asks for an external authentication plugin */
+ if (opt_plugin_dir_ptr && *opt_plugin_dir_ptr)
+ mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir_ptr);
+
while (!(slave_was_killed = io_slave_killed(thd,mi)) &&
(reconnect ? mysql_reconnect(mysql) != 0 :
mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0,
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 885db292699..4df77b5b15b 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2348,6 +2348,12 @@ case SQLCOM_PREPARE:
goto end_with_restore_list;
#endif
/*
+ If no engine type was given, work out the default now
+ rather than at parse-time.
+ */
+ if (!(create_info.used_fields & HA_CREATE_USED_ENGINE))
+ create_info.db_type= ha_default_handlerton(thd);
+ /*
If we are using SET CHARSET without DEFAULT, add an implicit
DEFAULT to not confuse old users. (This may change).
*/
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 6fe9626b11d..145c6c86714 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -2038,7 +2038,6 @@ create:
lex->change=NullS;
bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.options=$2 | $4;
- lex->create_info.db_type= ha_default_handlerton(thd);
lex->create_info.default_table_charset= NULL;
lex->name.str= 0;
lex->name.length= 0;
@@ -2048,7 +2047,8 @@ create:
{
LEX *lex= YYTHD->lex;
lex->current_select= &lex->select_lex;
- if (!lex->create_info.db_type)
+ if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
+ !lex->create_info.db_type)
{
lex->create_info.db_type= ha_default_handlerton(YYTHD);
push_warning_printf(YYTHD, MYSQL_ERROR::WARN_LEVEL_WARN,
@@ -5036,8 +5036,7 @@ create_table_option:
ENGINE_SYM opt_equal storage_engines
{
Lex->create_info.db_type= $3;
- if ($3)
- Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE;
+ Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE;
}
| MAX_ROWS opt_equal ulonglong_num
{
@@ -6748,6 +6747,11 @@ alter_list_item:
{
LEX *lex=Lex;
lex->alter_info.flags|= ALTER_OPTIONS;
+ if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
+ !lex->create_info.db_type)
+ {
+ lex->create_info.used_fields&= ~HA_CREATE_USED_ENGINE;
+ }
}
| FORCE_SYM
{
diff --git a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c
index 3d8fadeaf92..6a6f0025fa5 100644
--- a/storage/innobase/btr/btr0btr.c
+++ b/storage/innobase/btr/btr0btr.c
@@ -690,7 +690,8 @@ btr_root_block_get(
zip_size = dict_table_zip_size(index->table);
root_page_no = dict_index_get_page(index);
- block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
+ block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
+ index, mtr);
ut_a((ibool)!!page_is_comp(buf_block_get_frame(block))
== dict_table_is_comp(index->table));
#ifdef UNIV_BTR_DEBUG
@@ -891,7 +892,7 @@ btr_page_alloc_for_ibuf(
dict_table_zip_size(index->table),
node_addr.page, RW_X_LATCH, mtr);
new_page = buf_block_get_frame(new_block);
- buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW);
+ buf_block_dbg_add_level(new_block, SYNC_IBUF_TREE_NODE_NEW);
flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
new_page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE,
@@ -905,28 +906,29 @@ btr_page_alloc_for_ibuf(
/**************************************************************//**
Allocates a new file page to be used in an index tree. NOTE: we assume
that the caller has made the reservation for free extents!
-@return new allocated block, x-latched; NULL if out of space */
-UNIV_INTERN
-buf_block_t*
-btr_page_alloc(
-/*===========*/
+@return allocated page number, FIL_NULL if out of space */
+static __attribute__((nonnull(1,5), warn_unused_result))
+ulint
+btr_page_alloc_low(
+/*===============*/
dict_index_t* index, /*!< in: index */
ulint hint_page_no, /*!< in: hint of a good page */
byte file_direction, /*!< in: direction where a possible
page split is made */
ulint level, /*!< in: level where the page is placed
in the tree */
- mtr_t* mtr) /*!< in: mtr */
+ mtr_t* mtr, /*!< in/out: mini-transaction
+ for the allocation */
+ mtr_t* init_mtr) /*!< in/out: mini-transaction
+ in which the page should be
+ initialized (may be the same
+ as mtr), or NULL if it should
+ not be initialized (the page
+ at hint was previously freed
+ in mtr) */
{
fseg_header_t* seg_header;
page_t* root;
- buf_block_t* new_block;
- ulint new_page_no;
-
- if (dict_index_is_ibuf(index)) {
-
- return(btr_page_alloc_for_ibuf(index, mtr));
- }
root = btr_root_get(index, mtr);
@@ -940,8 +942,42 @@ btr_page_alloc(
reservation for free extents, and thus we know that a page can
be allocated: */
- new_page_no = fseg_alloc_free_page_general(seg_header, hint_page_no,
- file_direction, TRUE, mtr);
+ return(fseg_alloc_free_page_general(
+ seg_header, hint_page_no, file_direction,
+ TRUE, mtr, init_mtr));
+}
+
+/**************************************************************//**
+Allocates a new file page to be used in an index tree. NOTE: we assume
+that the caller has made the reservation for free extents!
+@return new allocated block, x-latched; NULL if out of space */
+UNIV_INTERN
+buf_block_t*
+btr_page_alloc(
+/*===========*/
+ dict_index_t* index, /*!< in: index */
+ ulint hint_page_no, /*!< in: hint of a good page */
+ byte file_direction, /*!< in: direction where a possible
+ page split is made */
+ ulint level, /*!< in: level where the page is placed
+ in the tree */
+ mtr_t* mtr, /*!< in/out: mini-transaction
+ for the allocation */
+ mtr_t* init_mtr) /*!< in/out: mini-transaction
+ for x-latching and initializing
+ the page */
+{
+ buf_block_t* new_block;
+ ulint new_page_no;
+
+ if (dict_index_is_ibuf(index)) {
+
+ return(btr_page_alloc_for_ibuf(index, mtr));
+ }
+
+ new_page_no = btr_page_alloc_low(
+ index, hint_page_no, file_direction, level, mtr, init_mtr);
+
if (new_page_no == FIL_NULL) {
return(NULL);
@@ -949,9 +985,16 @@ btr_page_alloc(
new_block = buf_page_get(dict_index_get_space(index),
dict_table_zip_size(index->table),
- new_page_no, RW_X_LATCH, mtr);
+ new_page_no, RW_X_LATCH, init_mtr);
buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW);
+ if (mtr->freed_clust_leaf) {
+ mtr_memo_release(mtr, new_block, MTR_MEMO_FREE_CLUST_LEAF);
+ ut_ad(!mtr_memo_contains(mtr, new_block,
+ MTR_MEMO_FREE_CLUST_LEAF));
+ }
+
+ ut_ad(btr_freed_leaves_validate(mtr));
return(new_block);
}
@@ -1064,6 +1107,15 @@ btr_page_free_low(
fseg_free_page(seg_header,
buf_block_get_space(block),
buf_block_get_page_no(block), mtr);
+
+ /* The page was marked free in the allocation bitmap, but it
+ should remain buffer-fixed until mtr_commit(mtr) or until it
+ is explicitly freed from the mini-transaction. */
+ ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+ /* TODO: Discard any operations on the page from the redo log
+ and remove the block from the flush list and the buffer pool.
+ This would free up buffer pool earlier and reduce writes to
+ both the tablespace and the redo log. */
}
/**************************************************************//**
@@ -1077,12 +1129,139 @@ btr_page_free(
buf_block_t* block, /*!< in: block to be freed, x-latched */
mtr_t* mtr) /*!< in: mtr */
{
- ulint level;
-
- level = btr_page_get_level(buf_block_get_frame(block), mtr);
+ const page_t* page = buf_block_get_frame(block);
+ ulint level = btr_page_get_level(page, mtr);
+ ut_ad(fil_page_get_type(block->frame) == FIL_PAGE_INDEX);
btr_page_free_low(index, block, level, mtr);
+
+ /* The handling of MTR_MEMO_FREE_CLUST_LEAF assumes this. */
+ ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+
+ if (level == 0 && dict_index_is_clust(index)) {
+ /* We may have to call btr_mark_freed_leaves() to
+ temporarily mark the block nonfree for invoking
+ btr_store_big_rec_extern_fields_func() after an
+ update. Remember that the block was freed. */
+ mtr->freed_clust_leaf = TRUE;
+ mtr_memo_push(mtr, block, MTR_MEMO_FREE_CLUST_LEAF);
+ }
+
+ ut_ad(btr_freed_leaves_validate(mtr));
+}
+
+/**************************************************************//**
+Marks all MTR_MEMO_FREE_CLUST_LEAF pages nonfree or free.
+For invoking btr_store_big_rec_extern_fields() after an update,
+we must temporarily mark freed clustered index pages allocated, so
+that off-page columns will not be allocated from them. Between the
+btr_store_big_rec_extern_fields() and mtr_commit() we have to
+mark the pages free again, so that no pages will be leaked. */
+UNIV_INTERN
+void
+btr_mark_freed_leaves(
+/*==================*/
+ dict_index_t* index, /*!< in/out: clustered index */
+ mtr_t* mtr, /*!< in/out: mini-transaction */
+ ibool nonfree)/*!< in: TRUE=mark nonfree, FALSE=mark freed */
+{
+ /* This is loosely based on mtr_memo_release(). */
+
+ ulint offset;
+
+ ut_ad(dict_index_is_clust(index));
+ ut_ad(mtr->magic_n == MTR_MAGIC_N);
+ ut_ad(mtr->state == MTR_ACTIVE);
+
+ if (!mtr->freed_clust_leaf) {
+ return;
+ }
+
+ offset = dyn_array_get_data_size(&mtr->memo);
+
+ while (offset > 0) {
+ mtr_memo_slot_t* slot;
+ buf_block_t* block;
+
+ offset -= sizeof *slot;
+
+ slot = dyn_array_get_element(&mtr->memo, offset);
+
+ if (slot->type != MTR_MEMO_FREE_CLUST_LEAF) {
+ continue;
+ }
+
+ /* Because btr_page_alloc() does invoke
+ mtr_memo_release on MTR_MEMO_FREE_CLUST_LEAF, all
+ blocks tagged with MTR_MEMO_FREE_CLUST_LEAF in the
+ memo must still be clustered index leaf tree pages. */
+ block = slot->object;
+ ut_a(buf_block_get_space(block)
+ == dict_index_get_space(index));
+ ut_a(fil_page_get_type(buf_block_get_frame(block))
+ == FIL_PAGE_INDEX);
+ ut_a(page_is_leaf(buf_block_get_frame(block)));
+
+ if (nonfree) {
+ /* Allocate the same page again. */
+ ulint page_no;
+ page_no = btr_page_alloc_low(
+ index, buf_block_get_page_no(block),
+ FSP_NO_DIR, 0, mtr, NULL);
+ ut_a(page_no == buf_block_get_page_no(block));
+ } else {
+ /* Assert that the page is allocated and free it. */
+ btr_page_free_low(index, block, 0, mtr);
+ }
+ }
+
+ ut_ad(btr_freed_leaves_validate(mtr));
+}
+
+#ifdef UNIV_DEBUG
+/**************************************************************//**
+Validates all pages marked MTR_MEMO_FREE_CLUST_LEAF.
+@see btr_mark_freed_leaves()
+@return TRUE */
+UNIV_INTERN
+ibool
+btr_freed_leaves_validate(
+/*======================*/
+ mtr_t* mtr) /*!< in: mini-transaction */
+{
+ ulint offset;
+
+ ut_ad(mtr->magic_n == MTR_MAGIC_N);
+ ut_ad(mtr->state == MTR_ACTIVE);
+
+ offset = dyn_array_get_data_size(&mtr->memo);
+
+ while (offset > 0) {
+ const mtr_memo_slot_t* slot;
+ const buf_block_t* block;
+
+ offset -= sizeof *slot;
+
+ slot = dyn_array_get_element(&mtr->memo, offset);
+
+ if (slot->type != MTR_MEMO_FREE_CLUST_LEAF) {
+ continue;
+ }
+
+ ut_a(mtr->freed_clust_leaf);
+ /* Because btr_page_alloc() does invoke
+ mtr_memo_release on MTR_MEMO_FREE_CLUST_LEAF, all
+ blocks tagged with MTR_MEMO_FREE_CLUST_LEAF in the
+ memo must still be clustered index leaf tree pages. */
+ block = slot->object;
+ ut_a(fil_page_get_type(buf_block_get_frame(block))
+ == FIL_PAGE_INDEX);
+ ut_a(page_is_leaf(buf_block_get_frame(block)));
+ }
+
+ return(TRUE);
}
+#endif /* UNIV_DEBUG */
/**************************************************************//**
Sets the child node file address in a node pointer. */
@@ -1139,7 +1318,7 @@ btr_node_ptr_get_child(
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
return(btr_block_get(space, dict_table_zip_size(index->table),
- page_no, RW_X_LATCH, mtr));
+ page_no, RW_X_LATCH, index, mtr));
}
/************************************************************//**
@@ -1312,7 +1491,8 @@ btr_create(
space, 0,
IBUF_HEADER + IBUF_TREE_SEG_HEADER, mtr);
- buf_block_dbg_add_level(ibuf_hdr_block, SYNC_TREE_NODE_NEW);
+ buf_block_dbg_add_level(
+ ibuf_hdr_block, SYNC_IBUF_TREE_NODE_NEW);
ut_ad(buf_block_get_page_no(ibuf_hdr_block)
== IBUF_HEADER_PAGE_NO);
@@ -1350,10 +1530,9 @@ btr_create(
page_no = buf_block_get_page_no(block);
frame = buf_block_get_frame(block);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
-
if (type & DICT_IBUF) {
/* It is an insert buffer tree: initialize the free list */
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO);
@@ -1361,6 +1540,8 @@ btr_create(
} else {
/* It is a non-ibuf tree: create a file segment for leaf
pages */
+ buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
+
if (!fseg_create(space, page_no,
PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) {
/* Not enough space for new segment, free root
@@ -1432,7 +1613,8 @@ btr_free_but_not_root(
leaf_loop:
mtr_start(&mtr);
- root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, &mtr);
+ root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH,
+ NULL, &mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
+ root, space));
@@ -1454,7 +1636,8 @@ leaf_loop:
top_loop:
mtr_start(&mtr);
- root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, &mtr);
+ root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH,
+ NULL, &mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
+ root, space));
@@ -1480,13 +1663,13 @@ btr_free_root(
ulint zip_size, /*!< in: compressed page size in bytes
or 0 for uncompressed pages */
ulint root_page_no, /*!< in: root page number */
- mtr_t* mtr) /*!< in: a mini-transaction which has already
- been started */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
buf_block_t* block;
fseg_header_t* header;
- block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
+ block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
+ NULL, mtr);
btr_search_drop_page_hash_index(block);
@@ -1804,7 +1987,7 @@ btr_root_raise_and_insert(
level = btr_page_get_level(root, mtr);
- new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr);
+ new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr, mtr);
new_page = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block);
ut_a(!new_page_zip == !root_page_zip);
@@ -2365,9 +2548,8 @@ btr_attach_half_pages(
/* Update page links of the level */
if (prev_page_no != FIL_NULL) {
- buf_block_t* prev_block = btr_block_get(space, zip_size,
- prev_page_no,
- RW_X_LATCH, mtr);
+ buf_block_t* prev_block = btr_block_get(
+ space, zip_size, prev_page_no, RW_X_LATCH, index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(prev_block->frame) == page_is_comp(page));
ut_a(btr_page_get_next(prev_block->frame, mtr)
@@ -2380,9 +2562,8 @@ btr_attach_half_pages(
}
if (next_page_no != FIL_NULL) {
- buf_block_t* next_block = btr_block_get(space, zip_size,
- next_page_no,
- RW_X_LATCH, mtr);
+ buf_block_t* next_block = btr_block_get(
+ space, zip_size, next_page_no, RW_X_LATCH, index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(next_block->frame) == page_is_comp(page));
ut_a(btr_page_get_prev(next_block->frame, mtr)
@@ -2542,7 +2723,7 @@ func_start:
/* 2. Allocate a new page to the index */
new_block = btr_page_alloc(cursor->index, hint_page_no, direction,
- btr_page_get_level(page, mtr), mtr);
+ btr_page_get_level(page, mtr), mtr, mtr);
new_page = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block);
btr_page_create(new_block, new_page_zip, cursor->index,
@@ -2804,17 +2985,42 @@ func_exit:
return(rec);
}
+#ifdef UNIV_SYNC_DEBUG
+/*************************************************************//**
+Removes a page from the level list of pages.
+@param space in: space where removed
+@param zip_size in: compressed page size in bytes, or 0 for uncompressed
+@param page in/out: page to remove
+@param index in: index tree
+@param mtr in/out: mini-transaction */
+# define btr_level_list_remove(space,zip_size,page,index,mtr) \
+ btr_level_list_remove_func(space,zip_size,page,index,mtr)
+#else /* UNIV_SYNC_DEBUG */
+/*************************************************************//**
+Removes a page from the level list of pages.
+@param space in: space where removed
+@param zip_size in: compressed page size in bytes, or 0 for uncompressed
+@param page in/out: page to remove
+@param index in: index tree
+@param mtr in/out: mini-transaction */
+# define btr_level_list_remove(space,zip_size,page,index,mtr) \
+ btr_level_list_remove_func(space,zip_size,page,mtr)
+#endif /* UNIV_SYNC_DEBUG */
+
/*************************************************************//**
Removes a page from the level list of pages. */
-static
+static __attribute__((nonnull))
void
-btr_level_list_remove(
-/*==================*/
- ulint space, /*!< in: space where removed */
- ulint zip_size,/*!< in: compressed page size in bytes
- or 0 for uncompressed pages */
- page_t* page, /*!< in: page to remove */
- mtr_t* mtr) /*!< in: mtr */
+btr_level_list_remove_func(
+/*=======================*/
+ ulint space, /*!< in: space where removed */
+ ulint zip_size,/*!< in: compressed page size in bytes
+ or 0 for uncompressed pages */
+ page_t* page, /*!< in/out: page to remove */
+#ifdef UNIV_SYNC_DEBUG
+ const dict_index_t* index, /*!< in: index tree */
+#endif /* UNIV_SYNC_DEBUG */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint prev_page_no;
ulint next_page_no;
@@ -2832,7 +3038,7 @@ btr_level_list_remove(
if (prev_page_no != FIL_NULL) {
buf_block_t* prev_block
= btr_block_get(space, zip_size, prev_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
page_t* prev_page
= buf_block_get_frame(prev_block);
#ifdef UNIV_BTR_DEBUG
@@ -2849,7 +3055,7 @@ btr_level_list_remove(
if (next_page_no != FIL_NULL) {
buf_block_t* next_block
= btr_block_get(space, zip_size, next_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
page_t* next_page
= buf_block_get_frame(next_block);
#ifdef UNIV_BTR_DEBUG
@@ -3175,7 +3381,7 @@ btr_compress(
if (is_left) {
merge_block = btr_block_get(space, zip_size, left_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_next(merge_page, mtr)
@@ -3184,7 +3390,7 @@ btr_compress(
} else if (right_page_no != FIL_NULL) {
merge_block = btr_block_get(space, zip_size, right_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_prev(merge_page, mtr)
@@ -3273,7 +3479,7 @@ err_exit:
btr_search_drop_page_hash_index(block);
/* Remove the page from the level list */
- btr_level_list_remove(space, zip_size, page, mtr);
+ btr_level_list_remove(space, zip_size, page, index, mtr);
btr_node_ptr_delete(index, block, mtr);
lock_update_merge_left(merge_block, orig_pred, block);
@@ -3330,7 +3536,7 @@ err_exit:
#endif /* UNIV_BTR_DEBUG */
/* Remove the page from the level list */
- btr_level_list_remove(space, zip_size, page, mtr);
+ btr_level_list_remove(space, zip_size, page, index, mtr);
/* Replace the address of the old child node (= page) with the
address of the merge page to the right */
@@ -3522,7 +3728,7 @@ btr_discard_page(
if (left_page_no != FIL_NULL) {
merge_block = btr_block_get(space, zip_size, left_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_next(merge_page, mtr)
@@ -3530,7 +3736,7 @@ btr_discard_page(
#endif /* UNIV_BTR_DEBUG */
} else if (right_page_no != FIL_NULL) {
merge_block = btr_block_get(space, zip_size, right_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_prev(merge_page, mtr)
@@ -3565,7 +3771,7 @@ btr_discard_page(
btr_node_ptr_delete(index, block, mtr);
/* Remove the page from the level list */
- btr_level_list_remove(space, zip_size, page, mtr);
+ btr_level_list_remove(space, zip_size, page, index, mtr);
#ifdef UNIV_ZIP_DEBUG
{
page_zip_des_t* merge_page_zip
@@ -4083,7 +4289,7 @@ loop:
if (right_page_no != FIL_NULL) {
const rec_t* right_rec;
right_block = btr_block_get(space, zip_size, right_page_no,
- RW_X_LATCH, &mtr);
+ RW_X_LATCH, index, &mtr);
right_page = buf_block_get_frame(right_block);
if (UNIV_UNLIKELY(btr_page_get_prev(right_page, &mtr)
!= page_get_page_no(page))) {
@@ -4309,7 +4515,7 @@ node_ptr_fails:
mtr_start(&mtr);
block = btr_block_get(space, zip_size, right_page_no,
- RW_X_LATCH, &mtr);
+ RW_X_LATCH, index, &mtr);
page = buf_block_get_frame(block);
goto loop;
diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
index 46a52b549af..3021bb71929 100644
--- a/storage/innobase/btr/btr0cur.c
+++ b/storage/innobase/btr/btr0cur.c
@@ -249,7 +249,8 @@ btr_cur_latch_leaves(
case BTR_SEARCH_LEAF:
case BTR_MODIFY_LEAF:
mode = latch_mode == BTR_SEARCH_LEAF ? RW_S_LATCH : RW_X_LATCH;
- get_block = btr_block_get(space, zip_size, page_no, mode, mtr);
+ get_block = btr_block_get(
+ space, zip_size, page_no, mode, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
#endif /* UNIV_BTR_DEBUG */
@@ -260,9 +261,9 @@ btr_cur_latch_leaves(
left_page_no = btr_page_get_prev(page, mtr);
if (left_page_no != FIL_NULL) {
- get_block = btr_block_get(space, zip_size,
- left_page_no,
- RW_X_LATCH, mtr);
+ get_block = btr_block_get(
+ space, zip_size, left_page_no,
+ RW_X_LATCH, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame)
== page_is_comp(page));
@@ -272,8 +273,9 @@ btr_cur_latch_leaves(
get_block->check_index_page_at_flush = TRUE;
}
- get_block = btr_block_get(space, zip_size, page_no,
- RW_X_LATCH, mtr);
+ get_block = btr_block_get(
+ space, zip_size, page_no,
+ RW_X_LATCH, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
#endif /* UNIV_BTR_DEBUG */
@@ -282,9 +284,9 @@ btr_cur_latch_leaves(
right_page_no = btr_page_get_next(page, mtr);
if (right_page_no != FIL_NULL) {
- get_block = btr_block_get(space, zip_size,
- right_page_no,
- RW_X_LATCH, mtr);
+ get_block = btr_block_get(
+ space, zip_size, right_page_no,
+ RW_X_LATCH, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame)
== page_is_comp(page));
@@ -303,8 +305,9 @@ btr_cur_latch_leaves(
left_page_no = btr_page_get_prev(page, mtr);
if (left_page_no != FIL_NULL) {
- get_block = btr_block_get(space, zip_size,
- left_page_no, mode, mtr);
+ get_block = btr_block_get(
+ space, zip_size,
+ left_page_no, mode, cursor->index, mtr);
cursor->left_block = get_block;
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame)
@@ -315,7 +318,8 @@ btr_cur_latch_leaves(
get_block->check_index_page_at_flush = TRUE;
}
- get_block = btr_block_get(space, zip_size, page_no, mode, mtr);
+ get_block = btr_block_get(
+ space, zip_size, page_no, mode, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
#endif /* UNIV_BTR_DEBUG */
@@ -669,7 +673,9 @@ retry_page_get:
ut_a(!page_zip || page_zip_validate(page_zip, page));
#endif /* UNIV_ZIP_DEBUG */
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(
+ block, dict_index_is_ibuf(index)
+ ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
}
ut_ad(index->id == btr_page_get_index_id(page));
@@ -767,7 +773,7 @@ retry_page_get:
if (level != 0) {
/* x-latch the page */
page = btr_page_get(
- space, zip_size, page_no, RW_X_LATCH, mtr);
+ space, zip_size, page_no, RW_X_LATCH, index, mtr);
ut_a((ibool)!!page_is_comp(page)
== dict_table_is_comp(index->table));
@@ -1839,6 +1845,7 @@ btr_cur_update_in_place(
roll_ptr_t roll_ptr = 0;
trx_t* trx;
ulint was_delete_marked;
+ ibool is_hashed;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
@@ -1880,7 +1887,21 @@ btr_cur_update_in_place(
return(err);
}
- if (block->is_hashed) {
+ if (!(flags & BTR_KEEP_SYS_FLAG)) {
+ row_upd_rec_sys_fields(rec, NULL,
+ index, offsets, trx, roll_ptr);
+ }
+
+ was_delete_marked = rec_get_deleted_flag(
+ rec, page_is_comp(buf_block_get_frame(block)));
+
+ is_hashed = block->is_hashed;
+
+ if (is_hashed) {
+ /* TO DO: Can we skip this if none of the fields
+ index->search_info->curr_n_fields
+ are being updated? */
+
/* The function row_upd_changes_ord_field_binary works only
if the update vector was built for a clustered index, we must
NOT call it if index is secondary */
@@ -1896,17 +1917,9 @@ btr_cur_update_in_place(
rw_lock_x_lock(&btr_search_latch);
}
- if (!(flags & BTR_KEEP_SYS_FLAG)) {
- row_upd_rec_sys_fields(rec, NULL,
- index, offsets, trx, roll_ptr);
- }
-
- was_delete_marked = rec_get_deleted_flag(
- rec, page_is_comp(buf_block_get_frame(block)));
-
row_upd_rec_in_place(rec, index, offsets, update, page_zip);
- if (block->is_hashed) {
+ if (is_hashed) {
rw_lock_x_unlock(&btr_search_latch);
}
@@ -2526,39 +2539,6 @@ return_after_reservations:
return(err);
}
-/**************************************************************//**
-Commits and restarts a mini-transaction so that it will retain an
-x-lock on index->lock and the cursor page. */
-UNIV_INTERN
-void
-btr_cur_mtr_commit_and_start(
-/*=========================*/
- btr_cur_t* cursor, /*!< in: cursor */
- mtr_t* mtr) /*!< in/out: mini-transaction */
-{
- buf_block_t* block;
-
- block = btr_cur_get_block(cursor);
-
- ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(cursor->index),
- MTR_MEMO_X_LOCK));
- ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
- /* Keep the locks across the mtr_commit(mtr). */
- rw_lock_x_lock(dict_index_get_lock(cursor->index));
- rw_lock_x_lock(&block->lock);
- mutex_enter(&block->mutex);
- buf_block_buf_fix_inc(block, __FILE__, __LINE__);
- mutex_exit(&block->mutex);
- /* Write out the redo log. */
- mtr_commit(mtr);
- mtr_start(mtr);
- /* Reassociate the locks with the mini-transaction.
- They will be released on mtr_commit(mtr). */
- mtr_memo_push(mtr, dict_index_get_lock(cursor->index),
- MTR_MEMO_X_LOCK);
- mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX);
-}
-
/*==================== B-TREE DELETE MARK AND UNMARK ===============*/
/****************************************************************//**
@@ -2665,7 +2645,8 @@ btr_cur_parse_del_mark_set_clust_rec(
/* We do not need to reserve btr_search_latch, as the page
is only being recovered, and there cannot be a hash index to
- it. */
+ it. Besides, these fields are being updated in place
+ and the adaptive hash index does not depend on them. */
btr_rec_set_deleted_flag(rec, page_zip, val);
@@ -2745,9 +2726,9 @@ btr_cur_del_mark_set_clust_rec(
return(err);
}
- if (block->is_hashed) {
- rw_lock_x_lock(&btr_search_latch);
- }
+ /* The btr_search_latch is not needed here, because
+ the adaptive hash index does not depend on the delete-mark
+ and the delete-mark is being updated in place. */
page_zip = buf_block_get_page_zip(block);
@@ -2761,10 +2742,6 @@ btr_cur_del_mark_set_clust_rec(
index, offsets, trx, roll_ptr);
}
- if (block->is_hashed) {
- rw_lock_x_unlock(&btr_search_latch);
- }
-
btr_cur_del_mark_set_clust_rec_log(flags, rec, index, val, trx,
roll_ptr, mtr);
@@ -2840,7 +2817,8 @@ btr_cur_parse_del_mark_set_sec_rec(
/* We do not need to reserve btr_search_latch, as the page
is only being recovered, and there cannot be a hash index to
- it. */
+ it. Besides, the delete-mark flag is being updated in place
+ and the adaptive hash index does not depend on it. */
btr_rec_set_deleted_flag(rec, page_zip, val);
}
@@ -2888,16 +2866,11 @@ btr_cur_del_mark_set_sec_rec(
ut_ad(!!page_rec_is_comp(rec)
== dict_table_is_comp(cursor->index->table));
- if (block->is_hashed) {
- rw_lock_x_lock(&btr_search_latch);
- }
-
+ /* We do not need to reserve btr_search_latch, as the
+ delete-mark flag is being updated in place and the adaptive
+ hash index does not depend on it. */
btr_rec_set_deleted_flag(rec, buf_block_get_page_zip(block), val);
- if (block->is_hashed) {
- rw_lock_x_unlock(&btr_search_latch);
- }
-
btr_cur_del_mark_set_sec_rec_log(rec, val, mtr);
return(DB_SUCCESS);
@@ -2918,8 +2891,11 @@ btr_cur_set_deleted_flag_for_ibuf(
ibool val, /*!< in: value to set */
mtr_t* mtr) /*!< in: mtr */
{
- /* We do not need to reserve btr_search_latch, as the page has just
- been read to the buffer pool and there cannot be a hash index to it. */
+ /* We do not need to reserve btr_search_latch, as the page
+ has just been read to the buffer pool and there cannot be
+ a hash index to it. Besides, the delete-mark flag is being
+ updated in place and the adaptive hash index does not depend
+ on it. */
btr_rec_set_deleted_flag(rec, page_zip, val);
@@ -4184,6 +4160,9 @@ btr_store_big_rec_extern_fields_func(
the "external storage" flags in offsets
will not correspond to rec when
this function returns */
+ const big_rec_t*big_rec_vec, /*!< in: vector containing fields
+ to be stored externally */
+
#ifdef UNIV_DEBUG
mtr_t* local_mtr, /*!< in: mtr containing the
latch to rec and to the tree */
@@ -4192,9 +4171,11 @@ btr_store_big_rec_extern_fields_func(
ibool update_in_place,/*! in: TRUE if the record is updated
in place (not delete+insert) */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
- const big_rec_t*big_rec_vec) /*!< in: vector containing fields
- to be stored externally */
-
+ mtr_t* alloc_mtr) /*!< in/out: in an insert, NULL;
+ in an update, local_mtr for
+ allocating BLOB pages and
+ updating BLOB pointers; alloc_mtr
+ must not have freed any leaf pages */
{
ulint rec_page_no;
byte* field_ref;
@@ -4213,6 +4194,9 @@ btr_store_big_rec_extern_fields_func(
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(rec_offs_any_extern(offsets));
+ ut_ad(local_mtr);
+ ut_ad(!alloc_mtr || alloc_mtr == local_mtr);
+ ut_ad(!update_in_place || alloc_mtr);
ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index),
MTR_MEMO_X_LOCK));
ut_ad(mtr_memo_contains(local_mtr, rec_block, MTR_MEMO_PAGE_X_FIX));
@@ -4228,6 +4212,25 @@ btr_store_big_rec_extern_fields_func(
rec_page_no = buf_block_get_page_no(rec_block);
ut_a(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX);
+ if (alloc_mtr) {
+ /* Because alloc_mtr will be committed after
+ mtr, it is possible that the tablespace has been
+ extended when the B-tree record was updated or
+ inserted, or it will be extended while allocating
+ pages for big_rec.
+
+ TODO: In mtr (not alloc_mtr), write a redo log record
+ about extending the tablespace to its current size,
+ and remember the current size. Whenever the tablespace
+ grows as pages are allocated, write further redo log
+ records to mtr. (Currently tablespace extension is not
+ covered by the redo log. If it were, the record would
+ only be written to alloc_mtr, which is committed after
+ mtr.) */
+ } else {
+ alloc_mtr = &mtr;
+ }
+
if (UNIV_LIKELY_NULL(page_zip)) {
int err;
@@ -4304,7 +4307,7 @@ btr_store_big_rec_extern_fields_func(
}
block = btr_page_alloc(index, hint_page_no,
- FSP_NO_DIR, 0, &mtr);
+ FSP_NO_DIR, 0, alloc_mtr, &mtr);
if (UNIV_UNLIKELY(block == NULL)) {
mtr_commit(&mtr);
@@ -4431,11 +4434,15 @@ btr_store_big_rec_extern_fields_func(
goto next_zip_page;
}
- rec_block = buf_page_get(space_id, zip_size,
- rec_page_no,
- RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(rec_block,
- SYNC_NO_ORDER_CHECK);
+ if (alloc_mtr == &mtr) {
+ rec_block = buf_page_get(
+ space_id, zip_size,
+ rec_page_no,
+ RW_X_LATCH, &mtr);
+ buf_block_dbg_add_level(
+ rec_block,
+ SYNC_NO_ORDER_CHECK);
+ }
if (err == Z_STREAM_END) {
mach_write_to_4(field_ref
@@ -4469,7 +4476,8 @@ btr_store_big_rec_extern_fields_func(
page_zip_write_blob_ptr(
page_zip, rec, index, offsets,
- big_rec_vec->fields[i].field_no, &mtr);
+ big_rec_vec->fields[i].field_no,
+ alloc_mtr);
next_zip_page:
prev_page_no = page_no;
@@ -4514,19 +4522,23 @@ next_zip_page:
extern_len -= store_len;
- rec_block = buf_page_get(space_id, zip_size,
- rec_page_no,
- RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(rec_block,
- SYNC_NO_ORDER_CHECK);
+ if (alloc_mtr == &mtr) {
+ rec_block = buf_page_get(
+ space_id, zip_size,
+ rec_page_no,
+ RW_X_LATCH, &mtr);
+ buf_block_dbg_add_level(
+ rec_block,
+ SYNC_NO_ORDER_CHECK);
+ }
mlog_write_ulint(field_ref + BTR_EXTERN_LEN, 0,
- MLOG_4BYTES, &mtr);
+ MLOG_4BYTES, alloc_mtr);
mlog_write_ulint(field_ref
+ BTR_EXTERN_LEN + 4,
big_rec_vec->fields[i].len
- extern_len,
- MLOG_4BYTES, &mtr);
+ MLOG_4BYTES, alloc_mtr);
if (prev_page_no == FIL_NULL) {
btr_blob_dbg_add_blob(
@@ -4536,18 +4548,19 @@ next_zip_page:
mlog_write_ulint(field_ref
+ BTR_EXTERN_SPACE_ID,
- space_id,
- MLOG_4BYTES, &mtr);
+ space_id, MLOG_4BYTES,
+ alloc_mtr);
mlog_write_ulint(field_ref
+ BTR_EXTERN_PAGE_NO,
- page_no,
- MLOG_4BYTES, &mtr);
+ page_no, MLOG_4BYTES,
+ alloc_mtr);
mlog_write_ulint(field_ref
+ BTR_EXTERN_OFFSET,
FIL_PAGE_DATA,
- MLOG_4BYTES, &mtr);
+ MLOG_4BYTES,
+ alloc_mtr);
}
prev_page_no = page_no;
diff --git a/storage/innobase/btr/btr0pcur.c b/storage/innobase/btr/btr0pcur.c
index e3e3e53f98e..cbb0d21a7ed 100644
--- a/storage/innobase/btr/btr0pcur.c
+++ b/storage/innobase/btr/btr0pcur.c
@@ -266,8 +266,10 @@ btr_pcur_restore_position_func(
file, line, mtr))) {
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
- buf_block_dbg_add_level(btr_pcur_get_block(cursor),
- SYNC_TREE_NODE);
+ buf_block_dbg_add_level(
+ btr_pcur_get_block(cursor),
+ dict_index_is_ibuf(index)
+ ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
if (cursor->rel_pos == BTR_PCUR_ON) {
#ifdef UNIV_DEBUG
@@ -390,7 +392,8 @@ btr_pcur_move_to_next_page(
ut_ad(next_page_no != FIL_NULL);
next_block = btr_block_get(space, zip_size, next_page_no,
- cursor->latch_mode, mtr);
+ cursor->latch_mode,
+ btr_pcur_get_btr_cur(cursor)->index, mtr);
next_page = buf_block_get_frame(next_block);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(next_page) == page_is_comp(page));
diff --git a/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c
index 93573a300e4..7070420425c 100644
--- a/storage/innobase/btr/btr0sea.c
+++ b/storage/innobase/btr/btr0sea.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -845,6 +845,7 @@ btr_search_guess_on_hash(
btr_pcur_t pcur;
#endif
ut_ad(index && info && tuple && cursor && mtr);
+ ut_ad(!dict_index_is_ibuf(index));
ut_ad((latch_mode == BTR_SEARCH_LEAF)
|| (latch_mode == BTR_MODIFY_LEAF));
diff --git a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c
index b11bf02c747..30c31dd71a0 100644
--- a/storage/innobase/buf/buf0buddy.c
+++ b/storage/innobase/buf/buf0buddy.c
@@ -330,7 +330,6 @@ buf_buddy_relocate(
{
buf_page_t* bpage;
const ulint size = BUF_BUDDY_LOW << i;
- ullint usec = ut_time_us(NULL);
mutex_t* mutex;
ulint space;
ulint page_no;
@@ -397,6 +396,7 @@ buf_buddy_relocate(
if (buf_page_can_relocate(bpage)) {
/* Relocate the compressed page. */
+ ullint usec = ut_time_us(NULL);
ut_a(bpage->zip.data == src);
memcpy(dst, src, size);
bpage->zip.data = dst;
diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
index 648e53ac4a6..e0b9e979970 100644
--- a/storage/innobase/buf/buf0buf.c
+++ b/storage/innobase/buf/buf0buf.c
@@ -1716,31 +1716,6 @@ buf_page_set_accessed_make_young(
}
/********************************************************************//**
-Resets the check_index_page_at_flush field of a page if found in the buffer
-pool. */
-UNIV_INTERN
-void
-buf_reset_check_index_page_at_flush(
-/*================================*/
- ulint space, /*!< in: space id */
- ulint offset) /*!< in: page number */
-{
- buf_block_t* block;
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
-
- buf_pool_mutex_enter(buf_pool);
-
- block = (buf_block_t*) buf_page_hash_get(buf_pool, space, offset);
-
- if (block && buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE) {
- ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
- block->check_index_page_at_flush = FALSE;
- }
-
- buf_pool_mutex_exit(buf_pool);
-}
-
-/********************************************************************//**
Returns the current state of is_hashed of a page. FALSE if the page is
not in the pool. NOTE that this operation does not fix the page in the
pool if it is found there.
@@ -3015,19 +2990,20 @@ buf_page_init_low(
/********************************************************************//**
Inits a page to the buffer buf_pool. */
-static
+static __attribute__((nonnull))
void
buf_page_init(
/*==========*/
+ buf_pool_t* buf_pool,/*!< in/out: buffer pool */
ulint space, /*!< in: space id */
ulint offset, /*!< in: offset of the page within space
in units of a page */
ulint fold, /*!< in: buf_page_address_fold(space,offset) */
- buf_block_t* block) /*!< in: block to init */
+ buf_block_t* block) /*!< in/out: block to init */
{
buf_page_t* hash_page;
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
+ ut_ad(buf_pool == buf_pool_get(space, offset));
ut_ad(buf_pool_mutex_own(buf_pool));
ut_ad(mutex_own(&(block->mutex)));
ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
@@ -3186,7 +3162,7 @@ err_exit:
ut_ad(buf_pool_from_bpage(bpage) == buf_pool);
- buf_page_init(space, offset, fold, block);
+ buf_page_init(buf_pool, space, offset, fold, block);
/* The block must be put to the LRU list, to the old blocks */
buf_LRU_add_block(bpage, TRUE/* to old blocks */);
@@ -3390,7 +3366,7 @@ buf_page_create(
mutex_enter(&block->mutex);
- buf_page_init(space, offset, fold, block);
+ buf_page_init(buf_pool, space, offset, fold, block);
/* The block must be put to the LRU list */
buf_LRU_add_block(&block->page, FALSE);
@@ -3474,6 +3450,53 @@ buf_page_create(
}
/********************************************************************//**
+Mark a table with the specified space pointed by bpage->space corrupted.
+Also remove the bpage from LRU list.
+@return TRUE if successful */
+static
+ibool
+buf_mark_space_corrupt(
+/*===================*/
+ buf_page_t* bpage) /*!< in: pointer to the block in question */
+{
+ buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
+ const ibool uncompressed = (buf_page_get_state(bpage)
+ == BUF_BLOCK_FILE_PAGE);
+ ulint space = bpage->space;
+ ibool ret = TRUE;
+
+ /* First unfix and release lock on the bpage */
+ buf_pool_mutex_enter(buf_pool);
+ mutex_enter(buf_page_get_mutex(bpage));
+ ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ);
+ ut_ad(bpage->buf_fix_count == 0);
+
+ /* Set BUF_IO_NONE before we remove the block from LRU list */
+ buf_page_set_io_fix(bpage, BUF_IO_NONE);
+
+ if (uncompressed) {
+ rw_lock_x_unlock_gen(
+ &((buf_block_t*) bpage)->lock,
+ BUF_IO_READ);
+ }
+
+ /* Find the table with specified space id, and mark it corrupted */
+ if (dict_set_corrupted_by_space(space)) {
+ buf_LRU_free_one_page(bpage);
+ } else {
+ ret = FALSE;
+ }
+
+ ut_ad(buf_pool->n_pend_reads > 0);
+ buf_pool->n_pend_reads--;
+
+ mutex_exit(buf_page_get_mutex(bpage));
+ buf_pool_mutex_exit(buf_pool);
+
+ return(ret);
+}
+
+/********************************************************************//**
Completes an asynchronous read or write request of a file page to or from
the buffer pool. */
UNIV_INTERN
@@ -3598,10 +3621,19 @@ corrupt:
"InnoDB: about forcing recovery.\n", stderr);
if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
- fputs("InnoDB: Ending processing because of"
- " a corrupt database page.\n",
- stderr);
- exit(1);
+ /* If page space id is larger than TRX_SYS_SPACE
+ (0), we will attempt to mark the corresponding
+ table as corrupted instead of crashing server */
+ if (bpage->space > TRX_SYS_SPACE
+ && buf_mark_space_corrupt(bpage)) {
+ return;
+ } else {
+ fputs("InnoDB: Ending processing"
+ " because of"
+ " a corrupt database page.\n",
+ stderr);
+ ut_error;
+ }
}
}
diff --git a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
index 93c98719e29..b5ca21e14a6 100644
--- a/storage/innobase/buf/buf0lru.c
+++ b/storage/innobase/buf/buf0lru.c
@@ -1885,6 +1885,22 @@ buf_LRU_block_free_hashed_page(
buf_LRU_block_free_non_file_page(block);
}
+/******************************************************************//**
+Remove one page from LRU list and put it to free list */
+UNIV_INTERN
+void
+buf_LRU_free_one_page(
+/*==================*/
+ buf_page_t* bpage) /*!< in/out: block, must contain a file page and
+ be in a state where it can be freed; there
+ may or may not be a hash index to the page */
+{
+ if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
+ != BUF_BLOCK_ZIP_FREE) {
+ buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
+ }
+}
+
/**********************************************************************//**
Updates buf_pool->LRU_old_ratio for one buffer pool instance.
@return updated old_pct */
diff --git a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.c
index 9a528d679a7..d7373a4b8ef 100644
--- a/storage/innobase/dict/dict0crea.c
+++ b/storage/innobase/dict/dict0crea.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, 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
@@ -827,7 +827,7 @@ dict_truncate_index_tree(
appropriate field in the SYS_INDEXES record: this mini-transaction
marks the B-tree totally truncated */
- btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
+ btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, NULL, mtr);
btr_free_root(space, zip_size, root_page_no, mtr);
create:
diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
index 1e3aed92cf7..2a2c7652817 100644
--- a/storage/innobase/dict/dict0dict.c
+++ b/storage/innobase/dict/dict0dict.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, 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
@@ -54,6 +54,7 @@ UNIV_INTERN dict_index_t* dict_ind_compact;
#include "row0merge.h"
#include "m_ctype.h" /* my_isspace() */
#include "ha_prototypes.h" /* innobase_strcasecmp(), innobase_casedn_str()*/
+#include "row0upd.h"
#include <ctype.h>
@@ -611,8 +612,7 @@ dict_table_get_on_id(
{
dict_table_t* table;
- if (table_id <= DICT_FIELDS_ID
- || trx->dict_operation_lock_mode == RW_X_LATCH) {
+ if (trx->dict_operation_lock_mode == RW_X_LATCH) {
/* Note: An X latch implies that the transaction
already owns the dictionary mutex. */
@@ -1714,7 +1714,8 @@ undo_size_ok:
new_index->page = page_no;
rw_lock_create(index_tree_rw_lock_key, &new_index->lock,
- SYNC_INDEX_TREE);
+ dict_index_is_ibuf(index)
+ ? SYNC_IBUF_INDEX_TREE : SYNC_INDEX_TREE);
if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
@@ -5045,4 +5046,187 @@ dict_close(void)
rw_lock_free(&dict_table_stats_latches[i]);
}
}
+
+/**********************************************************************//**
+Find a table in dict_sys->table_LRU list with specified space id
+@return table if found, NULL if not */
+static
+dict_table_t*
+dict_find_table_by_space(
+/*=====================*/
+ ulint space_id) /*!< in: space ID */
+{
+ dict_table_t* table;
+ ulint num_item;
+ ulint count = 0;
+
+ ut_ad(space_id > 0);
+
+ table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
+ num_item = UT_LIST_GET_LEN(dict_sys->table_LRU);
+
+ /* This function intentionally does not acquire mutex as it is used
+ by error handling code in deep call stack as last means to avoid
+ killing the server, so it worth to risk some consequencies for
+ the action. */
+ while (table && count < num_item) {
+ if (table->space == space_id) {
+ return(table);
+ }
+
+ table = UT_LIST_GET_NEXT(table_LRU, table);
+ count++;
+ }
+
+ return(NULL);
+}
+
+/**********************************************************************//**
+Flags a table with specified space_id corrupted in the data dictionary
+cache
+@return TRUE if successful */
+UNIV_INTERN
+ibool
+dict_set_corrupted_by_space(
+/*========================*/
+ ulint space_id) /*!< in: space ID */
+{
+ dict_table_t* table;
+
+ table = dict_find_table_by_space(space_id);
+
+ if (!table) {
+ return(FALSE);
+ }
+
+ /* mark the table->corrupted bit only, since the caller
+ could be too deep in the stack for SYS_INDEXES update */
+ table->corrupted = TRUE;
+
+ return(TRUE);
+}
+
+/**********************************************************************//**
+Flags an index corrupted both in the data dictionary cache
+and in the SYS_INDEXES */
+UNIV_INTERN
+void
+dict_set_corrupted(
+/*===============*/
+ dict_index_t* index) /*!< in/out: index */
+{
+ mem_heap_t* heap;
+ mtr_t mtr;
+ dict_index_t* sys_index;
+ dtuple_t* tuple;
+ dfield_t* dfield;
+ byte* buf;
+ const char* status;
+ btr_cur_t cursor;
+
+ ut_ad(index);
+ ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(!dict_table_is_comp(dict_sys->sys_tables));
+ ut_ad(!dict_table_is_comp(dict_sys->sys_indexes));
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(sync_thread_levels_empty_except_dict());
+#endif
+
+ /* Mark the table as corrupted only if the clustered index
+ is corrupted */
+ if (dict_index_is_clust(index)) {
+ index->table->corrupted = TRUE;
+ }
+
+ if (UNIV_UNLIKELY(dict_index_is_corrupted(index))) {
+ /* The index was already flagged corrupted. */
+ ut_ad(index->table->corrupted);
+ return;
+ }
+
+ heap = mem_heap_create(sizeof(dtuple_t) + 2 * (sizeof(dfield_t)
+ + sizeof(que_fork_t) + sizeof(upd_node_t)
+ + sizeof(upd_t) + 12));
+ mtr_start(&mtr);
+ index->type |= DICT_CORRUPT;
+
+ sys_index = UT_LIST_GET_FIRST(dict_sys->sys_indexes->indexes);
+
+ /* Find the index row in SYS_INDEXES */
+ tuple = dtuple_create(heap, 2);
+
+ dfield = dtuple_get_nth_field(tuple, 0);
+ buf = mem_heap_alloc(heap, 8);
+ mach_write_to_8(buf, index->table->id);
+ dfield_set_data(dfield, buf, 8);
+
+ dfield = dtuple_get_nth_field(tuple, 1);
+ buf = mem_heap_alloc(heap, 8);
+ mach_write_to_8(buf, index->id);
+ dfield_set_data(dfield, buf, 8);
+
+ dict_index_copy_types(tuple, sys_index, 2);
+
+ btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_GE,
+ BTR_MODIFY_LEAF,
+ &cursor, 0, __FILE__, __LINE__, &mtr);
+
+ if (cursor.up_match == dtuple_get_n_fields(tuple)) {
+ /* UPDATE SYS_INDEXES SET TYPE=index->type
+ WHERE TABLE_ID=index->table->id AND INDEX_ID=index->id */
+ ulint len;
+ byte* field = rec_get_nth_field_old(
+ btr_cur_get_rec(&cursor),
+ DICT_SYS_INDEXES_TYPE_FIELD, &len);
+ if (len != 4) {
+ goto fail;
+ }
+ mlog_write_ulint(field, index->type, MLOG_4BYTES, &mtr);
+ status = " InnoDB: Flagged corruption of ";
+ } else {
+fail:
+ status = " InnoDB: Unable to flag corruption of ";
+ }
+
+ mtr_commit(&mtr);
+ mem_heap_free(heap);
+
+ ut_print_timestamp(stderr);
+ fputs(status, stderr);
+ dict_index_name_print(stderr, NULL, index);
+ putc('\n', stderr);
+}
+
+/**********************************************************************//**
+Flags an index corrupted in the data dictionary cache only. This
+is used mostly to mark a corrupted index when index's own dictionary
+is corrupted, and we force to load such index for repair purpose */
+UNIV_INTERN
+void
+dict_set_corrupted_index_cache_only(
+/*================================*/
+ dict_index_t* index, /*!< in/out: index */
+ dict_table_t* table) /*!< in/out: table */
+{
+ ut_ad(index);
+ ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(!dict_table_is_comp(dict_sys->sys_tables));
+ ut_ad(!dict_table_is_comp(dict_sys->sys_indexes));
+
+ /* Mark the table as corrupted only if the clustered index
+ is corrupted */
+ if (dict_index_is_clust(index)) {
+ dict_table_t* corrupt_table;
+
+ corrupt_table = table ? table : index->table;
+ ut_ad(!index->table || !table || index->table == table);
+
+ if (corrupt_table) {
+ corrupt_table->corrupted = TRUE;
+ }
+ }
+
+ index->type |= DICT_CORRUPT;
+}
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c
index ab1fb16361e..e13cc1b31f1 100644
--- a/storage/innobase/dict/dict0load.c
+++ b/storage/innobase/dict/dict0load.c
@@ -52,6 +52,11 @@ static const char* SYSTEM_TABLE_NAME[] = {
"SYS_FOREIGN",
"SYS_FOREIGN_COLS"
};
+
+/* If this flag is TRUE, then we will load the cluster index's (and tables')
+metadata even if it is marked as "corrupted". */
+UNIV_INTERN my_bool srv_load_corrupted = FALSE;
+
/****************************************************************//**
Compare the name of an index column.
@return TRUE if the i'th column of index is 'name'. */
@@ -1324,6 +1329,9 @@ err_len:
goto err_len;
}
type = mach_read_from_4(field);
+ if (UNIV_UNLIKELY(type & (~0 << DICT_IT_BITS))) {
+ return("unknown SYS_INDEXES.TYPE bits");
+ }
field = rec_get_nth_field_old(rec, 7/*SPACE*/, &len);
if (UNIV_UNLIKELY(len != 4)) {
@@ -1423,16 +1431,47 @@ dict_load_indexes(
goto next_rec;
} else if (err_msg) {
fprintf(stderr, "InnoDB: %s\n", err_msg);
+ if (ignore_err & DICT_ERR_IGNORE_CORRUPT) {
+ goto next_rec;
+ }
error = DB_CORRUPTION;
goto func_exit;
}
ut_ad(index);
+ /* Check whether the index is corrupted */
+ if (dict_index_is_corrupted(index)) {
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: ", stderr);
+ dict_index_name_print(stderr, NULL, index);
+ fputs(" is corrupted\n", stderr);
+
+ if (!srv_load_corrupted
+ && !(ignore_err & DICT_ERR_IGNORE_CORRUPT)
+ && dict_index_is_clust(index)) {
+ dict_mem_index_free(index);
+
+ error = DB_INDEX_CORRUPT;
+ goto func_exit;
+ } else {
+ /* We will load the index if
+ 1) srv_load_corrupted is TRUE
+ 2) ignore_err is set with
+ DICT_ERR_IGNORE_CORRUPT
+ 3) if the index corrupted is a secondary
+ index */
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: load corrupted index ", stderr);
+ dict_index_name_print(stderr, NULL, index);
+ putc('\n', stderr);
+ }
+ }
+
/* We check for unsupported types first, so that the
subsequent checks are relevant for the supported types. */
- if (index->type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
-
+ if (index->type & ~(DICT_CLUSTERED | DICT_UNIQUE
+ | DICT_CORRUPT)) {
fprintf(stderr,
"InnoDB: Error: unknown type %lu"
" of index %s of table %s\n",
@@ -1453,9 +1492,14 @@ dict_load_indexes(
/* If caller can tolerate this error,
we will continue to load the index and
let caller deal with this error. However
- mark the index and table corrupted */
- index->corrupted = TRUE;
- table->corrupted = TRUE;
+ mark the index and table corrupted. We
+ only need to mark such in the index
+ dictionary cache for such metadata corruption,
+ since we would always be able to set it
+ when loading the dictionary cache */
+ dict_set_corrupted_index_cache_only(
+ index, table);
+
fprintf(stderr,
"InnoDB: Index is corrupt but forcing"
" load into data dictionary\n");
@@ -1495,9 +1539,10 @@ corrupted:
index->name, table->name);
/* If the force recovery flag is set, and
- if the failed index is not the primary index, we
- will continue and open other indexes */
- if (srv_force_recovery
+ if the failed index is not the clustered index,
+ we will continue and open other indexes */
+ if ((srv_force_recovery
+ || srv_load_corrupted)
&& !dict_index_is_clust(index)) {
error = DB_SUCCESS;
goto next_rec;
@@ -1812,6 +1857,30 @@ err_exit:
err = dict_load_indexes(table, heap, ignore_err);
+ if (err == DB_INDEX_CORRUPT) {
+ /* Refuse to load the table if the table has a corrupted
+ cluster index */
+ if (!srv_load_corrupted) {
+ fprintf(stderr, "InnoDB: Error: Load table ");
+ ut_print_name(stderr, NULL, TRUE, table->name);
+ fprintf(stderr, " failed, the table has corrupted"
+ " clustered indexes. Turn on"
+ " 'innodb_force_load_corrupted'"
+ " to drop it\n");
+
+ dict_table_remove_from_cache(table);
+ table = NULL;
+ goto func_exit;
+ } else {
+ dict_index_t* clust_index;
+ clust_index = dict_table_get_first_index(table);
+
+ if (dict_index_is_corrupted(clust_index)) {
+ table->corrupted = TRUE;
+ }
+ }
+ }
+
/* Initialize table foreign_child value. Its value could be
changed when dict_load_foreigns() is called below */
table->fk_max_recusive_level = 0;
@@ -1838,9 +1907,15 @@ err_exit:
index = dict_table_get_first_index(table);
if (!srv_force_recovery || !index
- || !dict_index_is_clust(index)) {
+ || !dict_index_is_clust(index)) {
dict_table_remove_from_cache(table);
table = NULL;
+ } else if (dict_index_is_corrupted(index)) {
+
+ /* It is possible we force to load a corrupted
+ clustered index if srv_load_corrupted is set.
+ Mark the table as corrupted in this case */
+ table->corrupted = TRUE;
}
}
#if 0
@@ -1867,6 +1942,7 @@ err_exit:
mutex_exit(&dict_foreign_err_mutex);
}
#endif /* 0 */
+func_exit:
mem_heap_free(heap);
return(table);
diff --git a/storage/innobase/fsp/fsp0fsp.c b/storage/innobase/fsp/fsp0fsp.c
index 3f09732a676..96d29e8ae32 100644
--- a/storage/innobase/fsp/fsp0fsp.c
+++ b/storage/innobase/fsp/fsp0fsp.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, 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
@@ -311,8 +311,9 @@ fsp_fill_free_list(
descriptor page and ibuf bitmap page;
then we do not allocate more extents */
ulint space, /*!< in: space */
- fsp_header_t* header, /*!< in: space header */
- mtr_t* mtr); /*!< in: mtr */
+ fsp_header_t* header, /*!< in/out: space header */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+ UNIV_COLD __attribute__((nonnull));
/**********************************************************************//**
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space
@@ -325,14 +326,20 @@ fseg_alloc_free_page_low(
ulint space, /*!< in: space */
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
- fseg_inode_t* seg_inode, /*!< in: segment inode */
+ fseg_inode_t* seg_inode, /*!< in/out: segment inode */
ulint hint, /*!< in: hint of which page would be desirable */
byte direction, /*!< in: if the new page is needed because
of an index page split, and records are
inserted there in order, into which
direction they go alphabetically: FSP_DOWN,
FSP_UP, FSP_NO_DIR */
- mtr_t* mtr); /*!< in: mtr handle */
+ mtr_t* mtr, /*!< in/out: mini-transaction */
+ mtr_t* init_mtr)/*!< in/out: mini-transaction in which the
+ page should be initialized
+ (may be the same as mtr), or NULL if it
+ should not be initialized (the page at hint
+ was previously freed in mtr) */
+ __attribute__((warn_unused_result, nonnull(3,6)));
#endif /* !UNIV_HOTBACKUP */
/**********************************************************************//**
@@ -700,17 +707,18 @@ list, if not free limit == space size. This adding is necessary to make the
descriptor defined, as they are uninitialized above the free limit.
@return pointer to the extent descriptor, NULL if the page does not
exist in the space or if the offset exceeds the free limit */
-UNIV_INLINE
+UNIV_INLINE __attribute__((nonnull, warn_unused_result))
xdes_t*
xdes_get_descriptor_with_space_hdr(
/*===============================*/
- fsp_header_t* sp_header,/*!< in/out: space header, x-latched */
- ulint space, /*!< in: space id */
- ulint offset, /*!< in: page offset;
- if equal to the free limit,
- we try to add new extents to
- the space free list */
- mtr_t* mtr) /*!< in: mtr handle */
+ fsp_header_t* sp_header, /*!< in/out: space header, x-latched
+ in mtr */
+ ulint space, /*!< in: space id */
+ ulint offset, /*!< in: page offset; if equal
+ to the free limit, we try to
+ add new extents to the space
+ free list */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint limit;
ulint size;
@@ -718,11 +726,9 @@ xdes_get_descriptor_with_space_hdr(
ulint descr_page_no;
page_t* descr_page;
- ut_ad(mtr);
ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
MTR_MEMO_X_LOCK));
- ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_S_FIX)
- || mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX));
+ ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX));
ut_ad(page_offset(sp_header) == FSP_HEADER_OFFSET);
/* Read free limit and space size */
limit = mach_read_from_4(sp_header + FSP_FREE_LIMIT);
@@ -772,7 +778,7 @@ is necessary to make the descriptor defined, as they are uninitialized
above the free limit.
@return pointer to the extent descriptor, NULL if the page does not
exist in the space or if the offset exceeds the free limit */
-static
+static __attribute__((nonnull, warn_unused_result))
xdes_t*
xdes_get_descriptor(
/*================*/
@@ -781,7 +787,7 @@ xdes_get_descriptor(
or 0 for uncompressed pages */
ulint offset, /*!< in: page offset; if equal to the free limit,
we try to add new extents to the space free list */
- mtr_t* mtr) /*!< in: mtr handle */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
buf_block_t* block;
fsp_header_t* sp_header;
@@ -1159,14 +1165,14 @@ fsp_header_get_tablespace_size(void)
Tries to extend a single-table tablespace so that a page would fit in the
data file.
@return TRUE if success */
-static
+static UNIV_COLD __attribute__((nonnull, warn_unused_result))
ibool
fsp_try_extend_data_file_with_pages(
/*================================*/
ulint space, /*!< in: space */
ulint page_no, /*!< in: page number */
- fsp_header_t* header, /*!< in: space header */
- mtr_t* mtr) /*!< in: mtr */
+ fsp_header_t* header, /*!< in/out: space header */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ibool success;
ulint actual_size;
@@ -1191,7 +1197,7 @@ fsp_try_extend_data_file_with_pages(
/***********************************************************************//**
Tries to extend the last data file of a tablespace if it is auto-extending.
@return FALSE if not auto-extending */
-static
+static UNIV_COLD __attribute__((nonnull))
ibool
fsp_try_extend_data_file(
/*=====================*/
@@ -1201,8 +1207,8 @@ fsp_try_extend_data_file(
the actual file size rounded down to
megabyte */
ulint space, /*!< in: space */
- fsp_header_t* header, /*!< in: space header */
- mtr_t* mtr) /*!< in: mtr */
+ fsp_header_t* header, /*!< in/out: space header */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint size;
ulint zip_size;
@@ -1338,7 +1344,7 @@ fsp_fill_free_list(
then we do not allocate more extents */
ulint space, /*!< in: space */
fsp_header_t* header, /*!< in/out: space header */
- mtr_t* mtr) /*!< in: mtr */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint limit;
ulint size;
@@ -1537,9 +1543,46 @@ fsp_alloc_free_extent(
}
/**********************************************************************//**
+Allocates a single free page from a space. */
+static __attribute__((nonnull))
+void
+fsp_alloc_from_free_frag(
+/*=====================*/
+ fsp_header_t* header, /*!< in/out: tablespace header */
+ xdes_t* descr, /*!< in/out: extent descriptor */
+ ulint bit, /*!< in: slot to allocate in the extent */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+{
+ ulint frag_n_used;
+
+ ut_ad(xdes_get_state(descr, mtr) == XDES_FREE_FRAG);
+ ut_a(xdes_get_bit(descr, XDES_FREE_BIT, bit, mtr));
+ xdes_set_bit(descr, XDES_FREE_BIT, bit, FALSE, mtr);
+
+ /* Update the FRAG_N_USED field */
+ frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
+ mtr);
+ frag_n_used++;
+ mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES,
+ mtr);
+ if (xdes_is_full(descr, mtr)) {
+ /* The fragment is full: move it to another list */
+ flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
+ mtr);
+ xdes_set_state(descr, XDES_FULL_FRAG, mtr);
+
+ flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
+ mtr);
+ mlog_write_ulint(header + FSP_FRAG_N_USED,
+ frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES,
+ mtr);
+ }
+}
+
+/**********************************************************************//**
Allocates a single free page from a space. The page is marked as used.
@return the page offset, FIL_NULL if no page could be allocated */
-static
+static __attribute__((nonnull, warn_unused_result))
ulint
fsp_alloc_free_page(
/*================*/
@@ -1547,19 +1590,22 @@ fsp_alloc_free_page(
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
ulint hint, /*!< in: hint of which page would be desirable */
- mtr_t* mtr) /*!< in: mtr handle */
+ mtr_t* mtr, /*!< in/out: mini-transaction */
+ mtr_t* init_mtr)/*!< in/out: mini-transaction in which the
+ page should be initialized
+ (may be the same as mtr) */
{
fsp_header_t* header;
fil_addr_t first;
xdes_t* descr;
buf_block_t* block;
ulint free;
- ulint frag_n_used;
ulint page_no;
ulint space_size;
ibool success;
ut_ad(mtr);
+ ut_ad(init_mtr);
header = fsp_get_space_header(space, zip_size, mtr);
@@ -1641,38 +1687,19 @@ fsp_alloc_free_page(
}
}
- xdes_set_bit(descr, XDES_FREE_BIT, free, FALSE, mtr);
-
- /* Update the FRAG_N_USED field */
- frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
- mtr);
- frag_n_used++;
- mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES,
- mtr);
- if (xdes_is_full(descr, mtr)) {
- /* The fragment is full: move it to another list */
- flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
- mtr);
- xdes_set_state(descr, XDES_FULL_FRAG, mtr);
-
- flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
- mtr);
- mlog_write_ulint(header + FSP_FRAG_N_USED,
- frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES,
- mtr);
- }
+ fsp_alloc_from_free_frag(header, descr, free, mtr);
/* Initialize the allocated page to the buffer pool, so that it can
be obtained immediately with buf_page_get without need for a disk
read. */
- buf_page_create(space, page_no, zip_size, mtr);
+ buf_page_create(space, page_no, zip_size, init_mtr);
- block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, mtr);
+ block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, init_mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
/* Prior contents of the page should be ignored */
- fsp_init_file_page(block, mtr);
+ fsp_init_file_page(block, init_mtr);
return(page_no);
}
@@ -1908,7 +1935,7 @@ fsp_alloc_seg_inode_page(
zip_size = dict_table_flags_to_zip_size(
mach_read_from_4(FSP_SPACE_FLAGS + space_header));
- page_no = fsp_alloc_free_page(space, zip_size, 0, mtr);
+ page_no = fsp_alloc_free_page(space, zip_size, 0, mtr, mtr);
if (page_no == FIL_NULL) {
@@ -2320,7 +2347,7 @@ fseg_create_general(
if (page == 0) {
page = fseg_alloc_free_page_low(space, zip_size,
- inode, 0, FSP_UP, mtr);
+ inode, 0, FSP_UP, mtr, mtr);
if (page == FIL_NULL) {
@@ -2569,14 +2596,19 @@ fseg_alloc_free_page_low(
ulint space, /*!< in: space */
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
- fseg_inode_t* seg_inode, /*!< in: segment inode */
+ fseg_inode_t* seg_inode, /*!< in/out: segment inode */
ulint hint, /*!< in: hint of which page would be desirable */
byte direction, /*!< in: if the new page is needed because
of an index page split, and records are
inserted there in order, into which
direction they go alphabetically: FSP_DOWN,
FSP_UP, FSP_NO_DIR */
- mtr_t* mtr) /*!< in: mtr handle */
+ mtr_t* mtr, /*!< in/out: mini-transaction */
+ mtr_t* init_mtr)/*!< in/out: mini-transaction in which the
+ page should be initialized
+ (may be the same as mtr), or NULL if it
+ should not be initialized (the page at hint
+ was previously freed in mtr) */
{
fsp_header_t* space_header;
ulint space_size;
@@ -2587,7 +2619,6 @@ fseg_alloc_free_page_low(
ulint ret_page; /*!< the allocated page offset, FIL_NULL
if could not be allocated */
xdes_t* ret_descr; /*!< the extent of the allocated page */
- ibool frag_page_allocated = FALSE;
ibool success;
ulint n;
@@ -2609,6 +2640,8 @@ fseg_alloc_free_page_low(
if (descr == NULL) {
/* Hint outside space or too high above free limit: reset
hint */
+ ut_a(init_mtr);
+ /* The file space header page is always allocated. */
hint = 0;
descr = xdes_get_descriptor(space, zip_size, hint, mtr);
}
@@ -2619,15 +2652,20 @@ fseg_alloc_free_page_low(
&& mach_read_from_8(descr + XDES_ID) == seg_id
&& (xdes_get_bit(descr, XDES_FREE_BIT,
hint % FSP_EXTENT_SIZE, mtr) == TRUE)) {
-
+take_hinted_page:
/* 1. We can take the hinted page
=================================*/
ret_descr = descr;
ret_page = hint;
+ /* Skip the check for extending the tablespace. If the
+ page hint were not within the size of the tablespace,
+ we would have got (descr == NULL) above and reset the hint. */
+ goto got_hinted_page;
/*-----------------------------------------------------------*/
- } else if ((xdes_get_state(descr, mtr) == XDES_FREE)
- && ((reserved - used) < reserved / FSEG_FILLFACTOR)
- && (used >= FSEG_FRAG_LIMIT)) {
+ } else if (xdes_get_state(descr, mtr) == XDES_FREE
+ && (!init_mtr
+ || ((reserved - used < reserved / FSEG_FILLFACTOR)
+ && used >= FSEG_FRAG_LIMIT))) {
/* 2. We allocate the free extent from space and can take
=========================================================
@@ -2645,8 +2683,20 @@ fseg_alloc_free_page_low(
/* Try to fill the segment free list */
fseg_fill_free_list(seg_inode, space, zip_size,
hint + FSP_EXTENT_SIZE, mtr);
- ret_page = hint;
+ goto take_hinted_page;
/*-----------------------------------------------------------*/
+ } else if (!init_mtr) {
+ ut_a(xdes_get_state(descr, mtr) == XDES_FREE_FRAG);
+ fsp_alloc_from_free_frag(space_header, descr,
+ hint % FSP_EXTENT_SIZE, mtr);
+ ret_page = hint;
+ ret_descr = NULL;
+
+ /* Put the page in the fragment page array of the segment */
+ n = fseg_find_free_frag_page_slot(seg_inode, mtr);
+ ut_a(n != FIL_NULL);
+ fseg_set_nth_frag_page_no(seg_inode, n, ret_page, mtr);
+ goto got_hinted_page;
} else if ((direction != FSP_NO_DIR)
&& ((reserved - used) < reserved / FSEG_FILLFACTOR)
&& (used >= FSEG_FRAG_LIMIT)
@@ -2705,11 +2755,10 @@ fseg_alloc_free_page_low(
} else if (used < FSEG_FRAG_LIMIT) {
/* 6. We allocate an individual page from the space
===================================================*/
- ret_page = fsp_alloc_free_page(space, zip_size, hint, mtr);
+ ret_page = fsp_alloc_free_page(space, zip_size, hint,
+ mtr, init_mtr);
ret_descr = NULL;
- frag_page_allocated = TRUE;
-
if (ret_page != FIL_NULL) {
/* Put the page in the fragment page array of the
segment */
@@ -2719,6 +2768,10 @@ fseg_alloc_free_page_low(
fseg_set_nth_frag_page_no(seg_inode, n, ret_page,
mtr);
}
+
+ /* fsp_alloc_free_page() invoked fsp_init_file_page()
+ already. */
+ return(ret_page);
/*-----------------------------------------------------------*/
} else {
/* 7. We allocate a new extent and take its first page
@@ -2766,26 +2819,34 @@ fseg_alloc_free_page_low(
}
}
- if (!frag_page_allocated) {
+got_hinted_page:
+ {
/* Initialize the allocated page to buffer pool, so that it
can be obtained immediately with buf_page_get without need
for a disk read */
buf_block_t* block;
ulint zip_size = dict_table_flags_to_zip_size(
mach_read_from_4(FSP_SPACE_FLAGS + space_header));
+ mtr_t* block_mtr = init_mtr ? init_mtr : mtr;
- block = buf_page_create(space, ret_page, zip_size, mtr);
+ block = buf_page_create(space, ret_page, zip_size, block_mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
if (UNIV_UNLIKELY(block != buf_page_get(space, zip_size,
ret_page, RW_X_LATCH,
- mtr))) {
+ block_mtr))) {
ut_error;
}
- /* The prior contents of the page should be ignored */
- fsp_init_file_page(block, mtr);
+ if (init_mtr) {
+ /* The prior contents of the page should be ignored */
+ fsp_init_file_page(block, init_mtr);
+ }
+ }
+ /* ret_descr == NULL if the block was allocated from free_frag
+ (XDES_FREE_FRAG) */
+ if (ret_descr != NULL) {
/* At this point we know the extent and the page offset.
The extent is still in the appropriate list (FSEG_NOT_FULL
or FSEG_FREE), and the page is not yet marked as used. */
@@ -2798,8 +2859,6 @@ fseg_alloc_free_page_low(
fseg_mark_page_used(seg_inode, space, zip_size, ret_page, mtr);
}
- buf_reset_check_index_page_at_flush(space, ret_page);
-
return(ret_page);
}
@@ -2812,7 +2871,7 @@ UNIV_INTERN
ulint
fseg_alloc_free_page_general(
/*=========================*/
- fseg_header_t* seg_header,/*!< in: segment header */
+ fseg_header_t* seg_header,/*!< in/out: segment header */
ulint hint, /*!< in: hint of which page would be desirable */
byte direction,/*!< in: if the new page is needed because
of an index page split, and records are
@@ -2824,7 +2883,11 @@ fseg_alloc_free_page_general(
with fsp_reserve_free_extents, then there
is no need to do the check for this individual
page */
- mtr_t* mtr) /*!< in: mtr handle */
+ mtr_t* mtr, /*!< in/out: mini-transaction handle */
+ mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
+ in which the page should be initialized,
+ or NULL if this is a "fake allocation" of
+ a page that was previously freed in mtr */
{
fseg_inode_t* inode;
ulint space;
@@ -2866,7 +2929,8 @@ fseg_alloc_free_page_general(
}
page_no = fseg_alloc_free_page_low(space, zip_size,
- inode, hint, direction, mtr);
+ inode, hint, direction,
+ mtr, init_mtr);
if (!has_done_reservation) {
fil_space_release_free_extents(space, n_reserved);
}
@@ -2875,28 +2939,6 @@ fseg_alloc_free_page_general(
}
/**********************************************************************//**
-Allocates a single free page from a segment. This function implements
-the intelligent allocation strategy which tries to minimize file space
-fragmentation.
-@return allocated page offset, FIL_NULL if no page could be allocated */
-UNIV_INTERN
-ulint
-fseg_alloc_free_page(
-/*=================*/
- fseg_header_t* seg_header,/*!< in: segment header */
- ulint hint, /*!< in: hint of which page would be desirable */
- byte direction,/*!< in: if the new page is needed because
- of an index page split, and records are
- inserted there in order, into which
- direction they go alphabetically: FSP_DOWN,
- FSP_UP, FSP_NO_DIR */
- mtr_t* mtr) /*!< in: mtr handle */
-{
- return(fseg_alloc_free_page_general(seg_header, hint, direction,
- FALSE, mtr));
-}
-
-/**********************************************************************//**
Checks that we have at least 2 frag pages free in the first extent of a
single-table tablespace, and they are also physically initialized to the data
file. That is we have already extended the data file so that those pages are
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 4648b4300b8..ce08b594f3e 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -1043,6 +1043,10 @@ convert_error_code_to_mysql(
#endif /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
case DB_UNSUPPORTED:
return(HA_ERR_UNSUPPORTED);
+ case DB_INDEX_CORRUPT:
+ return(HA_ERR_INDEX_CORRUPT);
+ case DB_UNDO_RECORD_TOO_BIG:
+ return(HA_ERR_UNDO_REC_TOO_BIG);
}
}
@@ -2078,6 +2082,29 @@ no_db_name:
}
+/*****************************************************************//**
+A wrapper function of innobase_convert_name(), convert a table or
+index name to the MySQL system_charset_info (UTF-8) and quote it if needed.
+@return pointer to the end of buf */
+static inline
+void
+innobase_format_name(
+/*==================*/
+ char* buf, /*!< out: buffer for converted identifier */
+ ulint buflen, /*!< in: length of buf, in bytes */
+ const char* name, /*!< in: index or table name to format */
+ ibool is_index_name) /*!< in: index name */
+{
+ const char* bufend;
+
+ bufend = innobase_convert_name(buf, buflen, name, strlen(name),
+ NULL, !is_index_name);
+
+ ut_ad((ulint) (bufend - buf) < buflen);
+
+ buf[bufend - buf] = '\0';
+}
+
/**********************************************************************//**
Determines if the currently running transaction has been interrupted.
@return TRUE if interrupted */
@@ -5645,12 +5672,14 @@ ha_innobase::index_read(
index = prebuilt->index;
- if (UNIV_UNLIKELY(index == NULL)) {
+ if (UNIV_UNLIKELY(index == NULL) || dict_index_is_corrupted(index)) {
prebuilt->index_usable = FALSE;
DBUG_RETURN(HA_ERR_CRASHED);
}
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
- DBUG_RETURN(HA_ERR_TABLE_DEF_CHANGED);
+ DBUG_RETURN(dict_index_is_corrupted(index)
+ ? HA_ERR_INDEX_CORRUPT
+ : HA_ERR_TABLE_DEF_CHANGED);
}
/* Note that if the index for which the search template is built is not
@@ -5836,10 +5865,33 @@ ha_innobase::change_active_index(
prebuilt->index);
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
- push_warning_printf(user_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- HA_ERR_TABLE_DEF_CHANGED,
- "InnoDB: insufficient history for index %u",
- keynr);
+ if (dict_index_is_corrupted(prebuilt->index)) {
+ char index_name[MAX_FULL_NAME_LEN + 1];
+ char table_name[MAX_FULL_NAME_LEN + 1];
+
+ innobase_format_name(
+ index_name, sizeof index_name,
+ prebuilt->index->name, TRUE);
+
+ innobase_format_name(
+ table_name, sizeof table_name,
+ prebuilt->index->table->name, FALSE);
+
+ push_warning_printf(
+ user_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ HA_ERR_INDEX_CORRUPT,
+ "InnoDB: Index %s for table %s is"
+ " marked as corrupted",
+ index_name, table_name);
+ DBUG_RETURN(1);
+ } else {
+ push_warning_printf(
+ user_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ HA_ERR_TABLE_DEF_CHANGED,
+ "InnoDB: insufficient history for index %u",
+ keynr);
+ }
+
/* The caller seems to ignore this. Thus, we must check
this again in row_search_for_mysql(). */
DBUG_RETURN(2);
@@ -7499,6 +7551,10 @@ ha_innobase::records_in_range(
n_rows = HA_POS_ERROR;
goto func_exit;
}
+ if (dict_index_is_corrupted(index)) {
+ n_rows = HA_ERR_INDEX_CORRUPT;
+ goto func_exit;
+ }
if (UNIV_UNLIKELY(!row_merge_is_index_usable(prebuilt->trx, index))) {
n_rows = HA_ERR_TABLE_DEF_CHANGED;
goto func_exit;
@@ -8165,6 +8221,7 @@ ha_innobase::check(
ulint n_rows_in_table = ULINT_UNDEFINED;
ibool is_ok = TRUE;
ulint old_isolation_level;
+ ibool table_corrupted;
DBUG_ENTER("ha_innobase::check");
DBUG_ASSERT(thd == ha_thd());
@@ -8206,6 +8263,14 @@ ha_innobase::check(
prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
+ /* Check whether the table is already marked as corrupted
+ before running the check table */
+ table_corrupted = prebuilt->table->corrupted;
+
+ /* Reset table->corrupted bit so that check table can proceed to
+ do additional check */
+ prebuilt->table->corrupted = FALSE;
+
/* Enlarge the fatal lock wait timeout during CHECK TABLE. */
mutex_enter(&kernel_mutex);
srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
@@ -8214,6 +8279,7 @@ ha_innobase::check(
for (index = dict_table_get_first_index(prebuilt->table);
index != NULL;
index = dict_table_get_next_index(index)) {
+ char index_name[MAX_FULL_NAME_LEN + 1];
#if 0
fputs("Validating index ", stderr);
ut_print_name(stderr, trx, FALSE, index->name);
@@ -8222,11 +8288,16 @@ ha_innobase::check(
if (!btr_validate_index(index, prebuilt->trx)) {
is_ok = FALSE;
+
+ innobase_format_name(
+ index_name, sizeof index_name,
+ prebuilt->index->name, TRUE);
+
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_NOT_KEYFILE,
"InnoDB: The B-tree of"
- " index '%-.200s' is corrupted.",
- index->name);
+ " index %s is corrupted.",
+ index_name);
continue;
}
@@ -8239,11 +8310,26 @@ ha_innobase::check(
prebuilt->trx, prebuilt->index);
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- HA_ERR_TABLE_DEF_CHANGED,
- "InnoDB: Insufficient history for"
- " index '%-.200s'",
- index->name);
+ innobase_format_name(
+ index_name, sizeof index_name,
+ prebuilt->index->name, TRUE);
+
+ if (dict_index_is_corrupted(prebuilt->index)) {
+ push_warning_printf(
+ user_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ HA_ERR_INDEX_CORRUPT,
+ "InnoDB: Index %s is marked as"
+ " corrupted",
+ index_name);
+ is_ok = FALSE;
+ } else {
+ push_warning_printf(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ HA_ERR_TABLE_DEF_CHANGED,
+ "InnoDB: Insufficient history for"
+ " index %s",
+ index_name);
+ }
continue;
}
@@ -8257,12 +8343,19 @@ ha_innobase::check(
prebuilt->select_lock_type = LOCK_NONE;
if (!row_check_index_for_mysql(prebuilt, index, &n_rows)) {
+ innobase_format_name(
+ index_name, sizeof index_name,
+ index->name, TRUE);
+
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_NOT_KEYFILE,
"InnoDB: The B-tree of"
- " index '%-.200s' is corrupted.",
- index->name);
+ " index %s is corrupted.",
+ index_name);
is_ok = FALSE;
+ row_mysql_lock_data_dictionary(prebuilt->trx);
+ dict_set_corrupted(index);
+ row_mysql_unlock_data_dictionary(prebuilt->trx);
}
if (thd_killed(user_thd)) {
@@ -8289,6 +8382,20 @@ ha_innobase::check(
}
}
+ if (table_corrupted) {
+ /* If some previous operation has marked the table as
+ corrupted in memory, and has not propagated such to
+ clustered index, we will do so here */
+ index = dict_table_get_first_index(prebuilt->table);
+
+ if (!dict_index_is_corrupted(index)) {
+ mutex_enter(&dict_sys->mutex);
+ dict_set_corrupted(index);
+ mutex_exit(&dict_sys->mutex);
+ }
+ prebuilt->table->corrupted = TRUE;
+ }
+
/* Restore the original isolation level */
prebuilt->trx->isolation_level = old_isolation_level;
@@ -11082,6 +11189,11 @@ static MYSQL_SYSVAR_BOOL(large_prefix, innobase_large_prefix,
"Support large index prefix length of REC_VERSION_56_MAX_INDEX_COL_LEN (3072) bytes.",
NULL, NULL, FALSE);
+static MYSQL_SYSVAR_BOOL(force_load_corrupted, srv_load_corrupted,
+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
+ "Force InnoDB to load metadata of corrupted table.",
+ NULL, NULL, FALSE);
+
static MYSQL_SYSVAR_BOOL(locks_unsafe_for_binlog, innobase_locks_unsafe_for_binlog,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
"Force InnoDB to not use next-key locking, to use only row-level locking.",
@@ -11341,6 +11453,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(flush_method),
MYSQL_SYSVAR(force_recovery),
MYSQL_SYSVAR(large_prefix),
+ MYSQL_SYSVAR(force_load_corrupted),
MYSQL_SYSVAR(locks_unsafe_for_binlog),
MYSQL_SYSVAR(lock_wait_timeout),
#ifdef UNIV_LOG_ARCHIVE
diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c
index 7d94ebc6438..7f6acb2b042 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.c
+++ b/storage/innobase/ibuf/ibuf0ibuf.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1997, 2011, 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
@@ -402,7 +402,7 @@ ibuf_tree_root_get(
block = buf_page_get(
IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO, RW_X_LATCH, mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
root = buf_block_get_frame(block);
@@ -549,7 +549,7 @@ ibuf_init_at_db_start(void)
block = buf_page_get(
IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO,
RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
root = buf_block_get_frame(block);
}
@@ -2209,16 +2209,17 @@ ibuf_add_free_page(void)
} else {
buf_block_t* block = buf_page_get(
IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
- page = buf_block_get_frame(block);
- }
+ ibuf_enter(&mtr);
- ibuf_enter(&mtr);
+ mutex_enter(&ibuf_mutex);
- mutex_enter(&ibuf_mutex);
+ root = ibuf_tree_root_get(&mtr);
- root = ibuf_tree_root_get(&mtr);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
+
+ page = buf_block_get_frame(block);
+ }
/* Add the page to the free list and update the ibuf size data */
@@ -2332,8 +2333,7 @@ ibuf_remove_free_page(void)
block = buf_page_get(
IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
-
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
page = buf_block_get_frame(block);
}
@@ -3022,7 +3022,7 @@ ibuf_get_volume_buffered(
IBUF_SPACE_ID, 0, prev_page_no, RW_X_LATCH,
mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
prev_page = buf_block_get_frame(block);
@@ -3095,7 +3095,7 @@ count_later:
IBUF_SPACE_ID, 0, next_page_no, RW_X_LATCH,
mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
next_page = buf_block_get_frame(block);
@@ -3333,7 +3333,7 @@ ibuf_set_entry_counter(
IBUF_SPACE_ID, 0, prev_page_no,
RW_X_LATCH, mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
prev_page = buf_block_get_frame(block);
@@ -4419,6 +4419,7 @@ ibuf_merge_or_delete_for_page(
ut_ad(!block || buf_block_get_space(block) == space);
ut_ad(!block || buf_block_get_page_no(block) == page_no);
ut_ad(!block || buf_block_get_zip_size(block) == zip_size);
+ ut_ad(!block || buf_block_get_io_fix(block) == BUF_IO_READ);
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE
|| trx_sys_hdr_page(space, page_no)) {
@@ -4571,7 +4572,13 @@ loop:
ut_a(success);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ /* This is a user page (secondary index leaf page),
+ but we pretend that it is a change buffer page in
+ order to obey the latching order. This should be OK,
+ because buffered changes are applied immediately while
+ the block is io-fixed. Other threads must not try to
+ latch an io-fixed block. */
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
}
/* Position pcur in the insert buffer at the first entry for this
@@ -4675,7 +4682,12 @@ loop:
__FILE__, __LINE__, &mtr);
ut_a(success);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ /* This is a user page (secondary
+ index leaf page), but it should be OK
+ to use too low latching order for it,
+ as the block is io-fixed. */
+ buf_block_dbg_add_level(
+ block, SYNC_IBUF_TREE_NODE);
if (!ibuf_restore_pos(space, page_no,
search_tuple,
diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h
index 24f3801c7f8..3dfd98ceb08 100644
--- a/storage/innobase/include/btr0btr.h
+++ b/storage/innobase/include/btr0btr.h
@@ -199,26 +199,45 @@ btr_block_get_func(
ulint mode, /*!< in: latch mode */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
- mtr_t* mtr) /*!< in/out: mtr */
- __attribute__((nonnull));
+# ifdef UNIV_SYNC_DEBUG
+ const dict_index_t* index, /*!< in: index tree, may be NULL
+ if it is not an insert buffer tree */
+# endif /* UNIV_SYNC_DEBUG */
+ mtr_t* mtr); /*!< in/out: mini-transaction */
+# ifdef UNIV_SYNC_DEBUG
/** Gets a buffer page and declares its latching order level.
@param space tablespace identifier
@param zip_size compressed page size in bytes or 0 for uncompressed pages
@param page_no page number
@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(space,zip_size,page_no,mode,mtr) \
+# define btr_block_get(space,zip_size,page_no,mode,index,mtr) \
+ btr_block_get_func(space,zip_size,page_no,mode, \
+ __FILE__,__LINE__,index,mtr)
+# else /* UNIV_SYNC_DEBUG */
+/** Gets a buffer page and declares its latching order level.
+@param space tablespace identifier
+@param zip_size compressed page size in bytes or 0 for uncompressed pages
+@param page_no page number
+@param mode latch mode
+@param idx index tree, may be NULL if not the insert buffer tree
+@param mtr mini-transaction handle
+@return the block descriptor */
+# define btr_block_get(space,zip_size,page_no,mode,idx,mtr) \
btr_block_get_func(space,zip_size,page_no,mode,__FILE__,__LINE__,mtr)
+# endif /* UNIV_SYNC_DEBUG */
/** Gets a buffer page and declares its latching order level.
@param space tablespace identifier
@param zip_size compressed page size in bytes or 0 for uncompressed pages
@param page_no page number
@param mode latch mode
+@param idx index tree, may be NULL if not the insert buffer tree
@param mtr mini-transaction handle
@return the uncompressed page frame */
-# define btr_page_get(space,zip_size,page_no,mode,mtr) \
- buf_block_get_frame(btr_block_get(space,zip_size,page_no,mode,mtr))
+# define btr_page_get(space,zip_size,page_no,mode,idx,mtr) \
+ buf_block_get_frame(btr_block_get(space,zip_size,page_no,mode,idx,mtr))
#endif /* !UNIV_HOTBACKUP */
/**************************************************************//**
Gets the index id field of a page.
@@ -344,8 +363,7 @@ btr_free_root(
ulint zip_size, /*!< in: compressed page size in bytes
or 0 for uncompressed pages */
ulint root_page_no, /*!< in: root page number */
- mtr_t* mtr); /*!< in: a mini-transaction which has already
- been started */
+ mtr_t* mtr); /*!< in/out: mini-transaction */
/*************************************************************//**
Makes tree one level higher by splitting the root, and inserts
the tuple. It is assumed that mtr contains an x-latch on the tree.
@@ -550,7 +568,12 @@ btr_page_alloc(
page split is made */
ulint level, /*!< in: level where the page is placed
in the tree */
- mtr_t* mtr); /*!< in: mtr */
+ mtr_t* mtr, /*!< in/out: mini-transaction
+ for the allocation */
+ mtr_t* init_mtr) /*!< in/out: mini-transaction
+ for x-latching and initializing
+ the page */
+ __attribute__((nonnull, warn_unused_result));
/**************************************************************//**
Frees a file page used in an index tree. NOTE: cannot free field external
storage pages because the page must contain info on its level. */
@@ -573,6 +596,33 @@ btr_page_free_low(
buf_block_t* block, /*!< in: block to be freed, x-latched */
ulint level, /*!< in: page level */
mtr_t* mtr); /*!< in: mtr */
+/**************************************************************//**
+Marks all MTR_MEMO_FREE_CLUST_LEAF pages nonfree or free.
+For invoking btr_store_big_rec_extern_fields() after an update,
+we must temporarily mark freed clustered index pages allocated, so
+that off-page columns will not be allocated from them. Between the
+btr_store_big_rec_extern_fields() and mtr_commit() we have to
+mark the pages free again, so that no pages will be leaked. */
+UNIV_INTERN
+void
+btr_mark_freed_leaves(
+/*==================*/
+ dict_index_t* index, /*!< in/out: clustered index */
+ mtr_t* mtr, /*!< in/out: mini-transaction */
+ ibool nonfree)/*!< in: TRUE=mark nonfree, FALSE=mark freed */
+ UNIV_COLD __attribute__((nonnull));
+#ifdef UNIV_DEBUG
+/**************************************************************//**
+Validates all pages marked MTR_MEMO_FREE_CLUST_LEAF.
+@see btr_mark_freed_leaves()
+@return TRUE */
+UNIV_INTERN
+ibool
+btr_freed_leaves_validate(
+/*======================*/
+ mtr_t* mtr) /*!< in: mini-transaction */
+ __attribute__((nonnull, warn_unused_result));
+#endif /* UNIV_DEBUG */
#ifdef UNIV_BTR_PRINT
/*************************************************************//**
Prints size info of a B-tree. */
diff --git a/storage/innobase/include/btr0btr.ic b/storage/innobase/include/btr0btr.ic
index ccf41904fd0..1bd22a0ebc6 100644
--- a/storage/innobase/include/btr0btr.ic
+++ b/storage/innobase/include/btr0btr.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -48,6 +48,10 @@ btr_block_get_func(
ulint mode, /*!< in: latch mode */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
+#ifdef UNIV_SYNC_DEBUG
+ const dict_index_t* index, /*!< in: index tree, may be NULL
+ if it is not an insert buffer tree */
+#endif /* UNIV_SYNC_DEBUG */
mtr_t* mtr) /*!< in/out: mtr */
{
buf_block_t* block;
@@ -57,7 +61,9 @@ btr_block_get_func(
if (mode != RW_NO_LATCH) {
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(
+ block, index != NULL && dict_index_is_ibuf(index)
+ ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
}
return(block);
diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h
index e0907ac7bd0..26ed766dbd4 100644
--- a/storage/innobase/include/btr0cur.h
+++ b/storage/innobase/include/btr0cur.h
@@ -327,16 +327,6 @@ btr_cur_pessimistic_update(
que_thr_t* thr, /*!< in: query thread */
mtr_t* mtr); /*!< in: mtr; must be committed before
latching any further pages */
-/*****************************************************************
-Commits and restarts a mini-transaction so that it will retain an
-x-lock on index->lock and the cursor page. */
-UNIV_INTERN
-void
-btr_cur_mtr_commit_and_start(
-/*=========================*/
- btr_cur_t* cursor, /*!< in: cursor */
- mtr_t* mtr) /*!< in/out: mini-transaction */
- UNIV_COLD __attribute__((nonnull));
/***********************************************************//**
Marks a clustered index record deleted. Writes an undo log record to
undo log on this delete marking. Writes in the trx id field the id
@@ -528,6 +518,8 @@ btr_store_big_rec_extern_fields_func(
the "external storage" flags in offsets
will not correspond to rec when
this function returns */
+ const big_rec_t*big_rec_vec, /*!< in: vector containing fields
+ to be stored externally */
#ifdef UNIV_DEBUG
mtr_t* local_mtr, /*!< in: mtr containing the
latch to rec and to the tree */
@@ -536,9 +528,12 @@ btr_store_big_rec_extern_fields_func(
ibool update_in_place,/*! in: TRUE if the record is updated
in place (not delete+insert) */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
- const big_rec_t*big_rec_vec) /*!< in: vector containing fields
- to be stored externally */
- __attribute__((nonnull));
+ mtr_t* alloc_mtr) /*!< in/out: in an insert, NULL;
+ in an update, local_mtr for
+ allocating BLOB pages and
+ updating BLOB pointers; alloc_mtr
+ must not have freed any leaf pages */
+ __attribute__((nonnull(1,2,3,4,5), warn_unused_result));
/** Stores the fields in big_rec_vec to the tablespace and puts pointers to
them in rec. The extern flags in rec will have to be set beforehand.
@@ -547,21 +542,22 @@ file segment of the index tree.
@param index in: clustered index; MUST be X-latched by mtr
@param b in/out: block containing rec; MUST be X-latched by mtr
@param rec in/out: clustered index record
-@param offsets in: rec_get_offsets(rec, index);
+@param offs in: rec_get_offsets(rec, index);
the "external storage" flags in offsets will not be adjusted
+@param big in: vector containing fields to be stored externally
@param mtr in: mini-transaction that holds x-latch on index and b
@param upd in: TRUE if the record is updated in place (not delete+insert)
-@param big in: vector containing fields to be stored externally
+@param rmtr in/out: in updates, the mini-transaction that holds rec
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
#ifdef UNIV_DEBUG
-# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
- btr_store_big_rec_extern_fields_func(index,b,rec,offsets,mtr,upd,big)
+# define btr_store_big_rec_extern_fields(index,b,rec,offs,big,mtr,upd,rmtr) \
+ btr_store_big_rec_extern_fields_func(index,b,rec,offs,big,mtr,upd,rmtr)
#elif defined UNIV_BLOB_LIGHT_DEBUG
-# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
- btr_store_big_rec_extern_fields_func(index,b,rec,offsets,upd,big)
+# define btr_store_big_rec_extern_fields(index,b,rec,offs,big,mtr,upd,rmtr) \
+ btr_store_big_rec_extern_fields_func(index,b,rec,offs,big,upd,rmtr)
#else
-# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
- btr_store_big_rec_extern_fields_func(index,b,rec,offsets,big)
+# define btr_store_big_rec_extern_fields(index,b,rec,offs,big,mtr,upd,rmtr) \
+ btr_store_big_rec_extern_fields_func(index,b,rec,offs,big,rmtr)
#endif
/*******************************************************************//**
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index 98931067850..03b80fce2e8 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -491,15 +491,6 @@ buf_page_peek(
/*==========*/
ulint space, /*!< in: space id */
ulint offset);/*!< in: page number */
-/********************************************************************//**
-Resets the check_index_page_at_flush field of a page if found in the buffer
-pool. */
-UNIV_INTERN
-void
-buf_reset_check_index_page_at_flush(
-/*================================*/
- ulint space, /*!< in: space id */
- ulint offset);/*!< in: page number */
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
/********************************************************************//**
Sets file_page_was_freed TRUE if the page is found in the buffer pool.
diff --git a/storage/innobase/include/buf0lru.h b/storage/innobase/include/buf0lru.h
index 74ef2d2dab7..eb40621abbe 100644
--- a/storage/innobase/include/buf0lru.h
+++ b/storage/innobase/include/buf0lru.h
@@ -203,6 +203,17 @@ void
buf_LRU_stat_update(void);
/*=====================*/
+/******************************************************************//**
+Remove one page from LRU list and put it to free list */
+UNIV_INTERN
+void
+buf_LRU_free_one_page(
+/*==================*/
+ buf_page_t* bpage) /*!< in/out: block, must contain a file page and
+ be in a state where it can be freed; there
+ may or may not be a hash index to the page */
+ __attribute__((nonnull));
+
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
/**********************************************************************//**
Validates the LRU list.
diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h
index 28ef64500cc..e0952f0709d 100644
--- a/storage/innobase/include/db0err.h
+++ b/storage/innobase/include/db0err.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, 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
@@ -110,6 +110,8 @@ enum db_err {
foreign keys as its prefix columns */
DB_TOO_BIG_INDEX_COL, /* index column size exceeds maximum
limit */
+ DB_INDEX_CORRUPT, /* we have corrupted index */
+ DB_UNDO_RECORD_TOO_BIG, /* the undo log record is too big */
/* The following are partial failure codes */
DB_FAIL = 1000,
diff --git a/storage/innobase/include/dict0boot.h b/storage/innobase/include/dict0boot.h
index 22df826da65..5d136862bc6 100644
--- a/storage/innobase/include/dict0boot.h
+++ b/storage/innobase/include/dict0boot.h
@@ -137,8 +137,10 @@ dict_create(void);
header is created */
/*-------------------------------------------------------------*/
-/* The field number of the page number field in the sys_indexes table
-clustered index */
+/* The field numbers in the SYS_TABLES clustered index */
+#define DICT_SYS_TABLES_TYPE_FIELD 5
+
+/* The field numbers in the SYS_INDEXES clustered index */
#define DICT_SYS_INDEXES_PAGE_NO_FIELD 8
#define DICT_SYS_INDEXES_SPACE_NO_FIELD 7
#define DICT_SYS_INDEXES_TYPE_FIELD 6
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index f979d0fcc96..57e51cbb6ba 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -585,6 +585,20 @@ dict_table_get_next_index(
# define dict_table_get_next_index(index) UT_LIST_GET_NEXT(indexes, index)
#endif /* UNIV_DEBUG */
#endif /* !UNIV_HOTBACKUP */
+
+/* Skip corrupted index */
+#define dict_table_skip_corrupt_index(index) \
+ while (index && dict_index_is_corrupted(index)) { \
+ index = dict_table_get_next_index(index); \
+ }
+
+/* Get the next non-corrupt index */
+#define dict_table_next_uncorrupted_index(index) \
+do { \
+ index = dict_table_get_next_index(index); \
+ dict_table_skip_corrupt_index(index); \
+} while (0)
+
/********************************************************************//**
Check whether the index is the clustered index.
@return nonzero for clustered index, zero for other indexes */
@@ -593,7 +607,7 @@ ulint
dict_index_is_clust(
/*================*/
const dict_index_t* index) /*!< in: index */
- __attribute__((pure));
+ __attribute__((nonnull, pure, warn_unused_result));
/********************************************************************//**
Check whether the index is unique.
@return nonzero for unique index, zero for other indexes */
@@ -602,7 +616,7 @@ ulint
dict_index_is_unique(
/*=================*/
const dict_index_t* index) /*!< in: index */
- __attribute__((pure));
+ __attribute__((nonnull, pure, warn_unused_result));
/********************************************************************//**
Check whether the index is the insert buffer tree.
@return nonzero for insert buffer, zero for other indexes */
@@ -611,7 +625,7 @@ ulint
dict_index_is_ibuf(
/*===============*/
const dict_index_t* index) /*!< in: index */
- __attribute__((pure));
+ __attribute__((nonnull, pure, warn_unused_result));
/********************************************************************//**
Check whether the index is a secondary index or the insert buffer tree.
@return nonzero for insert buffer, zero for other indexes */
@@ -620,7 +634,7 @@ ulint
dict_index_is_sec_or_ibuf(
/*======================*/
const dict_index_t* index) /*!< in: index */
- __attribute__((pure));
+ __attribute__((nonnull, pure, warn_unused_result));
/********************************************************************//**
Gets the number of user-defined columns in a table in the dictionary
@@ -630,7 +644,8 @@ UNIV_INLINE
ulint
dict_table_get_n_user_cols(
/*=======================*/
- const dict_table_t* table); /*!< in: table */
+ const dict_table_t* table) /*!< in: table */
+ __attribute__((nonnull, pure, warn_unused_result));
/********************************************************************//**
Gets the number of system columns in a table in the dictionary cache.
@return number of system (e.g., ROW_ID) columns of a table */
@@ -638,7 +653,8 @@ UNIV_INLINE
ulint
dict_table_get_n_sys_cols(
/*======================*/
- const dict_table_t* table); /*!< in: table */
+ const dict_table_t* table) /*!< in: table */
+ __attribute__((nonnull, pure, warn_unused_result));
/********************************************************************//**
Gets the number of all columns (also system) in a table in the dictionary
cache.
@@ -647,7 +663,8 @@ UNIV_INLINE
ulint
dict_table_get_n_cols(
/*==================*/
- const dict_table_t* table); /*!< in: table */
+ const dict_table_t* table) /*!< in: table */
+ __attribute__((nonnull, pure, warn_unused_result));
#ifdef UNIV_DEBUG
/********************************************************************//**
Gets the nth column of a table.
@@ -1243,6 +1260,57 @@ void
dict_close(void);
/*============*/
+/**********************************************************************//**
+Check whether the table is corrupted.
+@return nonzero for corrupted table, zero for valid tables */
+UNIV_INLINE
+ulint
+dict_table_is_corrupted(
+/*====================*/
+ const dict_table_t* table) /*!< in: table */
+ __attribute__((nonnull, pure, warn_unused_result));
+
+/**********************************************************************//**
+Check whether the index is corrupted.
+@return nonzero for corrupted index, zero for valid indexes */
+UNIV_INLINE
+ulint
+dict_index_is_corrupted(
+/*====================*/
+ const dict_index_t* index) /*!< in: index */
+ __attribute__((nonnull, pure, warn_unused_result));
+
+/**********************************************************************//**
+Flags an index and table corrupted both in the data dictionary cache
+and in the system table SYS_INDEXES. */
+UNIV_INTERN
+void
+dict_set_corrupted(
+/*===============*/
+ dict_index_t* index) /*!< in/out: index */
+ UNIV_COLD __attribute__((nonnull));
+
+/**********************************************************************//**
+Flags an index corrupted in the data dictionary cache only. This
+is used mostly to mark a corrupted index when index's own dictionary
+is corrupted, and we force to load such index for repair purpose */
+UNIV_INTERN
+void
+dict_set_corrupted_index_cache_only(
+/*================================*/
+ dict_index_t* index, /*!< in/out: index */
+ dict_table_t* table); /*!< in/out: table */
+
+/**********************************************************************//**
+Flags a table with specified space_id corrupted in the table dictionary
+cache.
+@return TRUE if successful */
+UNIV_INTERN
+ibool
+dict_set_corrupted_by_space(
+/*========================*/
+ ulint space_id); /*!< in: space ID */
+
#ifndef UNIV_NONINL
#include "dict0dict.ic"
#endif
diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic
index 59811568556..ade9e627e29 100644
--- a/storage/innobase/include/dict0dict.ic
+++ b/storage/innobase/include/dict0dict.ic
@@ -27,6 +27,7 @@ Created 1/8/1996 Heikki Tuuri
#ifndef UNIV_HOTBACKUP
#include "dict0load.h"
#include "rem0types.h"
+#include "srv0srv.h"
/*********************************************************************//**
Gets the minimum number of bytes per character.
@@ -828,7 +829,7 @@ dict_table_check_if_in_cache_low(
}
/**********************************************************************//**
-load a table into dictionary cache, ignore any error specified during load;
+load a table into dictionary cache, ignore any error specified during load;
@return table, NULL if not found */
UNIV_INLINE
dict_table_t*
@@ -872,6 +873,18 @@ dict_table_get_low(
table = dict_table_check_if_in_cache_low(table_name);
+ if (table && table->corrupted) {
+ fprintf(stderr, "InnoDB: table");
+ ut_print_name(stderr, NULL, TRUE, table->name);
+ if (srv_load_corrupted) {
+ fputs(" is corrupted, but"
+ " innodb_force_load_corrupted is set\n", stderr);
+ } else {
+ fputs(" is corrupted\n", stderr);
+ return(NULL);
+ }
+ }
+
if (table == NULL) {
table = dict_load_table(table_name, TRUE, DICT_ERR_IGNORE_NONE);
}
@@ -937,4 +950,35 @@ dict_max_field_len_store_undo(
return(prefix_len);
}
+/********************************************************************//**
+Check whether the table is corrupted.
+@return nonzero for corrupted table, zero for valid tables */
+UNIV_INLINE
+ulint
+dict_table_is_corrupted(
+/*====================*/
+ const dict_table_t* table) /*!< in: table */
+{
+ ut_ad(table);
+ ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
+
+ return(UNIV_UNLIKELY(table->corrupted));
+}
+
+/********************************************************************//**
+Check whether the index is corrupted.
+@return nonzero for corrupted index, zero for valid indexes */
+UNIV_INLINE
+ulint
+dict_index_is_corrupted(
+/*====================*/
+ const dict_index_t* index) /*!< in: index */
+{
+ ut_ad(index);
+ ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
+
+ return(UNIV_UNLIKELY((index->type & DICT_CORRUPT)
+ || (index->table && index->table->corrupted)));
+}
+
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
index 3a475fa85fc..9ded0dba39b 100644
--- a/storage/innobase/include/dict0mem.h
+++ b/storage/innobase/include/dict0mem.h
@@ -51,7 +51,12 @@ combination of types */
#define DICT_UNIQUE 2 /*!< unique index */
#define DICT_UNIVERSAL 4 /*!< index which can contain records from any
other index */
-#define DICT_IBUF 8 /*!< insert buffer tree */
+#define DICT_IBUF 8 /*!< insert buffer tree */
+#define DICT_CORRUPT 16 /*!< bit to store the corrupted flag
+ in SYS_INDEXES.TYPE */
+
+#define DICT_IT_BITS 5 /*!< number of bits used for
+ SYS_INDEXES.TYPE */
/* @} */
/** Types for a table object */
@@ -369,8 +374,9 @@ struct dict_index_struct{
/*!< space where the index tree is placed */
unsigned page:32;/*!< index tree root page number */
#endif /* !UNIV_HOTBACKUP */
- unsigned type:4; /*!< index type (DICT_CLUSTERED, DICT_UNIQUE,
- DICT_UNIVERSAL, DICT_IBUF) */
+ unsigned type:DICT_IT_BITS;
+ /*!< index type (DICT_CLUSTERED, DICT_UNIQUE,
+ DICT_UNIVERSAL, DICT_IBUF, DICT_CORRUPT) */
unsigned trx_id_offset:10;/*!< position of the trx id column
in a clustered index record, if the fields
before it are known to be of a fixed size,
@@ -391,8 +397,6 @@ struct dict_index_struct{
/*!< TRUE if this index is marked to be
dropped in ha_innobase::prepare_drop_index(),
otherwise FALSE */
- unsigned corrupted:1;
- /*!< TRUE if the index object is corrupted */
dict_field_t* fields; /*!< array of field descriptions */
#ifndef UNIV_HOTBACKUP
UT_LIST_NODE_T(dict_index_t)
diff --git a/storage/innobase/include/dict0types.h b/storage/innobase/include/dict0types.h
index 8cbd7cd5783..f0a05a38070 100644
--- a/storage/innobase/include/dict0types.h
+++ b/storage/innobase/include/dict0types.h
@@ -51,7 +51,8 @@ be or-ed together */
enum dict_err_ignore {
DICT_ERR_IGNORE_NONE = 0, /*!< no error to ignore */
DICT_ERR_IGNORE_INDEX_ROOT = 1, /*!< ignore error if index root
- page is FIL_NUL or incorrect value */
+ page is FIL_NULL or incorrect value */
+ DICT_ERR_IGNORE_CORRUPT = 2, /*!< skip corrupted indexes */
DICT_ERR_IGNORE_ALL = 0xFFFF /*!< ignore all errors */
};
diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h
index 7abd3914eda..2221380c9a2 100644
--- a/storage/innobase/include/fsp0fsp.h
+++ b/storage/innobase/include/fsp0fsp.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, 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
@@ -176,19 +176,18 @@ fseg_n_reserved_pages(
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize
file space fragmentation.
-@return the allocated page offset FIL_NULL if no page could be allocated */
-UNIV_INTERN
-ulint
-fseg_alloc_free_page(
-/*=================*/
- fseg_header_t* seg_header, /*!< in: segment header */
- ulint hint, /*!< in: hint of which page would be desirable */
- byte direction, /*!< in: if the new page is needed because
+@param[in/out] seg_header segment header
+@param[in] hint hint of which page would be desirable
+@param[in] direction if the new page is needed because
of an index page split, and records are
inserted there in order, into which
direction they go alphabetically: FSP_DOWN,
- FSP_UP, FSP_NO_DIR */
- mtr_t* mtr); /*!< in: mtr handle */
+ FSP_UP, FSP_NO_DIR
+@param[in/out] mtr mini-transaction
+@return the allocated page offset FIL_NULL if no page could be allocated */
+#define fseg_alloc_free_page(seg_header, hint, direction, mtr) \
+ fseg_alloc_free_page_general(seg_header, hint, direction, \
+ FALSE, mtr, mtr)
/**********************************************************************//**
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space
@@ -198,7 +197,7 @@ UNIV_INTERN
ulint
fseg_alloc_free_page_general(
/*=========================*/
- fseg_header_t* seg_header,/*!< in: segment header */
+ fseg_header_t* seg_header,/*!< in/out: segment header */
ulint hint, /*!< in: hint of which page would be desirable */
byte direction,/*!< in: if the new page is needed because
of an index page split, and records are
@@ -210,7 +209,12 @@ fseg_alloc_free_page_general(
with fsp_reserve_free_extents, then there
is no need to do the check for this individual
page */
- mtr_t* mtr); /*!< in: mtr handle */
+ mtr_t* mtr, /*!< in/out: mini-transaction */
+ mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
+ in which the page should be initialized,
+ or NULL if this is a "fake allocation" of
+ a page that was previously freed in mtr */
+ __attribute__((warn_unused_result, nonnull(1,5)));
/**********************************************************************//**
Reserves free pages from a tablespace. All mini-transactions which may
use several pages from the tablespace should call this function beforehand
diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h
index 6385af15b3d..185a0953231 100644
--- a/storage/innobase/include/mtr0mtr.h
+++ b/storage/innobase/include/mtr0mtr.h
@@ -53,6 +53,8 @@ first 3 values must be RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
#define MTR_MEMO_MODIFY 54
#define MTR_MEMO_S_LOCK 55
#define MTR_MEMO_X_LOCK 56
+/** The mini-transaction freed a clustered index leaf page. */
+#define MTR_MEMO_FREE_CLUST_LEAF 57
/** @name Log item types
The log items are declared 'byte' so that the compiler can warn if val
@@ -368,11 +370,14 @@ struct mtr_struct{
#endif
dyn_array_t memo; /*!< memo stack for locks etc. */
dyn_array_t log; /*!< mini-transaction log */
- ibool inside_ibuf;
+ unsigned inside_ibuf:1;
/*!< TRUE if inside ibuf changes */
- ibool modifications;
- /* TRUE if the mtr made modifications to
- buffer pool pages */
+ unsigned modifications:1;
+ /*!< TRUE if the mini-transaction
+ modified buffer pool pages */
+ unsigned freed_clust_leaf:1;
+ /*!< TRUE if MTR_MEMO_FREE_CLUST_LEAF
+ was logged in the mini-transaction */
ulint n_log_recs;
/* count of how many page initial log records
have been written to the mtr log */
diff --git a/storage/innobase/include/mtr0mtr.ic b/storage/innobase/include/mtr0mtr.ic
index 1db4a4bd735..3541f359338 100644
--- a/storage/innobase/include/mtr0mtr.ic
+++ b/storage/innobase/include/mtr0mtr.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, 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
@@ -43,8 +43,9 @@ mtr_start(
dyn_array_create(&(mtr->log));
mtr->log_mode = MTR_LOG_ALL;
- mtr->modifications = FALSE;
mtr->inside_ibuf = FALSE;
+ mtr->modifications = FALSE;
+ mtr->freed_clust_leaf = FALSE;
mtr->n_log_recs = 0;
ut_d(mtr->state = MTR_ACTIVE);
@@ -66,7 +67,8 @@ mtr_memo_push(
ut_ad(object);
ut_ad(type >= MTR_MEMO_PAGE_S_FIX);
- ut_ad(type <= MTR_MEMO_X_LOCK);
+ ut_ad(type <= MTR_MEMO_FREE_CLUST_LEAF);
+ ut_ad(type != MTR_MEMO_FREE_CLUST_LEAF || mtr->freed_clust_leaf);
ut_ad(mtr);
ut_ad(mtr->magic_n == MTR_MAGIC_N);
ut_ad(mtr->state == MTR_ACTIVE);
diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h
index 346f65302f7..ad1445b3935 100644
--- a/storage/innobase/include/page0page.h
+++ b/storage/innobase/include/page0page.h
@@ -68,10 +68,7 @@ typedef byte page_header_t;
#define PAGE_MAX_TRX_ID 18 /* highest id of a trx which may have modified
a record on the page; trx_id_t; defined only
in secondary indexes and in the insert buffer
- tree; NOTE: this may be modified only
- when the thread has an x-latch to the page,
- and ALSO an x-latch to btr_search_latch
- if there is a hash index to the page! */
+ tree */
#define PAGE_HEADER_PRIV_END 26 /* end of private data structure of the page
header which are set in a page create */
/*----*/
diff --git a/storage/innobase/include/row0upd.ic b/storage/innobase/include/row0upd.ic
index 0894ed373b0..11db82f64da 100644
--- a/storage/innobase/include/row0upd.ic
+++ b/storage/innobase/include/row0upd.ic
@@ -157,11 +157,6 @@ row_upd_rec_sys_fields(
{
ut_ad(dict_index_is_clust(index));
ut_ad(rec_offs_validate(rec, index, offsets));
-#ifdef UNIV_SYNC_DEBUG
- if (!rw_lock_own(&btr_search_latch, RW_LOCK_EX)) {
- ut_ad(!buf_block_align(rec)->is_hashed);
- }
-#endif /* UNIV_SYNC_DEBUG */
if (UNIV_LIKELY_NULL(page_zip)) {
ulint pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
index 7a93548cb03..dfe7397d189 100644
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
@@ -141,6 +141,10 @@ extern ulint srv_log_buffer_size;
extern ulong srv_flush_log_at_trx_commit;
extern char srv_adaptive_flushing;
+/* If this flag is TRUE, then we will load the indexes' (and tables') metadata
+even if they are marked as "corrupted". Mostly it is for DBA to process
+corrupted index and table */
+extern my_bool srv_load_corrupted;
/* The sort order table of the MySQL latin1_swedish_ci character set
collation */
diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h
index dd74ccee523..f6b8897522f 100644
--- a/storage/innobase/include/sync0sync.h
+++ b/storage/innobase/include/sync0sync.h
@@ -638,10 +638,6 @@ or row lock! */
#define SYNC_DICT_HEADER 995
#define SYNC_IBUF_HEADER 914
#define SYNC_IBUF_PESS_INSERT_MUTEX 912
-#define SYNC_IBUF_MUTEX 910 /* ibuf mutex is really below
- SYNC_FSP_PAGE: we assign a value this
- high only to make the program to pass
- the debug checks */
/*-------------------------------*/
#define SYNC_INDEX_TREE 900
#define SYNC_TREE_NODE_NEW 892
@@ -657,8 +653,11 @@ or row lock! */
#define SYNC_FSP 400
#define SYNC_FSP_PAGE 395
/*------------------------------------- Insert buffer headers */
-/*------------------------------------- ibuf_mutex */
+#define SYNC_IBUF_MUTEX 370 /* ibuf_mutex */
/*------------------------------------- Insert buffer tree */
+#define SYNC_IBUF_INDEX_TREE 360
+#define SYNC_IBUF_TREE_NODE_NEW 359
+#define SYNC_IBUF_TREE_NODE 358
#define SYNC_IBUF_BITMAP_MUTEX 351
#define SYNC_IBUF_BITMAP 350
/*------------------------------------- MySQL query cache mutex */
@@ -685,7 +684,6 @@ or row lock! */
#define SYNC_BUF_FLUSH_LIST 145 /* Buffer flush list mutex */
#define SYNC_DOUBLEWRITE 140
#define SYNC_ANY_LATCH 135
-#define SYNC_THR_LOCAL 133
#define SYNC_MEM_HASH 131
#define SYNC_MEM_POOL 130
diff --git a/storage/innobase/include/sync0sync.ic b/storage/innobase/include/sync0sync.ic
index 2977f71154a..eb21f44c65e 100644
--- a/storage/innobase/include/sync0sync.ic
+++ b/storage/innobase/include/sync0sync.ic
@@ -272,11 +272,10 @@ pfs_mutex_enter_nowait_func(
ulint ret;
struct PSI_mutex_locker* locker = NULL;
PSI_mutex_locker_state state;
- int result = 0;
if (UNIV_LIKELY(PSI_server && mutex->pfs_psi)) {
locker = PSI_server->get_thread_mutex_locker(
- &state, mutex->pfs_psi, PSI_MUTEX_LOCK);
+ &state, mutex->pfs_psi, PSI_MUTEX_TRYLOCK);
if (locker) {
PSI_server->start_mutex_wait(locker, file_name, line);
}
@@ -285,7 +284,7 @@ pfs_mutex_enter_nowait_func(
ret = mutex_enter_nowait_func(mutex, file_name, line);
if (locker) {
- PSI_server->end_mutex_wait(locker, result);
+ PSI_server->end_mutex_wait(locker, ret);
}
return(ret);
diff --git a/storage/innobase/include/trx0undo.h b/storage/innobase/include/trx0undo.h
index df16c939070..50aa6d0ac09 100644
--- a/storage/innobase/include/trx0undo.h
+++ b/storage/innobase/include/trx0undo.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, 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
@@ -204,17 +204,51 @@ trx_undo_add_page(
mtr_t* mtr); /*!< in: mtr which does not have a latch to any
undo log page; the caller must have reserved
the rollback segment mutex */
+/********************************************************************//**
+Frees the last undo log page.
+The caller must hold the rollback segment mutex. */
+UNIV_INTERN
+void
+trx_undo_free_last_page_func(
+/*==========================*/
+#ifdef UNIV_DEBUG
+ const trx_t* trx, /*!< in: transaction */
+#endif /* UNIV_DEBUG */
+ trx_undo_t* undo, /*!< in/out: undo log memory copy */
+ mtr_t* mtr) /*!< in/out: mini-transaction which does not
+ have a latch to any undo log page or which
+ has allocated the undo log page */
+ __attribute__((nonnull));
+#ifdef UNIV_DEBUG
+# define trx_undo_free_last_page(trx,undo,mtr) \
+ trx_undo_free_last_page_func(trx,undo,mtr)
+#else /* UNIV_DEBUG */
+# define trx_undo_free_last_page(trx,undo,mtr) \
+ trx_undo_free_last_page_func(undo,mtr)
+#endif /* UNIV_DEBUG */
+
/***********************************************************************//**
Truncates an undo log from the end. This function is used during a rollback
to free space from an undo log. */
UNIV_INTERN
void
-trx_undo_truncate_end(
-/*==================*/
- trx_t* trx, /*!< in: transaction whose undo log it is */
- trx_undo_t* undo, /*!< in: undo log */
- undo_no_t limit); /*!< in: all undo records with undo number
+trx_undo_truncate_end_func(
+/*=======================*/
+#ifdef UNIV_DEBUG
+ const trx_t* trx, /*!< in: transaction whose undo log it is */
+#endif /* UNIV_DEBUG */
+ trx_undo_t* undo, /*!< in/out: undo log */
+ undo_no_t limit) /*!< in: all undo records with undo number
>= this value should be truncated */
+ __attribute__((nonnull));
+#ifdef UNIV_DEBUG
+# define trx_undo_truncate_end(trx,undo,limit) \
+ trx_undo_truncate_end_func(trx,undo,limit)
+#else /* UNIV_DEBUG */
+# define trx_undo_truncate_end(trx,undo,limit) \
+ trx_undo_truncate_end_func(undo,limit)
+#endif /* UNIV_DEBUG */
+
/***********************************************************************//**
Truncates an undo log from the start. This function is used during a purge
operation. */
diff --git a/storage/innobase/mtr/mtr0mtr.c b/storage/innobase/mtr/mtr0mtr.c
index 05031370017..fde87cb3cd3 100644
--- a/storage/innobase/mtr/mtr0mtr.c
+++ b/storage/innobase/mtr/mtr0mtr.c
@@ -64,12 +64,11 @@ mtr_memo_slot_release(
buf_page_release((buf_block_t*)object, type);
} else if (type == MTR_MEMO_S_LOCK) {
rw_lock_s_unlock((rw_lock_t*)object);
-#ifdef UNIV_DEBUG
} else if (type != MTR_MEMO_X_LOCK) {
- ut_ad(type == MTR_MEMO_MODIFY);
+ ut_ad(type == MTR_MEMO_MODIFY
+ || type == MTR_MEMO_FREE_CLUST_LEAF);
ut_ad(mtr_memo_contains(mtr, object,
MTR_MEMO_PAGE_X_FIX));
-#endif /* UNIV_DEBUG */
} else {
rw_lock_x_unlock((rw_lock_t*)object);
}
diff --git a/storage/innobase/pars/pars0opt.c b/storage/innobase/pars/pars0opt.c
index 2e392ba4836..d992805d9ef 100644
--- a/storage/innobase/pars/pars0opt.c
+++ b/storage/innobase/pars/pars0opt.c
@@ -568,7 +568,7 @@ opt_search_plan_for_table(
best_last_op = last_op;
}
- index = dict_table_get_next_index(index);
+ dict_table_next_uncorrupted_index(index);
}
plan->index = best_index;
diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c
index 715e376f8f9..5f10a763fc4 100644
--- a/storage/innobase/row/row0ins.c
+++ b/storage/innobase/row/row0ins.c
@@ -118,6 +118,9 @@ ins_node_create_entry_list(
node->entry_sys_heap);
UT_LIST_ADD_LAST(tuple_list, node->entry_list, entry);
+ /* We will include all indexes (include those corrupted
+ secondary indexes) in the entry list. Filteration of
+ these corrupted index will be done in row_ins() */
index = dict_table_get_next_index(index);
}
}
@@ -2046,7 +2049,6 @@ row_ins_index_entry_low(
mtr_start(&mtr);
if (err != DB_SUCCESS) {
-
goto function_exit;
}
@@ -2086,15 +2088,20 @@ row_ins_index_entry_low(
if (big_rec) {
ut_a(err == DB_SUCCESS);
/* Write out the externally stored
- columns while still x-latching
- index->lock and block->lock. We have
- to mtr_commit(mtr) first, so that the
- redo log will be written in the
- correct order. Otherwise, we would run
- into trouble on crash recovery if mtr
- freed B-tree pages on which some of
- the big_rec fields will be written. */
- btr_cur_mtr_commit_and_start(&cursor, &mtr);
+ columns, but allocate the pages and
+ write the pointers using the
+ mini-transaction of the record update.
+ If any pages were freed in the update,
+ temporarily mark them allocated so
+ that off-page columns will not
+ overwrite them. We must do this,
+ because we will write the redo log for
+ the BLOB writes before writing the
+ redo log for the record update. Thus,
+ redo log application at crash recovery
+ will see BLOBs being written to free pages. */
+
+ btr_mark_freed_leaves(index, &mtr, TRUE);
rec = btr_cur_get_rec(&cursor);
offsets = rec_get_offsets(
@@ -2103,7 +2110,8 @@ row_ins_index_entry_low(
err = btr_store_big_rec_extern_fields(
index, btr_cur_get_block(&cursor),
- rec, offsets, &mtr, FALSE, big_rec);
+ rec, offsets, big_rec, &mtr,
+ FALSE, &mtr);
/* If writing big_rec fails (for
example, because of DB_OUT_OF_FILE_SPACE),
the record will be corrupted. Even if
@@ -2116,6 +2124,9 @@ row_ins_index_entry_low(
undo log, and thus the record cannot
be rolled back. */
ut_a(err == DB_SUCCESS);
+ /* Free the pages again
+ in order to avoid a leak. */
+ btr_mark_freed_leaves(index, &mtr, FALSE);
goto stored_big_rec;
}
} else {
@@ -2157,7 +2168,7 @@ function_exit:
err = btr_store_big_rec_extern_fields(
index, btr_cur_get_block(&cursor),
- rec, offsets, &mtr, FALSE, big_rec);
+ rec, offsets, big_rec, &mtr, FALSE, NULL);
stored_big_rec:
if (modify) {
@@ -2431,6 +2442,13 @@ row_ins(
node->index = dict_table_get_next_index(node->index);
node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry);
+
+ /* Skip corrupted secondary index and its entry */
+ while (node->index && dict_index_is_corrupted(node->index)) {
+
+ node->index = dict_table_get_next_index(node->index);
+ node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry);
+ }
}
ut_ad(node->entry == NULL);
diff --git a/storage/innobase/row/row0merge.c b/storage/innobase/row/row0merge.c
index 5be437add5a..d42f21241ca 100644
--- a/storage/innobase/row/row0merge.c
+++ b/storage/innobase/row/row0merge.c
@@ -2554,8 +2554,9 @@ row_merge_is_index_usable(
const trx_t* trx, /*!< in: transaction */
const dict_index_t* index) /*!< in: index to check */
{
- return(!trx->read_view
- || read_view_sees_trx_id(trx->read_view, index->trx_id));
+ return(!dict_index_is_corrupted(index)
+ && (!trx->read_view
+ || read_view_sees_trx_id(trx->read_view, index->trx_id)));
}
/*********************************************************************//**
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index a56d419d1f0..d0bedd69842 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -576,6 +576,7 @@ handle_new_error:
case DB_DUPLICATE_KEY:
case DB_FOREIGN_DUPLICATE_KEY:
case DB_TOO_BIG_RECORD:
+ case DB_UNDO_RECORD_TOO_BIG:
case DB_ROW_IS_REFERENCED:
case DB_NO_REFERENCED_ROW:
case DB_CANNOT_ADD_CONSTRAINT:
@@ -3098,7 +3099,8 @@ row_drop_table_for_mysql(
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- table = dict_table_get_low_ignore_err(name, DICT_ERR_IGNORE_INDEX_ROOT);
+ table = dict_table_get_low_ignore_err(
+ name, DICT_ERR_IGNORE_INDEX_ROOT | DICT_ERR_IGNORE_CORRUPT);
if (!table) {
err = DB_TABLE_NOT_FOUND;
@@ -3245,6 +3247,19 @@ check_next_foreign:
"index_id CHAR;\n"
"foreign_id CHAR;\n"
"found INT;\n"
+
+ "DECLARE CURSOR cur_fk IS\n"
+ "SELECT ID FROM SYS_FOREIGN\n"
+ "WHERE FOR_NAME = :table_name\n"
+ "AND TO_BINARY(FOR_NAME)\n"
+ " = TO_BINARY(:table_name)\n"
+ "LOCK IN SHARE MODE;\n"
+
+ "DECLARE CURSOR cur_idx IS\n"
+ "SELECT ID FROM SYS_INDEXES\n"
+ "WHERE TABLE_ID = table_id\n"
+ "LOCK IN SHARE MODE;\n"
+
"BEGIN\n"
"SELECT ID INTO table_id\n"
"FROM SYS_TABLES\n"
@@ -3267,13 +3282,9 @@ check_next_foreign:
"IF (:table_name = 'SYS_FOREIGN_COLS') THEN\n"
" found := 0;\n"
"END IF;\n"
+ "OPEN cur_fk;\n"
"WHILE found = 1 LOOP\n"
- " SELECT ID INTO foreign_id\n"
- " FROM SYS_FOREIGN\n"
- " WHERE FOR_NAME = :table_name\n"
- " AND TO_BINARY(FOR_NAME)\n"
- " = TO_BINARY(:table_name)\n"
- " LOCK IN SHARE MODE;\n"
+ " FETCH cur_fk INTO foreign_id;\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE\n"
@@ -3283,12 +3294,11 @@ check_next_foreign:
" WHERE ID = foreign_id;\n"
" END IF;\n"
"END LOOP;\n"
+ "CLOSE cur_fk;\n"
"found := 1;\n"
+ "OPEN cur_idx;\n"
"WHILE found = 1 LOOP\n"
- " SELECT ID INTO index_id\n"
- " FROM SYS_INDEXES\n"
- " WHERE TABLE_ID = table_id\n"
- " LOCK IN SHARE MODE;\n"
+ " FETCH cur_idx INTO index_id;\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE\n"
@@ -3299,6 +3309,7 @@ check_next_foreign:
" AND TABLE_ID = table_id;\n"
" END IF;\n"
"END LOOP;\n"
+ "CLOSE cur_idx;\n"
"DELETE FROM SYS_COLUMNS\n"
"WHERE TABLE_ID = table_id;\n"
"DELETE FROM SYS_TABLES\n"
diff --git a/storage/innobase/row/row0purge.c b/storage/innobase/row/row0purge.c
index 83e7c9e4857..e23995b8a52 100644
--- a/storage/innobase/row/row0purge.c
+++ b/storage/innobase/row/row0purge.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1997, 2011, 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
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -469,6 +469,13 @@ row_purge_del_mark(
heap = mem_heap_create(1024);
while (node->index != NULL) {
+ /* skip corrupted secondary index */
+ dict_table_skip_corrupt_index(node->index);
+
+ if (!node->index) {
+ break;
+ }
+
index = node->index;
/* Build the index entry */
@@ -508,7 +515,8 @@ row_purge_upd_exist_or_extern_func(
ut_ad(node);
- if (node->rec_type == TRX_UNDO_UPD_DEL_REC) {
+ if ((node->rec_type == TRX_UNDO_UPD_DEL_REC)
+ || (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
goto skip_secondaries;
}
@@ -516,6 +524,12 @@ row_purge_upd_exist_or_extern_func(
heap = mem_heap_create(1024);
while (node->index != NULL) {
+ dict_table_skip_corrupt_index(node->index);
+
+ if (!node->index) {
+ break;
+ }
+
index = node->index;
if (row_upd_changes_ord_field_binary(node->index, node->update,
@@ -632,14 +646,14 @@ row_purge_parse_undo_rec(
roll_ptr_t roll_ptr;
ulint info_bits;
ulint type;
- ulint cmpl_info;
ut_ad(node && thr);
trx = thr_get_trx(thr);
- ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info,
- updated_extern, &undo_no, &table_id);
+ ptr = trx_undo_rec_get_pars(
+ node->undo_rec, &type, &node->cmpl_info,
+ updated_extern, &undo_no, &table_id);
node->rec_type = type;
if (type == TRX_UNDO_UPD_DEL_REC && !(*updated_extern)) {
@@ -652,7 +666,8 @@ row_purge_parse_undo_rec(
node->table = NULL;
if (type == TRX_UNDO_UPD_EXIST_REC
- && cmpl_info & UPD_NODE_NO_ORD_CHANGE && !(*updated_extern)) {
+ && node->cmpl_info & UPD_NODE_NO_ORD_CHANGE
+ && !(*updated_extern)) {
/* Purge requires no changes to indexes: we may return */
@@ -702,7 +717,7 @@ err_exit:
/* Read to the partial row the fields that occur in indexes */
- if (!(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
+ if (!(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
ptr = trx_undo_rec_get_partial_row(
ptr, clust_index, &node->row,
type == TRX_UNDO_UPD_DEL_REC,
diff --git a/storage/innobase/row/row0row.c b/storage/innobase/row/row0row.c
index 4f75ac5b604..8892c8dc289 100644
--- a/storage/innobase/row/row0row.c
+++ b/storage/innobase/row/row0row.c
@@ -243,19 +243,20 @@ row_build(
}
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
- /* This condition can occur during crash recovery before
- trx_rollback_active() has completed execution.
-
- This condition is possible if the server crashed
- during an insert or update before
- btr_store_big_rec_extern_fields() did mtr_commit() all
- BLOB pointers to the clustered index record.
-
- If the record contains a null BLOB pointer, look up the
- transaction that holds the implicit lock on this record, and
- assert that it was recovered (and will soon be rolled back). */
- ut_a(!rec_offs_any_null_extern(rec, offsets)
- || trx_assert_recovered(row_get_rec_trx_id(rec, index, offsets)));
+ if (rec_offs_any_null_extern(rec, offsets)) {
+ /* This condition can occur during crash recovery
+ before trx_rollback_active() has completed execution.
+
+ This condition is possible if the server crashed
+ during an insert or update-by-delete-and-insert before
+ btr_store_big_rec_extern_fields() did mtr_commit() all
+ BLOB pointers to the freshly inserted clustered index
+ record. */
+ ut_a(trx_assert_recovered(
+ row_get_rec_trx_id(rec, index, offsets)));
+ ut_a(trx_undo_roll_ptr_is_insert(
+ row_get_rec_roll_ptr(rec, index, offsets)));
+ }
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
if (type != ROW_COPY_POINTERS) {
diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c
index 36da621e077..5d8f53f68da 100644
--- a/storage/innobase/row/row0sel.c
+++ b/storage/innobase/row/row0sel.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -99,14 +99,22 @@ row_sel_sec_rec_is_for_blob(
ulint clust_len, /*!< in: length of clust_field */
const byte* sec_field, /*!< in: column in secondary index */
ulint sec_len, /*!< in: length of sec_field */
+ ulint prefix_len, /*!< in: index column prefix length
+ in bytes */
dict_table_t* table) /*!< in: table */
{
ulint len;
byte buf[REC_VERSION_56_MAX_INDEX_COL_LEN];
ulint zip_size = dict_table_flags_to_zip_size(table->flags);
- ulint max_prefix_len = DICT_MAX_FIELD_LEN_BY_FORMAT(table);
+ /* This function should never be invoked on an Antelope format
+ table, because they should always contain enough prefix in the
+ clustered index record. */
+ ut_ad(dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP);
ut_a(clust_len >= BTR_EXTERN_FIELD_REF_SIZE);
+ ut_ad(prefix_len >= sec_len);
+ ut_ad(prefix_len > 0);
+ ut_a(prefix_len <= sizeof buf);
if (UNIV_UNLIKELY
(!memcmp(clust_field + clust_len - BTR_EXTERN_FIELD_REF_SIZE,
@@ -118,7 +126,7 @@ row_sel_sec_rec_is_for_blob(
return(FALSE);
}
- len = btr_copy_externally_stored_field_prefix(buf, max_prefix_len,
+ len = btr_copy_externally_stored_field_prefix(buf, prefix_len,
zip_size,
clust_field, clust_len);
@@ -132,7 +140,7 @@ row_sel_sec_rec_is_for_blob(
}
len = dtype_get_at_most_n_mbchars(prtype, mbminmaxlen,
- sec_len, len, (const char*) buf);
+ prefix_len, len, (const char*) buf);
return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
}
@@ -224,6 +232,7 @@ row_sel_sec_rec_is_for_clust_rec(
col->mbminmaxlen,
clust_field, clust_len,
sec_field, sec_len,
+ ifield->prefix_len,
clust_index->table)) {
goto inequal;
}
@@ -493,7 +502,7 @@ sel_col_prefetch_buf_alloc(
sel_buf = column->prefetch_buf + i;
sel_buf->data = NULL;
-
+ sel_buf->len = 0;
sel_buf->val_buf_size = 0;
}
}
@@ -518,6 +527,8 @@ sel_col_prefetch_buf_free(
mem_free(sel_buf->data);
}
}
+
+ mem_free(prefetch_buf);
}
/*********************************************************************//**
@@ -3441,6 +3452,13 @@ row_search_for_mysql(
return(DB_MISSING_HISTORY);
}
+ if (dict_index_is_corrupted(index)) {
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
+ return(DB_CORRUPTION);
+ }
+
if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) {
fprintf(stderr,
"InnoDB: Error: trying to free a corrupt\n"
diff --git a/storage/innobase/row/row0uins.c b/storage/innobase/row/row0uins.c
index d25afed3840..4fa97c9355d 100644
--- a/storage/innobase/row/row0uins.c
+++ b/storage/innobase/row/row0uins.c
@@ -328,6 +328,8 @@ row_undo_ins(
node->index = dict_table_get_next_index(
dict_table_get_first_index(node->table));
+ dict_table_skip_corrupt_index(node->index);
+
while (node->index != NULL) {
dtuple_t* entry;
ulint err;
@@ -355,7 +357,7 @@ row_undo_ins(
}
}
- node->index = dict_table_get_next_index(node->index);
+ dict_table_next_uncorrupted_index(node->index);
}
log_free_check();
diff --git a/storage/innobase/row/row0umod.c b/storage/innobase/row/row0umod.c
index 2188fdeff49..b86ce9eeabd 100644
--- a/storage/innobase/row/row0umod.c
+++ b/storage/innobase/row/row0umod.c
@@ -573,6 +573,14 @@ row_undo_mod_upd_del_sec(
heap = mem_heap_create(1024);
while (node->index != NULL) {
+
+ /* Skip all corrupted secondary index */
+ dict_table_skip_corrupt_index(node->index);
+
+ if (!node->index) {
+ break;
+ }
+
index = node->index;
entry = row_build_index_entry(node->row, node->ext,
@@ -626,6 +634,13 @@ row_undo_mod_del_mark_sec(
heap = mem_heap_create(1024);
while (node->index != NULL) {
+ /* Skip all corrupted secondary index */
+ dict_table_skip_corrupt_index(node->index);
+
+ if (!node->index) {
+ break;
+ }
+
index = node->index;
entry = row_build_index_entry(node->row, node->ext,
@@ -677,6 +692,13 @@ row_undo_mod_upd_exist_sec(
heap = mem_heap_create(1024);
while (node->index != NULL) {
+ /* Skip all corrupted secondary index */
+ dict_table_skip_corrupt_index(node->index);
+
+ if (!node->index) {
+ break;
+ }
+
index = node->index;
if (row_upd_changes_ord_field_binary(node->index, node->update,
@@ -859,6 +881,9 @@ row_undo_mod(
node->index = dict_table_get_next_index(
dict_table_get_first_index(node->table));
+ /* Skip all corrupted secondary index */
+ dict_table_skip_corrupt_index(node->index);
+
if (node->rec_type == TRX_UNDO_UPD_EXIST_REC) {
err = row_undo_mod_upd_exist_sec(node, thr);
diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c
index a2f6c17413f..2401fc88553 100644
--- a/storage/innobase/row/row0upd.c
+++ b/storage/innobase/row/row0upd.c
@@ -2008,21 +2008,22 @@ row_upd_clust_rec(
rec_offs_init(offsets_);
ut_a(err == DB_SUCCESS);
- /* Write out the externally stored columns while still
- x-latching index->lock and block->lock. We have to
- mtr_commit(mtr) first, so that the redo log will be
- written in the correct order. Otherwise, we would run
- into trouble on crash recovery if mtr freed B-tree
- pages on which some of the big_rec fields will be
- written. */
- btr_cur_mtr_commit_and_start(btr_cur, mtr);
-
+ /* Write out the externally stored columns, but
+ allocate the pages and write the pointers using the
+ mini-transaction of the record update. If any pages
+ were freed in the update, temporarily mark them
+ allocated so that off-page columns will not overwrite
+ them. We must do this, because we write the redo log
+ for the BLOB writes before writing the redo log for
+ the record update. */
+
+ btr_mark_freed_leaves(index, mtr, TRUE);
rec = btr_cur_get_rec(btr_cur);
err = btr_store_big_rec_extern_fields(
index, btr_cur_get_block(btr_cur), rec,
rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
- mtr, TRUE, big_rec);
+ big_rec, mtr, TRUE, mtr);
/* If writing big_rec fails (for example, because of
DB_OUT_OF_FILE_SPACE), the record will be corrupted.
Even if we did not update any externally stored
@@ -2032,6 +2033,8 @@ row_upd_clust_rec(
to the undo log, and thus the record cannot be rolled
back. */
ut_a(err == DB_SUCCESS);
+ /* Free the pages again in order to avoid a leak. */
+ btr_mark_freed_leaves(index, mtr, FALSE);
}
mtr_commit(mtr);
@@ -2320,6 +2323,13 @@ row_upd(
while (node->index != NULL) {
+ /* Skip corrupted index */
+ dict_table_skip_corrupt_index(node->index);
+
+ if (!node->index) {
+ break;
+ }
+
log_free_check();
err = row_upd_sec_step(node, thr);
diff --git a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.c
index 251a392a02c..af6e3f0e275 100644
--- a/storage/innobase/sync/sync0sync.c
+++ b/storage/innobase/sync/sync0sync.c
@@ -1214,7 +1214,6 @@ sync_thread_add_level(
case SYNC_WORK_QUEUE:
case SYNC_LOG:
case SYNC_LOG_FLUSH_ORDER:
- case SYNC_THR_LOCAL:
case SYNC_ANY_LATCH:
case SYNC_FILE_FORMAT_TAG:
case SYNC_DOUBLEWRITE:
@@ -1232,6 +1231,7 @@ sync_thread_add_level(
case SYNC_DICT_HEADER:
case SYNC_TRX_I_S_RWLOCK:
case SYNC_TRX_I_S_LAST_READ:
+ case SYNC_IBUF_MUTEX:
if (!sync_thread_levels_g(array, level, TRUE)) {
fprintf(stderr,
"InnoDB: sync_thread_levels_g(array, %lu)"
@@ -1317,22 +1317,33 @@ sync_thread_add_level(
|| sync_thread_levels_g(array, SYNC_TREE_NODE - 1, TRUE));
break;
case SYNC_TREE_NODE_NEW:
- ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE)
- || sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
+ ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE));
break;
case SYNC_INDEX_TREE:
- if (sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)
- && sync_thread_levels_contain(array, SYNC_FSP)) {
- ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1,
- TRUE));
+ ut_a(sync_thread_levels_g(array, SYNC_TREE_NODE - 1, TRUE));
+ break;
+ case SYNC_IBUF_TREE_NODE:
+ ut_a(sync_thread_levels_contain(array, SYNC_IBUF_INDEX_TREE)
+ || sync_thread_levels_g(array, SYNC_IBUF_TREE_NODE - 1,
+ TRUE));
+ break;
+ case SYNC_IBUF_TREE_NODE_NEW:
+ /* ibuf_add_free_page() allocates new pages for the
+ change buffer while only holding the tablespace
+ x-latch. These pre-allocated new pages may only be
+ taken in use while holding ibuf_mutex, in
+ btr_page_alloc_for_ibuf(). */
+ ut_a(sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)
+ || sync_thread_levels_contain(array, SYNC_FSP));
+ break;
+ case SYNC_IBUF_INDEX_TREE:
+ if (sync_thread_levels_contain(array, SYNC_FSP)) {
+ ut_a(sync_thread_levels_g(array, level - 1, TRUE));
} else {
- ut_a(sync_thread_levels_g(array, SYNC_TREE_NODE - 1,
- TRUE));
+ ut_a(sync_thread_levels_g(
+ array, SYNC_IBUF_TREE_NODE - 1, TRUE));
}
break;
- case SYNC_IBUF_MUTEX:
- ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1, TRUE));
- break;
case SYNC_IBUF_PESS_INSERT_MUTEX:
ut_a(sync_thread_levels_g(array, SYNC_FSP - 1, TRUE));
ut_a(!sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
diff --git a/storage/innobase/trx/trx0rec.c b/storage/innobase/trx/trx0rec.c
index 5f83a9f5fd9..ad209110e60 100644
--- a/storage/innobase/trx/trx0rec.c
+++ b/storage/innobase/trx/trx0rec.c
@@ -669,7 +669,6 @@ trx_undo_page_report_modify(
/* Save to the undo log the old values of the columns to be updated. */
if (update) {
-
if (trx_undo_left(undo_page, ptr) < 5) {
return(0);
@@ -1119,13 +1118,14 @@ trx_undo_rec_get_partial_row(
#endif /* !UNIV_HOTBACKUP */
/***********************************************************************//**
-Erases the unused undo log page end. */
-static
-void
+Erases the unused undo log page end.
+@return TRUE if the page contained something, FALSE if it was empty */
+static __attribute__((nonnull))
+ibool
trx_undo_erase_page_end(
/*====================*/
- page_t* undo_page, /*!< in: undo page whose end to erase */
- mtr_t* mtr) /*!< in: mtr */
+ page_t* undo_page, /*!< in/out: undo page whose end to erase */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint first_free;
@@ -1135,6 +1135,7 @@ trx_undo_erase_page_end(
(UNIV_PAGE_SIZE - FIL_PAGE_DATA_END) - first_free);
mlog_write_initial_log_record(undo_page, MLOG_UNDO_ERASE_END, mtr);
+ return(first_free != TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE);
}
/***********************************************************//**
@@ -1202,6 +1203,9 @@ trx_undo_report_row_operation(
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
+#ifdef UNIV_DEBUG
+ int loop_count = 0;
+#endif /* UNIV_DEBUG */
rec_offs_init(offsets_);
ut_a(dict_index_is_clust(index));
@@ -1264,7 +1268,7 @@ trx_undo_report_row_operation(
mtr_start(&mtr);
- for (;;) {
+ do {
buf_block_t* undo_block;
page_t* undo_page;
ulint offset;
@@ -1293,7 +1297,31 @@ trx_undo_report_row_operation(
version the replicate page constructed using the log
records stays identical to the original page */
- trx_undo_erase_page_end(undo_page, &mtr);
+ if (!trx_undo_erase_page_end(undo_page, &mtr)) {
+ /* The record did not fit on an empty
+ undo page. Discard the freshly allocated
+ page and return an error. */
+
+ /* When we remove a page from an undo
+ log, this is analogous to a
+ pessimistic insert in a B-tree, and we
+ must reserve the counterpart of the
+ tree latch, which is the rseg
+ mutex. We must commit the mini-transaction
+ first, because it may be holding lower-level
+ latches, such as SYNC_FSP and SYNC_FSP_PAGE. */
+
+ mtr_commit(&mtr);
+ mtr_start(&mtr);
+
+ mutex_enter(&rseg->mutex);
+ trx_undo_free_last_page(trx, undo, &mtr);
+ mutex_exit(&rseg->mutex);
+
+ err = DB_UNDO_RECORD_TOO_BIG;
+ goto err_exit;
+ }
+
mtr_commit(&mtr);
} else {
/* Success */
@@ -1313,16 +1341,15 @@ trx_undo_report_row_operation(
*roll_ptr = trx_undo_build_roll_ptr(
op_type == TRX_UNDO_INSERT_OP,
rseg->id, page_no, offset);
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
- return(DB_SUCCESS);
+ err = DB_SUCCESS;
+ goto func_exit;
}
ut_ad(page_no == undo->last_page_no);
/* We have to extend the undo log by one page */
+ ut_ad(++loop_count < 2);
mtr_start(&mtr);
/* When we add a page to an undo log, this is analogous to
@@ -1334,18 +1361,19 @@ trx_undo_report_row_operation(
page_no = trx_undo_add_page(trx, undo, &mtr);
mutex_exit(&(rseg->mutex));
+ } while (UNIV_LIKELY(page_no != FIL_NULL));
- if (UNIV_UNLIKELY(page_no == FIL_NULL)) {
- /* Did not succeed: out of space */
+ /* Did not succeed: out of space */
+ err = DB_OUT_OF_FILE_SPACE;
- mutex_exit(&(trx->undo_mutex));
- mtr_commit(&mtr);
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
- return(DB_OUT_OF_FILE_SPACE);
- }
+err_exit:
+ mutex_exit(&trx->undo_mutex);
+ mtr_commit(&mtr);
+func_exit:
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
}
+ return(err);
}
/*============== BUILDING PREVIOUS VERSION OF A RECORD ===============*/
diff --git a/storage/innobase/trx/trx0undo.c b/storage/innobase/trx/trx0undo.c
index 4cb4b7b79c5..805fdcee242 100644
--- a/storage/innobase/trx/trx0undo.c
+++ b/storage/innobase/trx/trx0undo.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, 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
@@ -918,7 +918,7 @@ trx_undo_add_page(
page_no = fseg_alloc_free_page_general(header_page + TRX_UNDO_SEG_HDR
+ TRX_UNDO_FSEG_HEADER,
undo->top_page_no + 1, FSP_UP,
- TRUE, mtr);
+ TRUE, mtr, mtr);
fil_space_release_free_extents(undo->space, n_reserved);
@@ -1004,29 +1004,28 @@ trx_undo_free_page(
}
/********************************************************************//**
-Frees an undo log page when there is also the memory object for the undo
-log. */
-static
+Frees the last undo log page.
+The caller must hold the rollback segment mutex. */
+UNIV_INTERN
void
-trx_undo_free_page_in_rollback(
-/*===========================*/
- trx_t* trx __attribute__((unused)), /*!< in: transaction */
- trx_undo_t* undo, /*!< in: undo log memory copy */
- ulint page_no,/*!< in: page number to free: must not be the
- header page */
- mtr_t* mtr) /*!< in: mtr which does not have a latch to any
- undo log page; the caller must have reserved
- the rollback segment mutex */
+trx_undo_free_last_page_func(
+/*==========================*/
+#ifdef UNIV_DEBUG
+ const trx_t* trx, /*!< in: transaction */
+#endif /* UNIV_DEBUG */
+ trx_undo_t* undo, /*!< in/out: undo log memory copy */
+ mtr_t* mtr) /*!< in/out: mini-transaction which does not
+ have a latch to any undo log page or which
+ has allocated the undo log page */
{
- ulint last_page_no;
-
- ut_ad(undo->hdr_page_no != page_no);
- ut_ad(mutex_own(&(trx->undo_mutex)));
+ ut_ad(mutex_own(&trx->undo_mutex));
+ ut_ad(undo->hdr_page_no != undo->last_page_no);
+ ut_ad(undo->size > 0);
- last_page_no = trx_undo_free_page(undo->rseg, FALSE, undo->space,
- undo->hdr_page_no, page_no, mtr);
+ undo->last_page_no = trx_undo_free_page(
+ undo->rseg, FALSE, undo->space,
+ undo->hdr_page_no, undo->last_page_no, mtr);
- undo->last_page_no = last_page_no;
undo->size--;
}
@@ -1062,9 +1061,11 @@ Truncates an undo log from the end. This function is used during a rollback
to free space from an undo log. */
UNIV_INTERN
void
-trx_undo_truncate_end(
-/*==================*/
- trx_t* trx, /*!< in: transaction whose undo log it is */
+trx_undo_truncate_end_func(
+/*=======================*/
+#ifdef UNIV_DEBUG
+ const trx_t* trx, /*!< in: transaction whose undo log it is */
+#endif /* UNIV_DEBUG */
trx_undo_t* undo, /*!< in: undo log */
undo_no_t limit) /*!< in: all undo records with undo number
>= this value should be truncated */
@@ -1090,18 +1091,7 @@ trx_undo_truncate_end(
rec = trx_undo_page_get_last_rec(undo_page, undo->hdr_page_no,
undo->hdr_offset);
- for (;;) {
- if (rec == NULL) {
- if (last_page_no == undo->hdr_page_no) {
-
- goto function_exit;
- }
-
- trx_undo_free_page_in_rollback(
- trx, undo, last_page_no, &mtr);
- break;
- }
-
+ while (rec) {
if (trx_undo_rec_get_undo_no(rec) >= limit) {
/* Truncate at least this record off, maybe
more */
@@ -1115,6 +1105,14 @@ trx_undo_truncate_end(
undo->hdr_offset);
}
+ if (last_page_no == undo->hdr_page_no) {
+
+ goto function_exit;
+ }
+
+ ut_ad(last_page_no == undo->last_page_no);
+ trx_undo_free_last_page(trx, undo, &mtr);
+
mtr_commit(&mtr);
}
diff --git a/storage/innobase/ut/ut0ut.c b/storage/innobase/ut/ut0ut.c
index 1ef1a082bb2..f6dfb3ba0b3 100644
--- a/storage/innobase/ut/ut0ut.c
+++ b/storage/innobase/ut/ut0ut.c
@@ -712,6 +712,10 @@ ut_strerr(
return("No index on referencing keys in referencing table");
case DB_PARENT_NO_INDEX:
return("No index on referenced keys in referenced table");
+ case DB_INDEX_CORRUPT:
+ return("Index corrupted");
+ case DB_UNDO_RECORD_TOO_BIG:
+ return("Undo record too big");
case DB_END_OF_INDEX:
return("End of index");
/* do not add default: in order to produce a warning if new code
diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c
index ae32f541dab..43db42c8383 100644
--- a/storage/myisam/ft_boolean_search.c
+++ b/storage/myisam/ft_boolean_search.c
@@ -360,7 +360,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
int subkeys=1;
my_bool can_go_down;
MI_INFO *info=ftb->info;
- uint UNINIT_VAR(off), extra=HA_FT_WLEN+info->s->base.rec_reflength;
+ uint UNINIT_VAR(off), extra= HA_FT_WLEN + info->s->rec_reflength;
uchar *lastkey_buf=ftbw->word+ftbw->off;
if (ftbw->flags & FTB_FLAG_TRUNC)
diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c
index 0dc82fb4c25..175f061f168 100644
--- a/storage/myisam/ft_nlq_search.c
+++ b/storage/myisam/ft_nlq_search.c
@@ -72,7 +72,7 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
uchar *keybuff=aio->keybuff;
MI_KEYDEF *keyinfo=info->s->keyinfo+aio->keynr;
my_off_t key_root=info->s->state.key_root[aio->keynr];
- uint extra=HA_FT_WLEN+info->s->base.rec_reflength;
+ uint extra= HA_FT_WLEN + info->s->rec_reflength;
#if HA_FT_WTYPE == HA_KEYTYPE_FLOAT
float tmp_weight;
#else
diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c
index f4b78939778..d2b0c63cfe9 100644
--- a/storage/myisam/mi_check.c
+++ b/storage/myisam/mi_check.c
@@ -3899,7 +3899,7 @@ static int sort_ft_key_write(MI_SORT_PARAM *sort_param, const void *a)
SORT_FT_BUF *ft_buf=sort_info->ft_buf;
SORT_KEY_BLOCKS *key_block=sort_info->key_block;
- val_len=HA_FT_WLEN+sort_info->info->s->base.rec_reflength;
+ val_len= HA_FT_WLEN + sort_info->info->s->rec_reflength;
get_key_full_length_rdonly(a_len, (uchar *)a);
if (!ft_buf)
@@ -3909,7 +3909,7 @@ static int sort_ft_key_write(MI_SORT_PARAM *sort_param, const void *a)
and row format is NOT static - for _mi_dpointer not to garble offsets
*/
if ((sort_info->info->s->base.key_reflength <=
- sort_info->info->s->base.rec_reflength) &&
+ sort_info->info->s->rec_reflength) &&
(sort_info->info->s->options &
(HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
ft_buf=(SORT_FT_BUF *)my_malloc(sort_param->keyinfo->block_length +
diff --git a/storage/myisam/mi_write.c b/storage/myisam/mi_write.c
index 246255395df..b1bbf209e25 100644
--- a/storage/myisam/mi_write.c
+++ b/storage/myisam/mi_write.c
@@ -519,7 +519,7 @@ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo,
{
if (keyinfo->block_length - a_length < 32 &&
keyinfo->flag & HA_FULLTEXT && key_pos == endpos &&
- info->s->base.key_reflength <= info->s->base.rec_reflength &&
+ info->s->base.key_reflength <= info->s->rec_reflength &&
info->s->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))
{
/*
diff --git a/strings/decimal.c b/strings/decimal.c
index b18a8c3fa50..954b04ea446 100644
--- a/strings/decimal.c
+++ b/strings/decimal.c
@@ -1403,11 +1403,18 @@ int bin2decimal(const uchar *from, decimal_t *to, int precision, int scale)
buf++;
}
my_afree(d_copy);
+
+ /*
+ No digits? We have read the number zero, of unspecified precision.
+ Make it a proper zero, with non-zero precision.
+ */
+ if (to->intg == 0 && to->frac == 0)
+ decimal_make_zero(to);
return error;
err:
my_afree(d_copy);
- decimal_make_zero(((decimal_t*) to));
+ decimal_make_zero(to);
return(E_DEC_BAD_NUM);
}
diff --git a/strings/dtoa.c b/strings/dtoa.c
index e4eb10bb6f8..05c9bb6e529 100644
--- a/strings/dtoa.c
+++ b/strings/dtoa.c
@@ -46,7 +46,7 @@
see if it is possible to get rid of malloc().
this constant is sufficient to avoid malloc() on all inputs I have tried.
*/
-#define DTOA_BUFF_SIZE (420 * sizeof(void *))
+#define DTOA_BUFF_SIZE (460 * sizeof(void *))
/* Magic value returned by dtoa() to indicate overflow */
#define DTOA_OVERFLOW 9999
@@ -659,6 +659,7 @@ typedef struct Stack_alloc
static Bigint *Balloc(int k, Stack_alloc *alloc)
{
Bigint *rv;
+ DBUG_ASSERT(k <= Kmax);
if (k <= Kmax && alloc->freelist[k])
{
rv= alloc->freelist[k];
@@ -1005,7 +1006,7 @@ static Bigint p5_a[]=
static Bigint *pow5mult(Bigint *b, int k, Stack_alloc *alloc)
{
- Bigint *b1, *p5, *p51;
+ Bigint *b1, *p5, *p51=NULL;
int i;
static int p05[3]= { 5, 25, 125 };
@@ -1037,6 +1038,8 @@ static Bigint *pow5mult(Bigint *b, int k, Stack_alloc *alloc)
p5= p51;
}
}
+ if (p51)
+ Bfree(p51, alloc);
return b;
}
diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index 4b0c6438199..1442e1b96bd 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -139,43 +139,62 @@
%endif
%endif
%else
- %if %(test -f /etc/redhat-release && echo 1 || echo 0)
- %define rhelver %(rpm -qf --qf '%%{version}\\n' /etc/redhat-release | sed -e 's/^\\([0-9]*\\).*/\\1/g')
- %if "%rhelver" == "4"
- %define distro_description Red Hat Enterprise Linux 4
- %define distro_releasetag rhel4
- %define distro_buildreq gcc-c++ gperf ncurses-devel perl readline-devel time zlib-devel
+ %if %(test -f /etc/oracle-release && echo 1 || echo 0)
+ %define elver %(rpm -qf --qf '%%{version}\\n' /etc/oracle-release | sed -e 's/^\\([0-9]*\\).*/\\1/g')
+ %if "%elver" == "6"
+ %define distro_description Oracle Linux 6
+ %define distro_releasetag el6
+ %define distro_buildreq gcc-c++ ncurses-devel perl readline-devel time zlib-devel
%define distro_requires chkconfig coreutils grep procps shadow-utils net-tools
%else
- %if "%rhelver" == "5"
- %define distro_description Red Hat Enterprise Linux 5
- %define distro_releasetag rhel5
- %define distro_buildreq gcc-c++ gperf ncurses-devel perl readline-devel time zlib-devel
- %define distro_requires chkconfig coreutils grep procps shadow-utils net-tools
- %else
- %{error:Red Hat Enterprise Linux %{rhelver} is unsupported}
- %endif
+ %{error:Oracle Linux %{elver} is unsupported}
%endif
%else
- %if %(test -f /etc/SuSE-release && echo 1 || echo 0)
- %define susever %(rpm -qf --qf '%%{version}\\n' /etc/SuSE-release)
- %if "%susever" == "10"
- %define distro_description SUSE Linux Enterprise Server 10
- %define distro_releasetag sles10
- %define distro_buildreq gcc-c++ gdbm-devel gperf ncurses-devel openldap2-client readline-devel zlib-devel
- %define distro_requires aaa_base coreutils grep procps pwdutils
+ %if %(test -f /etc/redhat-release && echo 1 || echo 0)
+ %define rhelver %(rpm -qf --qf '%%{version}\\n' /etc/redhat-release | sed -e 's/^\\([0-9]*\\).*/\\1/g')
+ %if "%rhelver" == "4"
+ %define distro_description Red Hat Enterprise Linux 4
+ %define distro_releasetag rhel4
+ %define distro_buildreq gcc-c++ gperf ncurses-devel perl readline-devel time zlib-devel
+ %define distro_requires chkconfig coreutils grep procps shadow-utils net-tools
%else
- %if "%susever" == "11"
- %define distro_description SUSE Linux Enterprise Server 11
- %define distro_releasetag sles11
- %define distro_buildreq gcc-c++ gdbm-devel gperf ncurses-devel openldap2-client procps pwdutils readline-devel zlib-devel
- %define distro_requires aaa_base coreutils grep procps pwdutils
+ %if "%rhelver" == "5"
+ %define distro_description Red Hat Enterprise Linux 5
+ %define distro_releasetag rhel5
+ %define distro_buildreq gcc-c++ gperf ncurses-devel perl readline-devel time zlib-devel
+ %define distro_requires chkconfig coreutils grep procps shadow-utils net-tools
%else
- %{error:SuSE %{susever} is unsupported}
+ %if "%rhelver" == "6"
+ %define distro_description Red Hat Enterprise Linux 6
+ %define distro_releasetag rhel6
+ %define distro_buildreq gcc-c++ ncurses-devel perl readline-devel time zlib-devel
+ %define distro_requires chkconfig coreutils grep procps shadow-utils net-tools
+ %else
+ %{error:Red Hat Enterprise Linux %{rhelver} is unsupported}
+ %endif
%endif
%endif
%else
- %{error:Unsupported distribution}
+ %if %(test -f /etc/SuSE-release && echo 1 || echo 0)
+ %define susever %(rpm -qf --qf '%%{version}\\n' /etc/SuSE-release)
+ %if "%susever" == "10"
+ %define distro_description SUSE Linux Enterprise Server 10
+ %define distro_releasetag sles10
+ %define distro_buildreq gcc-c++ gdbm-devel gperf ncurses-devel openldap2-client readline-devel zlib-devel
+ %define distro_requires aaa_base coreutils grep procps pwdutils
+ %else
+ %if "%susever" == "11"
+ %define distro_description SUSE Linux Enterprise Server 11
+ %define distro_releasetag sles11
+ %define distro_buildreq gcc-c++ gdbm-devel gperf ncurses-devel openldap2-client procps pwdutils readline-devel zlib-devel
+ %define distro_requires aaa_base coreutils grep procps pwdutils
+ %else
+ %{error:SuSE %{susever} is unsupported}
+ %endif
+ %endif
+ %else
+ %{error:Unsupported distribution}
+ %endif
%endif
%endif
%endif
@@ -228,7 +247,7 @@ Distribution: %{distro_description}
License: Copyright (c) 2000, @MYSQL_COPYRIGHT_YEAR@, %{mysql_vendor}. All rights reserved. Under %{license_type} license as shown in the Description field.
Source: http://www.mysql.com/Downloads/MySQL-@MYSQL_BASE_VERSION@/%{src_dir}.tar.gz
URL: http://www.mysql.com/
-Packager: MySQL Build Team <build@mysql.com>
+Packager: MySQL Release Engineering <mysql-build@oss.oracle.com>
Vendor: %{mysql_vendor}
Provides: msqlormysql MySQL-server mysql
BuildRequires: %{distro_buildreq}
@@ -421,7 +440,7 @@ mkdir debug
# XXX: install_layout so we can't just set it based on INSTALL_LAYOUT=RPM
${CMAKE} ../%{src_dir} -DBUILD_CONFIG=mysql_release -DINSTALL_LAYOUT=RPM \
-DCMAKE_BUILD_TYPE=Debug \
- -DMYSQL_UNIX_ADDR="/var/lib/mysql/mysql.sock" \
+ -DMYSQL_UNIX_ADDR="%{mysqldatadir}/mysql.sock" \
-DFEATURE_SET="%{feature_set}" \
-DCOMPILATION_COMMENT="%{compilation_comment_debug}" \
-DMYSQL_SERVER_SUFFIX="%{server_suffix}"
@@ -436,7 +455,7 @@ mkdir release
# XXX: install_layout so we can't just set it based on INSTALL_LAYOUT=RPM
${CMAKE} ../%{src_dir} -DBUILD_CONFIG=mysql_release -DINSTALL_LAYOUT=RPM \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
- -DMYSQL_UNIX_ADDR="/var/lib/mysql/mysql.sock" \
+ -DMYSQL_UNIX_ADDR="%{mysqldatadir}/mysql.sock" \
-DFEATURE_SET="%{feature_set}" \
-DCOMPILATION_COMMENT="%{compilation_comment_release}" \
-DMYSQL_SERVER_SUFFIX="%{server_suffix}"
@@ -444,25 +463,6 @@ mkdir release
make ${MAKE_JFLAG} VERBOSE=1
)
-# Use the build root for temporary storage of the shared libraries.
-RBR=$RPM_BUILD_ROOT
-
-# Clean up the BuildRoot first
-[ "$RBR" != "/" ] && [ -d "$RBR" ] && rm -rf "$RBR";
-
-# For gcc builds, include libgcc.a in the devel subpackage (BUG 4921). This
-# needs to be during build phase as $CC is not set during install.
-if "$CC" -v 2>&1 | grep '^gcc.version' >/dev/null 2>&1
-then
- libgcc=`$CC $CFLAGS --print-libgcc-file`
- if [ -f $libgcc ]
- then
- mkdir -p $RBR%{_libdir}/mysql
- install -m 644 $libgcc $RBR%{_libdir}/mysql/libmygcc.a
- echo "%{_libdir}/mysql/libmygcc.a" >>optional-files-devel
- fi
-fi
-
##############################################################################
%install
@@ -485,6 +485,23 @@ install -d $RBR%{_sbindir}
make DESTDIR=$RBR install
)
+# For gcc builds, include libgcc.a in the devel subpackage (BUG 4921). Do
+# this in a sub-shell to ensure we don't pollute the install environment
+# with compiler bits.
+(
+ PATH=${MYSQL_BUILD_PATH:-$PATH}
+ CC=${MYSQL_BUILD_CC:-${CC:-gcc}}
+ CFLAGS=${MYSQL_BUILD_CFLAGS:-${CFLAGS:-$RPM_OPT_FLAGS}}
+ if "${CC}" -v 2>&1 | grep '^gcc.version' >/dev/null 2>&1; then
+ libgcc=`${CC} ${CFLAGS} --print-libgcc-file`
+ if [ -f ${libgcc} ]; then
+ mkdir -p $RBR%{_libdir}/mysql
+ install -m 644 ${libgcc} $RBR%{_libdir}/mysql/libmygcc.a
+ echo "%{_libdir}/mysql/libmygcc.a" >>optional-files-devel
+ fi
+ fi
+)
+
# FIXME: at some point we should stop doing this and just install everything
# FIXME: directly into %{_libdir}/mysql - perhaps at the same time as renaming
# FIXME: the shared libraries to use libmysql*-$major.$minor.so syntax
@@ -516,7 +533,7 @@ install -m 644 "%{malloc_lib_source}" \
# Remove man pages we explicitly do not want to package, avoids 'unpackaged
# files' warning.
-rm -f $RBR%{_mandir}/man1/make_win_bin_dist.1*
+# This has become obsolete: rm -f $RBR%{_mandir}/man1/make_win_bin_dist.1*
##############################################################################
# Post processing actions, i.e. when installed
@@ -970,6 +987,7 @@ echo "=====" >> $STATUS_HISTORY
%doc %attr(644, root, man) %{_mandir}/man1/mysqld_safe.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysqldumpslow.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql_install_db.1*
+%doc %attr(644, root, man) %{_mandir}/man1/mysql_plugin.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql_secure_installation.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql_setpermission.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql_upgrade.1*
@@ -997,6 +1015,7 @@ echo "=====" >> $STATUS_HISTORY
%attr(755, root, root) %{_bindir}/mysql_convert_table_format
%attr(755, root, root) %{_bindir}/mysql_fix_extensions
%attr(755, root, root) %{_bindir}/mysql_install_db
+%attr(755, root, root) %{_bindir}/mysql_plugin
%attr(755, root, root) %{_bindir}/mysql_secure_installation
%attr(755, root, root) %{_bindir}/mysql_setpermission
%attr(755, root, root) %{_bindir}/mysql_tzinfo_to_sql
@@ -1112,10 +1131,30 @@ echo "=====" >> $STATUS_HISTORY
# merging BK trees)
##############################################################################
%changelog
+* Tue Sep 13 2011 Jonathan Perkin <jonathan.perkin@oracle.com>
+
+- Add support for Oracle Linux 6 and Red Hat Enterprise Linux 6. Due to
+ changes in RPM behaviour ($RPM_BUILD_ROOT is removed prior to install)
+ this necessitated a move of the libmygcc.a installation to the install
+ phase, which is probably where it belonged in the first place.
+
+* Tue Sep 13 2011 Joerg Bruehe <joerg.bruehe@oracle.com>
+
+- "make_win_bin_dist" and its manual are dropped, cmake does it different.
+
* Thu Sep 08 2011 Daniel Fischer <daniel.fischer@oracle.com>
- Add mysql_plugin man page.
+* Tue Aug 30 2011 Joerg Bruehe <joerg.bruehe@oracle.com>
+
+- Add the manual page for "mysql_plugin" to the server package.
+
+* Fri Aug 19 2011 Joerg Bruehe <joerg.bruehe@oracle.com>
+
+- Null-upmerge the fix of bug#37165: This spec file is not affected.
+- Replace "/var/lib/mysql" by the spec file variable "%{mysqldatadir}".
+
* Fri Aug 12 2011 Daniel Fischer <daniel.fischer@oracle.com>
- Source plugin library files list from cmake-generated file.