summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorgi Kodinov <Georgi.Kodinov@Oracle.com>2011-10-12 14:34:44 +0300
committerGeorgi Kodinov <Georgi.Kodinov@Oracle.com>2011-10-12 14:34:44 +0300
commit494b581f14abd7c073dae2da11d75c0ff697d967 (patch)
tree3a78110500a95c0e6c6410e6a7b730d882f168e5
parent8c2943ba437404973912b90cdf4c6d724f5f6ed3 (diff)
parent73db2a1504188611c3348e1bd55d181aea6ab533 (diff)
downloadmariadb-git-494b581f14abd7c073dae2da11d75c0ff697d967.tar.gz
auto-merge mysql-5.1->mysql-5.1-security
-rw-r--r--client/mysql.cc2
-rw-r--r--client/mysqltest.cc27
-rw-r--r--configure.in4
-rw-r--r--extra/innochecksum.c8
-rw-r--r--include/decimal.h9
-rw-r--r--include/heap.h2
-rw-r--r--mysql-test/include/have_federated_plugin.inc5
-rw-r--r--mysql-test/include/mtr_check.sql13
-rw-r--r--mysql-test/lib/mtr_cases.pm29
-rwxr-xr-xmysql-test/mysql-test-run.pl29
-rw-r--r--mysql-test/r/error_simulation.result13
-rw-r--r--mysql-test/r/group_by.result32
-rw-r--r--mysql-test/r/heap.result4
-rw-r--r--mysql-test/r/merge.result29
-rw-r--r--mysql-test/r/myisampack.result32
-rw-r--r--mysql-test/r/mysqltest.result11
-rw-r--r--mysql-test/r/partition_innodb_plugin.result2
-rw-r--r--mysql-test/r/select_safe.result12
-rw-r--r--mysql-test/r/show_check.result44
-rw-r--r--mysql-test/r/sp_trans.result46
-rw-r--r--mysql-test/r/type_newdecimal.result11
-rw-r--r--mysql-test/suite/engines/funcs/r/de_calendar_range.result2
-rw-r--r--mysql-test/suite/engines/funcs/r/in_calendar_2_unique_constraints_duplicate_update.result2
-rw-r--r--mysql-test/suite/engines/funcs/r/in_calendar_pk_constraint_duplicate_update.result2
-rw-r--r--mysql-test/suite/engines/funcs/r/in_calendar_pk_constraint_error.result2
-rw-r--r--mysql-test/suite/engines/funcs/r/in_calendar_pk_constraint_ignore.result2
-rw-r--r--mysql-test/suite/engines/funcs/r/in_calendar_unique_constraint_duplicate_update.result2
-rw-r--r--mysql-test/suite/engines/funcs/r/in_calendar_unique_constraint_error.result2
-rw-r--r--mysql-test/suite/engines/funcs/r/in_calendar_unique_constraint_ignore.result2
-rw-r--r--mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_pk_constraint_duplicate_update.result2
-rw-r--r--mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_pk_constraint_error.result2
-rw-r--r--mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_pk_constraint_ignore.result2
-rw-r--r--mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_unique_constraint_duplicate_update.result2
-rw-r--r--mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_unique_constraint_error.result2
-rw-r--r--mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_unique_constraint_ignore.result2
-rw-r--r--mysql-test/suite/engines/funcs/r/in_multicolumn_number_pk_constraint_duplicate_update.result2
-rw-r--r--mysql-test/suite/engines/funcs/r/up_calendar_range.result2
-rw-r--r--mysql-test/suite/engines/funcs/t/de_calendar_range.test5
-rw-r--r--mysql-test/suite/engines/funcs/t/in_calendar_2_unique_constraints_duplicate_update.test4
-rw-r--r--mysql-test/suite/engines/funcs/t/in_calendar_pk_constraint_duplicate_update.test5
-rw-r--r--mysql-test/suite/engines/funcs/t/in_calendar_pk_constraint_error.test5
-rw-r--r--mysql-test/suite/engines/funcs/t/in_calendar_pk_constraint_ignore.test4
-rw-r--r--mysql-test/suite/engines/funcs/t/in_calendar_unique_constraint_duplicate_update.test5
-rw-r--r--mysql-test/suite/engines/funcs/t/in_calendar_unique_constraint_error.test5
-rw-r--r--mysql-test/suite/engines/funcs/t/in_calendar_unique_constraint_ignore.test5
-rw-r--r--mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_pk_constraint_duplicate_update.test4
-rw-r--r--mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_pk_constraint_error.test5
-rw-r--r--mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_pk_constraint_ignore.test5
-rw-r--r--mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_unique_constraint_duplicate_update.test5
-rw-r--r--mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_unique_constraint_error.test5
-rw-r--r--mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_unique_constraint_ignore.test4
-rw-r--r--mysql-test/suite/engines/funcs/t/in_multicolumn_number_pk_constraint_duplicate_update.test4
-rw-r--r--mysql-test/suite/engines/funcs/t/up_calendar_range.test5
-rw-r--r--mysql-test/suite/federated/federated_plugin-master.opt2
-rw-r--r--mysql-test/suite/federated/federated_plugin.result19
-rw-r--r--mysql-test/suite/federated/federated_plugin.test37
-rw-r--r--mysql-test/suite/innodb_plugin/r/innodb-index.result98
-rw-r--r--mysql-test/suite/innodb_plugin/r/innodb_bug52745.result1
-rw-r--r--mysql-test/suite/innodb_plugin/r/innodb_bug53591.result1
-rw-r--r--mysql-test/suite/innodb_plugin/t/innodb-autoinc-18274.test9
-rw-r--r--mysql-test/suite/innodb_plugin/t/innodb-autoinc-44030.test9
-rw-r--r--mysql-test/suite/innodb_plugin/t/innodb-autoinc-56228.test9
-rw-r--r--mysql-test/suite/innodb_plugin/t/innodb-autoinc.test9
-rwxr-xr-xmysql-test/suite/innodb_plugin/t/innodb-create-options.test2
-rw-r--r--mysql-test/suite/innodb_plugin/t/innodb-index.test105
-rw-r--r--mysql-test/suite/innodb_plugin/t/innodb-zip.test2
-rw-r--r--mysql-test/suite/innodb_plugin/t/innodb_bug36172.test2
-rw-r--r--mysql-test/suite/innodb_plugin/t/innodb_bug47167-master.opt1
-rw-r--r--mysql-test/suite/innodb_plugin/t/innodb_bug52745.test2
-rw-r--r--mysql-test/suite/innodb_plugin/t/innodb_bug53591.test2
-rw-r--r--mysql-test/suite/innodb_plugin/t/innodb_bug56680.test2
-rw-r--r--mysql-test/suite/innodb_plugin/t/innodb_bug59641.test4
-rw-r--r--mysql-test/suite/innodb_plugin/t/innodb_file_format-master.opt1
-rw-r--r--mysql-test/suite/ndb/t/ndb_partition_error2.test1
-rw-r--r--mysql-test/suite/sys_vars/r/max_join_size_func.result4
-rw-r--r--mysql-test/suite/sys_vars/r/sql_big_selects_func.result2
-rw-r--r--mysql-test/suite/sys_vars/r/sql_max_join_size_func.result2
-rw-r--r--mysql-test/t/error_simulation.test14
-rw-r--r--mysql-test/t/group_by.test14
-rw-r--r--mysql-test/t/heap.test2
-rw-r--r--mysql-test/t/merge.test45
-rw-r--r--mysql-test/t/myisampack.test45
-rw-r--r--mysql-test/t/mysqltest.test25
-rw-r--r--mysql-test/t/partition_innodb_plugin.test2
-rw-r--r--mysql-test/t/show_check.test20
-rw-r--r--mysql-test/t/sp_trans.test33
-rw-r--r--mysql-test/t/type_newdecimal.test14
-rw-r--r--mysql-test/valgrind.supp37
-rw-r--r--scripts/mysql_install_db.pl.in5
-rw-r--r--scripts/mysql_install_db.sh5
-rw-r--r--sql/filesort.cc16
-rw-r--r--sql/item_subselect.cc13
-rw-r--r--sql/item_subselect.h1
-rw-r--r--sql/my_decimal.h6
-rw-r--r--sql/rpl_rli.h8
-rw-r--r--sql/share/errmsg.txt4
-rw-r--r--sql/slave.cc11
-rw-r--r--sql/sql_base.cc183
-rw-r--r--sql/sql_parse.cc6
-rw-r--r--sql/sql_select.cc10
-rw-r--r--sql/sql_yacc.yy4
-rw-r--r--storage/federated/Makefile.am4
-rw-r--r--storage/heap/ha_heap.cc1
-rw-r--r--storage/heap/hp_create.c1
-rw-r--r--storage/heap/hp_info.c1
-rw-r--r--storage/innobase/btr/btr0btr.c222
-rw-r--r--storage/innobase/btr/btr0cur.c92
-rw-r--r--storage/innobase/buf/buf0buf.c23
-rw-r--r--storage/innobase/fsp/fsp0fsp.c168
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.c8
-rw-r--r--storage/innobase/include/btr0btr.h31
-rw-r--r--storage/innobase/include/btr0cur.h14
-rw-r--r--storage/innobase/include/buf0buf.h9
-rw-r--r--storage/innobase/include/fsp0fsp.h8
-rw-r--r--storage/innobase/include/mtr0mtr.h7
-rw-r--r--storage/innobase/include/mtr0mtr.ic4
-rw-r--r--storage/innobase/include/sync0rw.h3
-rw-r--r--storage/innobase/include/sync0rw.ic1
-rw-r--r--storage/innobase/mtr/mtr0mtr.c10
-rw-r--r--storage/innobase/row/row0ins.c32
-rw-r--r--storage/innobase/row/row0purge.c14
-rw-r--r--storage/innobase/row/row0row.c38
-rw-r--r--storage/innobase/row/row0upd.c23
-rw-r--r--storage/innobase/sync/sync0rw.c13
-rw-r--r--storage/innobase/trx/trx0undo.c2
-rw-r--r--storage/innodb_plugin/ChangeLog50
-rw-r--r--storage/innodb_plugin/btr/btr0btr.c320
-rw-r--r--storage/innodb_plugin/btr/btr0cur.c211
-rw-r--r--storage/innodb_plugin/btr/btr0pcur.c9
-rw-r--r--storage/innodb_plugin/btr/btr0sea.c3
-rw-r--r--storage/innodb_plugin/buf/buf0buddy.c2
-rw-r--r--storage/innodb_plugin/buf/buf0buf.c23
-rw-r--r--storage/innodb_plugin/dict/dict0crea.c4
-rw-r--r--storage/innodb_plugin/dict/dict0dict.c6
-rw-r--r--storage/innodb_plugin/fsp/fsp0fsp.c234
-rw-r--r--storage/innodb_plugin/ibuf/ibuf0ibuf.c35
-rw-r--r--storage/innodb_plugin/include/btr0btr.h66
-rw-r--r--storage/innodb_plugin/include/btr0btr.ic10
-rw-r--r--storage/innodb_plugin/include/btr0cur.h38
-rw-r--r--storage/innodb_plugin/include/buf0buf.h9
-rw-r--r--storage/innodb_plugin/include/fsp0fsp.h30
-rw-r--r--storage/innodb_plugin/include/mtr0mtr.h11
-rw-r--r--storage/innodb_plugin/include/mtr0mtr.ic6
-rw-r--r--storage/innodb_plugin/include/page0page.h5
-rw-r--r--storage/innodb_plugin/include/row0upd.ic5
-rw-r--r--storage/innodb_plugin/include/sync0rw.h3
-rw-r--r--storage/innodb_plugin/include/sync0rw.ic1
-rw-r--r--storage/innodb_plugin/include/sync0sync.h9
-rw-r--r--storage/innodb_plugin/include/trx0undo.h46
-rw-r--r--storage/innodb_plugin/mtr/mtr0mtr.c5
-rw-r--r--storage/innodb_plugin/row/row0ins.c31
-rw-r--r--storage/innodb_plugin/row/row0mysql.c29
-rw-r--r--storage/innodb_plugin/row/row0purge.c20
-rw-r--r--storage/innodb_plugin/row/row0row.c27
-rw-r--r--storage/innodb_plugin/row/row0sel.c24
-rw-r--r--storage/innodb_plugin/row/row0upd.c23
-rw-r--r--storage/innodb_plugin/sync/sync0rw.c7
-rw-r--r--storage/innodb_plugin/sync/sync0sync.c34
-rw-r--r--storage/innodb_plugin/trx/trx0rec.c69
-rw-r--r--storage/innodb_plugin/trx/trx0undo.c70
-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--support-files/mysql.spec.sh91
166 files changed, 2625 insertions, 1009 deletions
diff --git a/client/mysql.cc b/client/mysql.cc
index 0a6b4da34b0..49d58a832a2 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -4290,7 +4290,7 @@ sql_real_connect(char *host,char *database,char *user,char *password,
{
char init_command[100];
sprintf(init_command,
- "SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=%lu,SQL_MAX_JOIN_SIZE=%lu",
+ "SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=%lu,MAX_JOIN_SIZE=%lu",
select_limit,max_join_size);
mysql_options(&mysql, MYSQL_INIT_COMMAND, init_command);
}
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 9985b70fcbc..593bb8ea290 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -451,6 +451,7 @@ TYPELIB command_typelib= {array_elements(command_names),"",
command_names, 0};
DYNAMIC_STRING ds_res;
+struct st_command *curr_command= 0;
char builtin_echo[FN_REFLEN];
@@ -2212,9 +2213,16 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
init_dynamic_string(&ds_query, 0, (end - query) + 32, 256);
do_eval(&ds_query, query, end, FALSE);
- if (mysql_real_query(mysql, ds_query.str, ds_query.length))
- die("Error running query '%s': %d %s", ds_query.str,
- mysql_errno(mysql), mysql_error(mysql));
+ if (mysql_real_query(mysql, ds_query.str, ds_query.length))
+ {
+ handle_error (curr_command, mysql_errno(mysql), mysql_error(mysql),
+ mysql_sqlstate(mysql), &ds_res);
+ /* If error was acceptable, return empty string */
+ dynstr_free(&ds_query);
+ eval_expr(var, "", 0);
+ DBUG_VOID_RETURN;
+ }
+
if (!(res= mysql_store_result(mysql)))
die("Query '%s' didn't return a result set", ds_query.str);
dynstr_free(&ds_query);
@@ -2315,8 +2323,15 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
/* Run the query */
if (mysql_real_query(mysql, ds_query.str, ds_query.length))
- die("Error running query '%s': %d %s", ds_query.str,
- mysql_errno(mysql), mysql_error(mysql));
+ {
+ handle_error (curr_command, mysql_errno(mysql), mysql_error(mysql),
+ mysql_sqlstate(mysql), &ds_res);
+ /* If error was acceptable, return empty string */
+ dynstr_free(&ds_query);
+ eval_expr(var, "", 0);
+ DBUG_VOID_RETURN;
+ }
+
if (!(res= mysql_store_result(mysql)))
die("Query '%s' didn't return a result set", ds_query.str);
@@ -8147,6 +8162,8 @@ int main(int argc, char **argv)
{
command->last_argument= command->first_argument;
processed = 1;
+ /* Need to remember this for handle_error() */
+ curr_command= command;
switch (command->type) {
case Q_CONNECT:
do_connect(command);
diff --git a/configure.in b/configure.in
index e56a18540b5..120717d6afa 100644
--- a/configure.in
+++ b/configure.in
@@ -2711,7 +2711,7 @@ then
MAN_DROP="$MAN_DROP embedded"
grep -v 'embedded' $MANLISTFIL > $TMPLISTFIL ; mv -f $TMPLISTFIL $MANLISTFIL
fi
- if test X"$with_plugin_innobase" != Xyes
+ if test X"$with_plugin_innobase" != Xyes -a X"$with_plugin_innodb_plugin" != Xyes
then
MAN_DROP="$MAN_DROP innodb"
grep -v 'inno' $MANLISTFIL > $TMPLISTFIL ; mv -f $TMPLISTFIL $MANLISTFIL
@@ -2790,7 +2790,7 @@ then
fi
# "innochecksum" is not in the "innobase/" subdirectory, but should be switched
-AM_CONDITIONAL([BUILD_INNODB_TOOLS], [test X"$with_plugin_innobase" = Xyes])
+AM_CONDITIONAL([BUILD_INNODB_TOOLS], [test X"$with_plugin_innobase" = Xyes -o X"$with_plugin_innodb_plugin" = Xyes ])
# IMPORTANT - do not modify LIBS past this line - this hack is the only way
# I know to add the static NSS magic if we have static NSS libraries with
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 530ed9e1757..c377bd4a400 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/heap.h b/include/heap.h
index 0abdd71461e..7adaac33096 100644
--- a/include/heap.h
+++ b/include/heap.h
@@ -50,6 +50,7 @@ typedef struct st_heapinfo /* Struct from heap_info */
uint reclength; /* Length of one record */
int errkey;
ulonglong auto_increment;
+ time_t create_time;
} HEAPINFO;
@@ -146,6 +147,7 @@ typedef struct st_heap_share
uint open_count;
uchar *del_link; /* Link to next block with del. rec */
char * name; /* Name of "memory-file" */
+ time_t create_time;
#ifdef THREAD
THR_LOCK lock;
pthread_mutex_t intern_lock; /* Locking for use with _locking */
diff --git a/mysql-test/include/have_federated_plugin.inc b/mysql-test/include/have_federated_plugin.inc
new file mode 100644
index 00000000000..5c7549de53f
--- /dev/null
+++ b/mysql-test/include/have_federated_plugin.inc
@@ -0,0 +1,5 @@
+if (`select plugin_library IS NULL from information_schema.plugins where plugin_name LIKE '%federated%'`)
+{
+ --skip federated plugin not available
+}
+
diff --git a/mysql-test/include/mtr_check.sql b/mysql-test/include/mtr_check.sql
index 55e346c2007..64bb7c01544 100644
--- a/mysql-test/include/mtr_check.sql
+++ b/mysql-test/include/mtr_check.sql
@@ -27,7 +27,8 @@ BEGIN
-- Dump all global variables except those
-- that are supposed to change
SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
- WHERE variable_name != 'timestamp' ORDER BY VARIABLE_NAME;
+ WHERE variable_name NOT IN ('timestamp', 'innodb_file_format_check')
+ ORDER BY VARIABLE_NAME;
-- Dump all databases, there should be none
-- except those that was created during bootstrap
@@ -72,3 +73,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/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm
index 708b8e90fc4..9b5608241a3 100644
--- a/mysql-test/lib/mtr_cases.pm
+++ b/mysql-test/lib/mtr_cases.pm
@@ -222,8 +222,11 @@ sub collect_test_cases ($$$) {
sub split_testname {
my ($test_name)= @_;
- # Get rid of directory part and split name on .'s
- my @parts= split(/\./, basename($test_name));
+ # If .test file name is used, get rid of directory part
+ $test_name= basename($test_name) if $test_name =~ /\.test$/;
+
+ # Now split name on .'s
+ my @parts= split(/\./, $test_name);
if (@parts == 1){
# Only testname given, ex: alias
@@ -317,10 +320,30 @@ sub collect_one_suite($)
my %disabled;
if ( open(DISABLED, "$testdir/disabled.def" ) )
{
+ # $^O on Windows considered not generic enough
+ my $plat= (IS_WINDOWS) ? 'windows' : $^O;
+
while ( <DISABLED> )
{
chomp;
- if ( /^\s*(\S+)\s*:\s*(.*?)\s*$/ )
+ #diasble the test case if platform matches
+ if ( /\@/ )
+ {
+ if ( /\@$plat/ )
+ {
+ /^\s*(\S+)\s*\@$plat.*:\s*(.*?)\s*$/ ;
+ $disabled{$1}= $2;
+ }
+ elsif ( /\@!(\S*)/ )
+ {
+ if ( $1 ne $plat)
+ {
+ /^\s*(\S+)\s*\@!.*:\s*(.*?)\s*$/ ;
+ $disabled{$1}= $2;
+ }
+ }
+ }
+ elsif ( /^\s*(\S+)\s*:\s*(.*?)\s*$/ )
{
$disabled{$1}= $2;
}
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 1c7efccc69d..4e4333767da 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -1979,6 +1979,24 @@ sub environment_setup {
$ENV{'EXAMPLE_PLUGIN_LOAD'}="--plugin_load=EXAMPLE=".$plugin_filename;
}
+ # --------------------------------------------------------------------------
+ # Add the path where mysqld will find ha_federated.so
+ # --------------------------------------------------------------------------
+ my $fedplug_filename;
+ if (IS_WINDOWS) {
+ $fedplug_filename = "ha_federated.dll";
+ } else {
+ $fedplug_filename = "ha_federated.so";
+ }
+ my $lib_fed_plugin=
+ mtr_file_exists(vs_config_dirs('storage/federated',$fedplug_filename),
+ "$basedir/storage/federated/.libs/".$fedplug_filename,
+ "$basedir/lib/mysql/plugin/".$fedplug_filename);
+
+ $ENV{'FEDERATED_PLUGIN'}= $fedplug_filename;
+ $ENV{'FEDERATED_PLUGIN_DIR'}=
+ ($lib_fed_plugin ? dirname($lib_fed_plugin) : "");
+
# ----------------------------------------------------
# Add the path where mysqld will find mypluglib.so
# ----------------------------------------------------
@@ -2112,6 +2130,12 @@ sub environment_setup {
$ENV{'MYSQL_FIX_SYSTEM_TABLES'}= mysql_fix_arguments();
$ENV{'EXE_MYSQL'}= $exe_mysql;
+ my $exe_mysqld= find_mysqld($basedir);
+ $ENV{'MYSQLD'}= $exe_mysqld;
+ my $extra_opts= join (" ", @opt_extra_mysqld_opt);
+ $ENV{'MYSQLD_CMD'}= "$exe_mysqld --defaults-group-suffix=.1 ".
+ "--defaults-file=$path_config_file $extra_opts";
+
# ----------------------------------------------------
# bug25714 executable may _not_ exist in
# some versions, test using it should be skipped
@@ -3831,6 +3855,11 @@ sub extract_server_log ($$) {
else
{
push(@lines, $line);
+ if (scalar(@lines) > 1000000) {
+ $Ferr = undef;
+ mtr_warning("Too much log from test, bailing out from extracting");
+ return ();
+ }
}
}
else
diff --git a/mysql-test/r/error_simulation.result b/mysql-test/r/error_simulation.result
index b6b79cb596b..f1835186787 100644
--- a/mysql-test/r/error_simulation.result
+++ b/mysql-test/r/error_simulation.result
@@ -83,5 +83,18 @@ a a b filler
SET SESSION debug = DEFAULT;
DROP TABLE t1, t2;
#
+# Bug#11747970 34660: CRASH WHEN FEDERATED TABLE LOSES CONNECTION DURING INSERT ... SELECT
+#
+CREATE TABLE t1(f1 INT, KEY(f1));
+CREATE TABLE t2(f1 INT);
+INSERT INTO t1 VALUES (1),(2);
+INSERT INTO t2 VALUES (1),(2);
+SET SESSION debug='d,bug11747970_simulate_error';
+INSERT IGNORE INTO t2 SELECT f1 FROM t1 a WHERE NOT EXISTS (SELECT 1 FROM t2 b WHERE a.f1 = b.f1);
+Warnings:
+Error 1105 Unknown error
+SET SESSION debug = DEFAULT;
+DROP TABLE t1,t2;
+#
# End of 5.1 tests
#
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 1dfb0f5860a..2c9f6116eed 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -1891,4 +1891,36 @@ 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
diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result
index ddf675e2f73..fd072bbab5d 100644
--- a/mysql-test/r/heap.result
+++ b/mysql-test/r/heap.result
@@ -715,8 +715,8 @@ create table t1 (c char(10)) engine=memory;
create table t2 (c varchar(10)) engine=memory;
show table status like 't_';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 MEMORY 10 Fixed 0 11 0 # 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 MEMORY 10 Fixed 0 12 0 # 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 MEMORY 10 Fixed 0 11 0 # 0 0 NULL # NULL NULL latin1_swedish_ci NULL
+t2 MEMORY 10 Fixed 0 12 0 # 0 0 NULL # NULL NULL latin1_swedish_ci NULL
drop table t1, t2;
CREATE TABLE t1(a VARCHAR(1), b VARCHAR(2), c VARCHAR(256),
KEY(a), KEY(b), KEY(c)) ENGINE=MEMORY;
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index 3af152672ab..a4f1c79dff4 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -2341,4 +2341,33 @@ REPAIR TABLE m1;
Table Op Msg_type Msg_text
test.m1 repair note The storage engine for the table doesn't support repair
DROP TABLE m1, t1;
+#
+# BUG#11763712 - 56458: KILLING A FLUSH TABLE FOR A MERGE/CHILD
+# CRASHES SERVER
+#
+CREATE TABLE t1(a INT);
+CREATE TABLE t2(a INT);
+CREATE TABLE t3(a INT, b INT);
+CREATE TABLE m1(a INT) ENGINE=MERGE UNION=(t1, t2);
+# Test reopen merge parent failure
+LOCK TABLES m1 READ;
+# Remove 'm1' table using file operations.
+FLUSH TABLES;
+ERROR 42S02: Table 'test.m1' doesn't exist
+UNLOCK TABLES;
+CREATE TABLE m1(a INT) ENGINE=MERGE UNION=(t1, t2);
+# Test reopen merge child failure
+LOCK TABLES m1 READ;
+# Remove 't1' table using file operations.
+FLUSH TABLES;
+ERROR 42S02: Table 'test.t1' doesn't exist
+UNLOCK TABLES;
+CREATE TABLE t1(a INT);
+# Test reattach merge failure
+LOCK TABLES m1 READ;
+# Replace 't1' with 't3' table using file operations.
+FLUSH TABLES;
+ERROR HY000: Can't reopen table: 'm1'
+UNLOCK TABLES;
+DROP TABLE t1, t2, t3, m1;
End of 5.1 tests
diff --git a/mysql-test/r/myisampack.result b/mysql-test/r/myisampack.result
index fbcd8aed17a..f19a9c49427 100644
--- a/mysql-test/r/myisampack.result
+++ b/mysql-test/r/myisampack.result
@@ -87,3 +87,35 @@ COUNT(*)
128
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 a16b3ec2670..ecfd526ebc9 100644
--- a/mysql-test/r/mysqltest.result
+++ b/mysql-test/r/mysqltest.result
@@ -135,6 +135,10 @@ 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...
+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
+ is empty
+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 'nonsense' at line 1
+ is empty
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 1064 as "after_--enable_abort_on_error" ;
@@ -143,6 +147,9 @@ after_--enable_abort_on_error
select 3 from t1 ;
ERROR 42S02: Table 'test.t1' doesn't exist
mysqltest: At line 1: query 'select 3 from t1' failed with wrong errno 1146: 'Table 'test.t1' doesn't exist', instead of 1064...
+ is empty
+ is empty
+"Yes it's empty"
hello
hello
;;;;;;;;
@@ -315,7 +322,7 @@ insert into t1 values ('$dollar');
$dollar
`select 42`
drop table t1;
-mysqltest: At line 1: Error running query 'failing query': 1064 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 'failing query' at line 1
+mysqltest: At line 1: query 'let $var2= `failing query`' failed: 1064: 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 'failing query' at line 1
mysqltest: At line 1: Missing required argument 'filename' to command 'source'
mysqltest: At line 1: Could not open './non_existingFile' for reading, errno: 2
mysqltest: In included file "MYSQLTEST_VARDIR/tmp/recursive.sql":
@@ -813,7 +820,7 @@ mysqltest: At line 1: Could not find column 'column_not_exists' in the result of
mysqltest: At line 1: Query 'SET @A = 1' didn't return a result set
mysqltest: At line 1: Could not find column '1 AS B' in the result of 'SELECT 1 AS A'
value= No such row
-mysqltest: At line 1: Error running query 'SHOW COLNS FROM t1': 1064 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 'COLNS FROM t1' at line 1
+mysqltest: At line 1: query 'let $value= query_get_value(SHOW COLNS FROM t1, Field, 1)' failed: 1064: 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 'COLNS FROM t1' at line 1
Field Type Null Key Default Extra
a int(11) YES -><- NULL
diff --git a/mysql-test/r/partition_innodb_plugin.result b/mysql-test/r/partition_innodb_plugin.result
index cebee0b84c6..42ac9c699de 100644
--- a/mysql-test/r/partition_innodb_plugin.result
+++ b/mysql-test/r/partition_innodb_plugin.result
@@ -25,7 +25,6 @@ call mtr.add_suppression("nnoDB: Error: table `test`.`t1` .* Partition.* InnoDB
#
# Bug#55091: Server crashes on ADD PARTITION after a failed attempt
#
-SET @old_innodb_file_format_check = @@global.innodb_file_format_check;
SET @old_innodb_file_format = @@global.innodb_file_format;
SET @old_innodb_file_per_table = @@global.innodb_file_per_table;
SET @old_innodb_strict_mode = @@global.innodb_strict_mode;
@@ -93,7 +92,6 @@ DROP TABLE t1;
SET @@global.innodb_strict_mode = @old_innodb_strict_mode;
SET @@global.innodb_file_format = @old_innodb_file_format;
SET @@global.innodb_file_per_table = @old_innodb_file_per_table;
-SET @@global.innodb_file_format_check = @old_innodb_file_format_check;
SET NAMES utf8;
CREATE TABLE `t``\""e` (a INT, PRIMARY KEY (a))
ENGINE=InnoDB
diff --git a/mysql-test/r/select_safe.result b/mysql-test/r/select_safe.result
index feac9efcb13..d810271e337 100644
--- a/mysql-test/r/select_safe.result
+++ b/mysql-test/r/select_safe.result
@@ -30,7 +30,7 @@ ERROR HY000: You are using safe update mode and you tried to update a table with
delete from t1 where a+0=1;
ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
select 1 from t1,t1 as t2,t1 as t3,t1 as t4,t1 as t5;
-ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
+ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay
update t1 set b="a" limit 1;
update t1 set b="a" where b="b" limit 2;
delete from t1 where b="test" limit 1;
@@ -42,7 +42,7 @@ SELECT @@MAX_JOIN_SIZE, @@SQL_BIG_SELECTS;
2 0
insert into t1 values (null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a");
SELECT * from t1 order by a;
-ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
+ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay
SET SQL_BIG_SELECTS=1;
SELECT * from t1 order by a;
a b
@@ -52,7 +52,7 @@ a b
5 a
SET MAX_JOIN_SIZE=2;
SELECT * from t1;
-ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
+ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay
SET MAX_JOIN_SIZE=DEFAULT;
SELECT * from t1;
a b
@@ -82,12 +82,12 @@ insert into t1 select * from t1;
insert into t1 select * from t1;
set local max_join_size=8;
select * from (select * from t1) x;
-ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
+ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay
set local max_join_size=1;
select * from (select a.a as aa, b.a as ba from t1 a, t1 b) x;
-ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
+ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay
set local max_join_size=1;
select * from (select 1 union select 2 union select 3) x;
-ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
+ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay
drop table t1;
SET SQL_SAFE_UPDATES=0,SQL_SELECT_LIMIT=DEFAULT, SQL_MAX_JOIN_SIZE=DEFAULT;
diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result
index 7cb3f696449..7b633d42f44 100644
--- a/mysql-test/r/show_check.result
+++ b/mysql-test/r/show_check.result
@@ -458,57 +458,57 @@ insert into t2 values (1),(2);
insert into t3 values (1,1),(2,2);
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 MEMORY 10 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 MEMORY 10 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 MEMORY 10 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 MEMORY 10 Fixed 2 # # # # 0 NULL # NULL NULL latin1_swedish_ci NULL
+t2 MEMORY 10 Fixed 2 # # # # 0 NULL # NULL NULL latin1_swedish_ci NULL
+t3 MEMORY 10 Fixed 2 # # # # 0 NULL # NULL NULL latin1_swedish_ci NULL
insert into t1 values (3),(4);
insert into t2 values (3),(4);
insert into t3 values (3,3),(4,4);
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 MEMORY 10 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 MEMORY 10 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 MEMORY 10 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 MEMORY 10 Fixed 4 # # # # 0 NULL # NULL NULL latin1_swedish_ci NULL
+t2 MEMORY 10 Fixed 4 # # # # 0 NULL # NULL NULL latin1_swedish_ci NULL
+t3 MEMORY 10 Fixed 4 # # # # 0 NULL # NULL NULL latin1_swedish_ci NULL
insert into t1 values (5);
insert into t2 values (5);
insert into t3 values (5,5);
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 MEMORY 10 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 MEMORY 10 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 MEMORY 10 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 MEMORY 10 Fixed 5 # # # # 0 NULL # NULL NULL latin1_swedish_ci NULL
+t2 MEMORY 10 Fixed 5 # # # # 0 NULL # NULL NULL latin1_swedish_ci NULL
+t3 MEMORY 10 Fixed 5 # # # # 0 NULL # NULL NULL latin1_swedish_ci NULL
delete from t1 where a=3;
delete from t2 where b=3;
delete from t3 where a=3;
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 MEMORY 10 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 MEMORY 10 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 MEMORY 10 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 MEMORY 10 Fixed 4 # # # # # NULL # NULL NULL latin1_swedish_ci NULL
+t2 MEMORY 10 Fixed 4 # # # # # NULL # NULL NULL latin1_swedish_ci NULL
+t3 MEMORY 10 Fixed 4 # # # # # NULL # NULL NULL latin1_swedish_ci NULL
truncate table t1;
truncate table t2;
truncate table t3;
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 MEMORY 10 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 MEMORY 10 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 MEMORY 10 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 MEMORY 10 Fixed 0 # # # # 0 NULL # NULL NULL latin1_swedish_ci NULL
+t2 MEMORY 10 Fixed 0 # # # # 0 NULL # NULL NULL latin1_swedish_ci NULL
+t3 MEMORY 10 Fixed 0 # # # # 0 NULL # NULL NULL latin1_swedish_ci NULL
insert into t1 values (5);
insert into t2 values (5);
insert into t3 values (5,5);
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 MEMORY 10 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 MEMORY 10 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 MEMORY 10 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 MEMORY 10 Fixed 1 # # # # 0 NULL # NULL NULL latin1_swedish_ci NULL
+t2 MEMORY 10 Fixed 1 # # # # 0 NULL # NULL NULL latin1_swedish_ci NULL
+t3 MEMORY 10 Fixed 1 # # # # 0 NULL # NULL NULL latin1_swedish_ci NULL
delete from t1 where a=5;
delete from t2 where b=5;
delete from t3 where a=5;
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 MEMORY 10 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 MEMORY 10 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 MEMORY 10 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 MEMORY 10 Fixed 0 # # # # # NULL # NULL NULL latin1_swedish_ci NULL
+t2 MEMORY 10 Fixed 0 # # # # # NULL # NULL NULL latin1_swedish_ci NULL
+t3 MEMORY 10 Fixed 0 # # # # # NULL # NULL NULL latin1_swedish_ci NULL
drop table t1, t2, t3;
create database mysqltest;
show create database mysqltest;
@@ -659,7 +659,7 @@ DROP TABLE t1;
flush tables;
SHOW TABLE STATUS like 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 NULL NULL NULL NULL # # # # NULL NULL NULL NULL NULL NULL NULL NULL Incorrect information in file: './test/t1.frm'
+t1 NULL NULL NULL NULL # # # # NULL NULL # NULL NULL NULL NULL NULL Incorrect information in file: './test/t1.frm'
Warnings:
Warning 1033 Incorrect information in file: './test/t1.frm'
show create table t1;
diff --git a/mysql-test/r/sp_trans.result b/mysql-test/r/sp_trans.result
index a64f53efde7..dec37db652a 100644
--- a/mysql-test/r/sp_trans.result
+++ b/mysql-test/r/sp_trans.result
@@ -556,3 +556,49 @@ 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|
diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result
index c301a7dd629..0c6c1333e9b 100644
--- a/mysql-test/r/type_newdecimal.result
+++ b/mysql-test/r/type_newdecimal.result
@@ -1927,3 +1927,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/suite/engines/funcs/r/de_calendar_range.result b/mysql-test/suite/engines/funcs/r/de_calendar_range.result
index 904b14c06b5..07543e0c8c4 100644
--- a/mysql-test/suite/engines/funcs/r/de_calendar_range.result
+++ b/mysql-test/suite/engines/funcs/r/de_calendar_range.result
@@ -1,4 +1,5 @@
DROP TABLE IF EXISTS t1,t2,t3;
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL PRIMARY KEY);
SET TIMESTAMP=1171346973;
INSERT INTO t1 (c1) VALUES(NOW());
@@ -89,3 +90,4 @@ c1
2007-02-16 12:10:34
2007-02-17 13:10:34
DROP TABLE t1;
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/r/in_calendar_2_unique_constraints_duplicate_update.result b/mysql-test/suite/engines/funcs/r/in_calendar_2_unique_constraints_duplicate_update.result
index 7479cf3ea0b..9c56e23574d 100644
--- a/mysql-test/suite/engines/funcs/r/in_calendar_2_unique_constraints_duplicate_update.result
+++ b/mysql-test/suite/engines/funcs/r/in_calendar_2_unique_constraints_duplicate_update.result
@@ -1,4 +1,5 @@
DROP TABLE IF EXISTS t1;
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL, c2 DATE NULL, c3 DATE NULL, PRIMARY KEY(c1), UNIQUE(c2));
SET TIMESTAMP=1171346973;
INSERT INTO t1 (c1,c2,c3) VALUES(NOW(),ADDTIME(NOW(),'4 04:01:01'),NOW());
@@ -128,3 +129,4 @@ c1 c2 c3
2003 2001 2000
2004 2000 2000
DROP TABLE t1;
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/r/in_calendar_pk_constraint_duplicate_update.result b/mysql-test/suite/engines/funcs/r/in_calendar_pk_constraint_duplicate_update.result
index 763e9f564c6..47355681eae 100644
--- a/mysql-test/suite/engines/funcs/r/in_calendar_pk_constraint_duplicate_update.result
+++ b/mysql-test/suite/engines/funcs/r/in_calendar_pk_constraint_duplicate_update.result
@@ -1,4 +1,5 @@
DROP TABLE IF EXISTS t1;
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL PRIMARY KEY);
SET TIMESTAMP=1171346973;
INSERT INTO t1 (c1) VALUES(NOW());
@@ -82,3 +83,4 @@ c1
2000
2011
DROP TABLE t1;
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/r/in_calendar_pk_constraint_error.result b/mysql-test/suite/engines/funcs/r/in_calendar_pk_constraint_error.result
index 3f2b1546995..f8bff355901 100644
--- a/mysql-test/suite/engines/funcs/r/in_calendar_pk_constraint_error.result
+++ b/mysql-test/suite/engines/funcs/r/in_calendar_pk_constraint_error.result
@@ -1,4 +1,5 @@
DROP TABLE IF EXISTS t1;
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL PRIMARY KEY);
SET TIMESTAMP=1171346973;
INSERT INTO t1 (c1) VALUES(NOW());
@@ -87,3 +88,4 @@ c1
1999
2000
DROP TABLE t1;
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/r/in_calendar_pk_constraint_ignore.result b/mysql-test/suite/engines/funcs/r/in_calendar_pk_constraint_ignore.result
index 3f2b1546995..f8bff355901 100644
--- a/mysql-test/suite/engines/funcs/r/in_calendar_pk_constraint_ignore.result
+++ b/mysql-test/suite/engines/funcs/r/in_calendar_pk_constraint_ignore.result
@@ -1,4 +1,5 @@
DROP TABLE IF EXISTS t1;
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL PRIMARY KEY);
SET TIMESTAMP=1171346973;
INSERT INTO t1 (c1) VALUES(NOW());
@@ -87,3 +88,4 @@ c1
1999
2000
DROP TABLE t1;
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/r/in_calendar_unique_constraint_duplicate_update.result b/mysql-test/suite/engines/funcs/r/in_calendar_unique_constraint_duplicate_update.result
index 154c44426bc..5c4307158fa 100644
--- a/mysql-test/suite/engines/funcs/r/in_calendar_unique_constraint_duplicate_update.result
+++ b/mysql-test/suite/engines/funcs/r/in_calendar_unique_constraint_duplicate_update.result
@@ -1,4 +1,5 @@
DROP TABLE IF EXISTS t1;
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NULL UNIQUE);
SET TIMESTAMP=1171346973;
INSERT INTO t1 (c1) VALUES(NOW());
@@ -82,3 +83,4 @@ c1
2000
2011
DROP TABLE t1;
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/r/in_calendar_unique_constraint_error.result b/mysql-test/suite/engines/funcs/r/in_calendar_unique_constraint_error.result
index 6c395c5f6b9..9f6a205530c 100644
--- a/mysql-test/suite/engines/funcs/r/in_calendar_unique_constraint_error.result
+++ b/mysql-test/suite/engines/funcs/r/in_calendar_unique_constraint_error.result
@@ -1,4 +1,5 @@
DROP TABLE IF EXISTS t1;
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NULL UNIQUE);
SET TIMESTAMP=1171346973;
INSERT INTO t1 (c1) VALUES(NOW());
@@ -87,3 +88,4 @@ c1
1999
2000
DROP TABLE t1;
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/r/in_calendar_unique_constraint_ignore.result b/mysql-test/suite/engines/funcs/r/in_calendar_unique_constraint_ignore.result
index 58802aab0b2..5469527b762 100644
--- a/mysql-test/suite/engines/funcs/r/in_calendar_unique_constraint_ignore.result
+++ b/mysql-test/suite/engines/funcs/r/in_calendar_unique_constraint_ignore.result
@@ -1,4 +1,5 @@
DROP TABLE IF EXISTS t1;
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NULL UNIQUE);
SET TIMESTAMP=1171346973;
INSERT INTO t1 (c1) VALUES(NOW());
@@ -81,3 +82,4 @@ c1
1999
2000
DROP TABLE t1;
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_pk_constraint_duplicate_update.result b/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_pk_constraint_duplicate_update.result
index f2cafdfce52..d7dfc9d794c 100644
--- a/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_pk_constraint_duplicate_update.result
+++ b/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_pk_constraint_duplicate_update.result
@@ -1,4 +1,5 @@
DROP TABLE IF EXISTS t1;
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL, c2 DATE NOT NULL, c3 DATE NOT NULL, PRIMARY KEY(c1,c2,c3));
SET TIMESTAMP=1171346973;
INSERT INTO t1 (c1,c2,c3) VALUES(NOW(),NOW(),NOW());
@@ -144,3 +145,4 @@ c1 c2 c3
2011 2011 2000
2011 2011 2011
DROP TABLE t1;
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_pk_constraint_error.result b/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_pk_constraint_error.result
index b630d3f519f..d71af8d6375 100644
--- a/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_pk_constraint_error.result
+++ b/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_pk_constraint_error.result
@@ -1,4 +1,5 @@
DROP TABLE IF EXISTS t1;
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL, c2 DATE NOT NULL, c3 DATE NOT NULL, PRIMARY KEY(c1,c2,c3));
SET TIMESTAMP=1171346973;
INSERT INTO t1 (c1,c2,c3) VALUES(NOW(),NOW(),NOW());
@@ -147,3 +148,4 @@ c1 c2 c3
1999 2000 1999
2000 1999 1999
DROP TABLE t1;
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_pk_constraint_ignore.result b/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_pk_constraint_ignore.result
index b630d3f519f..d71af8d6375 100644
--- a/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_pk_constraint_ignore.result
+++ b/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_pk_constraint_ignore.result
@@ -1,4 +1,5 @@
DROP TABLE IF EXISTS t1;
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL, c2 DATE NOT NULL, c3 DATE NOT NULL, PRIMARY KEY(c1,c2,c3));
SET TIMESTAMP=1171346973;
INSERT INTO t1 (c1,c2,c3) VALUES(NOW(),NOW(),NOW());
@@ -147,3 +148,4 @@ c1 c2 c3
1999 2000 1999
2000 1999 1999
DROP TABLE t1;
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_unique_constraint_duplicate_update.result b/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_unique_constraint_duplicate_update.result
index 3b40a2f57ab..edad4bb218d 100644
--- a/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_unique_constraint_duplicate_update.result
+++ b/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_unique_constraint_duplicate_update.result
@@ -1,4 +1,5 @@
DROP TABLE IF EXISTS t1;
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NULL, c2 DATE NULL, c3 DATE NULL, UNIQUE(c1,c2,c3));
SET TIMESTAMP=1171346973;
INSERT INTO t1 (c1,c2,c3) VALUES(NOW(),NOW(),NOW());
@@ -144,3 +145,4 @@ c1 c2 c3
2011 2011 2000
2011 2011 2011
DROP TABLE t1;
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_unique_constraint_error.result b/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_unique_constraint_error.result
index 84f626d3347..4d7cadac70c 100644
--- a/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_unique_constraint_error.result
+++ b/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_unique_constraint_error.result
@@ -1,4 +1,5 @@
DROP TABLE IF EXISTS t1;
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NULL, c2 DATE NULL, c3 DATE NULL, UNIQUE(c1,c2,c3));
SET TIMESTAMP=1171346973;
INSERT INTO t1 (c1,c2,c3) VALUES(NOW(),NOW(),NOW());
@@ -147,3 +148,4 @@ c1 c2 c3
1999 2000 1999
2000 1999 1999
DROP TABLE t1;
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_unique_constraint_ignore.result b/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_unique_constraint_ignore.result
index f34b39ec1b4..31f7db1dc9a 100644
--- a/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_unique_constraint_ignore.result
+++ b/mysql-test/suite/engines/funcs/r/in_multicolumn_calendar_unique_constraint_ignore.result
@@ -1,4 +1,5 @@
DROP TABLE IF EXISTS t1;
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NULL, c2 DATE NULL, c3 DATE NULL, UNIQUE(c1,c2,c3));
SET TIMESTAMP=1171346973;
INSERT INTO t1 (c1,c2,c3) VALUES(NOW(),NOW(),NOW());
@@ -139,3 +140,4 @@ c1 c2 c3
1999 2000 1999
2000 1999 1999
DROP TABLE t1;
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/r/in_multicolumn_number_pk_constraint_duplicate_update.result b/mysql-test/suite/engines/funcs/r/in_multicolumn_number_pk_constraint_duplicate_update.result
index f2cafdfce52..d7dfc9d794c 100644
--- a/mysql-test/suite/engines/funcs/r/in_multicolumn_number_pk_constraint_duplicate_update.result
+++ b/mysql-test/suite/engines/funcs/r/in_multicolumn_number_pk_constraint_duplicate_update.result
@@ -1,4 +1,5 @@
DROP TABLE IF EXISTS t1;
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL, c2 DATE NOT NULL, c3 DATE NOT NULL, PRIMARY KEY(c1,c2,c3));
SET TIMESTAMP=1171346973;
INSERT INTO t1 (c1,c2,c3) VALUES(NOW(),NOW(),NOW());
@@ -144,3 +145,4 @@ c1 c2 c3
2011 2011 2000
2011 2011 2011
DROP TABLE t1;
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/r/up_calendar_range.result b/mysql-test/suite/engines/funcs/r/up_calendar_range.result
index 7185fc3c6ee..dbd6e2cf8a6 100644
--- a/mysql-test/suite/engines/funcs/r/up_calendar_range.result
+++ b/mysql-test/suite/engines/funcs/r/up_calendar_range.result
@@ -1,4 +1,5 @@
DROP TABLE IF EXISTS t1,t2,t3;
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL);
SET TIMESTAMP=1171346973;
INSERT INTO t1 (c1) VALUES(NOW());
@@ -104,3 +105,4 @@ c1
2007-02-13 09:09:33
2007-02-14 10:10:34
DROP TABLE t1;
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/t/de_calendar_range.test b/mysql-test/suite/engines/funcs/t/de_calendar_range.test
index c1e191fdd97..6e3f1915e9a 100644
--- a/mysql-test/suite/engines/funcs/t/de_calendar_range.test
+++ b/mysql-test/suite/engines/funcs/t/de_calendar_range.test
@@ -1,6 +1,8 @@
--disable_warnings
DROP TABLE IF EXISTS t1,t2,t3;
--enable_warnings
+# Set Correct timezone to match result
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL PRIMARY KEY);
SET TIMESTAMP=1171346973; # 2007-02-13 15:09:33
INSERT INTO t1 (c1) VALUES(NOW());
@@ -45,4 +47,5 @@ SELECT * FROM t1 ORDER BY c1;
DELETE FROM t1 WHERE c1 <= ADDTIME(NOW(),'2 02:01:01');
SELECT * FROM t1 ORDER BY c1;
DROP TABLE t1;
-
+# Restore timezone to default
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/t/in_calendar_2_unique_constraints_duplicate_update.test b/mysql-test/suite/engines/funcs/t/in_calendar_2_unique_constraints_duplicate_update.test
index 8c6f960b60d..5ae519abdc8 100644
--- a/mysql-test/suite/engines/funcs/t/in_calendar_2_unique_constraints_duplicate_update.test
+++ b/mysql-test/suite/engines/funcs/t/in_calendar_2_unique_constraints_duplicate_update.test
@@ -1,6 +1,8 @@
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
+# Set Correct timezone to match result
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL, c2 DATE NULL, c3 DATE NULL, PRIMARY KEY(c1), UNIQUE(c2));
SET TIMESTAMP=1171346973; # 2007-02-13 15:09:33
INSERT INTO t1 (c1,c2,c3) VALUES(NOW(),ADDTIME(NOW(),'4 04:01:01'),NOW());
@@ -70,4 +72,6 @@ INSERT INTO t1 (c1,c2,c3) VALUES(2000,2000,2000) ON DUPLICATE KEY UPDATE c3=2011
--sorted_result
SELECT * FROM t1;
DROP TABLE t1;
+# Restore timezone to default
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/t/in_calendar_pk_constraint_duplicate_update.test b/mysql-test/suite/engines/funcs/t/in_calendar_pk_constraint_duplicate_update.test
index 65c7c34f907..fdfb6edb139 100644
--- a/mysql-test/suite/engines/funcs/t/in_calendar_pk_constraint_duplicate_update.test
+++ b/mysql-test/suite/engines/funcs/t/in_calendar_pk_constraint_duplicate_update.test
@@ -1,6 +1,8 @@
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
+# Set Correct timezone to match result
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL PRIMARY KEY);
SET TIMESTAMP=1171346973; # 2007-02-13 15:09:33
INSERT INTO t1 (c1) VALUES(NOW());
@@ -61,4 +63,5 @@ INSERT INTO t1 (c1) VALUES(1999) ON DUPLICATE KEY UPDATE c1=2011;
--sorted_result
SELECT * FROM t1;
DROP TABLE t1;
-
+# Restore timezone to default
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/t/in_calendar_pk_constraint_error.test b/mysql-test/suite/engines/funcs/t/in_calendar_pk_constraint_error.test
index 36a8ef3a0a7..f65c705031b 100644
--- a/mysql-test/suite/engines/funcs/t/in_calendar_pk_constraint_error.test
+++ b/mysql-test/suite/engines/funcs/t/in_calendar_pk_constraint_error.test
@@ -1,6 +1,8 @@
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
+# Set Correct timezone to match result
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL PRIMARY KEY);
SET TIMESTAMP=1171346973; # 2007-02-13 15:09:33
INSERT INTO t1 (c1) VALUES(NOW());
@@ -61,4 +63,5 @@ INSERT INTO t1 (c1) VALUES(2000);
INSERT INTO t1 (c1) VALUES(1999);
SELECT * FROM t1;
DROP TABLE t1;
-
+# Restore timezone to default
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/t/in_calendar_pk_constraint_ignore.test b/mysql-test/suite/engines/funcs/t/in_calendar_pk_constraint_ignore.test
index 36a8ef3a0a7..bac71b99a97 100644
--- a/mysql-test/suite/engines/funcs/t/in_calendar_pk_constraint_ignore.test
+++ b/mysql-test/suite/engines/funcs/t/in_calendar_pk_constraint_ignore.test
@@ -1,6 +1,8 @@
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
+# Set Correct timezone to match result
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL PRIMARY KEY);
SET TIMESTAMP=1171346973; # 2007-02-13 15:09:33
INSERT INTO t1 (c1) VALUES(NOW());
@@ -61,4 +63,6 @@ INSERT INTO t1 (c1) VALUES(2000);
INSERT INTO t1 (c1) VALUES(1999);
SELECT * FROM t1;
DROP TABLE t1;
+# Restore timezone to default
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/t/in_calendar_unique_constraint_duplicate_update.test b/mysql-test/suite/engines/funcs/t/in_calendar_unique_constraint_duplicate_update.test
index 20da85f5b66..e6235e77603 100644
--- a/mysql-test/suite/engines/funcs/t/in_calendar_unique_constraint_duplicate_update.test
+++ b/mysql-test/suite/engines/funcs/t/in_calendar_unique_constraint_duplicate_update.test
@@ -1,6 +1,8 @@
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
+# Set Correct timezone to match result
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NULL UNIQUE);
SET TIMESTAMP=1171346973; # 2007-02-13 15:09:33
INSERT INTO t1 (c1) VALUES(NOW());
@@ -61,4 +63,5 @@ INSERT INTO t1 (c1) VALUES(1999) ON DUPLICATE KEY UPDATE c1=2011;
--sorted_result
SELECT * FROM t1;
DROP TABLE t1;
-
+# Restore timezone to default
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/t/in_calendar_unique_constraint_error.test b/mysql-test/suite/engines/funcs/t/in_calendar_unique_constraint_error.test
index 73b8c3d0775..f9d101d8327 100644
--- a/mysql-test/suite/engines/funcs/t/in_calendar_unique_constraint_error.test
+++ b/mysql-test/suite/engines/funcs/t/in_calendar_unique_constraint_error.test
@@ -1,6 +1,8 @@
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
+# Set Correct timezone to match result
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NULL UNIQUE);
SET TIMESTAMP=1171346973; # 2007-02-13 15:09:33
INSERT INTO t1 (c1) VALUES(NOW());
@@ -61,4 +63,5 @@ INSERT INTO t1 (c1) VALUES(2000);
INSERT INTO t1 (c1) VALUES(1999);
SELECT * FROM t1;
DROP TABLE t1;
-
+# Restore timezone to default
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/t/in_calendar_unique_constraint_ignore.test b/mysql-test/suite/engines/funcs/t/in_calendar_unique_constraint_ignore.test
index 91e4f8faef9..a4e96a7ccc3 100644
--- a/mysql-test/suite/engines/funcs/t/in_calendar_unique_constraint_ignore.test
+++ b/mysql-test/suite/engines/funcs/t/in_calendar_unique_constraint_ignore.test
@@ -1,6 +1,8 @@
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
+# Set Correct timezone to match result
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NULL UNIQUE);
SET TIMESTAMP=1171346973; # 2007-02-13 15:09:33
INSERT INTO t1 (c1) VALUES(NOW());
@@ -53,4 +55,5 @@ INSERT INTO t1 (c1) VALUES(2000);
INSERT IGNORE INTO t1 (c1) VALUES(1999);
SELECT * FROM t1;
DROP TABLE t1;
-
+#restore timezone to default
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_pk_constraint_duplicate_update.test b/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_pk_constraint_duplicate_update.test
index a7648a55128..12307232d64 100644
--- a/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_pk_constraint_duplicate_update.test
+++ b/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_pk_constraint_duplicate_update.test
@@ -1,6 +1,8 @@
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
+# Set Correct timezone to match result
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL, c2 DATE NOT NULL, c3 DATE NOT NULL, PRIMARY KEY(c1,c2,c3));
SET TIMESTAMP=1171346973; # 2007-02-13 15:09:33
INSERT INTO t1 (c1,c2,c3) VALUES(NOW(),NOW(),NOW());
@@ -85,4 +87,6 @@ INSERT INTO t1 (c1,c2,c3) VALUES(1999,1999,2000) ON DUPLICATE KEY UPDATE c1=2011
--sorted_result
SELECT * FROM t1;
DROP TABLE t1;
+# Restore timezone to default
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_pk_constraint_error.test b/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_pk_constraint_error.test
index 9678ddd716b..8d994cb3d7a 100644
--- a/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_pk_constraint_error.test
+++ b/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_pk_constraint_error.test
@@ -1,6 +1,8 @@
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
+# Set Correct timezone to match result
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL, c2 DATE NOT NULL, c3 DATE NOT NULL, PRIMARY KEY(c1,c2,c3));
SET TIMESTAMP=1171346973; # 2007-02-13 15:09:33
INSERT INTO t1 (c1,c2,c3) VALUES(NOW(),NOW(),NOW());
@@ -93,4 +95,5 @@ INSERT INTO t1 (c1,c2,c3) VALUES(1999,1999,1999);
INSERT INTO t1 (c1,c2,c3) VALUES(1999,1999,2000);
SELECT * FROM t1;
DROP TABLE t1;
-
+# Restore timezone to default
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_pk_constraint_ignore.test b/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_pk_constraint_ignore.test
index 9678ddd716b..8d994cb3d7a 100644
--- a/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_pk_constraint_ignore.test
+++ b/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_pk_constraint_ignore.test
@@ -1,6 +1,8 @@
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
+# Set Correct timezone to match result
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL, c2 DATE NOT NULL, c3 DATE NOT NULL, PRIMARY KEY(c1,c2,c3));
SET TIMESTAMP=1171346973; # 2007-02-13 15:09:33
INSERT INTO t1 (c1,c2,c3) VALUES(NOW(),NOW(),NOW());
@@ -93,4 +95,5 @@ INSERT INTO t1 (c1,c2,c3) VALUES(1999,1999,1999);
INSERT INTO t1 (c1,c2,c3) VALUES(1999,1999,2000);
SELECT * FROM t1;
DROP TABLE t1;
-
+# Restore timezone to default
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_unique_constraint_duplicate_update.test b/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_unique_constraint_duplicate_update.test
index 13575722c1f..3d455bcb5d8 100644
--- a/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_unique_constraint_duplicate_update.test
+++ b/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_unique_constraint_duplicate_update.test
@@ -1,6 +1,8 @@
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
+# Set Correct timezone to match result
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NULL, c2 DATE NULL, c3 DATE NULL, UNIQUE(c1,c2,c3));
SET TIMESTAMP=1171346973; # 2007-02-13 15:09:33
INSERT INTO t1 (c1,c2,c3) VALUES(NOW(),NOW(),NOW());
@@ -85,4 +87,5 @@ INSERT INTO t1 (c1,c2,c3) VALUES(1999,1999,2000) ON DUPLICATE KEY UPDATE c1=2011
--sorted_result
SELECT * FROM t1;
DROP TABLE t1;
-
+# Restore timezone to default
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_unique_constraint_error.test b/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_unique_constraint_error.test
index 916b0c527eb..9cbafd3b8d0 100644
--- a/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_unique_constraint_error.test
+++ b/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_unique_constraint_error.test
@@ -1,6 +1,8 @@
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
+# Set Correct timezone to match result
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NULL, c2 DATE NULL, c3 DATE NULL, UNIQUE(c1,c2,c3));
SET TIMESTAMP=1171346973; # 2007-02-13 15:09:33
INSERT INTO t1 (c1,c2,c3) VALUES(NOW(),NOW(),NOW());
@@ -93,4 +95,5 @@ INSERT INTO t1 (c1,c2,c3) VALUES(1999,1999,1999);
INSERT INTO t1 (c1,c2,c3) VALUES(1999,1999,2000);
SELECT * FROM t1;
DROP TABLE t1;
-
+# Restore timezone to default
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_unique_constraint_ignore.test b/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_unique_constraint_ignore.test
index b43ff52abe3..e313f29edfb 100644
--- a/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_unique_constraint_ignore.test
+++ b/mysql-test/suite/engines/funcs/t/in_multicolumn_calendar_unique_constraint_ignore.test
@@ -1,6 +1,8 @@
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
+# Set Correct timezone to match result
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NULL, c2 DATE NULL, c3 DATE NULL, UNIQUE(c1,c2,c3));
SET TIMESTAMP=1171346973; # 2007-02-13 15:09:33
INSERT INTO t1 (c1,c2,c3) VALUES(NOW(),NOW(),NOW());
@@ -85,4 +87,6 @@ INSERT IGNORE INTO t1 (c1,c2,c3) VALUES(1999,1999,2000);
--sorted_result
SELECT * FROM t1;
DROP TABLE t1;
+# Restore timezone to default
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/t/in_multicolumn_number_pk_constraint_duplicate_update.test b/mysql-test/suite/engines/funcs/t/in_multicolumn_number_pk_constraint_duplicate_update.test
index 71848c1ac38..df4a194a2cf 100644
--- a/mysql-test/suite/engines/funcs/t/in_multicolumn_number_pk_constraint_duplicate_update.test
+++ b/mysql-test/suite/engines/funcs/t/in_multicolumn_number_pk_constraint_duplicate_update.test
@@ -1,6 +1,8 @@
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
+# Set Correct timezone to match result
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL, c2 DATE NOT NULL, c3 DATE NOT NULL, PRIMARY KEY(c1,c2,c3));
SET TIMESTAMP=1171346973; # 2007-02-13 15:09:33
INSERT INTO t1 (c1,c2,c3) VALUES(NOW(),NOW(),NOW());
@@ -93,4 +95,6 @@ INSERT INTO t1 (c1,c2,c3) VALUES(1999,1999,2000) ON DUPLICATE KEY UPDATE c1=2011
--sorted_result
SELECT * FROM t1;
DROP TABLE t1;
+# Restore timezone to default
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/engines/funcs/t/up_calendar_range.test b/mysql-test/suite/engines/funcs/t/up_calendar_range.test
index 9c88d52f826..d4aca03199d 100644
--- a/mysql-test/suite/engines/funcs/t/up_calendar_range.test
+++ b/mysql-test/suite/engines/funcs/t/up_calendar_range.test
@@ -1,6 +1,8 @@
--disable_warnings
DROP TABLE IF EXISTS t1,t2,t3;
--enable_warnings
+# Set Correct timezone to match result
+SET TIME_ZONE="+03:00";
CREATE TABLE t1(c1 DATE NOT NULL);
SET TIMESTAMP=1171346973; # 2007-02-13 15:09:33
INSERT INTO t1 (c1) VALUES(NOW());
@@ -53,4 +55,5 @@ UPDATE t1 SET c1 = NOW() WHERE c1 >= ADDTIME(NOW(),'2 02:01:01');
--sorted_result
SELECT * FROM t1 ORDER BY c1;
DROP TABLE t1;
-
+# Restore timezone to default
+SET TIME_ZONE= @@global.time_zone;
diff --git a/mysql-test/suite/federated/federated_plugin-master.opt b/mysql-test/suite/federated/federated_plugin-master.opt
new file mode 100644
index 00000000000..027a6d949c0
--- /dev/null
+++ b/mysql-test/suite/federated/federated_plugin-master.opt
@@ -0,0 +1,2 @@
+--plugin_dir=$FEDERATED_PLUGIN_DIR
+--loose-federated=ON
diff --git a/mysql-test/suite/federated/federated_plugin.result b/mysql-test/suite/federated/federated_plugin.result
new file mode 100644
index 00000000000..b49a977d9df
--- /dev/null
+++ b/mysql-test/suite/federated/federated_plugin.result
@@ -0,0 +1,19 @@
+CREATE TABLE t2(a int);
+CREATE TABLE t1(a int) ENGINE=FEDERATED
+CONNECTION='mysql://root@localhost:$MASTER_MYPORT/test/t2';
+Warnings:
+Warning 1286 Unknown table engine 'FEDERATED'
+Warning 1266 Using storage engine MyISAM for table 't1'
+DROP TABLE t1;
+INSTALL PLUGIN federated SONAME 'FEDERATED_PLUGIN';
+INSTALL PLUGIN FEDERATED SONAME 'FEDERATED_PLUGIN';
+ERROR HY000: Function 'FEDERATED' already exists
+UNINSTALL PLUGIN federated;
+INSTALL PLUGIN federated SONAME 'FEDERATED_PLUGIN';
+CREATE TABLE t1(a int) ENGINE=FEDERATED
+CONNECTION='mysql://root@localhost:$MASTER_MYPORT/test/t2';
+DROP TABLE t1;
+UNINSTALL PLUGIN federated;
+UNINSTALL PLUGIN federated;
+ERROR 42000: PLUGIN federated does not exist
+DROP TABLE t2;
diff --git a/mysql-test/suite/federated/federated_plugin.test b/mysql-test/suite/federated/federated_plugin.test
new file mode 100644
index 00000000000..8c465095cfa
--- /dev/null
+++ b/mysql-test/suite/federated/federated_plugin.test
@@ -0,0 +1,37 @@
+--source include/have_federated_plugin.inc
+
+# Uninstall will not uninstall if ps has been used
+--disable_ps_protocol
+
+connect (master,localhost,root,,test,$MASTER_MYPORT,);
+connect (slave,localhost,root,,test,$SLAVE_MYPORT,);
+
+connection master;
+CREATE TABLE t2(a int);
+
+connection slave;
+CREATE TABLE t1(a int) ENGINE=FEDERATED
+ CONNECTION='mysql://root@localhost:$MASTER_MYPORT/test/t2';
+DROP TABLE t1;
+
+--replace_result $FEDERATED_PLUGIN FEDERATED_PLUGIN
+eval INSTALL PLUGIN federated SONAME '$FEDERATED_PLUGIN';
+--replace_result $FEDERATED_PLUGIN FEDERATED_PLUGIN
+--error ER_UDF_EXISTS
+eval INSTALL PLUGIN FEDERATED SONAME '$FEDERATED_PLUGIN';
+
+UNINSTALL PLUGIN federated;
+
+--replace_result $FEDERATED_PLUGIN FEDERATED_PLUGIN
+eval INSTALL PLUGIN federated SONAME '$FEDERATED_PLUGIN';
+
+CREATE TABLE t1(a int) ENGINE=FEDERATED
+ CONNECTION='mysql://root@localhost:$MASTER_MYPORT/test/t2';
+DROP TABLE t1;
+
+UNINSTALL PLUGIN federated;
+--error ER_SP_DOES_NOT_EXIST
+UNINSTALL PLUGIN federated;
+
+connection master;
+DROP TABLE t2;
diff --git a/mysql-test/suite/innodb_plugin/r/innodb-index.result b/mysql-test/suite/innodb_plugin/r/innodb-index.result
index b24f282dfc4..8640ff94d9e 100644
--- a/mysql-test/suite/innodb_plugin/r/innodb-index.result
+++ b/mysql-test/suite/innodb_plugin/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;
@@ -1010,20 +1085,15 @@ ERROR HY000: Too big row
alter table t1 row_format=compact;
create index t1u on t1 (u(1));
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(10))
) 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',7731));
+COMMIT;
+UPDATE bug12547647 SET c = REPEAT('b',16928);
+ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. You have to change some columns to TEXT or BLOBs
+DROP TABLE bug12547647;
set global innodb_file_per_table=0;
set global innodb_file_format=Antelope;
set global innodb_file_format_check=Antelope;
@@ -1228,3 +1298,5 @@ a b
3 b
DROP TABLE t1;
DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge;
+DROP TABLE t12637786;
+DROP TABLE t12963823;
diff --git a/mysql-test/suite/innodb_plugin/r/innodb_bug52745.result b/mysql-test/suite/innodb_plugin/r/innodb_bug52745.result
index 254c6525257..74db8b0c20a 100644
--- a/mysql-test/suite/innodb_plugin/r/innodb_bug52745.result
+++ b/mysql-test/suite/innodb_plugin/r/innodb_bug52745.result
@@ -126,5 +126,4 @@ Warning 1265 Data truncated for column 'col79' at row 1
Warning 1264 Out of range value for column 'col84' at row 1
DROP TABLE bug52745;
SET GLOBAL innodb_file_format=Antelope;
-SET GLOBAL innodb_file_format_check=Antelope;
SET GLOBAL innodb_file_per_table=0;
diff --git a/mysql-test/suite/innodb_plugin/r/innodb_bug53591.result b/mysql-test/suite/innodb_plugin/r/innodb_bug53591.result
index 1f05b6d2a57..29f9d09a71c 100644
--- a/mysql-test/suite/innodb_plugin/r/innodb_bug53591.result
+++ b/mysql-test/suite/innodb_plugin/r/innodb_bug53591.result
@@ -12,5 +12,4 @@ Error 1118 Row size too large. The maximum row size for the used table type, not
Error 1030 Got error 139 from storage engine
DROP TABLE bug53591;
SET GLOBAL innodb_file_format=Antelope;
-SET GLOBAL innodb_file_format_check=Antelope;
SET GLOBAL innodb_file_per_table=0;
diff --git a/mysql-test/suite/innodb_plugin/t/innodb-autoinc-18274.test b/mysql-test/suite/innodb_plugin/t/innodb-autoinc-18274.test
index 8734311dd7a..9ac24c9e349 100644
--- a/mysql-test/suite/innodb_plugin/t/innodb-autoinc-18274.test
+++ b/mysql-test/suite/innodb_plugin/t/innodb-autoinc-18274.test
@@ -2,8 +2,6 @@
# embedded server ignores 'delayed', so skip this
-- source include/not_embedded.inc
-let $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
-
--disable_warnings
drop table if exists t1;
--enable_warnings
@@ -20,10 +18,3 @@ SHOW CREATE TABLE t1;
INSERT INTO t1 VALUES(null);
SELECT * FROM t1;
DROP TABLE t1;
-
-#
-# restore environment to the state it was before this test execution
-#
-
--- disable_query_log
-eval set global innodb_file_format_check=$innodb_file_format_check_orig;
diff --git a/mysql-test/suite/innodb_plugin/t/innodb-autoinc-44030.test b/mysql-test/suite/innodb_plugin/t/innodb-autoinc-44030.test
index 99cdac72e2e..150f6bb4f66 100644
--- a/mysql-test/suite/innodb_plugin/t/innodb-autoinc-44030.test
+++ b/mysql-test/suite/innodb_plugin/t/innodb-autoinc-44030.test
@@ -2,8 +2,6 @@
# embedded server ignores 'delayed', so skip this
-- source include/not_embedded.inc
-let $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
-
--disable_warnings
drop table if exists t1;
--enable_warnings
@@ -34,10 +32,3 @@ SHOW CREATE TABLE t1;
INSERT INTO t1 VALUES(null);
SELECT * FROM t1;
DROP TABLE t1;
-
-#
-# restore environment to the state it was before this test execution
-#
-
--- disable_query_log
-eval set global innodb_file_format_check=$innodb_file_format_check_orig;
diff --git a/mysql-test/suite/innodb_plugin/t/innodb-autoinc-56228.test b/mysql-test/suite/innodb_plugin/t/innodb-autoinc-56228.test
index eb38b21861d..41b8ac90fad 100644
--- a/mysql-test/suite/innodb_plugin/t/innodb-autoinc-56228.test
+++ b/mysql-test/suite/innodb_plugin/t/innodb-autoinc-56228.test
@@ -1,7 +1,5 @@
-- source include/have_innodb_plugin.inc
-let $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
-
##
# Bug #56228: dropping tables from within an active statement crashes server
#
@@ -33,10 +31,3 @@ SELECT bug56228();
DROP FUNCTION bug56228;
DROP TEMPORARY TABLE t2_56228;
DROP TEMPORARY TABLE IF EXISTS t1_56228;
-
-#
-# restore environment to the state it was before this test execution
-#
-
--- disable_query_log
-eval set global innodb_file_format_check=$innodb_file_format_check_orig;
diff --git a/mysql-test/suite/innodb_plugin/t/innodb-autoinc.test b/mysql-test/suite/innodb_plugin/t/innodb-autoinc.test
index 4967a6efbb9..633b0ef360b 100644
--- a/mysql-test/suite/innodb_plugin/t/innodb-autoinc.test
+++ b/mysql-test/suite/innodb_plugin/t/innodb-autoinc.test
@@ -2,8 +2,6 @@
# embedded server ignores 'delayed', so skip this
-- source include/not_embedded.inc
-let $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
-
--disable_warnings
drop table if exists t1;
--enable_warnings
@@ -639,10 +637,3 @@ INSERT INTO t1 VALUES (18446744073709551615);
-- source include/restart_mysqld.inc
SHOW CREATE TABLE t1;
DROP TABLE t1;
-
-#
-# restore environment to the state it was before this test execution
-#
-
--- disable_query_log
-eval set global innodb_file_format_check=$innodb_file_format_check_orig;
diff --git a/mysql-test/suite/innodb_plugin/t/innodb-create-options.test b/mysql-test/suite/innodb_plugin/t/innodb-create-options.test
index 2f95ccc45cb..85f214177aa 100755
--- a/mysql-test/suite/innodb_plugin/t/innodb-create-options.test
+++ b/mysql-test/suite/innodb_plugin/t/innodb-create-options.test
@@ -61,7 +61,6 @@ SET storage_engine=InnoDB;
--disable_query_log
# These values can change during the test
LET $innodb_file_format_orig=`select @@innodb_file_format`;
-LET $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
LET $innodb_file_per_table_orig=`select @@innodb_file_per_table`;
LET $innodb_strict_mode_orig=`select @@session.innodb_strict_mode`;
--enable_query_log
@@ -568,7 +567,6 @@ DROP TABLE IF EXISTS t1;
--disable_query_log
EVAL SET GLOBAL innodb_file_format=$innodb_file_format_orig;
-EVAL SET GLOBAL innodb_file_format_check=$innodb_file_format_check_orig;
EVAL SET GLOBAL innodb_file_per_table=$innodb_file_per_table_orig;
EVAL SET SESSION innodb_strict_mode=$innodb_strict_mode_orig;
--enable_query_log
diff --git a/mysql-test/suite/innodb_plugin/t/innodb-index.test b/mysql-test/suite/innodb_plugin/t/innodb-index.test
index 52f94990b15..568661c67f1 100644
--- a/mysql-test/suite/innodb_plugin/t/innodb-index.test
+++ b/mysql-test/suite/innodb_plugin/t/innodb-index.test
@@ -2,14 +2,12 @@
let $MYSQLD_DATADIR= `select @@datadir`;
-let $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
-
let $per_table=`select @@innodb_file_per_table`;
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 +57,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;
@@ -462,23 +522,18 @@ create index t1u on t1 (u(1));
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(10))
) 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',7731));
+COMMIT;
+# The following used to cause infinite undo log allocation.
+--error ER_TOO_BIG_ROWSIZE
+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;
@@ -617,11 +672,9 @@ disconnect a;
disconnect b;
DROP TABLE t1;
-DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge;
-#
-# restore environment to the state it was before this test execution
-#
-
--- disable_query_log
-eval SET GLOBAL innodb_file_format_check=$innodb_file_format_check_orig;
+# Drop these tables since the purge thread must have run by now
+# and did not crash.
+DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge;
+DROP TABLE t12637786;
+DROP TABLE t12963823;
diff --git a/mysql-test/suite/innodb_plugin/t/innodb-zip.test b/mysql-test/suite/innodb_plugin/t/innodb-zip.test
index 5ed101b7f20..760ab67ca54 100644
--- a/mysql-test/suite/innodb_plugin/t/innodb-zip.test
+++ b/mysql-test/suite/innodb_plugin/t/innodb-zip.test
@@ -2,7 +2,6 @@
let $per_table=`select @@innodb_file_per_table`;
let $format=`select @@innodb_file_format`;
-let $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
set global innodb_file_per_table=off;
set global innodb_file_format=`0`;
@@ -337,4 +336,3 @@ drop table normal_table, zip_table;
-- disable_query_log
eval set global innodb_file_format=$format;
eval set global innodb_file_per_table=$per_table;
-eval set global innodb_file_format_check=$innodb_file_format_check_orig;
diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug36172.test b/mysql-test/suite/innodb_plugin/t/innodb_bug36172.test
index fbd6d5605df..85a90f3785d 100644
--- a/mysql-test/suite/innodb_plugin/t/innodb_bug36172.test
+++ b/mysql-test/suite/innodb_plugin/t/innodb_bug36172.test
@@ -15,7 +15,6 @@ SET storage_engine=InnoDB;
-- disable_result_log
let $file_format=`select @@innodb_file_format`;
-let $file_format_check=`select @@innodb_file_format_check`;
let $file_per_table=`select @@innodb_file_per_table`;
SET GLOBAL innodb_file_format='Barracuda';
SET GLOBAL innodb_file_per_table=on;
@@ -28,5 +27,4 @@ INSERT IGNORE INTO `table0` SET `col19` = '19940127002709', `col20` = 2383927.90
CHECK TABLE table0 EXTENDED;
DROP TABLE table0;
EVAL SET GLOBAL innodb_file_format=$file_format;
-EVAL SET GLOBAL innodb_file_format_check=$file_format_check;
EVAL SET GLOBAL innodb_file_per_table=$file_per_table;
diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug47167-master.opt b/mysql-test/suite/innodb_plugin/t/innodb_bug47167-master.opt
new file mode 100644
index 00000000000..cef79bc8585
--- /dev/null
+++ b/mysql-test/suite/innodb_plugin/t/innodb_bug47167-master.opt
@@ -0,0 +1 @@
+--force-restart
diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug52745.test b/mysql-test/suite/innodb_plugin/t/innodb_bug52745.test
index b20a993a2d1..c1af389afbd 100644
--- a/mysql-test/suite/innodb_plugin/t/innodb_bug52745.test
+++ b/mysql-test/suite/innodb_plugin/t/innodb_bug52745.test
@@ -1,7 +1,6 @@
-- source include/have_innodb_plugin.inc
let $file_format=`select @@innodb_file_format`;
-let $file_format_check=`select @@innodb_file_format_check`;
let $file_per_table=`select @@innodb_file_per_table`;
SET GLOBAL innodb_file_format='Barracuda';
SET GLOBAL innodb_file_per_table=on;
@@ -105,5 +104,4 @@ SHOW WARNINGS;
DROP TABLE bug52745;
EVAL SET GLOBAL innodb_file_format=$file_format;
-EVAL SET GLOBAL innodb_file_format_check=$file_format_check;
EVAL SET GLOBAL innodb_file_per_table=$file_per_table;
diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug53591.test b/mysql-test/suite/innodb_plugin/t/innodb_bug53591.test
index 760b4630383..f32aace83b2 100644
--- a/mysql-test/suite/innodb_plugin/t/innodb_bug53591.test
+++ b/mysql-test/suite/innodb_plugin/t/innodb_bug53591.test
@@ -1,7 +1,6 @@
-- source include/have_innodb_plugin.inc
let $file_format=`select @@innodb_file_format`;
-let $file_format_check=`select @@innodb_file_format_check`;
let $file_per_table=`select @@innodb_file_per_table`;
SET GLOBAL innodb_file_format='Barracuda';
@@ -18,5 +17,4 @@ SHOW WARNINGS;
DROP TABLE bug53591;
EVAL SET GLOBAL innodb_file_format=$file_format;
-EVAL SET GLOBAL innodb_file_format_check=$file_format_check;
EVAL SET GLOBAL innodb_file_per_table=$file_per_table;
diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug56680.test b/mysql-test/suite/innodb_plugin/t/innodb_bug56680.test
index 8d0f685c723..fa8fa39b895 100644
--- a/mysql-test/suite/innodb_plugin/t/innodb_bug56680.test
+++ b/mysql-test/suite/innodb_plugin/t/innodb_bug56680.test
@@ -7,7 +7,6 @@
SET @tx_isolation_orig = @@tx_isolation;
SET @innodb_file_per_table_orig = @@innodb_file_per_table;
SET @innodb_file_format_orig = @@innodb_file_format;
-SET @innodb_file_format_check_orig = @@innodb_file_format_check;
# 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
@@ -137,6 +136,5 @@ DROP TABLE bug56680;
SET GLOBAL tx_isolation = @tx_isolation_orig;
SET GLOBAL innodb_file_per_table = @innodb_file_per_table_orig;
SET GLOBAL innodb_file_format = @innodb_file_format_orig;
-SET GLOBAL innodb_file_format_check = @innodb_file_format_check_orig;
-- error 0, ER_UNKNOWN_SYSTEM_VARIABLE
SET GLOBAL innodb_change_buffering_debug = @innodb_change_buffering_debug_orig;
diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug59641.test b/mysql-test/suite/innodb_plugin/t/innodb_bug59641.test
index 0fb24e47a54..028c21afe4a 100644
--- a/mysql-test/suite/innodb_plugin/t/innodb_bug59641.test
+++ b/mysql-test/suite/innodb_plugin/t/innodb_bug59641.test
@@ -3,8 +3,6 @@
-- source include/not_embedded.inc
-- source include/have_innodb_plugin.inc
-let $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
-
CREATE TABLE t(a INT PRIMARY KEY, b INT)ENGINE=InnoDB;
INSERT INTO t VALUES(2,2),(4,4),(8,8),(16,16),(32,32);
COMMIT;
@@ -66,5 +64,3 @@ XA COMMIT '789';
SELECT * FROM t;
DROP TABLE t;
---disable_query_log
-eval set global innodb_file_format_check=$innodb_file_format_check_orig;
diff --git a/mysql-test/suite/innodb_plugin/t/innodb_file_format-master.opt b/mysql-test/suite/innodb_plugin/t/innodb_file_format-master.opt
new file mode 100644
index 00000000000..cef79bc8585
--- /dev/null
+++ b/mysql-test/suite/innodb_plugin/t/innodb_file_format-master.opt
@@ -0,0 +1 @@
+--force-restart
diff --git a/mysql-test/suite/ndb/t/ndb_partition_error2.test b/mysql-test/suite/ndb/t/ndb_partition_error2.test
index afedd0e3c5c..58c38f2dd37 100644
--- a/mysql-test/suite/ndb/t/ndb_partition_error2.test
+++ b/mysql-test/suite/ndb/t/ndb_partition_error2.test
@@ -1,3 +1,4 @@
+-- source include/have_ndb.inc
disable_query_log;
--require r/true.require
select support = 'Enabled' as `TRUE` from information_schema.engines where engine = 'ndbcluster';
diff --git a/mysql-test/suite/sys_vars/r/max_join_size_func.result b/mysql-test/suite/sys_vars/r/max_join_size_func.result
index bf535579433..0bf4f507b0c 100644
--- a/mysql-test/suite/sys_vars/r/max_join_size_func.result
+++ b/mysql-test/suite/sys_vars/r/max_join_size_func.result
@@ -41,7 +41,7 @@ id name id name
SET @@session.max_join_size=8;
## Since total joins are more than max_join_size value so error will occur ##
SELECT * FROM t1 INNER JOIN t2 ON t1.id = t2.id;
-ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
+ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay
'#--------------------FN_DYNVARS_079_03-------------------------#'
## Setting global value of variable ##
SET @@global.max_join_size=8;
@@ -52,7 +52,7 @@ SELECT @@global.max_join_size;
8
## Since total joins are more than max_join_size value so error will occur ##
SELECT * FROM t1 INNER JOIN t2 ON t1.id = t2.id;
-ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
+ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay
## Dropping both the tables ##
Drop table t1, t2;
## Restoring values ##
diff --git a/mysql-test/suite/sys_vars/r/sql_big_selects_func.result b/mysql-test/suite/sys_vars/r/sql_big_selects_func.result
index fc7e1f32e00..6d7138a1a99 100644
--- a/mysql-test/suite/sys_vars/r/sql_big_selects_func.result
+++ b/mysql-test/suite/sys_vars/r/sql_big_selects_func.result
@@ -19,7 +19,7 @@ INSERT INTO t2 VALUES('aa4','bb');
'#--------------------FN_DYNVARS_154_01-------------------------#'
Expected error "Too big select"
SELECT * FROM t1 INNER JOIN t2 ON t1.a = t2.a;
-ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
+ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay
Expected error The SELECT would examine more than MAX_JOIN_SIZE rows.
'#--------------------FN_DYNVARS_154_02-------------------------#'
SET SESSION SQL_BIG_SELECTS = 1;
diff --git a/mysql-test/suite/sys_vars/r/sql_max_join_size_func.result b/mysql-test/suite/sys_vars/r/sql_max_join_size_func.result
index 0e406f6611e..32a1c2f31e5 100644
--- a/mysql-test/suite/sys_vars/r/sql_max_join_size_func.result
+++ b/mysql-test/suite/sys_vars/r/sql_max_join_size_func.result
@@ -17,7 +17,7 @@ INSERT INTO t2 VALUES('aa4','bb');
'#--------------------FN_DYNVARS_161_01-------------------------#'
SET SESSION sql_max_join_size=9;
SELECT * FROM t1 INNER JOIN t2 ON t1.a = t2.a;
-ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
+ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay
Expected error The SELECT would examine more than MAX_JOIN_SIZE rows.
'#--------------------FN_DYNVARS_161_02-------------------------#'
SET SESSION SQL_BIG_SELECTS = 1;
diff --git a/mysql-test/t/error_simulation.test b/mysql-test/t/error_simulation.test
index f6edacfaa29..95ec2c5b21d 100644
--- a/mysql-test/t/error_simulation.test
+++ b/mysql-test/t/error_simulation.test
@@ -89,6 +89,20 @@ SET SESSION debug = DEFAULT;
DROP TABLE t1, t2;
+
+--echo #
+--echo # Bug#11747970 34660: CRASH WHEN FEDERATED TABLE LOSES CONNECTION DURING INSERT ... SELECT
+--echo #
+CREATE TABLE t1(f1 INT, KEY(f1));
+CREATE TABLE t2(f1 INT);
+INSERT INTO t1 VALUES (1),(2);
+INSERT INTO t2 VALUES (1),(2);
+SET SESSION debug='d,bug11747970_simulate_error';
+INSERT IGNORE INTO t2 SELECT f1 FROM t1 a WHERE NOT EXISTS (SELECT 1 FROM t2 b WHERE a.f1 = b.f1);
+SET SESSION debug = DEFAULT;
+DROP TABLE t1,t2;
+
+
--echo #
--echo # End of 5.1 tests
--echo #
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index 1a4b9a3bab7..29ed26215bf 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -1283,5 +1283,19 @@ 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/heap.test b/mysql-test/t/heap.test
index 3f91b9966e7..1e69b43d79b 100644
--- a/mysql-test/t/heap.test
+++ b/mysql-test/t/heap.test
@@ -454,7 +454,7 @@ drop table t1;
#
create table t1 (c char(10)) engine=memory;
create table t2 (c varchar(10)) engine=memory;
---replace_column 8 #
+--replace_column 8 # 12 #
show table status like 't_';
drop table t1, t2;
diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test
index f290803bbd2..a6affbb0540 100644
--- a/mysql-test/t/merge.test
+++ b/mysql-test/t/merge.test
@@ -1783,4 +1783,49 @@ REPAIR TABLE m1;
#
DROP TABLE m1, t1;
+
+--echo #
+--echo # BUG#11763712 - 56458: KILLING A FLUSH TABLE FOR A MERGE/CHILD
+--echo # CRASHES SERVER
+--echo #
+CREATE TABLE t1(a INT);
+CREATE TABLE t2(a INT);
+CREATE TABLE t3(a INT, b INT);
+CREATE TABLE m1(a INT) ENGINE=MERGE UNION=(t1, t2);
+
+--echo # Test reopen merge parent failure
+LOCK TABLES m1 READ;
+--echo # Remove 'm1' table using file operations.
+remove_file $MYSQLD_DATADIR/test/m1.MRG;
+remove_file $MYSQLD_DATADIR/test/m1.frm;
+--error ER_NO_SUCH_TABLE
+FLUSH TABLES;
+UNLOCK TABLES;
+CREATE TABLE m1(a INT) ENGINE=MERGE UNION=(t1, t2);
+
+--echo # Test reopen merge child failure
+LOCK TABLES m1 READ;
+--echo # Remove 't1' table using file operations.
+remove_file $MYSQLD_DATADIR/test/t1.frm;
+remove_file $MYSQLD_DATADIR/test/t1.MYI;
+remove_file $MYSQLD_DATADIR/test/t1.MYD;
+--error ER_NO_SUCH_TABLE
+FLUSH TABLES;
+UNLOCK TABLES;
+CREATE TABLE t1(a INT);
+
+--echo # Test reattach merge failure
+LOCK TABLES m1 READ;
+--echo # Replace 't1' with 't3' table using file operations.
+remove_file $MYSQLD_DATADIR/test/t1.frm;
+remove_file $MYSQLD_DATADIR/test/t1.MYI;
+remove_file $MYSQLD_DATADIR/test/t1.MYD;
+copy_file $MYSQLD_DATADIR/test/t3.frm $MYSQLD_DATADIR/test/t1.frm;
+copy_file $MYSQLD_DATADIR/test/t3.MYI $MYSQLD_DATADIR/test/t1.MYI;
+copy_file $MYSQLD_DATADIR/test/t3.MYD $MYSQLD_DATADIR/test/t1.MYD;
+--error ER_CANT_REOPEN_TABLE
+FLUSH TABLES;
+UNLOCK TABLES;
+DROP TABLE t1, t2, t3, m1;
+
--echo End of 5.1 tests
diff --git a/mysql-test/t/myisampack.test b/mysql-test/t/myisampack.test
index 9d27ed53254..3bce8cfcfb8 100644
--- a/mysql-test/t/myisampack.test
+++ b/mysql-test/t/myisampack.test
@@ -107,3 +107,48 @@ SELECT COUNT(*) FROM mysql_db1.t1 WHERE c2 < 5;
#
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 52dfd8e86d3..7b897117b9b 100644
--- a/mysql-test/t/mysqltest.test
+++ b/mysql-test/t/mysqltest.test
@@ -335,6 +335,14 @@ eval select $mysql_errno as "after_!errno_masked_error" ;
EOF
# ----------------------------------------------------------------------------
+# Check backtick and query_get_value, result should be empty
+# ----------------------------------------------------------------------------
+let $empty= `garbage`;
+echo $empty is empty;
+let $empty= query_get_value(nonsense, blabla, 1);
+echo $empty is empty;
+
+# ----------------------------------------------------------------------------
# Switch the abort on error on and check the effect on $mysql_errno
# ----------------------------------------------------------------------------
--error ER_PARSE_ERROR
@@ -365,6 +373,23 @@ select 3 from t1 ;
# ----------------------------------------------------------------------------
+# Test --error with backtick operator or query_get_value
+# ----------------------------------------------------------------------------
+
+--error 0,ER_NO_SUCH_TABLE
+let $empty= `SELECT foo from bar`;
+echo $empty is empty;
+
+--error 0,ER_BAD_FIELD_ERROR
+let $empty= query_get_value(SELECT bar as foo, baz, 1);
+echo $empty is empty;
+
+--error 0,ER_NO_SUCH_TABLE
+if (!`SELECT foo from bar`) {
+ echo "Yes it's empty";
+}
+
+# ----------------------------------------------------------------------------
# Test comments
# ----------------------------------------------------------------------------
diff --git a/mysql-test/t/partition_innodb_plugin.test b/mysql-test/t/partition_innodb_plugin.test
index e9e1471f4bd..60fe91ce920 100644
--- a/mysql-test/t/partition_innodb_plugin.test
+++ b/mysql-test/t/partition_innodb_plugin.test
@@ -33,7 +33,6 @@ call mtr.add_suppression("nnoDB: Error: table `test`.`t1` .* Partition.* InnoDB
--echo #
--echo # Bug#55091: Server crashes on ADD PARTITION after a failed attempt
--echo #
-SET @old_innodb_file_format_check = @@global.innodb_file_format_check;
SET @old_innodb_file_format = @@global.innodb_file_format;
SET @old_innodb_file_per_table = @@global.innodb_file_per_table;
SET @old_innodb_strict_mode = @@global.innodb_strict_mode;
@@ -92,7 +91,6 @@ DROP TABLE t1;
SET @@global.innodb_strict_mode = @old_innodb_strict_mode;
SET @@global.innodb_file_format = @old_innodb_file_format;
SET @@global.innodb_file_per_table = @old_innodb_file_per_table;
-SET @@global.innodb_file_format_check = @old_innodb_file_format_check;
#
# Bug#32430 - show engine innodb status causes errors
diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test
index e5ca35bda32..1c1bf9fa6d3 100644
--- a/mysql-test/t/show_check.test
+++ b/mysql-test/t/show_check.test
@@ -230,7 +230,7 @@ DROP TABLE """a";
#set names latin1;
#create database `ä`;
#create table `ä`.`ä` (a int) engine=heap;
-#--replace_column 7 # 8 # 9 #
+#--replace_column 7 # 8 # 9 # 12 #
#show table status from `ä` LIKE 'ä';
#drop database `ä`;
@@ -276,37 +276,37 @@ CREATE TABLE t3 (
insert into t1 values (1),(2);
insert into t2 values (1),(2);
insert into t3 values (1,1),(2,2);
---replace_column 6 # 7 # 8 # 9 #
+--replace_column 6 # 7 # 8 # 9 # 12 #
show table status;
insert into t1 values (3),(4);
insert into t2 values (3),(4);
insert into t3 values (3,3),(4,4);
---replace_column 6 # 7 # 8 # 9 #
+--replace_column 6 # 7 # 8 # 9 # 12 #
show table status;
insert into t1 values (5);
insert into t2 values (5);
insert into t3 values (5,5);
---replace_column 6 # 7 # 8 # 9 #
+--replace_column 6 # 7 # 8 # 9 # 12 #
show table status;
delete from t1 where a=3;
delete from t2 where b=3;
delete from t3 where a=3;
---replace_column 6 # 7 # 8 # 9 # 10 #
+--replace_column 6 # 7 # 8 # 9 # 10 # 12 #
show table status;
truncate table t1;
truncate table t2;
truncate table t3;
---replace_column 6 # 7 # 8 # 9 #
+--replace_column 6 # 7 # 8 # 9 # 12 #
show table status;
insert into t1 values (5);
insert into t2 values (5);
insert into t3 values (5,5);
---replace_column 6 # 7 # 8 # 9 #
+--replace_column 6 # 7 # 8 # 9 # 12 #
show table status;
delete from t1 where a=5;
delete from t2 where b=5;
delete from t3 where a=5;
---replace_column 6 # 7 # 8 # 9 # 10 #
+--replace_column 6 # 7 # 8 # 9 # 10 # 12 #
show table status;
drop table t1, t2, t3;
@@ -367,7 +367,7 @@ flush privileges;
#set names latin1;
#create database `ä`;
#create table `ä`.`ä` (a int) engine=heap;
-#--replace_column 7 # 8 # 9 #
+#--replace_column 7 # 8 # 9 # 12 #
#show table status from `ä` LIKE 'ä';
#drop database `ä`;
@@ -430,7 +430,7 @@ flush tables;
# Create a junk frm file on disk
let $MYSQLD_DATADIR= `select @@datadir`;
system echo "this is a junk file for test" >> $MYSQLD_DATADIR/test/t1.frm ;
---replace_column 6 # 7 # 8 # 9 #
+--replace_column 6 # 7 # 8 # 9 # 12 #
SHOW TABLE STATUS like 't1';
--error ER_NOT_FORM_FILE
show create table t1;
diff --git a/mysql-test/t/sp_trans.test b/mysql-test/t/sp_trans.test
index 0b04b9d7668..2d59fb20bbd 100644
--- a/mysql-test/t/sp_trans.test
+++ b/mysql-test/t/sp_trans.test
@@ -594,6 +594,39 @@ 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|
+
+#
# BUG#NNNN: New bug synopsis
#
#--disable_warnings
diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test
index 31a8808da55..567d6c0b6a1 100644
--- a/mysql-test/t/type_newdecimal.test
+++ b/mysql-test/t/type_newdecimal.test
@@ -1526,3 +1526,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 8720cd511b9..e2fdc727da5 100644
--- a/mysql-test/valgrind.supp
+++ b/mysql-test/valgrind.supp
@@ -791,3 +791,40 @@
fun:fil_delete_tablespace
fun:row_drop_table_for_mysql
}
+
+# Note the wildcard in the (mangled) function signatures of
+# write_keys() and find_all_keys().
+# They both return ha_rows, which is platform dependent.
+{
+ 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:_Z8filesortP3THDP8st_tableP13st_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:_Z8filesortP3THDP8st_tableP13st_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:_Z8filesortP3THDP8st_tableP13st_sort_fieldjP10SQL_SELECTybPy
+}
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 b9b31a2d78e..9782a37c462 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/filesort.cc b/sql/filesort.cc
index 99e5156427a..715528bcd52 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -144,8 +144,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;
@@ -257,6 +255,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)
{
x_free(table_sort.buffpek);
@@ -959,21 +960,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/item_subselect.cc b/sql/item_subselect.cc
index 10dd6c93717..2fa0178ed8c 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1679,7 +1679,7 @@ subselect_single_select_engine(st_select_lex *select,
select_subselect *result_arg,
Item_subselect *item_arg)
:subselect_engine(item_arg, result_arg),
- prepared(0), optimized(0), executed(0),
+ prepared(0), optimized(0), executed(0), optimize_error(0),
select_lex(select), join(0)
{
select_lex->master_unit()->item= item_arg;
@@ -1689,7 +1689,7 @@ subselect_single_select_engine(st_select_lex *select,
void subselect_single_select_engine::cleanup()
{
DBUG_ENTER("subselect_single_select_engine::cleanup");
- prepared= optimized= executed= 0;
+ prepared= optimized= executed= optimize_error= 0;
join= 0;
result->cleanup();
DBUG_VOID_RETURN;
@@ -1885,6 +1885,10 @@ int join_read_next_same_or_null(READ_RECORD *info);
int subselect_single_select_engine::exec()
{
DBUG_ENTER("subselect_single_select_engine::exec");
+
+ if (optimize_error)
+ DBUG_RETURN(1);
+
char const *save_where= thd->where;
SELECT_LEX *save_select= thd->lex->current_select;
thd->lex->current_select= select_lex;
@@ -1892,12 +1896,15 @@ int subselect_single_select_engine::exec()
{
SELECT_LEX_UNIT *unit= select_lex->master_unit();
+ DBUG_EXECUTE_IF("bug11747970_simulate_error",
+ DBUG_SET("+d,bug11747970_raise_error"););
+
optimized= 1;
unit->set_limit(unit->global_parameters);
if (join->optimize())
{
thd->where= save_where;
- executed= 1;
+ optimize_error= 1;
thd->lex->current_select= save_select;
DBUG_RETURN(join->error ? join->error : 1);
}
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 74bbec626c1..65b415b44e9 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -419,6 +419,7 @@ class subselect_single_select_engine: public subselect_engine
my_bool prepared; /* simple subselect is prepared */
my_bool optimized; /* simple subselect is optimized */
my_bool executed; /* simple subselect is executed */
+ my_bool optimize_error; ///< simple subselect optimization failed
st_select_lex *select_lex; /* corresponding select_lex */
JOIN * join; /* corresponding JOIN structure */
public:
diff --git a/sql/my_decimal.h b/sql/my_decimal.h
index c7a99e10233..21f485560da 100644
--- a/sql/my_decimal.h
+++ b/sql/my_decimal.h
@@ -101,12 +101,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/rpl_rli.h b/sql/rpl_rli.h
index 811ad8eb864..ae8639c69ac 100644
--- a/sql/rpl_rli.h
+++ b/sql/rpl_rli.h
@@ -221,7 +221,13 @@ public:
#endif
/* if not set, the value of other members of the structure are undefined */
- bool inited;
+ /*
+ inited changes its value within LOCK_active_mi-guarded critical
+ sections at times of start_slave_threads() (0->1) and end_slave() (1->0).
+ Readers may not acquire the mutex while they realize potential concurrency
+ issue.
+ */
+ volatile bool inited;
volatile bool abort_slave;
volatile uint slave_running;
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index bbae17c4327..7cb9d9ebcc1 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -2494,10 +2494,10 @@ ER_TOO_BIG_SELECT 42000
cze "Zadan-Bý SELECT by procházel pøíli¹ mnoho záznamù a trval velmi dlouho. Zkontrolujte tvar WHERE a je-li SELECT v poøádku, pou¾ijte SET SQL_BIG_SELECTS=1"
dan "SELECT ville undersøge for mange poster og ville sandsynligvis tage meget lang tid. Undersøg WHERE delen og brug SET SQL_BIG_SELECTS=1 hvis udtrykket er korrekt"
nla "Het SELECT-statement zou te veel records analyseren en dus veel tijd in beslagnemen. Kijk het WHERE-gedeelte van de query na en kies SET SQL_BIG_SELECTS=1 als het stament in orde is."
- eng "The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay"
+ eng "The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay"
est "SELECT lause peab läbi vaatama suure hulga kirjeid ja võtaks tõenäoliselt liiga kaua aega. Tasub kontrollida WHERE klauslit ja vajadusel kasutada käsku SET SQL_BIG_SELECTS=1"
fre "SELECT va devoir examiner beaucoup d'enregistrements ce qui va prendre du temps. Vérifiez la clause WHERE et utilisez SET SQL_BIG_SELECTS=1 si SELECT se passe bien"
- ger "Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange dauern. Bitte WHERE-Klausel überprüfen und gegebenenfalls SET SQL_BIG_SELECTS=1 oder SET SQL_MAX_JOIN_SIZE=# verwenden"
+ ger "Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange dauern. Bitte WHERE-Klausel überprüfen und gegebenenfalls SET SQL_BIG_SELECTS=1 oder SET MAX_JOIN_SIZE=# verwenden"
greek "Ôï SELECT èá åîåôÜóåé ìåãÜëï áñéèìü åããñáöþí êáé ðéèáíþò èá êáèõóôåñÞóåé. Ðáñáêáëþ åîåôÜóôå ôéò ðáñáìÝôñïõò ôïõ WHERE êáé ÷ñçóéìïðïéåßóôå SET SQL_BIG_SELECTS=1 áí ôï SELECT åßíáé óùóôü"
hun "A SELECT tul sok rekordot fog megvizsgalni es nagyon sokaig fog tartani. Ellenorizze a WHERE-t es hasznalja a SET SQL_BIG_SELECTS=1 beallitast, ha a SELECT okay"
ita "La SELECT dovrebbe esaminare troppi record e usare troppo tempo. Controllare la WHERE e usa SET SQL_BIG_SELECTS=1 se e` tutto a posto."
diff --git a/sql/slave.cc b/sql/slave.cc
index 6c375238ce4..02d8cc2c199 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -598,11 +598,15 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock,
DBUG_PRINT("sleep",("Waiting for slave thread to start"));
const char* old_msg = thd->enter_cond(start_cond,cond_lock,
"Waiting for slave thread to start");
- pthread_cond_wait(start_cond,cond_lock);
+ pthread_cond_wait(start_cond, cond_lock);
thd->exit_cond(old_msg);
pthread_mutex_lock(cond_lock); // re-acquire it as exit_cond() released
if (thd->killed)
+ {
+ if (start_lock)
+ pthread_mutex_unlock(start_lock);
DBUG_RETURN(thd->killed_errno());
+ }
}
}
if (start_lock)
@@ -2531,6 +2535,7 @@ pthread_handler_t handle_slave_io(void *arg)
thd= new THD; // note that contructor of THD uses DBUG_ !
THD_CHECK_SENTRY(thd);
+ DBUG_ASSERT(mi->io_thd == 0);
mi->io_thd = thd;
pthread_detach_this_thread();
@@ -4489,9 +4494,6 @@ int rotate_relay_log(Master_info* mi)
Relay_log_info* rli= &mi->rli;
int error= 0;
- /* We don't lock rli->run_lock. This would lead to deadlocks. */
- pthread_mutex_lock(&mi->run_lock);
-
/*
We need to test inited because otherwise, new_file() will attempt to lock
LOCK_log, which may not be inited (if we're not a slave).
@@ -4521,7 +4523,6 @@ int rotate_relay_log(Master_info* mi)
*/
rli->relay_log.harvest_bytes_written(&rli->log_space_total);
end:
- pthread_mutex_unlock(&mi->run_lock);
DBUG_RETURN(error);
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index ab1ba156905..ace78947054 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -96,6 +96,13 @@ static TABLE_SHARE *oldest_unused_share, end_of_unused_share;
static pthread_mutex_t LOCK_table_share;
static bool table_def_inited= 0;
+/**
+ Dummy TABLE instance which is used in reopen_tables() and reattach_merge()
+ functions to mark MERGE tables and their children with which there is some
+ kind of problem and which therefore we need to close.
+*/
+static TABLE bad_merge_marker;
+
static int open_unireg_entry(THD *thd, TABLE *entry, TABLE_LIST *table_list,
const char *alias,
char *cache_key, uint cache_key_length,
@@ -3215,46 +3222,65 @@ void close_data_files_and_morph_locks(THD *thd, const char *db,
/**
+ @brief Mark merge parent and children with bad_merge_marker
+
+ @param[in,out] parent the TABLE object of the parent
+*/
+
+static void mark_merge_parent_and_children_as_bad(TABLE *parent)
+{
+ TABLE_LIST *child_l;
+ DBUG_ENTER("mark_merge_parent_and_children_as_bad");
+ parent->parent= &bad_merge_marker;
+ for (child_l= parent->child_l; ; child_l= child_l->next_global)
+ {
+ child_l->table->parent= &bad_merge_marker;
+ child_l->table= NULL;
+ if (&child_l->next_global == parent->child_last_l)
+ break;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/**
Reattach MERGE children after reopen.
@param[in] thd thread context
- @param[in,out] err_tables_p pointer to pointer of tables in error
+
+ @note If reattach failed for certain MERGE table, the table (and all
+ it's children) are marked with bad_merge_marker.
@return status
- @retval FALSE OK, err_tables_p unchanged
- @retval TRUE Error, err_tables_p contains table(s)
+ @retval FALSE OK
+ @retval TRUE Error
*/
-static bool reattach_merge(THD *thd, TABLE **err_tables_p)
+static bool reattach_merge(THD *thd)
{
TABLE *table;
- TABLE *next;
- TABLE **prv_p= &thd->open_tables;
bool error= FALSE;
DBUG_ENTER("reattach_merge");
- for (table= thd->open_tables; table; table= next)
+ for (table= thd->open_tables; table; table= table->next)
{
- next= table->next;
- DBUG_PRINT("tcache", ("check table: '%s'.'%s' 0x%lx next: 0x%lx",
+ DBUG_PRINT("tcache", ("check table: '%s'.'%s' 0x%lx",
table->s->db.str, table->s->table_name.str,
- (long) table, (long) next));
- /* Reattach children for MERGE tables with "closed data files" only. */
- if (table->child_l && !table->children_attached)
+ (long) table));
+ /*
+ Reattach children only for MERGE tables that had children or parent
+ with "closed data files" and were reopen. For extra safety skip MERGE
+ tables which we failed to reopen (should not happen with current code).
+ */
+ if (table->child_l && table->parent != &bad_merge_marker &&
+ !table->children_attached)
{
DBUG_PRINT("tcache", ("MERGE parent, attach children"));
- if(table->file->extra(HA_EXTRA_ATTACH_CHILDREN))
+ if (table->file->extra(HA_EXTRA_ATTACH_CHILDREN))
{
my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias);
error= TRUE;
- /* Remove table from open_tables. */
- *prv_p= next;
- if (next)
- prv_p= &next->next;
- /* Stack table on error list. */
- table->next= *err_tables_p;
- *err_tables_p= table;
- continue;
+ mark_merge_parent_and_children_as_bad(table);
}
else
{
@@ -3264,7 +3290,6 @@ static bool reattach_merge(THD *thd, TABLE **err_tables_p)
table->s->table_name.str, (long) table));
}
}
- prv_p= &table->next;
}
DBUG_RETURN(error);
}
@@ -3294,7 +3319,6 @@ bool reopen_tables(THD *thd, bool get_locks, bool mark_share_as_old)
{
TABLE *table,*next,**prev;
TABLE **tables,**tables_ptr; // For locks
- TABLE *err_tables= NULL;
bool error=0, not_used;
bool merge_table_found= FALSE;
const uint flags= MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN |
@@ -3328,29 +3352,69 @@ bool reopen_tables(THD *thd, bool get_locks, bool mark_share_as_old)
for (table=thd->open_tables; table ; table=next)
{
uint db_stat=table->db_stat;
+ TABLE *parent= table->child_l ? table : table->parent;
next=table->next;
DBUG_PRINT("tcache", ("open table: '%s'.'%s' 0x%lx "
"parent: 0x%lx db_stat: %u",
table->s->db.str, table->s->table_name.str,
(long) table, (long) table->parent, db_stat));
- if (table->child_l && !db_stat)
+ /*
+ If we need to reopen child or parent table in a MERGE table, then
+ children in this MERGE table has to be already detached at this
+ point.
+ */
+ DBUG_ASSERT(db_stat || !parent || !parent->children_attached);
+ /*
+ Thanks to the above assumption the below condition will guarantee that
+ merge_table_found is TRUE when we need to reopen child or parent table.
+ Note that it works even in situation when it is only a child and not a
+ parent that needs reopen (this can happen when get_locks == FALSE).
+ */
+ if (table->child_l && !table->children_attached)
merge_table_found= TRUE;
- if (!tables || (!db_stat && reopen_table(table)))
+
+ if (!tables)
{
- my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias);
/*
- If we could not allocate 'tables', we may close open tables
- here. If a MERGE table is affected, detach the children first.
- It is not necessary to clear the child or parent table reference
- of this table because the TABLE is freed. But we need to clear
- the child or parent references of the other belonging tables so
- that they cannot be moved into the unused_tables chain with
- these pointers set.
+ If we could not allocate 'tables' we close ALL open tables here.
+ Before closing MERGE child or parent we need to detach children
+ and/or clear references in/to them.
*/
- if (table->child_l || table->parent)
+ if (parent)
detach_merge_children(table, TRUE);
- VOID(hash_delete(&open_cache,(uchar*) table));
- error=1;
+ }
+ else if (table->parent == &bad_merge_marker)
+ {
+ /*
+ This is either a child or a parent of a MERGE table for which
+ we already decided that we are unable to reopen it. Close it.
+
+ Reset parent reference, it may be used while freeing the table.
+ */
+ table->parent= NULL;
+ }
+ else if (!db_stat && reopen_table(table))
+ {
+ /*
+ If we fail to reopen a child or a parent in a MERGE table and the
+ MERGE table is affected for the first time, mark all relevant tables
+ invalid. Otherwise handle it as usual.
+
+ All in all we must end up with:
+ - child tables are detached from parent. This was done earlier,
+ but child<->parent references were kept valid for reopen.
+ - parent is not in the to-be-locked tables
+ - all child tables and parent are not in the THD::open_tables.
+ - all child tables and parent are not in the open_cache.
+
+ Please note that below we do additional pass through THD::open_tables
+ list to achieve the last three points.
+ */
+ if (parent)
+ {
+ mark_merge_parent_and_children_as_bad(parent);
+ table->parent= NULL;
+ }
}
else
{
@@ -3366,21 +3430,56 @@ bool reopen_tables(THD *thd, bool get_locks, bool mark_share_as_old)
table->s->version=0;
table->open_placeholder= 0;
}
+ continue;
}
+ my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias);
+ VOID(hash_delete(&open_cache, (uchar *) table));
+ error= 1;
}
*prev=0;
/*
When all tables are open again, we can re-attach MERGE children to
- their parents. All TABLE objects are still present.
+ their parents.
+
+ If there was an error while reopening a child or a parent of a MERGE
+ table, or while reattaching child tables to their parents, some tables
+ may have been kept open but marked for close with bad_merge_marker.
+ Close these tables now.
*/
- DBUG_PRINT("tcache", ("re-attaching MERGE tables: %d", merge_table_found));
- if (!error && merge_table_found && reattach_merge(thd, &err_tables))
+ if (tables && merge_table_found && (error|= reattach_merge(thd)))
{
- while (err_tables)
+ prev= &thd->open_tables;
+ for (table= thd->open_tables; table; table= next)
{
- VOID(hash_delete(&open_cache, (uchar*) err_tables));
- err_tables= err_tables->next;
+ next= table->next;
+ if (table->parent == &bad_merge_marker)
+ {
+ /* Remove merge parent from to-be-locked tables array. */
+ if (get_locks && table->child_l)
+ {
+ TABLE **t;
+ for (t= tables; t < tables_ptr; t++)
+ {
+ if (*t == table)
+ {
+ tables_ptr--;
+ memmove(t, t + 1, (tables_ptr - t) * sizeof(TABLE *));
+ break;
+ }
+ }
+ }
+ /* Reset parent reference, it may be used while freeing the table. */
+ table->parent= NULL;
+ /* Free table. */
+ VOID(hash_delete(&open_cache, (uchar *) table));
+ }
+ else
+ {
+ *prev= table;
+ prev= &table->next;
+ }
}
+ *prev= 0;
}
DBUG_PRINT("tcache", ("open tables to lock: %u",
(uint) (tables_ptr - tables)));
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 55509a31f77..a88cc2fa8e5 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2642,6 +2642,12 @@ mysql_execute_command(THD *thd)
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_select.cc b/sql/sql_select.cc
index 516c9c37473..bf0cd7c9db8 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -2677,6 +2677,16 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
table_vector[i]=s->table=table=tables->table;
table->pos_in_table_list= tables;
error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+
+ DBUG_EXECUTE_IF("bug11747970_raise_error",
+ {
+ if (!error)
+ {
+ my_error(ER_UNKNOWN_ERROR, MYF(0));
+ goto error;
+ }
+ });
+
if (error)
{
table->file->print_error(error, MYF(0));
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index adb23a4a614..facbc6d3e95 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1838,7 +1838,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;
@@ -1847,7 +1846,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,
diff --git a/storage/federated/Makefile.am b/storage/federated/Makefile.am
index e0dae69539e..9b4e74af0a7 100644
--- a/storage/federated/Makefile.am
+++ b/storage/federated/Makefile.am
@@ -37,14 +37,14 @@ pkgplugin_LTLIBRARIES = @plugin_federated_shared_target@
ha_federated_la_LDFLAGS = -module -rpath $(pkgplugindir)
ha_federated_la_CXXFLAGS= $(AM_CXXFLAGS) -DMYSQL_DYNAMIC_PLUGIN
ha_federated_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
-ha_federated_la_SOURCES = ha_federated.cc
+ha_federated_la_SOURCES = ha_federated.cc $(top_srcdir)/mysys/string.c
EXTRA_LIBRARIES = libfederated.a
noinst_LIBRARIES = @plugin_federated_static_target@
libfederated_a_CXXFLAGS = $(AM_CXXFLAGS)
libfederated_a_CFLAGS = $(AM_CFLAGS)
-libfederated_a_SOURCES= ha_federated.cc
+libfederated_a_SOURCES= ha_federated.cc $(top_srcdir)/mysys/string.c
EXTRA_DIST = CMakeLists.txt plug.in
diff --git a/storage/heap/ha_heap.cc b/storage/heap/ha_heap.cc
index d805fac2783..5d819722b6e 100644
--- a/storage/heap/ha_heap.cc
+++ b/storage/heap/ha_heap.cc
@@ -382,6 +382,7 @@ int ha_heap::info(uint flag)
stats.index_file_length= hp_info.index_length;
stats.max_data_file_length= hp_info.max_records * hp_info.reclength;
stats.delete_length= hp_info.deleted * hp_info.reclength;
+ stats.create_time= (ulong) hp_info.create_time;
if (flag & HA_STATUS_AUTO)
stats.auto_increment_value= hp_info.auto_increment;
/*
diff --git a/storage/heap/hp_create.c b/storage/heap/hp_create.c
index b6814fc1614..5208d4676c3 100644
--- a/storage/heap/hp_create.c
+++ b/storage/heap/hp_create.c
@@ -186,6 +186,7 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
share->auto_key= create_info->auto_key;
share->auto_key_type= create_info->auto_key_type;
share->auto_increment= create_info->auto_increment;
+ share->create_time= (long) time((time_t*) 0);
/* Must be allocated separately for rename to work */
if (!(share->name= my_strdup(name,MYF(0))))
{
diff --git a/storage/heap/hp_info.c b/storage/heap/hp_info.c
index ea78c53fd40..c72dbaf2065 100644
--- a/storage/heap/hp_info.c
+++ b/storage/heap/hp_info.c
@@ -53,6 +53,7 @@ int heap_info(reg1 HP_INFO *info,reg2 HEAPINFO *x, int flag )
x->index_length = info->s->index_length;
x->max_records = info->s->max_records;
x->errkey = info->errkey;
+ x->create_time = info->s->create_time;
if (flag & HA_STATUS_AUTO)
x->auto_increment= info->s->auto_increment + 1;
DBUG_RETURN(0);
diff --git a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c
index 790582815a3..ad99913cf3b 100644
--- a/storage/innobase/btr/btr0btr.c
+++ b/storage/innobase/btr/btr0btr.c
@@ -300,29 +300,30 @@ 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! */
-
-page_t*
-btr_page_alloc(
-/*===========*/
- /* out: new allocated page, x-latched;
- NULL if out of space */
+static
+ulint
+btr_page_alloc_low(
+/*===============*/
+ /* out: allocated page number,
+ FIL_NULL if out of space */
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;
- page_t* new_page;
- ulint new_page_no;
-
- if (index->type & DICT_IBUF) {
-
- return(btr_page_alloc_for_ibuf(index, mtr));
- }
root = btr_root_get(index, mtr);
@@ -336,19 +337,61 @@ 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! */
+
+page_t*
+btr_page_alloc(
+/*===========*/
+ /* out: new allocated block, x-latched;
+ NULL if out of space */
+ 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 */
+{
+ page_t* new_page;
+ ulint new_page_no;
+
+ if (index->type & DICT_IBUF) {
+
+ 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);
}
new_page = buf_page_get(dict_index_get_space(index), new_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, init_mtr);
#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(new_page, SYNC_TREE_NODE_NEW);
#endif /* UNIV_SYNC_DEBUG */
+ if (mtr->freed_clust_leaf) {
+ mtr_memo_release(mtr, new_page, MTR_MEMO_FREE_CLUST_LEAF);
+ ut_ad(!mtr_memo_contains(mtr, buf_block_align(new_page),
+ MTR_MEMO_FREE_CLUST_LEAF));
+ }
+
+ ut_ad(btr_freed_leaves_validate(mtr));
return(new_page);
}
@@ -464,6 +507,16 @@ btr_page_free_low(
page_no = buf_frame_get_page_no(page);
fseg_free_page(seg_header, space, page_no, 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, buf_block_align(page),
+ 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. */
}
/******************************************************************
@@ -479,13 +532,144 @@ btr_page_free(
{
ulint level;
+ ut_ad(fil_page_get_type(page) == FIL_PAGE_INDEX);
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
level = btr_page_get_level(page, mtr);
btr_page_free_low(index, page, level, mtr);
+
+ /* The handling of MTR_MEMO_FREE_CLUST_LEAF assumes this. */
+ ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
+ MTR_MEMO_PAGE_X_FIX));
+
+ if (level == 0 && (index->type & DICT_CLUSTERED)) {
+ /* We may have to call btr_mark_freed_leaves() to
+ temporarily mark the block nonfree for invoking
+ btr_store_big_rec_extern_fields() after an
+ update. Remember that the block was freed. */
+ mtr->freed_clust_leaf = TRUE;
+ mtr_memo_push(mtr, buf_block_align(page),
+ 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. */
+
+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(index->type & DICT_CLUSTERED);
+ 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(btr_page_get_level(buf_block_get_frame(block), mtr) == 0);
+
+ 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, buf_block_get_frame(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(). */
+
+ibool
+btr_freed_leaves_validate(
+/*======================*/
+ /* out: TRUE if valid */
+ 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) {
+ 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;
+ }
+
+ 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(btr_page_get_level(buf_block_get_frame(block), mtr) == 0);
+ }
+
+ return(TRUE);
+}
+#endif /* UNIV_DEBUG */
+
/******************************************************************
Sets the child node file address in a node pointer. */
UNIV_INLINE
@@ -1015,7 +1199,7 @@ btr_root_raise_and_insert(
a node pointer to the new page, and then splitting the new page. */
new_page = btr_page_alloc(index, 0, FSP_NO_DIR,
- btr_page_get_level(root, mtr), mtr);
+ btr_page_get_level(root, mtr), mtr, mtr);
btr_page_create(new_page, index, mtr);
@@ -1636,7 +1820,7 @@ func_start:
/* 2. Allocate a new page to the index */
new_page = btr_page_alloc(cursor->index, hint_page_no, direction,
- btr_page_get_level(page, mtr), mtr);
+ btr_page_get_level(page, mtr), mtr, mtr);
btr_page_create(new_page, cursor->index, mtr);
/* 3. Calculate the first record on the upper half-page, and the
diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
index 9ce09929f9a..a1dda8edf69 100644
--- a/storage/innobase/btr/btr0cur.c
+++ b/storage/innobase/btr/btr0cur.c
@@ -2051,43 +2051,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. */
-
-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 = buf_block_align(btr_cur_get_rec(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);
-#ifdef UNIV_SYNC_DEBUG
- buf_block_buf_fix_inc_debug(block, __FILE__, __LINE__);
-#else
- buf_block_buf_fix_inc(block);
-#endif
- 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 ===============*/
/********************************************************************
@@ -3494,6 +3457,11 @@ btr_store_big_rec_extern_fields(
this function returns */
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 */
mtr_t* local_mtr __attribute__((unused))) /* in: mtr
containing the latch to rec and to the
tree */
@@ -3514,6 +3482,8 @@ btr_store_big_rec_extern_fields(
ulint i;
mtr_t mtr;
+ ut_ad(local_mtr);
+ ut_ad(!alloc_mtr || alloc_mtr == local_mtr);
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index),
MTR_MEMO_X_LOCK));
@@ -3523,6 +3493,25 @@ btr_store_big_rec_extern_fields(
space_id = buf_frame_get_space_id(rec);
+ 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;
+ }
+
/* We have to create a file segment to the tablespace
for each field and put the pointer to the field in rec */
@@ -3549,7 +3538,7 @@ btr_store_big_rec_extern_fields(
}
page = btr_page_alloc(index, hint_page_no,
- FSP_NO_DIR, 0, &mtr);
+ FSP_NO_DIR, 0, alloc_mtr, &mtr);
if (page == NULL) {
mtr_commit(&mtr);
@@ -3603,37 +3592,42 @@ btr_store_big_rec_extern_fields(
extern_len -= store_len;
+ if (alloc_mtr == &mtr) {
#ifdef UNIV_SYNC_DEBUG
- rec_page =
+ rec_page =
#endif /* UNIV_SYNC_DEBUG */
- buf_page_get(space_id,
- buf_frame_get_page_no(data),
- RW_X_LATCH, &mtr);
+ buf_page_get(
+ space_id,
+ buf_frame_get_page_no(data),
+ RW_X_LATCH, &mtr);
#ifdef UNIV_SYNC_DEBUG
- buf_page_dbg_add_level(rec_page, SYNC_NO_ORDER_CHECK);
+ buf_page_dbg_add_level(
+ rec_page, SYNC_NO_ORDER_CHECK);
#endif /* UNIV_SYNC_DEBUG */
+ }
+
mlog_write_ulint(data + local_len + BTR_EXTERN_LEN, 0,
- MLOG_4BYTES, &mtr);
+ MLOG_4BYTES, alloc_mtr);
mlog_write_ulint(data + local_len + 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) {
mlog_write_ulint(data + local_len
+ BTR_EXTERN_SPACE_ID,
space_id,
- MLOG_4BYTES, &mtr);
+ MLOG_4BYTES, alloc_mtr);
mlog_write_ulint(data + local_len
+ BTR_EXTERN_PAGE_NO,
page_no,
- MLOG_4BYTES, &mtr);
+ MLOG_4BYTES, alloc_mtr);
mlog_write_ulint(data + local_len
+ BTR_EXTERN_OFFSET,
FIL_PAGE_DATA,
- MLOG_4BYTES, &mtr);
+ MLOG_4BYTES, alloc_mtr);
/* Set the bit denoting that this field
in rec is stored externally */
@@ -3641,7 +3635,7 @@ btr_store_big_rec_extern_fields(
rec_set_nth_field_extern_bit(
rec, index,
big_rec_vec->fields[i].field_no,
- TRUE, &mtr);
+ TRUE, alloc_mtr);
}
prev_page_no = page_no;
diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
index 08e033e7a63..78b39812cff 100644
--- a/storage/innobase/buf/buf0buf.c
+++ b/storage/innobase/buf/buf0buf.c
@@ -1009,29 +1009,6 @@ buf_page_peek_block(
}
/************************************************************************
-Resets the check_index_page_at_flush field of a page if found in the buffer
-pool. */
-
-void
-buf_reset_check_index_page_at_flush(
-/*================================*/
- ulint space, /* in: space id */
- ulint offset) /* in: page number */
-{
- buf_block_t* block;
-
- mutex_enter_fast(&(buf_pool->mutex));
-
- block = buf_page_hash_get(space, offset);
-
- if (block) {
- block->check_index_page_at_flush = FALSE;
- }
-
- mutex_exit(&(buf_pool->mutex));
-}
-
-/************************************************************************
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. */
diff --git a/storage/innobase/fsp/fsp0fsp.c b/storage/innobase/fsp/fsp0fsp.c
index d228e683957..d5be8fca38f 100644
--- a/storage/innobase/fsp/fsp0fsp.c
+++ b/storage/innobase/fsp/fsp0fsp.c
@@ -293,15 +293,19 @@ fseg_alloc_free_page_low(
/* out: the allocated page number, FIL_NULL
if no page could be allocated */
ulint space, /* in: space */
- 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) */
/**************************************************************************
Reads the file space size stored in the header page. */
@@ -1371,6 +1375,43 @@ fsp_alloc_free_extent(
return(descr);
}
+/**********************************************************************//**
+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. */
static
@@ -1381,19 +1422,22 @@ fsp_alloc_free_page(
be allocated */
ulint space, /* in: space id */
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;
page_t* page;
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, mtr);
@@ -1441,6 +1485,7 @@ fsp_alloc_free_page(
if (free == ULINT_UNDEFINED) {
ut_print_buf(stderr, ((byte*)descr) - 500, 1000);
+ putc('\n', stderr);
ut_error;
}
@@ -1472,40 +1517,21 @@ 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, mtr);
+ buf_page_create(space, page_no, init_mtr);
- page = buf_page_get(space, page_no, RW_X_LATCH, mtr);
+ page = buf_page_get(space, page_no, RW_X_LATCH, init_mtr);
#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_FSP_PAGE);
#endif /* UNIV_SYNC_DEBUG */
/* Prior contents of the page should be ignored */
- fsp_init_file_page(page, mtr);
+ fsp_init_file_page(page, init_mtr);
return(page_no);
}
@@ -1724,7 +1750,7 @@ fsp_alloc_seg_inode_page(
space = buf_frame_get_space_id(space_header);
- page_no = fsp_alloc_free_page(space, 0, mtr);
+ page_no = fsp_alloc_free_page(space, 0, mtr, mtr);
if (page_no == FIL_NULL) {
@@ -2094,7 +2120,8 @@ fseg_create_general(
}
if (page == 0) {
- page = fseg_alloc_free_page_low(space, inode, 0, FSP_UP, mtr);
+ page = fseg_alloc_free_page_low(space,
+ inode, 0, FSP_UP, mtr, mtr);
if (page == FIL_NULL) {
@@ -2331,14 +2358,19 @@ fseg_alloc_free_page_low(
/* out: the allocated page number, FIL_NULL
if no page could be allocated */
ulint space, /* in: space */
- 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;
@@ -2350,7 +2382,6 @@ fseg_alloc_free_page_low(
if could not be allocated */
xdes_t* ret_descr; /* the extent of the allocated page */
page_t* page;
- ibool frag_page_allocated = FALSE;
ibool success;
ulint n;
@@ -2371,6 +2402,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, hint, mtr);
}
@@ -2382,15 +2415,20 @@ fseg_alloc_free_page_low(
mtr), 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
=========================================================
@@ -2408,8 +2446,20 @@ fseg_alloc_free_page_low(
/* Try to fill the segment free list */
fseg_fill_free_list(seg_inode, space,
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)
@@ -2467,11 +2517,9 @@ 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, hint, mtr);
+ ret_page = fsp_alloc_free_page(space, 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 */
@@ -2481,6 +2529,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
@@ -2527,22 +2579,31 @@ 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 */
+ mtr_t* block_mtr = init_mtr ? init_mtr : mtr;
- page = buf_page_create(space, ret_page, mtr);
+ page = buf_page_create(space, ret_page, block_mtr);
- ut_a(page == buf_page_get(space, ret_page, RW_X_LATCH, mtr));
+ ut_a(page == buf_page_get(space, ret_page, RW_X_LATCH,
+ block_mtr));
#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_FSP_PAGE);
#endif /* UNIV_SYNC_DEBUG */
- /* The prior contents of the page should be ignored */
- fsp_init_file_page(page, mtr);
+ if (init_mtr) {
+ /* The prior contents of the page should be ignored */
+ fsp_init_file_page(page, 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. */
@@ -2554,8 +2615,6 @@ fseg_alloc_free_page_low(
fseg_mark_page_used(seg_inode, space, ret_page, mtr);
}
- buf_reset_check_index_page_at_flush(space, ret_page);
-
return(ret_page);
}
@@ -2569,7 +2628,7 @@ fseg_alloc_free_page_general(
/*=========================*/
/* out: allocated page offset, FIL_NULL if no
page could be allocated */
- 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
@@ -2581,7 +2640,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;
@@ -2619,7 +2682,8 @@ fseg_alloc_free_page_general(
}
page_no = fseg_alloc_free_page_low(buf_frame_get_space_id(inode),
- inode, hint, direction, mtr);
+ inode, hint, direction,
+ mtr, init_mtr);
if (!has_done_reservation) {
fil_space_release_free_extents(space, n_reserved);
}
@@ -2647,7 +2711,7 @@ fseg_alloc_free_page(
mtr_t* mtr) /* in: mtr handle */
{
return(fseg_alloc_free_page_general(seg_header, hint, direction,
- FALSE, mtr));
+ FALSE, mtr, mtr));
}
/**************************************************************************
diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c
index 71ecc7ec49f..1406b2de4e9 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.c
+++ b/storage/innobase/ibuf/ibuf0ibuf.c
@@ -1683,16 +1683,16 @@ ibuf_add_free_page(
page = buf_page_get(space, page_no, RW_X_LATCH, &mtr);
-#ifdef UNIV_SYNC_DEBUG
- buf_page_dbg_add_level(page, SYNC_TREE_NODE_NEW);
-#endif /* UNIV_SYNC_DEBUG */
-
ibuf_enter();
mutex_enter(&ibuf_mutex);
root = ibuf_tree_root_get(ibuf_data, space, &mtr);
+#ifdef UNIV_SYNC_DEBUG
+ buf_page_dbg_add_level(page, SYNC_TREE_NODE_NEW);
+#endif /* UNIV_SYNC_DEBUG */
+
/* Add the page to the free list and update the ibuf size data */
flst_add_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h
index 269fa355558..3988019589d 100644
--- a/storage/innobase/include/btr0btr.h
+++ b/storage/innobase/include/btr0btr.h
@@ -379,7 +379,11 @@ 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 */
/******************************************************************
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. */
@@ -402,6 +406,31 @@ btr_page_free_low(
page_t* page, /* in: page 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. */
+
+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 */
+#ifdef UNIV_DEBUG
+/**************************************************************//**
+Validates all pages marked MTR_MEMO_FREE_CLUST_LEAF.
+See btr_mark_freed_leaves(). */
+
+ibool
+btr_freed_leaves_validate(
+/*======================*/
+ /* out: TRUE if valid */
+ mtr_t* mtr); /* in: mini-transaction */
+#endif /* UNIV_DEBUG */
#ifdef UNIV_BTR_PRINT
/*****************************************************************
Prints size info of a B-tree. */
diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h
index c068d8d3318..c2bf84ef9cb 100644
--- a/storage/innobase/include/btr0cur.h
+++ b/storage/innobase/include/btr0cur.h
@@ -252,15 +252,6 @@ btr_cur_pessimistic_update(
updates */
que_thr_t* thr, /* in: query thread */
mtr_t* mtr); /* in: mtr */
-/*****************************************************************
-Commits and restarts a mini-transaction so that it will retain an
-x-lock on index->lock and the cursor page. */
-
-void
-btr_cur_mtr_commit_and_start(
-/*=========================*/
- btr_cur_t* cursor, /* in: cursor */
- mtr_t* mtr); /* in/out: mini-transaction */
/***************************************************************
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
@@ -471,6 +462,11 @@ btr_store_big_rec_extern_fields(
this function returns */
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 */
mtr_t* local_mtr); /* in: mtr containing the latch to
rec and to the tree */
/***********************************************************************
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index b2adde9cbf4..50e0aa9376c 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -275,15 +275,6 @@ buf_page_peek_block(
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. */
-
-void
-buf_reset_check_index_page_at_flush(
-/*================================*/
- ulint space, /* in: space id */
- ulint offset);/* in: page number */
-/************************************************************************
Sets file_page_was_freed TRUE if the page is found in the buffer pool.
This function should be called when we free a file page and want the
debug version to check that it is not accessed any more unless
diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h
index 17bfbeec2c1..4c58d6075e6 100644
--- a/storage/innobase/include/fsp0fsp.h
+++ b/storage/innobase/include/fsp0fsp.h
@@ -167,7 +167,7 @@ fseg_alloc_free_page_general(
/*=========================*/
/* out: allocated page offset, FIL_NULL if no
page could be allocated */
- 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
@@ -179,7 +179,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 */
+ 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 */
/**************************************************************************
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 2b41fa0059a..58983063361 100644
--- a/storage/innobase/include/mtr0mtr.h
+++ b/storage/innobase/include/mtr0mtr.h
@@ -36,6 +36,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
/* Log item types: we have made them to be of the type 'byte'
for the compiler to warn if val and type parameters are switched
@@ -315,9 +317,12 @@ struct mtr_struct{
ulint state; /* MTR_ACTIVE, MTR_COMMITTING, MTR_COMMITTED */
dyn_array_t memo; /* memo stack for locks etc. */
dyn_array_t log; /* mini-transaction log */
- ibool modifications;
+ unsigned modifications:1;
/* TRUE if the mtr made modifications to
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 81eec3bfc92..6b4cacf0766 100644
--- a/storage/innobase/include/mtr0mtr.ic
+++ b/storage/innobase/include/mtr0mtr.ic
@@ -26,6 +26,7 @@ mtr_start(
mtr->log_mode = MTR_LOG_ALL;
mtr->modifications = FALSE;
+ mtr->freed_clust_leaf = FALSE;
mtr->n_log_recs = 0;
#ifdef UNIV_DEBUG
@@ -50,7 +51,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);
diff --git a/storage/innobase/include/sync0rw.h b/storage/innobase/include/sync0rw.h
index dd898557d6e..6bd81623ad2 100644
--- a/storage/innobase/include/sync0rw.h
+++ b/storage/innobase/include/sync0rw.h
@@ -484,7 +484,8 @@ struct rw_lock_struct {
#define RW_LOCK_MAGIC_N 22643
#ifdef UNIV_SYNC_DEBUG
-/* The structure for storing debug info of an rw-lock */
+/** The structure for storing debug info of an rw-lock. All access to this
+structure must be protected by rw_lock_debug_mutex_enter(). */
struct rw_lock_debug_struct {
os_thread_id_t thread_id; /* The thread id of the thread which
diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic
index eea639f26f4..2a674f00262 100644
--- a/storage/innobase/include/sync0rw.ic
+++ b/storage/innobase/include/sync0rw.ic
@@ -238,6 +238,7 @@ rw_lock_s_lock_func(
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */
+ ut_ad(!rw_lock_own(lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
mutex_enter(rw_lock_get_mutex(lock));
diff --git a/storage/innobase/mtr/mtr0mtr.c b/storage/innobase/mtr/mtr0mtr.c
index 728c37ce564..33b71f0766c 100644
--- a/storage/innobase/mtr/mtr0mtr.c
+++ b/storage/innobase/mtr/mtr0mtr.c
@@ -53,17 +53,13 @@ mtr_memo_slot_release(
buf_page_release((buf_block_t*)object, type, mtr);
} 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) {
- rw_lock_x_unlock((rw_lock_t*)object);
- } else {
- ut_ad(type == MTR_MEMO_MODIFY);
+ } else if (type != MTR_MEMO_X_LOCK) {
+ ut_ad(type == MTR_MEMO_MODIFY
+ || type == MTR_MEMO_FREE_CLUST_LEAF);
ut_ad(mtr_memo_contains(mtr, object,
MTR_MEMO_PAGE_X_FIX));
-#else
} else {
rw_lock_x_unlock((rw_lock_t*)object);
-#endif
}
}
diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c
index 7ff443a11ad..6366beb6b47 100644
--- a/storage/innobase/row/row0ins.c
+++ b/storage/innobase/row/row0ins.c
@@ -2089,15 +2089,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(rec, index, offsets,
@@ -2105,7 +2110,8 @@ row_ins_index_entry_low(
&heap);
err = btr_store_big_rec_extern_fields(
- index, rec, offsets, big_rec, &mtr);
+ index, rec, offsets, big_rec,
+ &mtr, &mtr);
/* If writing big_rec fails (for
example, because of DB_OUT_OF_FILE_SPACE),
the record will be corrupted. Even if
@@ -2118,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 {
@@ -2165,7 +2174,8 @@ function_exit:
ULINT_UNDEFINED, &heap);
err = btr_store_big_rec_extern_fields(index, rec,
- offsets, big_rec, &mtr);
+ offsets, big_rec,
+ NULL, &mtr);
stored_big_rec:
if (modify) {
dtuple_big_rec_free(big_rec);
diff --git a/storage/innobase/row/row0purge.c b/storage/innobase/row/row0purge.c
index deec3b0a454..506d92f052e 100644
--- a/storage/innobase/row/row0purge.c
+++ b/storage/innobase/row/row0purge.c
@@ -379,7 +379,8 @@ row_purge_upd_exist_or_extern(
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;
}
@@ -488,14 +489,14 @@ row_purge_parse_undo_rec(
dulint 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)) {
@@ -508,7 +509,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 */
@@ -563,7 +565,7 @@ row_purge_parse_undo_rec(
/* 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), node->heap);
}
diff --git a/storage/innobase/row/row0row.c b/storage/innobase/row/row0row.c
index 171039e34ac..ccb3c1f7781 100644
--- a/storage/innobase/row/row0row.c
+++ b/storage/innobase/row/row0row.c
@@ -212,23 +212,27 @@ row_build(
}
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
- /* This condition can occur during crash recovery before
- trx_rollback_or_clean_all_without_sess() 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 is active. (In this version of InnoDB, we
- cannot assert that it was recovered, because there is no
- trx->is_recovered field.) */
-
- ut_a(!rec_offs_any_null_extern(rec, offsets)
- || trx_assert_active(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_or_clean_all_without_sess() 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 is active. (In this version of InnoDB, we
+ cannot assert that it was recovered, because there is no
+ trx->is_recovered field.) */
+
+ ut_a(trx_assert_active(
+ 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/row0upd.c b/storage/innobase/row/row0upd.c
index 694b00ea265..58739edfd98 100644
--- a/storage/innobase/row/row0upd.c
+++ b/storage/innobase/row/row0upd.c
@@ -1591,21 +1591,22 @@ row_upd_clust_rec(
*offsets_ = (sizeof offsets_) / sizeof *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, rec,
rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
- big_rec, mtr);
+ big_rec, mtr, mtr);
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@@ -1618,6 +1619,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);
diff --git a/storage/innobase/sync/sync0rw.c b/storage/innobase/sync/sync0rw.c
index 089e87a8a5c..05ea8ff0fe9 100644
--- a/storage/innobase/sync/sync0rw.c
+++ b/storage/innobase/sync/sync0rw.c
@@ -476,6 +476,9 @@ rw_lock_x_lock_func(
ulint i; /* spin round count */
ut_ad(rw_lock_validate(lock));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
lock_loop:
/* Acquire the mutex protecting the rw-lock fields */
@@ -732,7 +735,7 @@ rw_lock_own(
ut_ad(lock);
ut_ad(rw_lock_validate(lock));
- mutex_enter(&(lock->mutex));
+ rw_lock_debug_mutex_enter();
info = UT_LIST_GET_FIRST(lock->debug_list);
@@ -742,7 +745,7 @@ rw_lock_own(
&& (info->pass == 0)
&& (info->lock_type == lock_type)) {
- mutex_exit(&(lock->mutex));
+ rw_lock_debug_mutex_exit();
/* Found! */
return(TRUE);
@@ -750,7 +753,7 @@ rw_lock_own(
info = UT_LIST_GET_NEXT(list, info);
}
- mutex_exit(&(lock->mutex));
+ rw_lock_debug_mutex_exit();
return(FALSE);
}
@@ -830,11 +833,13 @@ rw_lock_list_print_info(
putc('\n', file);
}
+ rw_lock_debug_mutex_enter();
info = UT_LIST_GET_FIRST(lock->debug_list);
while (info != NULL) {
rw_lock_debug_print(file, info);
info = UT_LIST_GET_NEXT(list, info);
}
+ rw_lock_debug_mutex_exit();
}
mutex_exit(&(lock->mutex));
@@ -870,11 +875,13 @@ rw_lock_print(
putc('\n', stderr);
}
+ rw_lock_debug_mutex_enter();
info = UT_LIST_GET_FIRST(lock->debug_list);
while (info != NULL) {
rw_lock_debug_print(stderr, info);
info = UT_LIST_GET_NEXT(list, info);
}
+ rw_lock_debug_mutex_exit();
}
}
diff --git a/storage/innobase/trx/trx0undo.c b/storage/innobase/trx/trx0undo.c
index 329565943c8..ce09862f317 100644
--- a/storage/innobase/trx/trx0undo.c
+++ b/storage/innobase/trx/trx0undo.c
@@ -864,7 +864,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);
diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog
index f873f3a24bd..cdf8e8351a8 100644
--- a/storage/innodb_plugin/ChangeLog
+++ b/storage/innodb_plugin/ChangeLog
@@ -1,3 +1,53 @@
+2011-10-04 The InnoDB Team
+
+ * include/sync0rw.h, sync/sync0rw.c:
+ Fix Bug#13034534 RQG TESTS FAIL ON WINDOWS WITH CRASH NEAR
+ RW_LOCK_DEBUG_PRINT
+
+2011-09-20 The InnoDB Team
+
+ * row/row0purge.c:
+ Fix Bug#12963823 CRASH IN PURGE THREAD UNDER UNUSUAL CIRCUMSTANCES
+
+2011-09-12 The InnoDB Team
+
+ * row/row0sel.c:
+ Fix Bug#12601439 CONSISTENT READ FAILURE IN COLUMN PREFIX INDEX
+
+2011-09-08 The InnoDB Team
+
+ * btr/btr0cur.c, include/page0page.h, include/row0upd.ic:
+ Fix Bug#12948130 UNNECESSARY X-LOCKING OF ADAPTIVE HASH INDEX
+
+2011-09-06 The InnoDB Team
+
+ * buf/buf0buddy.c:
+ Fix Bug#12950803 62294: BUF_BUDDY_RELOCATE CALLS GETTIMEOFDAY
+ WHILE HOLDING BUFFER POOL MUTEX
+
+2011-09-06 The InnoDB Team
+
+ * include/trx0undo.h, trx/trx0rec.c, trx/trx0undo.c:
+ Fix Bug#12547647 UPDATE LOGGING COULD EXCEED LOG PAGE SIZE
+
+2011-08-29 The InnoDB Team
+
+ * btr/btr0btr.c, btr/btr0cur.c, fsp/fsp0fsp.c,
+ include/btr0btr.h, include/btr0cur.h, include/fsp0fsp.h,
+ include/mtr0mtr.h, include/mtr0mtr.ic, mtr/mtr0mtr.c,
+ row/row0ins.c, row/row0row.c, row/row0upd.c, trx/trx0undo.c:
+ Fix Bug#12704861 Corruption after a crash during BLOB update
+ and other regressions from the fix of Bug#12612184
+
+2011-08-15 The InnoDB Team
+
+ * btr/btr0btr.c, btr/btr0cur.c, btr/btr0pcur.c, btr/btr0sea.c,
+ dict/dict0crea.c, dict/dict0dict.c, ibuf/ibuf0ibuf.c,
+ include/btr0btr.h, include/btr0btr.ic, include/sync0sync.h,
+ sync/sync0sync.c:
+ Fix Bug#11766591 59733: Possible deadlock when buffered changes
+ are to be discarded in buf_page_create()
+
2011-08-08 The InnoDB Team
* row/row0sel.c:
diff --git a/storage/innodb_plugin/btr/btr0btr.c b/storage/innodb_plugin/btr/btr0btr.c
index ac188c8c2fd..71e1599d19e 100644
--- a/storage/innodb_plugin/btr/btr0btr.c
+++ b/storage/innodb_plugin/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));
}
/************************************************************//**
@@ -1311,7 +1490,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);
@@ -1348,10 +1528,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);
@@ -1359,6 +1538,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
@@ -1430,7 +1611,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));
@@ -1452,7 +1634,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));
@@ -1478,13 +1661,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);
@@ -1801,7 +1984,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);
@@ -2362,9 +2545,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)
@@ -2377,9 +2559,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)
@@ -2539,7 +2720,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,
@@ -2801,17 +2982,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;
@@ -2829,7 +3035,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
@@ -2846,7 +3052,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
@@ -3172,7 +3378,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)
@@ -3181,7 +3387,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)
@@ -3270,7 +3476,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);
@@ -3327,7 +3533,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 */
@@ -3519,7 +3725,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)
@@ -3527,7 +3733,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)
@@ -3562,7 +3768,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
@@ -4080,7 +4286,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))) {
@@ -4306,7 +4512,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/innodb_plugin/btr/btr0cur.c b/storage/innodb_plugin/btr/btr0cur.c
index f378c477537..4baa21d7c71 100644
--- a/storage/innodb_plugin/btr/btr0cur.c
+++ b/storage/innodb_plugin/btr/btr0cur.c
@@ -238,7 +238,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 */
@@ -249,9 +250,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));
@@ -261,8 +262,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 */
@@ -271,9 +273,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));
@@ -292,8 +294,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)
@@ -304,7 +307,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 */
@@ -572,7 +576,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(0 == ut_dulint_cmp(index->id,
@@ -630,8 +636,8 @@ retry_page_get:
if (level > 0) {
/* x-latch the page */
- page = btr_page_get(space, zip_size,
- page_no, RW_X_LATCH, mtr);
+ page = btr_page_get(space, zip_size, page_no,
+ RW_X_LATCH, index, mtr);
ut_a((ibool)!!page_is_comp(page)
== dict_table_is_comp(index->table));
}
@@ -1721,6 +1727,7 @@ btr_cur_update_in_place(
roll_ptr_t roll_ptr = ut_dulint_zero;
trx_t* trx;
ulint was_delete_marked;
+ ibool is_hashed;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
@@ -1762,7 +1769,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 */
@@ -1778,17 +1799,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);
}
@@ -2408,39 +2421,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 ===============*/
/****************************************************************//**
@@ -2547,7 +2527,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);
@@ -2627,9 +2608,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);
@@ -2643,10 +2624,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);
@@ -2722,7 +2699,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);
}
@@ -2770,16 +2748,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);
@@ -2799,8 +2772,11 @@ btr_cur_del_unmark_for_ibuf(
uncompressed */
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, FALSE);
@@ -3895,6 +3871,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 */
@@ -3903,9 +3882,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;
@@ -3924,6 +3905,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));
@@ -3939,6 +3923,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;
@@ -4015,7 +4018,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);
@@ -4142,11 +4145,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
@@ -4180,7 +4187,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;
@@ -4225,19 +4233,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(
@@ -4247,18 +4259,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/innodb_plugin/btr/btr0pcur.c b/storage/innodb_plugin/btr/btr0pcur.c
index e3e3e53f98e..cbb0d21a7ed 100644
--- a/storage/innodb_plugin/btr/btr0pcur.c
+++ b/storage/innodb_plugin/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/innodb_plugin/btr/btr0sea.c b/storage/innodb_plugin/btr/btr0sea.c
index cd0eadbb1b8..88442b7d4f0 100644
--- a/storage/innodb_plugin/btr/btr0sea.c
+++ b/storage/innodb_plugin/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
@@ -832,6 +832,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/innodb_plugin/buf/buf0buddy.c b/storage/innodb_plugin/buf/buf0buddy.c
index de571743361..efc4fd46e90 100644
--- a/storage/innodb_plugin/buf/buf0buddy.c
+++ b/storage/innodb_plugin/buf/buf0buddy.c
@@ -327,7 +327,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;
@@ -394,6 +393,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/innodb_plugin/buf/buf0buf.c b/storage/innodb_plugin/buf/buf0buf.c
index cd1461d22b7..47300627acc 100644
--- a/storage/innodb_plugin/buf/buf0buf.c
+++ b/storage/innodb_plugin/buf/buf0buf.c
@@ -1175,29 +1175,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_mutex_enter();
-
- block = (buf_block_t*) buf_page_hash_get(space, offset);
-
- if (block && buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE) {
- block->check_index_page_at_flush = FALSE;
- }
-
- buf_pool_mutex_exit();
-}
-
-/********************************************************************//**
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.
diff --git a/storage/innodb_plugin/dict/dict0crea.c b/storage/innodb_plugin/dict/dict0crea.c
index 7d6cbc8c1c8..a57b2eca9e2 100644
--- a/storage/innodb_plugin/dict/dict0crea.c
+++ b/storage/innodb_plugin/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
@@ -828,7 +828,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/innodb_plugin/dict/dict0dict.c b/storage/innodb_plugin/dict/dict0dict.c
index a8787bbda61..2d2262acf87 100644
--- a/storage/innodb_plugin/dict/dict0dict.c
+++ b/storage/innodb_plugin/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
@@ -1661,7 +1661,9 @@ undo_size_ok:
new_index->stat_n_leaf_pages = 1;
new_index->page = page_no;
- rw_lock_create(&new_index->lock, SYNC_INDEX_TREE);
+ rw_lock_create(&new_index->lock,
+ dict_index_is_ibuf(index)
+ ? SYNC_IBUF_INDEX_TREE : SYNC_INDEX_TREE);
if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
diff --git a/storage/innodb_plugin/fsp/fsp0fsp.c b/storage/innodb_plugin/fsp/fsp0fsp.c
index d091a14c474..19846b63d5b 100644
--- a/storage/innodb_plugin/fsp/fsp0fsp.c
+++ b/storage/innodb_plugin/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
@@ -312,8 +312,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 */
+ __attribute__((nonnull));
/**********************************************************************//**
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space
@@ -326,14 +327,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 */
/**********************************************************************//**
@@ -701,17 +708,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;
@@ -719,11 +727,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);
@@ -773,7 +779,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(
/*================*/
@@ -782,7 +788,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;
@@ -1160,14 +1166,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 __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;
@@ -1192,7 +1198,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 __attribute__((nonnull))
ibool
fsp_try_extend_data_file(
/*=====================*/
@@ -1202,8 +1208,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;
@@ -1339,7 +1345,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;
@@ -1538,9 +1544,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(
/*================*/
@@ -1548,19 +1591,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);
@@ -1642,38 +1688,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);
}
@@ -1909,7 +1936,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) {
@@ -2323,7 +2350,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) {
@@ -2572,14 +2599,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;
@@ -2590,7 +2622,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;
@@ -2612,6 +2643,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);
}
@@ -2623,15 +2656,20 @@ fseg_alloc_free_page_low(
mtr), 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
=========================================================
@@ -2649,8 +2687,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)
@@ -2710,11 +2760,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 */
@@ -2724,6 +2773,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
@@ -2771,26 +2824,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. */
@@ -2803,8 +2864,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);
}
@@ -2817,7 +2876,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
@@ -2829,7 +2888,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;
@@ -2871,7 +2934,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);
}
@@ -2880,28 +2944,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/innodb_plugin/ibuf/ibuf0ibuf.c b/storage/innodb_plugin/ibuf/ibuf0ibuf.c
index 23981ac388e..e4d8f79a944 100644
--- a/storage/innodb_plugin/ibuf/ibuf0ibuf.c
+++ b/storage/innodb_plugin/ibuf/ibuf0ibuf.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2009, 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
@@ -356,7 +356,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);
return(buf_block_get_frame(block));
}
@@ -496,7 +496,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);
}
@@ -1766,17 +1766,16 @@ ibuf_add_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_NEW);
-
+ ibuf_enter();
- page = buf_block_get_frame(block);
- }
+ mutex_enter(&ibuf_mutex);
- ibuf_enter();
+ root = ibuf_tree_root_get(&mtr);
- mutex_enter(&ibuf_mutex);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
- root = ibuf_tree_root_get(&mtr);
+ page = buf_block_get_frame(block);
+ }
/* Add the page to the free list and update the ibuf size data */
@@ -1897,8 +1896,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);
}
@@ -2408,7 +2406,7 @@ ibuf_get_volume_buffered(
block = buf_page_get(
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);
@@ -2482,7 +2480,7 @@ count_later:
block = buf_page_get(
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);
@@ -3248,6 +3246,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)) {
@@ -3403,7 +3402,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
diff --git a/storage/innodb_plugin/include/btr0btr.h b/storage/innodb_plugin/include/btr0btr.h
index 987de03b349..476ad29adac 100644
--- a/storage/innodb_plugin/include/btr0btr.h
+++ b/storage/innodb_plugin/include/btr0btr.h
@@ -188,26 +188,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.
@@ -333,8 +352,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.
@@ -539,7 +557,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. */
@@ -562,6 +585,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 */
+ __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/innodb_plugin/include/btr0btr.ic b/storage/innodb_plugin/include/btr0btr.ic
index 83eb3627abb..1837d091ccf 100644
--- a/storage/innodb_plugin/include/btr0btr.ic
+++ b/storage/innodb_plugin/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/innodb_plugin/include/btr0cur.h b/storage/innodb_plugin/include/btr0cur.h
index 6094a2a6c7a..1d97c5b9452 100644
--- a/storage/innodb_plugin/include/btr0cur.h
+++ b/storage/innodb_plugin/include/btr0cur.h
@@ -326,16 +326,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 */
- __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
@@ -540,6 +530,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 */
@@ -548,9 +540,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.
@@ -559,21 +554,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/innodb_plugin/include/buf0buf.h b/storage/innodb_plugin/include/buf0buf.h
index 9856bfce409..557bc17d311 100644
--- a/storage/innodb_plugin/include/buf0buf.h
+++ b/storage/innodb_plugin/include/buf0buf.h
@@ -372,15 +372,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/innodb_plugin/include/fsp0fsp.h b/storage/innodb_plugin/include/fsp0fsp.h
index 7abd3914eda..2221380c9a2 100644
--- a/storage/innodb_plugin/include/fsp0fsp.h
+++ b/storage/innodb_plugin/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/innodb_plugin/include/mtr0mtr.h b/storage/innodb_plugin/include/mtr0mtr.h
index 8a9ec8ea7f0..3529519e7f4 100644
--- a/storage/innodb_plugin/include/mtr0mtr.h
+++ b/storage/innodb_plugin/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
@@ -377,9 +379,12 @@ struct mtr_struct{
#endif
dyn_array_t memo; /*!< memo stack for locks etc. */
dyn_array_t log; /*!< mini-transaction log */
- 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/innodb_plugin/include/mtr0mtr.ic b/storage/innodb_plugin/include/mtr0mtr.ic
index 18f8e87b3cf..9c0ddff9132 100644
--- a/storage/innodb_plugin/include/mtr0mtr.ic
+++ b/storage/innodb_plugin/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
@@ -44,6 +44,7 @@ mtr_start(
mtr->log_mode = MTR_LOG_ALL;
mtr->modifications = FALSE;
+ mtr->freed_clust_leaf = FALSE;
mtr->n_log_recs = 0;
ut_d(mtr->state = MTR_ACTIVE);
@@ -67,7 +68,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/innodb_plugin/include/page0page.h b/storage/innodb_plugin/include/page0page.h
index 9099fd7b65d..caf4cee2c57 100644
--- a/storage/innodb_plugin/include/page0page.h
+++ b/storage/innodb_plugin/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; a dulint; 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/innodb_plugin/include/row0upd.ic b/storage/innodb_plugin/include/row0upd.ic
index 0894ed373b0..11db82f64da 100644
--- a/storage/innodb_plugin/include/row0upd.ic
+++ b/storage/innodb_plugin/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/innodb_plugin/include/sync0rw.h b/storage/innodb_plugin/include/sync0rw.h
index 47f7dbfe0eb..40be1396a4c 100644
--- a/storage/innodb_plugin/include/sync0rw.h
+++ b/storage/innodb_plugin/include/sync0rw.h
@@ -564,7 +564,8 @@ struct rw_lock_struct {
};
#ifdef UNIV_SYNC_DEBUG
-/** The structure for storing debug info of an rw-lock */
+/** The structure for storing debug info of an rw-lock. All access to this
+structure must be protected by rw_lock_debug_mutex_enter(). */
struct rw_lock_debug_struct {
os_thread_id_t thread_id; /*!< The thread id of the thread which
diff --git a/storage/innodb_plugin/include/sync0rw.ic b/storage/innodb_plugin/include/sync0rw.ic
index 485a63a1b18..5eb3d017eca 100644
--- a/storage/innodb_plugin/include/sync0rw.ic
+++ b/storage/innodb_plugin/include/sync0rw.ic
@@ -406,6 +406,7 @@ rw_lock_s_lock_func(
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */
+ ut_ad(!rw_lock_own(lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
/* TODO: study performance of UNIV_LIKELY branch prediction hints. */
diff --git a/storage/innodb_plugin/include/sync0sync.h b/storage/innodb_plugin/include/sync0sync.h
index d9dcf91accb..f2013c202c1 100644
--- a/storage/innodb_plugin/include/sync0sync.h
+++ b/storage/innodb_plugin/include/sync0sync.h
@@ -448,10 +448,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
@@ -468,8 +464,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 */
diff --git a/storage/innodb_plugin/include/trx0undo.h b/storage/innodb_plugin/include/trx0undo.h
index 4f15cd85833..c95f99d6417 100644
--- a/storage/innodb_plugin/include/trx0undo.h
+++ b/storage/innodb_plugin/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/innodb_plugin/mtr/mtr0mtr.c b/storage/innodb_plugin/mtr/mtr0mtr.c
index 5fad61b2922..e3fefbedec7 100644
--- a/storage/innodb_plugin/mtr/mtr0mtr.c
+++ b/storage/innodb_plugin/mtr/mtr0mtr.c
@@ -58,12 +58,11 @@ mtr_memo_slot_release(
buf_page_release((buf_block_t*)object, type, mtr);
} 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/innodb_plugin/row/row0ins.c b/storage/innodb_plugin/row/row0ins.c
index ea43cbfb5f1..0f158cdc706 100644
--- a/storage/innodb_plugin/row/row0ins.c
+++ b/storage/innodb_plugin/row/row0ins.c
@@ -2094,15 +2094,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(
@@ -2111,7 +2116,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
@@ -2124,6 +2130,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 {
@@ -2165,7 +2174,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) {
diff --git a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c
index c4911400cee..4e6a49cf8b0 100644
--- a/storage/innodb_plugin/row/row0mysql.c
+++ b/storage/innodb_plugin/row/row0mysql.c
@@ -3221,6 +3221,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"
@@ -3243,13 +3256,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"
@@ -3259,12 +3268,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"
@@ -3275,6 +3283,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/innodb_plugin/row/row0purge.c b/storage/innodb_plugin/row/row0purge.c
index 752a2ec9e83..4d4c1afc458 100644
--- a/storage/innodb_plugin/row/row0purge.c
+++ b/storage/innodb_plugin/row/row0purge.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2009, 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
*****************************************************************************/
@@ -406,7 +406,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;
}
@@ -530,14 +531,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)) {
@@ -550,7 +551,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 */
@@ -600,7 +602,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/innodb_plugin/row/row0row.c b/storage/innodb_plugin/row/row0row.c
index 9cdbbe76e04..e476ffae84e 100644
--- a/storage/innodb_plugin/row/row0row.c
+++ b/storage/innodb_plugin/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/innodb_plugin/row/row0sel.c b/storage/innodb_plugin/row/row0sel.c
index 241584eaa20..32f21dbe198 100644
--- a/storage/innodb_plugin/row/row0sel.c
+++ b/storage/innodb_plugin/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
@@ -101,12 +101,17 @@ 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 */
ulint zip_size) /*!< in: compressed page size, or 0 */
{
ulint len;
byte buf[DICT_MAX_INDEX_COL_LEN];
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 +123,7 @@ row_sel_sec_rec_is_for_blob(
return(FALSE);
}
- len = btr_copy_externally_stored_field_prefix(buf, sizeof buf,
+ len = btr_copy_externally_stored_field_prefix(buf, prefix_len,
zip_size,
clust_field, clust_len);
@@ -132,7 +137,7 @@ row_sel_sec_rec_is_for_blob(
}
len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen,
- sec_len, len, (const char*) buf);
+ prefix_len, len, (const char*) buf);
return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
}
@@ -219,11 +224,20 @@ row_sel_sec_rec_is_for_clust_rec(
if (rec_offs_nth_extern(clust_offs, clust_pos)
&& len < sec_len) {
+ /* 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(clust_index->table)
+ >= DICT_TF_FORMAT_ZIP);
+
if (!row_sel_sec_rec_is_for_blob(
col->mtype, col->prtype,
col->mbminlen, col->mbmaxlen,
clust_field, clust_len,
sec_field, sec_len,
+ ifield->prefix_len,
dict_table_zip_size(
clust_index->table))) {
goto inequal;
@@ -494,7 +508,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;
}
}
@@ -519,6 +533,8 @@ sel_col_prefetch_buf_free(
mem_free(sel_buf->data);
}
}
+
+ mem_free(prefetch_buf);
}
/*********************************************************************//**
diff --git a/storage/innodb_plugin/row/row0upd.c b/storage/innodb_plugin/row/row0upd.c
index b5952ff0a78..05856687015 100644
--- a/storage/innodb_plugin/row/row0upd.c
+++ b/storage/innodb_plugin/row/row0upd.c
@@ -1978,21 +1978,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
@@ -2002,6 +2003,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);
diff --git a/storage/innodb_plugin/sync/sync0rw.c b/storage/innodb_plugin/sync/sync0rw.c
index 3df2b4e9bbd..bc060319246 100644
--- a/storage/innodb_plugin/sync/sync0rw.c
+++ b/storage/innodb_plugin/sync/sync0rw.c
@@ -612,6 +612,9 @@ rw_lock_x_lock_func(
ibool spinning = FALSE;
ut_ad(rw_lock_validate(lock));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
i = 0;
@@ -928,11 +931,13 @@ rw_lock_list_print_info(
putc('\n', file);
}
+ rw_lock_debug_mutex_enter();
info = UT_LIST_GET_FIRST(lock->debug_list);
while (info != NULL) {
rw_lock_debug_print(file, info);
info = UT_LIST_GET_NEXT(list, info);
}
+ rw_lock_debug_mutex_exit();
}
#ifndef INNODB_RW_LOCKS_USE_ATOMICS
mutex_exit(&(lock->mutex));
@@ -976,11 +981,13 @@ rw_lock_print(
putc('\n', stderr);
}
+ rw_lock_debug_mutex_enter();
info = UT_LIST_GET_FIRST(lock->debug_list);
while (info != NULL) {
rw_lock_debug_print(stderr, info);
info = UT_LIST_GET_NEXT(list, info);
}
+ rw_lock_debug_mutex_exit();
}
}
diff --git a/storage/innodb_plugin/sync/sync0sync.c b/storage/innodb_plugin/sync/sync0sync.c
index 59498386fda..3640e204525 100644
--- a/storage/innodb_plugin/sync/sync0sync.c
+++ b/storage/innodb_plugin/sync/sync0sync.c
@@ -1173,6 +1173,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)"
@@ -1236,22 +1237,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/innodb_plugin/trx/trx0rec.c b/storage/innodb_plugin/trx/trx0rec.c
index 9f2fd59d82b..2db98e029df 100644
--- a/storage/innodb_plugin/trx/trx0rec.c
+++ b/storage/innodb_plugin/trx/trx0rec.c
@@ -1097,13 +1097,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;
@@ -1113,6 +1114,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);
}
/***********************************************************//**
@@ -1180,6 +1182,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));
@@ -1242,7 +1247,7 @@ trx_undo_report_row_operation(
mtr_start(&mtr);
- for (;;) {
+ do {
buf_block_t* undo_block;
page_t* undo_page;
ulint offset;
@@ -1271,7 +1276,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_TOO_BIG_RECORD;
+ goto err_exit;
+ }
+
mtr_commit(&mtr);
} else {
/* Success */
@@ -1291,16 +1320,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
@@ -1312,18 +1340,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/innodb_plugin/trx/trx0undo.c b/storage/innodb_plugin/trx/trx0undo.c
index 7f03b68fb55..c36f55fbd9c 100644
--- a/storage/innodb_plugin/trx/trx0undo.c
+++ b/storage/innodb_plugin/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
@@ -912,7 +912,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);
@@ -998,29 +998,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--;
}
@@ -1056,9 +1055,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 */
@@ -1084,18 +1085,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 (ut_dulint_cmp(trx_undo_rec_get_undo_no(rec), limit)
>= 0) {
/* Truncate at least this record off, maybe
@@ -1110,6 +1100,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/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c
index fb1a03a2bd6..ac5da800ae3 100644
--- a/storage/myisam/ft_boolean_search.c
+++ b/storage/myisam/ft_boolean_search.c
@@ -361,7 +361,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 cd2c7f61a66..567b1044995 100644
--- a/storage/myisam/ft_nlq_search.c
+++ b/storage/myisam/ft_nlq_search.c
@@ -74,7 +74,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 3bbd2fb0469..4a0c2da5559 100644
--- a/storage/myisam/mi_check.c
+++ b/storage/myisam/mi_check.c
@@ -3913,7 +3913,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)
@@ -3923,7 +3923,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 70487f397f1..81262c229ce 100644
--- a/storage/myisam/mi_write.c
+++ b/storage/myisam/mi_write.c
@@ -528,7 +528,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 43957c7dc19..6c89657004c 100644
--- a/strings/decimal.c
+++ b/strings/decimal.c
@@ -1423,11 +1423,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/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index 006dea45e64..ee0211fd3e0 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -170,9 +170,11 @@ documentation and the manual for more information.
%package server
Summary: MySQL: a very fast and reliable SQL database server
Group: Applications/Databases
-Requires: coreutils grep procps /usr/sbin/useradd /usr/sbin/groupadd /sbin/chkconfig
-Provides: msqlormysql mysql-server mysql MySQL
-Obsoletes: MySQL mysql mysql-server
+Requires: coreutils grep procps /usr/sbin/useradd /usr/sbin/groupadd /sbin/chkconfig
+Provides: msqlormysql mysql MySQL mysql-server MySQL-server
+Obsoletes: mysql MySQL mysql-server MySQL-server
+Obsoletes: MySQL-server-classic MySQL-server-community MySQL-server-enterprise
+Obsoletes: MySQL-server-advanced MySQL-server-advanced-gpl MySQL-server-enterprise-gpl
%description server
The MySQL(TM) software delivers a very fast, multi-threaded, multi-user,
@@ -202,10 +204,12 @@ package "MySQL-client" as well!
# ------------------------------------------------------------------------------
%package client
-Summary: MySQL - Client
-Group: Applications/Databases
-Obsoletes: mysql-client
-Provides: mysql-client
+Summary: MySQL - Client
+Group: Applications/Databases
+Provides: mysql-client MySQL-client
+Obsoletes: mysql-client MySQL-client
+Obsoletes: MySQL-client-classic MySQL-client-community MySQL-client-enterprise
+Obsoletes: MySQL-client-advanced MySQL-client-advanced-gpl MySQL-client-enterprise-gpl
%description client
This package contains the standard MySQL clients and administration tools.
@@ -266,11 +270,14 @@ They should be used with caution.
# ------------------------------------------------------------------------------
%package test
-Requires: %{name}-client perl
-Summary: MySQL - Test suite
-Group: Applications/Databases
-Provides: mysql-test
-Obsoletes: mysql-bench mysql-test
+Summary: MySQL - Test suite
+Group: Applications/Databases
+Requires: %{name}-client perl
+Provides: mysql-test MySQL-test
+Obsoletes: mysql-test MySQL-test
+Obsoletes: mysql-bench MySQL-bench
+Obsoletes: MySQL-test-classic MySQL-test-community MySQL-test-enterprise
+Obsoletes: MySQL-test-advanced MySQL-test-advanced-gpl MySQL-test-enterprise-gpl
AutoReqProv: no
%description test
@@ -281,10 +288,12 @@ This package contains the MySQL regression test suite.
# ------------------------------------------------------------------------------
%package devel
-Summary: MySQL - Development header files and libraries
-Group: Applications/Databases
-Provides: mysql-devel
-Obsoletes: mysql-devel
+Summary: MySQL - Development header files and libraries
+Group: Applications/Databases
+Provides: mysql-devel MySQL-devel
+Obsoletes: mysql-devel MySQL-devel
+Obsoletes: MySQL-devel-classic MySQL-devel-community MySQL-devel-enterprise
+Obsoletes: MySQL-devel-advanced MySQL-devel-advanced-gpl MySQL-devel-enterprise-gpl
%description devel
This package contains the development header files and libraries
@@ -295,8 +304,14 @@ necessary to develop MySQL client applications.
# ------------------------------------------------------------------------------
%package shared
-Summary: MySQL - Shared libraries
-Group: Applications/Databases
+Summary: MySQL - Shared libraries
+Group: Applications/Databases
+Provides: mysql-shared MySQL-shared
+Obsoletes: mysql-shared MySQL-shared-standard MySQL-shared-pro
+Obsoletes: MySQL-shared-pro-cert MySQL-shared-pro-gpl
+Obsoletes: MySQL-shared-pro-gpl-cert MySQL-shared
+Obsoletes: MySQL-shared-classic MySQL-shared-community MySQL-shared-enterprise
+Obsoletes: MySQL-shared-advanced MySQL-shared-advanced-gpl MySQL-shared-enterprise-gpl
%description shared
This package contains the shared libraries (*.so*) which certain
@@ -307,10 +322,14 @@ languages and applications need to dynamically load and use MySQL.
%if %{EMBEDDED_BUILD}
%package embedded
-Requires: %{name}-devel
-Summary: MySQL - embedded library
-Group: Applications/Databases
-Obsoletes: mysql-embedded
+Summary: MySQL - Embedded library
+Group: Applications/Databases
+Requires: %{name}-devel
+Provides: mysql-embedded MySQL-embedded
+Obsoletes: mysql-embedded MySQL-embedded
+Obsoletes: MySQL-embedded-pro
+Obsoletes: MySQL-embedded-classic MySQL-embedded-community MySQL-embedded-enterprise
+Obsoletes: MySQL-embedded-advanced MySQL-embedded-advanced-gpl MySQL-embedded-enterprise-gpl
%description embedded
This package contains the MySQL server as an embedded library.
@@ -382,7 +401,7 @@ sh -c "PATH=\"${MYSQL_BUILD_PATH:-$PATH}\" \
--enable-local-infile \
--with-fast-mutexes \
--with-mysqld-user=%{mysqld_user} \
- --with-unix-socket-path=/var/lib/mysql/mysql.sock \
+ --with-unix-socket-path=%{mysqldatadir}/mysql.sock \
--with-pic \
--prefix=/ \
%if %{CLUSTER_BUILD}
@@ -858,6 +877,13 @@ chown -R %{mysqld_user}:%{mysqld_group} $mysql_datadir
# ----------------------------------------------------------------------
chmod -R og-rw $mysql_datadir/mysql
+# ----------------------------------------------------------------------
+# Deal with SELinux, if it is installed / used
+# ----------------------------------------------------------------------
+if [ -x /sbin/restorecon ] ; then
+ /sbin/restorecon -R %{mysqldatadir}
+fi
+
# Was the server running before the upgrade? If so, restart the new one.
if [ "$SERVER_TO_START" = "true" ] ; then
# Restart in the same way that mysqld will be started normally.
@@ -1165,6 +1191,25 @@ fi
# merging BK trees)
##############################################################################
%changelog
+* Wed Sep 14 2011 Joerg Bruehe <joerg.bruehe@oracle.com>
+
+- Let the RPM capabilities ("obsoletes" etc) ensure that an upgrade may replace
+ the RPMs of any configuration (of the current or the preceding release series)
+ by the new ones. This is done by not using the implicitly generated capabilities
+ (which include the configuration name) and relying on more generic ones which
+ just list the function ("server", "client", ...).
+ The implicit generation cannot be prevented, so all these capabilities must be
+ explicitly listed in "Obsoletes:"
+
+* Fri Aug 19 2011 Joerg Bruehe <joerg.bruehe@oracle.com>
+
+- Fix bug#37165 "((Generic rpm)) fail to install on Fedora 9 x86_64"
+ On Fedora, certain accesses to "/var/lib/mysql/HOSTNAME.err" were blocked
+ by SELinux policy, this made the server start fail with the message
+ Manager of pid-file quit without updating file
+ Calling "/sbin/restorecon -R /var/lib/mysql" fixes this.
+- Replace occurrences of that path name by the spec file variable %{mysqldatadir}.
+
* Thu Jul 07 2011 Joerg Bruehe <joerg.bruehe@oracle.com>
- Fix bug#45415: "rpm upgrade recreates test database"