summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README2
-rw-r--r--client/my_readline.h4
-rw-r--r--client/mysql.cc18
-rw-r--r--client/readline.cc43
-rw-r--r--include/my_pthread.h2
-rw-r--r--include/my_sys.h2
-rwxr-xr-xmysql-test/collections/default.weekly1
-rw-r--r--mysql-test/collections/mysql-5.1-bugteam.daily5
-rw-r--r--mysql-test/collections/mysql-5.1-bugteam.push4
-rw-r--r--mysql-test/include/mysqlhotcopy.inc2
-rw-r--r--mysql-test/include/rpl_sync.inc2
-rwxr-xr-xmysql-test/mysql-test-run.pl28
-rw-r--r--mysql-test/r/grant.result74
-rw-r--r--mysql-test/r/not_embedded_server.result4
-rw-r--r--mysql-test/r/order_by.result25
-rw-r--r--mysql-test/r/type_year.result14
-rw-r--r--mysql-test/r/user_var.result6
-rw-r--r--mysql-test/suite/binlog/r/binlog_unsafe.result2
-rw-r--r--mysql-test/suite/binlog/t/binlog_unsafe.test2
-rw-r--r--mysql-test/suite/engines/funcs/r/ps_string_not_null.resultbin11681 -> 11681 bytes
-rw-r--r--mysql-test/suite/engines/funcs/t/ps_string_not_null.test2
-rw-r--r--mysql-test/suite/innodb_plugin/r/innodb-autoinc-56228.result30
-rw-r--r--mysql-test/suite/innodb_plugin/t/innodb-autoinc-56228-master.opt1
-rw-r--r--mysql-test/suite/innodb_plugin/t/innodb-autoinc-56228.test42
-rw-r--r--mysql-test/suite/rpl/r/rpl_circular_for_4_hosts.result4
-rw-r--r--mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test4
-rw-r--r--mysql-test/suite/sys_vars/r/secure_file_priv2.result6
-rw-r--r--mysql-test/suite/sys_vars/t/secure_file_priv2-master.opt1
-rw-r--r--mysql-test/suite/sys_vars/t/secure_file_priv2.test23
-rw-r--r--mysql-test/t/grant.test101
-rw-r--r--mysql-test/t/mysql.test6
-rw-r--r--mysql-test/t/not_embedded_server.test10
-rw-r--r--mysql-test/t/order_by.test17
-rw-r--r--mysql-test/t/type_year.test10
-rw-r--r--mysql-test/t/user_var.test12
-rw-r--r--mysql-test/valgrind.supp47
-rw-r--r--mysys/my_fopen.c2
-rw-r--r--mysys/my_getsystime.c2
-rw-r--r--regex/my_regex.h4
-rw-r--r--regex/regcomp.c15
-rw-r--r--regex/reginit.c6
-rw-r--r--sql/handler.cc2
-rw-r--r--sql/item.h13
-rw-r--r--sql/item_cmpfunc.cc11
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/item_geofunc.h2
-rw-r--r--sql/log.cc2
-rw-r--r--sql/mysqld.cc19
-rw-r--r--sql/net_serv.cc2
-rw-r--r--sql/sql_base.cc14
-rw-r--r--sql/sql_load.cc85
-rw-r--r--sql/sql_select.cc225
-rw-r--r--sql/sql_show.cc2
-rw-r--r--sql/sql_view.cc2
-rw-r--r--storage/innodb_plugin/ChangeLog17
-rw-r--r--storage/innodb_plugin/btr/btr0cur.c156
-rw-r--r--storage/innodb_plugin/buf/buf0buf.c30
-rw-r--r--storage/innodb_plugin/dict/dict0dict.c10
-rw-r--r--storage/innodb_plugin/fsp/fsp0fsp.c8
-rw-r--r--storage/innodb_plugin/handler/ha_innodb.cc10
-rw-r--r--storage/innodb_plugin/handler/i_s.cc11
-rw-r--r--storage/innodb_plugin/ibuf/ibuf0ibuf.c8
-rw-r--r--storage/innodb_plugin/include/btr0cur.h42
-rw-r--r--storage/innodb_plugin/include/buf0buf.h8
-rw-r--r--storage/innodb_plugin/include/row0upd.h26
-rw-r--r--storage/innodb_plugin/include/univ.i19
-rw-r--r--storage/innodb_plugin/include/ut0vec.h19
-rw-r--r--storage/innodb_plugin/include/ut0vec.ic29
-rw-r--r--storage/innodb_plugin/lock/lock0lock.c78
-rw-r--r--storage/innodb_plugin/row/row0ins.c2
-rw-r--r--storage/innodb_plugin/row/row0merge.c4
-rw-r--r--storage/innodb_plugin/row/row0purge.c68
-rw-r--r--storage/innodb_plugin/row/row0umod.c35
-rw-r--r--storage/innodb_plugin/row/row0upd.c43
-rw-r--r--storage/innodb_plugin/trx/trx0roll.c4
75 files changed, 1199 insertions, 394 deletions
diff --git a/README b/README
index 5463de4a7e8..48948352e12 100644
--- a/README
+++ b/README
@@ -5,7 +5,7 @@ For the avoidance of doubt, this particular copy of the software
is released under the version 2 of the GNU General Public License.
MySQL is brought to you by the MySQL team at Oracle.
-Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
License information can be found in the COPYING file.
diff --git a/client/my_readline.h b/client/my_readline.h
index 62ad19bece9..3376fc81761 100644
--- a/client/my_readline.h
+++ b/client/my_readline.h
@@ -25,9 +25,11 @@ typedef struct st_line_buffer
uint eof;
ulong max_size;
ulong read_length; /* Length of last read string */
+ int error;
+ bool truncated;
} LINE_BUFFER;
extern LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file);
extern LINE_BUFFER *batch_readline_command(LINE_BUFFER *buffer, char * str);
-extern char *batch_readline(LINE_BUFFER *buffer, bool *truncated);
+extern char *batch_readline(LINE_BUFFER *buffer);
extern void batch_readline_end(LINE_BUFFER *buffer);
diff --git a/client/mysql.cc b/client/mysql.cc
index dafe76a2401..e7e7b244a49 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1131,6 +1131,8 @@ int main(int argc,char *argv[])
if (status.batch && !status.line_buff &&
!(status.line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, stdin)))
{
+ put_info("Can't initialize batch_readline - may be the input source is "
+ "a directory or a block device.", INFO_ERROR, 0);
free_defaults(defaults_argv);
my_end(0);
exit(1);
@@ -1872,14 +1874,13 @@ static int read_and_execute(bool interactive)
ulong line_number=0;
bool ml_comment= 0;
COMMANDS *com;
- bool truncated= 0;
status.exit_status=1;
-
+
for (;;)
{
if (!interactive)
{
- line=batch_readline(status.line_buff, &truncated);
+ line=batch_readline(status.line_buff);
/*
Skip UTF8 Byte Order Marker (BOM) 0xEFBBBF.
Editors like "notepad" put this marker in
@@ -1953,9 +1954,13 @@ static int read_and_execute(bool interactive)
if (opt_outfile && line)
fprintf(OUTFILE, "%s\n", line);
}
- if (!line) // End of file
+ // End of file or system error
+ if (!line)
{
- status.exit_status=0;
+ if (status.line_buff && status.line_buff->error)
+ status.exit_status= 1;
+ else
+ status.exit_status= 0;
break;
}
@@ -1976,7 +1981,8 @@ static int read_and_execute(bool interactive)
#endif
continue;
}
- if (add_line(glob_buffer,line,&in_string,&ml_comment, truncated))
+ if (add_line(glob_buffer, line, &in_string, &ml_comment,
+ status.line_buff ? status.line_buff->truncated : 0))
break;
}
/* if in batch mode, send last query even if it doesn't end with \g or go */
diff --git a/client/readline.cc b/client/readline.cc
index b32cb71b0de..fb8cde577b5 100644
--- a/client/readline.cc
+++ b/client/readline.cc
@@ -18,18 +18,28 @@
#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>
+#include <my_dir.h>
#include "my_readline.h"
static bool init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,
ulong max_size);
static bool init_line_buffer_from_string(LINE_BUFFER *buffer,char * str);
static size_t fill_buffer(LINE_BUFFER *buffer);
-static char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length, bool *truncated);
+static char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length);
LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
{
LINE_BUFFER *line_buff;
+ MY_STAT input_file_stat;
+
+#ifndef __WIN__
+ if (my_fstat(fileno(file), &input_file_stat, MYF(MY_WME)) ||
+ MY_S_ISDIR(input_file_stat.st_mode) ||
+ MY_S_ISBLK(input_file_stat.st_mode))
+ return 0;
+#endif
+
if (!(line_buff=(LINE_BUFFER*)
my_malloc(sizeof(*line_buff),MYF(MY_WME | MY_ZEROFILL))))
return 0;
@@ -42,13 +52,12 @@ LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
}
-char *batch_readline(LINE_BUFFER *line_buff, bool *truncated)
+char *batch_readline(LINE_BUFFER *line_buff)
{
char *pos;
ulong out_length;
- DBUG_ASSERT(truncated != NULL);
- if (!(pos=intern_read_line(line_buff,&out_length, truncated)))
+ if (!(pos=intern_read_line(line_buff, &out_length)))
return 0;
if (out_length && pos[out_length-1] == '\n')
if (--out_length && pos[out_length-1] == '\r') /* Remove '\n' */
@@ -162,7 +171,10 @@ static size_t fill_buffer(LINE_BUFFER *buffer)
if (!(buffer->buffer = (char*) my_realloc(buffer->buffer,
buffer->bufread+1,
MYF(MY_WME | MY_FAE))))
- return (uint) -1;
+ {
+ buffer->error= my_errno;
+ return (size_t) -1;
+ }
buffer->start_of_line=buffer->buffer+start_offset;
buffer->end=buffer->buffer+bufbytes;
}
@@ -177,7 +189,10 @@ static size_t fill_buffer(LINE_BUFFER *buffer)
/* Read in new stuff. */
if ((read_count= my_read(buffer->file, (uchar*) buffer->end, read_count,
MYF(MY_WME))) == MY_FILE_ERROR)
+ {
+ buffer->error= my_errno;
return (size_t) -1;
+ }
DBUG_PRINT("fill_buff", ("Got %lu bytes", (ulong) read_count));
@@ -198,8 +213,7 @@ static size_t fill_buffer(LINE_BUFFER *buffer)
}
-
-char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length, bool *truncated)
+char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length)
{
char *pos;
size_t length;
@@ -214,22 +228,25 @@ char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length, bool *truncated)
if (pos == buffer->end)
{
/*
- fill_buffer() can return 0 either on EOF in which case we abort
- or when the internal buffer has hit the size limit. In the latter case
- return what we have read so far and signal string truncation.
+ fill_buffer() can return NULL on EOF (in which case we abort),
+ on error, or when the internal buffer has hit the size limit.
+ In the latter case return what we have read so far and signal
+ string truncation.
*/
- if (!(length=fill_buffer(buffer)) || length == (uint) -1)
+ if (!(length= fill_buffer(buffer)))
{
if (buffer->eof)
DBUG_RETURN(0);
}
+ else if (length == (size_t) -1)
+ DBUG_RETURN(NULL);
else
continue;
pos--; /* break line here */
- *truncated= 1;
+ buffer->truncated= 1;
}
else
- *truncated= 0;
+ buffer->truncated= 0;
buffer->end_of_line=pos+1;
*out_length=(ulong) (pos + 1 - buffer->eof - buffer->start_of_line);
DBUG_RETURN(buffer->start_of_line);
diff --git a/include/my_pthread.h b/include/my_pthread.h
index 3880511da2d..87cdaaad0dd 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/include/my_sys.h b/include/my_sys.h
index 0ac220cec31..f6cd9dada99 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/mysql-test/collections/default.weekly b/mysql-test/collections/default.weekly
index f10bc0776a0..a2765bcaf0c 100755
--- a/mysql-test/collections/default.weekly
+++ b/mysql-test/collections/default.weekly
@@ -1,4 +1,3 @@
-perl mysql-test-run.pl --timer --force --comment=1st --experimental=collections/default.experimental 1st
perl mysql-test-run.pl --timer --force --comment=big-tests --experimental=collections/default.experimental --vardir=var-big-tests --big-test --testcase-timeout=60 --suite-timeout=600 parts.partition_alter1_2_ndb parts.part_supported_sql_func_innodb parts.partition_alter1_2_innodb parts.partition_alter4_innodb parts.partition_alter1_1_2_ndb parts.partition_alter1_1_2_innodb parts.partition_alter1_1_ndb rpl_ndb.rpl_truncate_7ndb_2 main.archive-big main.sum_distinct-big main.mysqlbinlog_row_big main.alter_table-big main.variables-big main.type_newdecimal-big main.read_many_rows_innodb main.log_tables-big main.count_distinct3 main.events_time_zone main.merge-big main.create-big main.events_stress main.ssl-big funcs_1.myisam_views-big
perl mysql-test-run.pl --timer --force --parallel=auto --comment=eits-tests-myisam-engine --experimental=collections/default.experimental --vardir=var-stmt-eits-tests-myisam-engine --suite=engines/iuds,engines/funcs --suite-timeout=500 --max-test-fail=0 --retry-failure=0 --mysqld=--default-storage-engine=myisam
perl mysql-test-run.pl --timer --force --parallel=auto --comment=eits-rpl-binlog-row-tests-myisam-engine --experimental=collections/default.experimental --vardir=var-binlog-row-eits-tests-myisam-engine --suite=engines/iuds,engines/funcs --suite-timeout=500 --max-test-fail=0 --retry-failure=0 --mysqld=--default-storage-engine=myisam --do-test=rpl --mysqld=--binlog-format=row
diff --git a/mysql-test/collections/mysql-5.1-bugteam.daily b/mysql-test/collections/mysql-5.1-bugteam.daily
deleted file mode 100644
index 0503bd49f73..00000000000
--- a/mysql-test/collections/mysql-5.1-bugteam.daily
+++ /dev/null
@@ -1,5 +0,0 @@
-perl mysql-test-run.pl --timer --force --parallel=auto --comment=n_mix --vardir=var-n_mix --mysqld=--binlog-format=mixed --experimental=collections/default.experimental
-perl mysql-test-run.pl --timer --force --parallel=auto --comment=ps_row --vardir=var-ps_row --ps-protocol --mysqld=--binlog-format=row --experimental=collections/default.experimental
-perl mysql-test-run.pl --timer --force --parallel=auto --comment=embedded --vardir=var-emebbed --embedded --experimental=collections/default.experimental
-perl mysql-test-run.pl --timer --force --parallel=auto --comment=rpl_binlog_row --vardir=var-rpl_binlog_row --suite=rpl,binlog --mysqld=--binlog-format=row --experimental=collections/default.experimental
-perl mysql-test-run.pl --timer --force --parallel=auto --comment=funcs_1 --vardir=var-funcs_1 --suite=funcs_1 --experimental=collections/default.experimental
diff --git a/mysql-test/collections/mysql-5.1-bugteam.push b/mysql-test/collections/mysql-5.1-bugteam.push
deleted file mode 100644
index d01b98eb87f..00000000000
--- a/mysql-test/collections/mysql-5.1-bugteam.push
+++ /dev/null
@@ -1,4 +0,0 @@
-perl mysql-test-run.pl --timer --force --parallel=auto --comment=n_mix --vardir=var-n_mix --mysqld=--binlog-format=mixed --experimental=collections/default.experimental --skip-ndb
-perl mysql-test-run.pl --timer --force --parallel=auto --comment=ps_row --vardir=var-ps_row --suite=main --ps-protocol --mysqld=--binlog-format=row --experimental=collections/default.experimental --skip-ndb
-perl mysql-test-run.pl --timer --force --parallel=auto --comment=embedded --vardir=var-emebbed --suite=main --embedded --experimental=collections/default.experimental --skip-ndb
-perl mysql-test-run.pl --timer --force --parallel=auto --comment=funcs_1 --vardir=var-funcs_1 --suite=funcs_1 --experimental=collections/default.experimental --skip-ndb
diff --git a/mysql-test/include/mysqlhotcopy.inc b/mysql-test/include/mysqlhotcopy.inc
index 110b0769ae1..fcf57a68644 100644
--- a/mysql-test/include/mysqlhotcopy.inc
+++ b/mysql-test/include/mysqlhotcopy.inc
@@ -107,7 +107,7 @@ DROP DATABASE hotcopy_save;
--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
--list_files $MYSQLD_DATADIR/hotcopy_save
--replace_result $MASTER_MYSOCK MASTER_MYSOCK
---error 9,2304
+--error 9,11,2304
--exec $MYSQLHOTCOPY --quiet -S $MASTER_MYSOCK -u root hotcopy_test hotcopy_save
--replace_result $MASTER_MYSOCK MASTER_MYSOCK
--exec $MYSQLHOTCOPY --quiet --allowold -S $MASTER_MYSOCK -u root hotcopy_test hotcopy_save
diff --git a/mysql-test/include/rpl_sync.inc b/mysql-test/include/rpl_sync.inc
index a05bee23981..be2904528ff 100644
--- a/mysql-test/include/rpl_sync.inc
+++ b/mysql-test/include/rpl_sync.inc
@@ -88,7 +88,7 @@ while ($_rpl_i) {
{
--echo Sync IO: $_rpl_slave_io_running; Sync SQL: $_rpl_slave_sql_running
}
- --let $_rpl_slave_io_running= `SELECT IF('$_rpl_slave_io_running' = 'Yes', 1, '')`
+ --let $_rpl_slave_io_running= `SELECT IF('$_rpl_slave_io_running' != 'No', 1, '')`
--let $_rpl_slave_sql_running= `SELECT IF('$_rpl_slave_sql_running' = 'Yes', 1, '')`
if ($_rpl_slave_io_running)
{
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 03dd3e5bd3f..2301b2444d3 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -182,6 +182,7 @@ my $opt_cursor_protocol;
my $opt_view_protocol;
our $opt_debug;
+our $opt_debug_server;
our @opt_cases; # The test cases names in argv
our $opt_embedded_server;
@@ -936,6 +937,7 @@ sub command_line_setup {
# Debugging
'debug' => \$opt_debug,
+ 'debug-server' => \$opt_debug_server,
'gdb' => \$opt_gdb,
'client-gdb' => \$opt_client_gdb,
'manual-gdb' => \$opt_manual_gdb,
@@ -1082,6 +1084,9 @@ sub command_line_setup {
my $path_share= dirname($path_language);
$path_charsetsdir= mtr_path_exists("$path_share/charsets");
+ # --debug implies we run debug server
+ $opt_debug_server= 1 if $opt_debug;
+
if (using_extern())
{
# Connect to the running mysqld and find out what it supports
@@ -1712,7 +1717,7 @@ sub find_mysqld {
my @mysqld_names= ("mysqld", "mysqld-max-nt", "mysqld-max",
"mysqld-nt");
- if ( $opt_debug ){
+ if ( $opt_debug_server ){
# Put mysqld-debug first in the list of binaries to look for
mtr_verbose("Adding mysqld-debug first in list of binaries to look for");
unshift(@mysqld_names, "mysqld-debug");
@@ -1783,9 +1788,12 @@ sub executable_setup () {
sub client_debug_arg($$) {
my ($args, $client_name)= @_;
+ # Workaround for Bug #50627: drop any debug opt
+ return if $client_name =~ /^mysqlbinlog/;
+
if ( $opt_debug ) {
mtr_add_arg($args,
- "--debug=d:t:A,%s/log/%s.trace",
+ "--loose-debug=d:t:A,%s/log/%s.trace",
$path_vardir_trace, $client_name)
}
}
@@ -2047,6 +2055,16 @@ sub environment_setup {
$ENV{'DEFAULT_MASTER_PORT'}= $mysqld_variables{'master-port'} || 3306;
$ENV{'MYSQL_TMP_DIR'}= $opt_tmpdir;
$ENV{'MYSQLTEST_VARDIR'}= $opt_vardir;
+
+ if (IS_WINDOWS)
+ {
+ $ENV{'SECURE_LOAD_PATH'}= $glob_mysql_test_dir."\\std_data";
+ }
+ else
+ {
+ $ENV{'SECURE_LOAD_PATH'}= $glob_mysql_test_dir."/std_data";
+ }
+
# ----------------------------------------------------
# Setup env for NDB
@@ -2399,9 +2417,9 @@ sub check_debug_support ($) {
#mtr_report(" - binaries are not debug compiled");
$debug_compiled_binaries= 0;
- if ( $opt_debug )
+ if ( $opt_debug_server )
{
- mtr_error("Can't use --debug, binaries does not support it");
+ mtr_error("Can't use --debug[-server], binary does not support it");
}
return;
}
@@ -5579,6 +5597,8 @@ Options for debugging the product
client-gdb Start mysqltest client in gdb
ddd Start mysqld in ddd
debug Dump trace output for all servers and client programs
+ debug-server Use debug version of server, but without turning on
+ tracing
debugger=NAME Start mysqld in the selected debugger
gdb Start the mysqld(s) in gdb
manual-debug Let user manually start mysqld in debugger, before
diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result
index f6277323964..aade98d49b6 100644
--- a/mysql-test/r/grant.result
+++ b/mysql-test/r/grant.result
@@ -1252,6 +1252,80 @@ CURRENT_USER()
root@localhost
SET PASSWORD FOR CURRENT_USER() = PASSWORD("admin");
SET PASSWORD FOR CURRENT_USER() = PASSWORD("");
+
+# Bug#57952
+
+DROP DATABASE IF EXISTS mysqltest1;
+DROP DATABASE IF EXISTS mysqltest2;
+CREATE DATABASE mysqltest1;
+CREATE DATABASE mysqltest2;
+use mysqltest1;
+CREATE TABLE t1(a INT, b INT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TABLE t2(a INT);
+INSERT INTO t2 VALUES (2);
+CREATE TABLE mysqltest2.t3(a INT);
+INSERT INTO mysqltest2.t3 VALUES (4);
+CREATE USER testuser@localhost;
+GRANT CREATE ROUTINE, EXECUTE ON mysqltest1.* TO testuser@localhost;
+GRANT SELECT(b) ON t1 TO testuser@localhost;
+GRANT SELECT ON t2 TO testuser@localhost;
+GRANT SELECT ON mysqltest2.* TO testuser@localhost;
+
+# Connection: bug57952_con1 (testuser@localhost, db: mysqltest1)
+PREPARE s1 FROM 'SELECT b FROM t1';
+PREPARE s2 FROM 'SELECT a FROM t2';
+PREPARE s3 FROM 'SHOW TABLES FROM mysqltest2';
+CREATE PROCEDURE p1() SELECT b FROM t1;
+CREATE PROCEDURE p2() SELECT a FROM t2;
+CREATE PROCEDURE p3() SHOW TABLES FROM mysqltest2;
+CALL p1;
+b
+1
+CALL p2;
+a
+2
+CALL p3;
+Tables_in_mysqltest2
+t3
+
+# Connection: default
+REVOKE SELECT ON t1 FROM testuser@localhost;
+GRANT SELECT(a) ON t1 TO testuser@localhost;
+REVOKE SELECT ON t2 FROM testuser@localhost;
+REVOKE SELECT ON mysqltest2.* FROM testuser@localhost;
+
+# Connection: bug57952_con1 (testuser@localhost, db: mysqltest1)
+# - Check column-level privileges...
+EXECUTE s1;
+ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for column 'b' in table 't1'
+SELECT b FROM t1;
+ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for column 'b' in table 't1'
+EXECUTE s1;
+ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for column 'b' in table 't1'
+CALL p1;
+ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for column 'b' in table 't1'
+# - Check table-level privileges...
+SELECT a FROM t2;
+ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for table 't2'
+EXECUTE s2;
+ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for table 't2'
+CALL p2;
+ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for table 't2'
+# - Check database-level privileges...
+SHOW TABLES FROM mysqltest2;
+ERROR 42000: Access denied for user 'testuser'@'localhost' to database 'mysqltest2'
+EXECUTE s3;
+ERROR 42000: Access denied for user 'testuser'@'localhost' to database 'mysqltest2'
+CALL p3;
+ERROR 42000: Access denied for user 'testuser'@'localhost' to database 'mysqltest2'
+
+# Connection: default
+DROP DATABASE mysqltest1;
+DROP DATABASE mysqltest2;
+DROP USER testuser@localhost;
+use test;
+
End of 5.0 tests
set names utf8;
grant select on test.* to юзер_юзер@localhost;
diff --git a/mysql-test/r/not_embedded_server.result b/mysql-test/r/not_embedded_server.result
index 60c92bd0196..7219e29b2a6 100644
--- a/mysql-test/r/not_embedded_server.result
+++ b/mysql-test/r/not_embedded_server.result
@@ -4,3 +4,7 @@ select 1;
SHOW VARIABLES like 'slave_skip_errors';
Variable_name Value
slave_skip_errors OFF
+#
+# Bug#58026: massive recursion and crash in regular expression handling
+#
+SELECT '1' RLIKE RPAD('1', 10000, '(');
diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index ba639fa9763..30879af418a 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -1638,4 +1638,29 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL a 8 NULL 10 Using index; Using temporary; Using filesort
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 Using where
DROP TABLE t1, t2;
+#
+# Bug #59110: Memory leak of QUICK_SELECT_I allocated memory
+# and
+# Bug #59308: Incorrect result for
+SELECT DISTINCT <col>... ORDER BY <col> DESC
+
+# Use Valgrind to detect #59110!
+#
+CREATE TABLE t1 (a INT,KEY (a));
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+EXPLAIN SELECT DISTINCT a,1 FROM t1 WHERE a <> 1 ORDER BY a DESC;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index a a 5 NULL 10 Using where; Using index; Using filesort
+SELECT DISTINCT a,1 FROM t1 WHERE a <> 1 ORDER BY a DESC;
+a 1
+10 1
+9 1
+8 1
+7 1
+6 1
+5 1
+4 1
+3 1
+2 1
+DROP TABLE t1;
End of 5.1 tests
diff --git a/mysql-test/r/type_year.result b/mysql-test/r/type_year.result
index 8948214f565..2dc491c6166 100644
--- a/mysql-test/r/type_year.result
+++ b/mysql-test/r/type_year.result
@@ -341,4 +341,18 @@ ta_y s tb_y s
2001 2001 2001 2001
DROP TABLE t1;
#
+# Bug #59211: Select Returns Different Value for min(year) Function
+#
+CREATE TABLE t1(c1 YEAR(4));
+INSERT INTO t1 VALUES (1901),(2155),(0000);
+SELECT * FROM t1;
+c1
+1901
+2155
+0000
+SELECT COUNT(*) AS total_rows, MIN(c1) AS min_value, MAX(c1) FROM t1;
+total_rows min_value MAX(c1)
+3 0 2155
+DROP TABLE t1;
+#
End of 5.1 tests
diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result
index cf82a18ea83..374520ff610 100644
--- a/mysql-test/r/user_var.result
+++ b/mysql-test/r/user_var.result
@@ -450,4 +450,10 @@ DROP TABLE t1;
select @v:=@v:=sum(1) from dual;
@v:=@v:=sum(1)
1
+CREATE TABLE t1(a DECIMAL(31,21));
+INSERT INTO t1 VALUES (0);
+SELECT (@v:=a) <> (@v:=1) FROM t1;
+(@v:=a) <> (@v:=1)
+1
+DROP TABLE t1;
End of 5.1 tests
diff --git a/mysql-test/suite/binlog/r/binlog_unsafe.result b/mysql-test/suite/binlog/r/binlog_unsafe.result
index 77fe5eb0b5e..e0e0babb8b7 100644
--- a/mysql-test/suite/binlog/r/binlog_unsafe.result
+++ b/mysql-test/suite/binlog/r/binlog_unsafe.result
@@ -271,7 +271,7 @@ INSERT INTO t1 SELECT * FROM t2 LIMIT 1;
DROP TABLE t1,t2;
"Should NOT have any warning message issued in the following func7() and trig"
CREATE TABLE t1 (a INT);
-CREATE TABLE t2 (a CHAR(40));
+CREATE TABLE t2 (a TEXT);
CREATE TABLE trigger_table (a CHAR(7));
CREATE FUNCTION func7()
RETURNS INT
diff --git a/mysql-test/suite/binlog/t/binlog_unsafe.test b/mysql-test/suite/binlog/t/binlog_unsafe.test
index a86e49e475a..1e2e31eacf7 100644
--- a/mysql-test/suite/binlog/t/binlog_unsafe.test
+++ b/mysql-test/suite/binlog/t/binlog_unsafe.test
@@ -329,7 +329,7 @@ DROP TABLE t1,t2;
--echo "Should NOT have any warning message issued in the following func7() and trig"
CREATE TABLE t1 (a INT);
-CREATE TABLE t2 (a CHAR(40));
+CREATE TABLE t2 (a TEXT);
CREATE TABLE trigger_table (a CHAR(7));
DELIMITER |;
CREATE FUNCTION func7()
diff --git a/mysql-test/suite/engines/funcs/r/ps_string_not_null.result b/mysql-test/suite/engines/funcs/r/ps_string_not_null.result
index 859fab8b490..5f2a630811c 100644
--- a/mysql-test/suite/engines/funcs/r/ps_string_not_null.result
+++ b/mysql-test/suite/engines/funcs/r/ps_string_not_null.result
Binary files differ
diff --git a/mysql-test/suite/engines/funcs/t/ps_string_not_null.test b/mysql-test/suite/engines/funcs/t/ps_string_not_null.test
index f9e937cb24d..662adfd7a88 100644
--- a/mysql-test/suite/engines/funcs/t/ps_string_not_null.test
+++ b/mysql-test/suite/engines/funcs/t/ps_string_not_null.test
@@ -1,5 +1,5 @@
--disable_warnings
-DROP TABLE IF EXISTS t2;
+DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1(c1 CHAR(100) NOT NULL);
PREPARE stmt1 FROM 'INSERT INTO t1 (c1) VALUES(?)';
diff --git a/mysql-test/suite/innodb_plugin/r/innodb-autoinc-56228.result b/mysql-test/suite/innodb_plugin/r/innodb-autoinc-56228.result
new file mode 100644
index 00000000000..2ff2bd2800a
--- /dev/null
+++ b/mysql-test/suite/innodb_plugin/r/innodb-autoinc-56228.result
@@ -0,0 +1,30 @@
+DROP TABLE IF EXISTS t1_56228;
+Warnings:
+Note 1051 Unknown table 't1_56228'
+DROP TABLE IF EXISTS t2_56228;
+Warnings:
+Note 1051 Unknown table 't2_56228'
+DROP FUNCTION IF EXISTS bug56228;
+Warnings:
+Note 1305 FUNCTION bug56228 does not exist
+CREATE TEMPORARY TABLE t1_56228(
+c1 iNT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
+CREATE TEMPORARY TABLE t2_56228(
+c1 iNT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
+CREATE FUNCTION bug56228() RETURNS INT DETERMINISTIC
+BEGIN
+INSERT INTO t1_56228 VALUES(NULL);
+INSERT INTO t2_56228 VALUES(NULL);
+INSERT INTO t1_56228 VALUES(NULL);
+INSERT INTO t2_56228 VALUES(NULL);
+DROP TEMPORARY TABLE t1_56228;
+RETURN 42;
+END //
+SELECT bug56228();
+bug56228()
+42
+DROP FUNCTION bug56228;
+DROP TEMPORARY TABLE t2_56228;
+DROP TEMPORARY TABLE IF EXISTS t1_56228;
+Warnings:
+Note 1051 Unknown table 't1_56228'
diff --git a/mysql-test/suite/innodb_plugin/t/innodb-autoinc-56228-master.opt b/mysql-test/suite/innodb_plugin/t/innodb-autoinc-56228-master.opt
new file mode 100644
index 00000000000..0eed7aaadad
--- /dev/null
+++ b/mysql-test/suite/innodb_plugin/t/innodb-autoinc-56228-master.opt
@@ -0,0 +1 @@
+--innodb_autoinc_lock_mode=0
diff --git a/mysql-test/suite/innodb_plugin/t/innodb-autoinc-56228.test b/mysql-test/suite/innodb_plugin/t/innodb-autoinc-56228.test
new file mode 100644
index 00000000000..eb38b21861d
--- /dev/null
+++ b/mysql-test/suite/innodb_plugin/t/innodb-autoinc-56228.test
@@ -0,0 +1,42 @@
+-- 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
+#
+DROP TABLE IF EXISTS t1_56228;
+DROP TABLE IF EXISTS t2_56228;
+DROP FUNCTION IF EXISTS bug56228;
+
+CREATE TEMPORARY TABLE t1_56228(
+ c1 iNT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
+CREATE TEMPORARY TABLE t2_56228(
+ c1 iNT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
+
+DELIMITER //;
+
+CREATE FUNCTION bug56228() RETURNS INT DETERMINISTIC
+BEGIN
+ INSERT INTO t1_56228 VALUES(NULL);
+ INSERT INTO t2_56228 VALUES(NULL);
+ INSERT INTO t1_56228 VALUES(NULL);
+ INSERT INTO t2_56228 VALUES(NULL);
+ DROP TEMPORARY TABLE t1_56228;
+ RETURN 42;
+END //
+
+DELIMITER ;//
+
+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/rpl/r/rpl_circular_for_4_hosts.result b/mysql-test/suite/rpl/r/rpl_circular_for_4_hosts.result
index fb1d3f8258e..6981e549918 100644
--- a/mysql-test/suite/rpl/r/rpl_circular_for_4_hosts.result
+++ b/mysql-test/suite/rpl/r/rpl_circular_for_4_hosts.result
@@ -121,11 +121,11 @@ Master D 12 D
* Remove wrong event from C and restore B->C->D *
include/stop_slave.inc
DELETE FROM t1 WHERE a = 6;
-START SLAVE;
+include/start_slave.inc
RESET MASTER;
RESET SLAVE;
include/rpl_change_topology.inc [new topology=1->2->3->4->1]
-START SLAVE;
+include/start_slave.inc
include/rpl_sync.inc
* Check data inserted before restoring schema A->B->C->D->A *
diff --git a/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test b/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test
index 6099637e3e9..820ffc42933 100644
--- a/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test
+++ b/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test
@@ -175,7 +175,7 @@ SELECT 'Master D',a,b FROM t1 WHERE c = 3 ORDER BY a,b;
source include/stop_slave.inc;
--connection server_3
DELETE FROM t1 WHERE a = 6;
-START SLAVE;
+--source include/start_slave.inc
--connection server_2
--sync_slave_with_master server_3
RESET MASTER;
@@ -189,7 +189,7 @@ RESET SLAVE;
--source include/rpl_change_topology.inc
#--replace_result $SERVER_MYPORT_3 SERVER_MYPORT_3 $file_d LOG_FILE $pos_d LOG_POS
#--eval CHANGE MASTER TO master_host='127.0.0.1',master_port=$SERVER_MYPORT_3,master_user='root',master_log_file='$file_d',master_log_pos=$pos_d
-START SLAVE;
+--source include/start_slave.inc
--connection server_3
--sync_slave_with_master server_4
--source include/rpl_sync.inc
diff --git a/mysql-test/suite/sys_vars/r/secure_file_priv2.result b/mysql-test/suite/sys_vars/r/secure_file_priv2.result
new file mode 100644
index 00000000000..ec91b6037d0
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/secure_file_priv2.result
@@ -0,0 +1,6 @@
+CREATE TABLE t1 (c1 INT);
+LOAD DATA INFILE "t1.MYI" into table t1;
+ERROR HY000: The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
+LOAD DATA INFILE "/test" into table t1;
+ERROR HY000: The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
+DROP TABLE t1;
diff --git a/mysql-test/suite/sys_vars/t/secure_file_priv2-master.opt b/mysql-test/suite/sys_vars/t/secure_file_priv2-master.opt
new file mode 100644
index 00000000000..1d9a49c8f75
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/secure_file_priv2-master.opt
@@ -0,0 +1 @@
+--secure_file_priv=$SECURE_LOAD_PATH
diff --git a/mysql-test/suite/sys_vars/t/secure_file_priv2.test b/mysql-test/suite/sys_vars/t/secure_file_priv2.test
new file mode 100644
index 00000000000..0ca0a1839e1
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/secure_file_priv2.test
@@ -0,0 +1,23 @@
+#
+# Bug58747 breaks secure_file_priv+not secure yet+still accesses other folders
+#
+CREATE TABLE t1 (c1 INT);
+#
+# Before the patch this statement failed with
+# Linux:
+# -> errno 13: 'Can't get stat of '
+# Windows:
+# -> Warning 1366 Incorrect integer value: '■■☺' for
+# -> column 'c1' at row 1
+# Now it should consistently fail with ER_OPTION_PREVENTS_STATEMENT
+# on all platforms.
+--error ER_OPTION_PREVENTS_STATEMENT
+LOAD DATA INFILE "t1.MYI" into table t1;
+
+#
+# The following test makes the assuption that /test isn't a valid path in any
+# operating system running the test suite.
+--error ER_OPTION_PREVENTS_STATEMENT
+LOAD DATA INFILE "/test" into table t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test
index 2fafeb7d264..0762ceda0ac 100644
--- a/mysql-test/t/grant.test
+++ b/mysql-test/t/grant.test
@@ -1295,6 +1295,107 @@ SELECT CURRENT_USER();
SET PASSWORD FOR CURRENT_USER() = PASSWORD("admin");
SET PASSWORD FOR CURRENT_USER() = PASSWORD("");
+#
+# Bug#57952: privilege change is not taken into account by EXECUTE.
+#
+
+--echo
+--echo # Bug#57952
+--echo
+
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest1;
+DROP DATABASE IF EXISTS mysqltest2;
+--enable_warnings
+
+CREATE DATABASE mysqltest1;
+CREATE DATABASE mysqltest2;
+
+use mysqltest1;
+CREATE TABLE t1(a INT, b INT);
+INSERT INTO t1 VALUES (1, 1);
+
+CREATE TABLE t2(a INT);
+INSERT INTO t2 VALUES (2);
+
+CREATE TABLE mysqltest2.t3(a INT);
+INSERT INTO mysqltest2.t3 VALUES (4);
+
+CREATE USER testuser@localhost;
+GRANT CREATE ROUTINE, EXECUTE ON mysqltest1.* TO testuser@localhost;
+GRANT SELECT(b) ON t1 TO testuser@localhost;
+GRANT SELECT ON t2 TO testuser@localhost;
+GRANT SELECT ON mysqltest2.* TO testuser@localhost;
+
+--echo
+--echo # Connection: bug57952_con1 (testuser@localhost, db: mysqltest1)
+--connect (bug57952_con1,localhost,testuser,,mysqltest1)
+PREPARE s1 FROM 'SELECT b FROM t1';
+PREPARE s2 FROM 'SELECT a FROM t2';
+PREPARE s3 FROM 'SHOW TABLES FROM mysqltest2';
+
+CREATE PROCEDURE p1() SELECT b FROM t1;
+CREATE PROCEDURE p2() SELECT a FROM t2;
+CREATE PROCEDURE p3() SHOW TABLES FROM mysqltest2;
+
+CALL p1;
+CALL p2;
+CALL p3;
+
+--echo
+--echo # Connection: default
+--connection default
+REVOKE SELECT ON t1 FROM testuser@localhost;
+GRANT SELECT(a) ON t1 TO testuser@localhost;
+REVOKE SELECT ON t2 FROM testuser@localhost;
+REVOKE SELECT ON mysqltest2.* FROM testuser@localhost;
+
+--echo
+--echo # Connection: bug57952_con1 (testuser@localhost, db: mysqltest1)
+--connection bug57952_con1
+--echo # - Check column-level privileges...
+--error ER_COLUMNACCESS_DENIED_ERROR
+EXECUTE s1;
+
+--error ER_COLUMNACCESS_DENIED_ERROR
+SELECT b FROM t1;
+
+--error ER_COLUMNACCESS_DENIED_ERROR
+EXECUTE s1;
+
+--error ER_COLUMNACCESS_DENIED_ERROR
+CALL p1;
+
+--echo # - Check table-level privileges...
+--error ER_TABLEACCESS_DENIED_ERROR
+SELECT a FROM t2;
+
+--error ER_TABLEACCESS_DENIED_ERROR
+EXECUTE s2;
+
+--error ER_TABLEACCESS_DENIED_ERROR
+CALL p2;
+
+--echo # - Check database-level privileges...
+--error ER_DBACCESS_DENIED_ERROR
+SHOW TABLES FROM mysqltest2;
+
+--error ER_DBACCESS_DENIED_ERROR
+EXECUTE s3;
+
+--error ER_DBACCESS_DENIED_ERROR
+CALL p3;
+
+--echo
+--echo # Connection: default
+--connection default
+--disconnect bug57952_con1
+DROP DATABASE mysqltest1;
+DROP DATABASE mysqltest2;
+DROP USER testuser@localhost;
+use test;
+--echo
+
--echo End of 5.0 tests
#
diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test
index 2dcc77a16c2..aa774036d10 100644
--- a/mysql-test/t/mysql.test
+++ b/mysql-test/t/mysql.test
@@ -412,6 +412,12 @@ drop table t1;
--echo
--exec $MYSQL --skip-column-names --vertical test -e "select 1 as a"
+#
+# Bug#57450: mysql client enter in an infinite loop if the standard input is a directory
+#
+--error 1
+--exec $MYSQL < .
+
--echo
--echo #
diff --git a/mysql-test/t/not_embedded_server.test b/mysql-test/t/not_embedded_server.test
index fa2b659ec57..43cdb977386 100644
--- a/mysql-test/t/not_embedded_server.test
+++ b/mysql-test/t/not_embedded_server.test
@@ -42,4 +42,14 @@ select 1;
SHOW VARIABLES like 'slave_skip_errors';
+--echo #
+--echo # Bug#58026: massive recursion and crash in regular expression handling
+--echo #
+
+--disable_result_log
+--error ER_STACK_OVERRUN_NEED_MORE
+SELECT '1' RLIKE RPAD('1', 10000, '(');
+--enable_result_log
+
+
# End of 5.1 tests
diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test
index a8a6ad00648..1064320b65c 100644
--- a/mysql-test/t/order_by.test
+++ b/mysql-test/t/order_by.test
@@ -1492,4 +1492,21 @@ LIMIT 2;
DROP TABLE t1, t2;
+--echo #
+--echo # Bug #59110: Memory leak of QUICK_SELECT_I allocated memory
+--echo # and
+--echo # Bug #59308: Incorrect result for
+--echo SELECT DISTINCT <col>... ORDER BY <col> DESC
+--echo
+--echo # Use Valgrind to detect #59110!
+--echo #
+
+CREATE TABLE t1 (a INT,KEY (a));
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+EXPLAIN SELECT DISTINCT a,1 FROM t1 WHERE a <> 1 ORDER BY a DESC;
+SELECT DISTINCT a,1 FROM t1 WHERE a <> 1 ORDER BY a DESC;
+
+DROP TABLE t1;
+
--echo End of 5.1 tests
diff --git a/mysql-test/t/type_year.test b/mysql-test/t/type_year.test
index d8da4ccc82c..1a9e66478e1 100644
--- a/mysql-test/t/type_year.test
+++ b/mysql-test/t/type_year.test
@@ -150,5 +150,15 @@ SELECT ta.y AS ta_y, ta.s, tb.y AS tb_y, tb.s FROM t1 ta, t1 tb HAVING ta_y = tb
DROP TABLE t1;
--echo #
+--echo # Bug #59211: Select Returns Different Value for min(year) Function
+--echo #
+
+CREATE TABLE t1(c1 YEAR(4));
+INSERT INTO t1 VALUES (1901),(2155),(0000);
+SELECT * FROM t1;
+SELECT COUNT(*) AS total_rows, MIN(c1) AS min_value, MAX(c1) FROM t1;
+DROP TABLE t1;
+
+--echo #
--echo End of 5.1 tests
diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test
index 56217fe67d5..efaf8afd91e 100644
--- a/mysql-test/t/user_var.test
+++ b/mysql-test/t/user_var.test
@@ -353,4 +353,16 @@ DROP TABLE t1;
select @v:=@v:=sum(1) from dual;
+#
+# Bug #57187: more user variable fun with multiple assignments and
+# comparison in query
+#
+
+CREATE TABLE t1(a DECIMAL(31,21));
+INSERT INTO t1 VALUES (0);
+
+SELECT (@v:=a) <> (@v:=1) FROM t1;
+
+DROP TABLE t1;
+
--echo End of 5.1 tests
diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp
index 1016923a360..1983a8e6137 100644
--- a/mysql-test/valgrind.supp
+++ b/mysql-test/valgrind.supp
@@ -744,3 +744,50 @@
Memcheck:Addr1
fun:buf_buddy_relocate
}
+
+{
+ Bug 59874 Valgrind warning in InnoDB compression code
+ Memcheck:Cond
+ fun:*
+ fun:*
+ fun:deflate
+ fun:btr_store_big_rec_extern_fields_func
+ fun:row_ins_index_entry_low
+ fun:row_ins_index_entry
+ fun:row_ins_index_entry_step
+ fun:row_ins
+ fun:row_ins_step
+ fun:row_insert_for_mysql
+}
+
+{
+ In page0zip.c we have already checked that the memory is initialized before calling deflate()
+ Memcheck:Cond
+ fun:*
+ fun:*
+ fun:deflate
+ fun:page_zip_compress
+ fun:page_cur_insert_rec_zip_reorg
+ fun:page_cur_insert_rec_zip
+ fun:page_cur_tuple_insert
+ fun:btr_cur_optimistic_insert
+ fun:row_ins_index_entry_low
+ fun:row_ins_index_entry
+ fun:row_ins_index_entry_step
+ fun:row_ins
+ fun:row_ins_step
+ fun:row_insert_for_mysql
+}
+
+{
+ Bug 59875 Valgrind warning in buf0buddy.c
+ Memcheck:Addr1
+ fun:mach_read_from_4
+ fun:buf_buddy_relocate
+ fun:buf_buddy_free_low
+ fun:buf_buddy_free
+ fun:buf_LRU_block_remove_hashed_page
+ fun:buf_LRU_invalidate_tablespace
+ fun:fil_delete_tablespace
+ fun:row_drop_table_for_mysql
+}
diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c
index b8373ecb3ab..72991490d75 100644
--- a/mysys/my_fopen.c
+++ b/mysys/my_fopen.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/mysys/my_getsystime.c b/mysys/my_getsystime.c
index dfd99f6380d..ebe6cea842b 100644
--- a/mysys/my_getsystime.c
+++ b/mysys/my_getsystime.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004 MySQL AB
+/* Copyright (c) 2004, 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
diff --git a/regex/my_regex.h b/regex/my_regex.h
index 0d1cedf5430..30896e29b91 100644
--- a/regex/my_regex.h
+++ b/regex/my_regex.h
@@ -28,6 +28,7 @@ typedef struct {
/* === regcomp.c === */
+typedef int (*my_regex_stack_check_t)();
extern int my_regcomp(my_regex_t *, const char *, int, CHARSET_INFO *charset);
#define REG_BASIC 0000
#define REG_EXTENDED 0001
@@ -76,7 +77,8 @@ extern void my_regfree(my_regex_t *);
/* === reginit.c === */
-extern void my_regex_init(CHARSET_INFO *cs); /* Should be called for multithread progs */
+/* Should be called for multithread progs */
+extern void my_regex_init(CHARSET_INFO *cs, my_regex_stack_check_t func);
extern void my_regex_end(void); /* If one wants a clean end */
#ifdef __cplusplus
diff --git a/regex/regcomp.c b/regex/regcomp.c
index 81c435ed552..e163a9ba7f4 100644
--- a/regex/regcomp.c
+++ b/regex/regcomp.c
@@ -31,6 +31,9 @@ struct parse {
CHARSET_INFO *charset; /* for ctype things */
};
+/* Check if there is enough stack space for recursion. */
+my_regex_stack_check_t my_regex_enough_mem_in_stack= NULL;
+
#include "regcomp.ih"
static char nuls[10]; /* place to point scanner in event of error */
@@ -117,7 +120,7 @@ CHARSET_INFO *charset;
# define GOODFLAGS(f) ((f)&~REG_DUMP)
#endif
- my_regex_init(charset); /* Init cclass if neaded */
+ my_regex_init(charset, NULL); /* Init cclass if neaded */
preg->charset=charset;
cflags = GOODFLAGS(cflags);
if ((cflags&REG_EXTENDED) && (cflags&REG_NOSPEC))
@@ -222,7 +225,15 @@ int stop; /* character this ERE should end at */
/* do a bunch of concatenated expressions */
conc = HERE();
while (MORE() && (c = PEEK()) != '|' && c != stop)
- p_ere_exp(p);
+ {
+ if (my_regex_enough_mem_in_stack &&
+ my_regex_enough_mem_in_stack())
+ {
+ SETERROR(REG_ESPACE);
+ return;
+ }
+ p_ere_exp(p);
+ }
if(REQUIRE(HERE() != conc, REG_EMPTY)) {}/* require nonempty */
if (!EAT('|'))
diff --git a/regex/reginit.c b/regex/reginit.c
index 5980de24030..3d2cd64d1e7 100644
--- a/regex/reginit.c
+++ b/regex/reginit.c
@@ -4,10 +4,12 @@
#include <m_ctype.h>
#include <m_string.h>
#include "cclass.h"
+#include "my_regex.h"
static my_bool regex_inited=0;
+extern my_regex_stack_check_t my_regex_enough_mem_in_stack;
-void my_regex_init(CHARSET_INFO *cs)
+void my_regex_init(CHARSET_INFO *cs, my_regex_stack_check_t func)
{
char buff[CCLASS_LAST][256];
int count[CCLASS_LAST];
@@ -16,6 +18,7 @@ void my_regex_init(CHARSET_INFO *cs)
if (!regex_inited)
{
regex_inited=1;
+ my_regex_enough_mem_in_stack= func;
bzero((uchar*) &count,sizeof(count));
for (i=1 ; i<= 255; i++)
@@ -74,6 +77,7 @@ void my_regex_end()
int i;
for (i=0; i < CCLASS_LAST ; i++)
free((char*) cclasses[i].chars);
+ my_regex_enough_mem_in_stack= NULL;
regex_inited=0;
}
}
diff --git a/sql/handler.cc b/sql/handler.cc
index 711d2942ce0..5968a78b587 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1,4 +1,4 @@
-/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/item.h b/sql/item.h
index b187c1b6717..8568e89542e 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2960,11 +2960,10 @@ class Item_cache: public Item_basic_constant
protected:
Item *example;
table_map used_table_map;
- /*
- Field that this object will get value from. This is set/used by
+ /**
+ Field that this object will get value from. This is used by
index-based subquery engines to detect and remove the equality injected
by IN->EXISTS transformation.
- For all other uses of Item_cache, cached_field doesn't matter.
*/
Field *cached_field;
enum enum_field_types cached_field_type;
@@ -3021,6 +3020,14 @@ public:
{
return this == item;
}
+
+ /**
+ If this item caches a field value, return pointer to underlying field.
+
+ @return Pointer to field, or NULL if this is not a cache for a field value.
+ */
+ Field* field() { return cached_field; }
+
virtual void store(Item *item);
virtual bool cache_value()= 0;
};
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 40056cfd1ef..36ca5537eb5 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1196,9 +1196,12 @@ get_year_value(THD *thd, Item ***item_arg, Item **cache_arg,
value of 2000.
*/
Item *real_item= item->real_item();
- if (!(real_item->type() == Item::FIELD_ITEM &&
- ((Item_field *)real_item)->field->type() == MYSQL_TYPE_YEAR &&
- ((Item_field *)real_item)->field->field_length == 4))
+ Field *field= NULL;
+ if (real_item->type() == Item::FIELD_ITEM)
+ field= ((Item_field *)real_item)->field;
+ else if (real_item->type() == Item::CACHE_ITEM)
+ field= ((Item_cache *)real_item)->field();
+ if (!(field && field->type() == MYSQL_TYPE_YEAR && field->field_length == 4))
{
if (value < 70)
value+= 100;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 786316447af..bffbd03e15a 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -4069,7 +4069,7 @@ my_decimal *user_var_entry::val_decimal(my_bool *null_value, my_decimal *val)
int2my_decimal(E_DEC_FATAL_ERROR, *(longlong*) value, 0, val);
break;
case DECIMAL_RESULT:
- val= (my_decimal *)value;
+ my_decimal2decimal((my_decimal *) value, val);
break;
case STRING_RESULT:
str2my_decimal(E_DEC_FATAL_ERROR, value, length, collation.collation, val);
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index 08161badfd3..0a6e8d03a46 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2003 MySQL AB
+/* Copyright (c) 2003, 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
diff --git a/sql/log.cc b/sql/log.cc
index 23182fa1902..17642696e7d 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1,4 +1,4 @@
-/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 54f93cccd5d..694d64c81df 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -3034,6 +3034,19 @@ sizeof(load_default_groups)/sizeof(load_default_groups[0]);
#endif
+#ifndef EMBEDDED_LIBRARY
+static
+int
+check_enough_stack_size()
+{
+ uchar stack_top;
+
+ return check_stack_overrun(current_thd, STACK_MIN_SIZE,
+ &stack_top);
+}
+#endif
+
+
/**
Initialize one of the global date/time format variables.
@@ -3415,7 +3428,11 @@ static int init_common_variables(const char *conf_file_name, int argc,
#endif
mysys_uses_curses=0;
#ifdef USE_REGEX
- my_regex_init(&my_charset_latin1);
+#ifndef EMBEDDED_LIBRARY
+ my_regex_init(&my_charset_latin1, check_enough_stack_size);
+#else
+ my_regex_init(&my_charset_latin1, NULL);
+#endif
#endif
/*
Process a comma-separated character set list and choose
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 0c559f5619d..e45d57e57dc 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index f609a073161..9765148cda1 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -5941,6 +5941,8 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
/*
Find field by name in a base table or a view with temp table algorithm.
+ The caller is expected to check column-level privileges.
+
SYNOPSIS
find_field_in_table()
thd thread handler
@@ -6048,6 +6050,8 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
This procedure detects the type of the table reference 'table_list'
and calls the corresponding search routine.
+ The routine checks column-level privieleges for the found field.
+
RETURN
0 field is not found
view_ref_found found value in VIEW (real result is in *ref)
@@ -6321,8 +6325,16 @@ find_field_in_tables(THD *thd, Item_ident *item,
when table_ref->field_translation != NULL.
*/
if (table_ref->table && !table_ref->view)
+ {
found= find_field_in_table(thd, table_ref->table, name, length,
TRUE, &(item->cached_field_index));
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ /* Check if there are sufficient access rights to the found field. */
+ if (found && check_privileges &&
+ check_column_grant_in_table_ref(thd, table_ref, name, length))
+ found= WRONG_GRANT;
+#endif
+ }
else
found= find_field_in_table_ref(thd, table_ref, name, length, item->name,
NULL, NULL, ref, check_privileges,
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index f2aedf5d0aa..c227fe69b62 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -314,56 +314,57 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
(void) fn_format(name, ex->file_name, mysql_real_data_home, "",
MY_RELATIVE_PATH | MY_UNPACK_FILENAME |
MY_RETURN_REAL_PATH);
-#if !defined(__WIN__) && ! defined(__NETWARE__)
- MY_STAT stat_info;
- if (!my_stat(name,&stat_info,MYF(MY_WME)))
- DBUG_RETURN(TRUE);
-
- // if we are not in slave thread, the file must be:
- if (!thd->slave_thread &&
- !((stat_info.st_mode & S_IROTH) == S_IROTH && // readable by others
- (stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
- ((stat_info.st_mode & S_IFREG) == S_IFREG ||
- (stat_info.st_mode & S_IFIFO) == S_IFIFO)))
- {
- my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
- DBUG_RETURN(TRUE);
- }
- if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
- is_fifo = 1;
-#endif
+ }
- if (thd->slave_thread)
- {
+ if (thd->slave_thread)
+ {
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
- if (strncmp(active_mi->rli.slave_patternload_file, name,
- active_mi->rli.slave_patternload_file_size))
- {
- /*
- LOAD DATA INFILE in the slave SQL Thread can only read from
- --slave-load-tmpdir". This should never happen. Please, report a bug.
- */
-
- sql_print_error("LOAD DATA INFILE in the slave SQL Thread can only read from --slave-load-tmpdir. " \
- "Please, report a bug.");
- my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--slave-load-tmpdir");
- DBUG_RETURN(TRUE);
- }
-#else
+ if (strncmp(active_mi->rli.slave_patternload_file, name,
+ active_mi->rli.slave_patternload_file_size))
+ {
/*
- This is impossible and should never happen.
+ LOAD DATA INFILE in the slave SQL Thread can only read from
+ --slave-load-tmpdir". This should never happen. Please, report a bug.
*/
- DBUG_ASSERT(FALSE);
-#endif
- }
- else if (!is_secure_file_path(name))
- {
- /* Read only allowed from within dir specified by secure_file_priv */
- my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
+
+ sql_print_error("LOAD DATA INFILE in the slave SQL Thread can only read from --slave-load-tmpdir. " \
+ "Please, report a bug.");
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--slave-load-tmpdir");
DBUG_RETURN(TRUE);
}
+#else
+ /*
+ This is impossible and should never happen.
+ */
+ DBUG_ASSERT(FALSE);
+#endif
+ }
+ else if (!is_secure_file_path(name))
+ {
+ /* Read only allowed from within dir specified by secure_file_priv */
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
+ DBUG_RETURN(TRUE);
+ }
+#if !defined(__WIN__) && ! defined(__NETWARE__)
+ MY_STAT stat_info;
+ if (!my_stat(name,&stat_info,MYF(MY_WME)))
+ DBUG_RETURN(TRUE);
+
+ // if we are not in slave thread, the file must be:
+ if (!thd->slave_thread &&
+ !((stat_info.st_mode & S_IROTH) == S_IROTH && // readable by others
+ (stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
+ ((stat_info.st_mode & S_IFREG) == S_IFREG ||
+ (stat_info.st_mode & S_IFIFO) == S_IFIFO)))
+ {
+ my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
+ DBUG_RETURN(TRUE);
}
+ if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
+ is_fifo = 1;
+#endif
+
if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) < 0)
DBUG_RETURN(TRUE);
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index e080dc9370c..869fd01ac60 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -13364,12 +13364,14 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
{
int ref_key;
uint ref_key_parts;
- int order_direction;
+ int order_direction= 0;
uint used_key_parts;
TABLE *table=tab->table;
SQL_SELECT *select=tab->select;
key_map usable_keys;
QUICK_SELECT_I *save_quick= 0;
+ int best_key= -1;
+
DBUG_ENTER("test_if_skip_sort_order");
LINT_INIT(ref_key_parts);
@@ -13473,13 +13475,14 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
new_ref_key_map.clear_all(); // Force the creation of quick select
new_ref_key_map.set_bit(new_ref_key); // only for new_ref_key.
+ select->quick= 0;
if (select->test_quick_select(tab->join->thd, new_ref_key_map, 0,
(tab->join->select_options &
OPTION_FOUND_ROWS) ?
HA_POS_ERROR :
tab->join->unit->select_limit_cnt,0) <=
0)
- DBUG_RETURN(0);
+ goto use_filesort;
}
ref_key= new_ref_key;
}
@@ -13504,7 +13507,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
int best_key_direction= 0;
ha_rows best_records= 0;
double read_time;
- int best_key= -1;
bool is_best_covering= FALSE;
double fanout= 1;
JOIN *join= tab->join;
@@ -13681,72 +13683,21 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
tab->join->tables > tab->join->const_tables + 1) &&
((unsigned) best_key != table->s->primary_key ||
!table->file->primary_key_is_clustered()))
- DBUG_RETURN(0);
+ goto use_filesort;
if (best_key >= 0)
{
- bool quick_created= FALSE;
if (table->quick_keys.is_set(best_key) && best_key != ref_key)
{
key_map map;
map.clear_all(); // Force the creation of quick select
map.set_bit(best_key); // only best_key.
- quick_created=
- select->test_quick_select(join->thd, map, 0,
- join->select_options & OPTION_FOUND_ROWS ?
- HA_POS_ERROR :
- join->unit->select_limit_cnt,
- 0) > 0;
- }
- if (!no_changes)
- {
- /*
- If ref_key used index tree reading only ('Using index' in EXPLAIN),
- and best_key doesn't, then revert the decision.
- */
- if (!table->covering_keys.is_set(best_key))
- table->set_keyread(FALSE);
- if (!quick_created)
- {
- tab->index= best_key;
- tab->read_first_record= best_key_direction > 0 ?
- join_read_first:join_read_last;
- tab->type=JT_NEXT; // Read with index_first(), index_next()
- if (select && select->quick)
- {
- delete select->quick;
- select->quick= 0;
- }
- if (table->covering_keys.is_set(best_key))
- table->set_keyread(TRUE);
- table->file->ha_index_or_rnd_end();
- if (join->select_options & SELECT_DESCRIBE)
- {
- tab->ref.key= -1;
- tab->ref.key_parts= 0;
- if (select_limit < table_records)
- tab->limit= select_limit;
- }
- }
- else if (tab->type != JT_ALL)
- {
- /*
- We're about to use a quick access to the table.
- We need to change the access method so as the quick access
- method is actually used.
- */
- DBUG_ASSERT(tab->select->quick);
- tab->type=JT_ALL;
- tab->use_quick=1;
- tab->ref.key= -1;
- tab->ref.key_parts=0; // Don't use ref key.
- tab->read_first_record= join_init_read_record;
- if (tab->is_using_loose_index_scan())
- join->tmp_table_param.precomputed_group_by= TRUE;
- /*
- TODO: update the number of records in join->best_positions[tablenr]
- */
- }
+ select->quick= 0;
+ select->test_quick_select(join->thd, map, 0,
+ join->select_options & OPTION_FOUND_ROWS ?
+ HA_POS_ERROR :
+ join->unit->select_limit_cnt,
+ 0);
}
order_direction= best_key_direction;
/*
@@ -13759,10 +13710,12 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
saved_best_key_parts : best_key_parts;
}
else
- DBUG_RETURN(0);
+ goto use_filesort;
}
check_reverse_order:
+ DBUG_ASSERT(order_direction != 0);
+
if (order_direction == -1) // If ORDER BY ... DESC
{
if (select && select->quick)
@@ -13771,9 +13724,10 @@ check_reverse_order:
Don't reverse the sort order, if it's already done.
(In some cases test_if_order_by_key() can be called multiple times
*/
- if (!select->quick->reverse_sorted())
+ if (select->quick->reverse_sorted())
+ goto skipped_filesort;
+ else
{
- QUICK_SELECT_DESC *tmp;
int quick_type= select->quick->get_type();
if (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE ||
quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
@@ -13781,39 +13735,132 @@ check_reverse_order:
quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
{
tab->limit= 0;
- select->quick= save_quick;
- DBUG_RETURN(0); // Use filesort
+ goto use_filesort; // Use filesort
}
-
- /* ORDER BY range_key DESC */
- tmp= new QUICK_SELECT_DESC((QUICK_RANGE_SELECT*)(select->quick),
- used_key_parts);
- if (!tmp || tmp->error)
- {
- delete tmp;
- select->quick= save_quick;
- tab->limit= 0;
- DBUG_RETURN(0); // Reverse sort not supported
- }
- select->quick=tmp;
}
}
- else if (tab->type != JT_NEXT && tab->type != JT_REF_OR_NULL &&
- tab->ref.key >= 0 && tab->ref.key_parts <= used_key_parts)
+ }
+
+ /*
+ Update query plan with access pattern for doing
+ ordered access according to what we have decided
+ above.
+ */
+ if (!no_changes) // We are allowed to update QEP
+ {
+ if (best_key >= 0)
{
- /*
- SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC
+ bool quick_created=
+ (select && select->quick && select->quick!=save_quick);
- Use a traversal function that starts by reading the last row
- with key part (A) and then traverse the index backwards.
+ /*
+ If ref_key used index tree reading only ('Using index' in EXPLAIN),
+ and best_key doesn't, then revert the decision.
*/
- tab->read_first_record= join_read_last_key;
- tab->read_record.read_record= join_read_prev_same;
+ if (!table->covering_keys.is_set(best_key))
+ table->set_keyread(FALSE);
+ if (!quick_created)
+ {
+ if (select) // Throw any existing quick select
+ select->quick= 0; // Cleanup either reset to save_quick,
+ // or 'delete save_quick'
+ tab->index= best_key;
+ tab->read_first_record= order_direction > 0 ?
+ join_read_first:join_read_last;
+ tab->type=JT_NEXT; // Read with index_first(), index_next()
+
+ if (table->covering_keys.is_set(best_key))
+ table->set_keyread(TRUE);
+ table->file->ha_index_or_rnd_end();
+ if (tab->join->select_options & SELECT_DESCRIBE)
+ {
+ tab->ref.key= -1;
+ tab->ref.key_parts= 0;
+ if (select_limit < table->file->stats.records)
+ tab->limit= select_limit;
+ }
+ }
+ else if (tab->type != JT_ALL)
+ {
+ /*
+ We're about to use a quick access to the table.
+ We need to change the access method so as the quick access
+ method is actually used.
+ */
+ DBUG_ASSERT(tab->select->quick);
+ tab->type=JT_ALL;
+ tab->use_quick=1;
+ tab->ref.key= -1;
+ tab->ref.key_parts=0; // Don't use ref key.
+ tab->read_first_record= join_init_read_record;
+ if (tab->is_using_loose_index_scan())
+ tab->join->tmp_table_param.precomputed_group_by= TRUE;
+ /*
+ TODO: update the number of records in join->best_positions[tablenr]
+ */
+ }
+ } // best_key >= 0
+
+ if (order_direction == -1) // If ORDER BY ... DESC
+ {
+ if (select && select->quick)
+ {
+ QUICK_SELECT_DESC *tmp;
+ /* ORDER BY range_key DESC */
+ tmp= new QUICK_SELECT_DESC((QUICK_RANGE_SELECT*)(select->quick),
+ used_key_parts);
+ if (tmp && select->quick == save_quick)
+ save_quick= 0; // ::QUICK_SELECT_DESC consumed it
+
+ if (!tmp || tmp->error)
+ {
+ delete tmp;
+ tab->limit= 0;
+ goto use_filesort; // Reverse sort failed -> filesort
+ }
+ select->quick= tmp;
+ }
+ else if (tab->type != JT_NEXT && tab->type != JT_REF_OR_NULL &&
+ tab->ref.key >= 0 && tab->ref.key_parts <= used_key_parts)
+ {
+ /*
+ SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC
+
+ Use a traversal function that starts by reading the last row
+ with key part (A) and then traverse the index backwards.
+ */
+ tab->read_first_record= join_read_last_key;
+ tab->read_record.read_record= join_read_prev_same;
+ }
}
+ else if (select && select->quick)
+ select->quick->sorted= 1;
+
+ } // QEP has been modified
+
+ /*
+ Cleanup:
+ We may have both a 'select->quick' and 'save_quick' (original)
+ at this point. Delete the one that we wan't use.
+ */
+
+skipped_filesort:
+ // Keep current (ordered) select->quick
+ if (select && save_quick != select->quick)
+ {
+ delete save_quick;
+ save_quick= NULL;
}
- else if (select && select->quick)
- select->quick->sorted= 1;
DBUG_RETURN(1);
+
+use_filesort:
+ // Restore original save_quick
+ if (select && select->quick != save_quick)
+ {
+ delete select->quick;
+ select->quick= save_quick;
+ }
+ DBUG_RETURN(0);
}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index cf6a34d4ef5..1524a8fb87f 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index a25ef931344..ab6da7c1925 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004 MySQL AB
+/* Copyright (c) 2004, 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
diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog
index 18ab48f32a5..102db3d7824 100644
--- a/storage/innodb_plugin/ChangeLog
+++ b/storage/innodb_plugin/ChangeLog
@@ -1,3 +1,10 @@
+2011-01-31 The InnoDB Team
+
+ * btr/btr0cur.c, include/row0upd.h,
+ row/row0purge.c, row/row0umod.c, row/row0upd.c:
+ Bug#59230 assert 0 row_upd_changes_ord_field_binary()
+ in post-crash rollback or purge
+
2011-01-27 The InnoDB Team
* btr/btr0cur.c:
@@ -50,6 +57,16 @@
bad "rows examined" estimates
2011-01-06 The InnoDB Team
+ * row/row0merge.c:
+ Fix Bug#59312 Examine MAX_FULL_NAME_LEN in InnoDB to address
+ possible insufficient name buffer
+
+2011-01-06 The InnoDB Team
+ * dict/dict0dict.c, handler/ha_innodb.cc, handler/i_s.cc,
+ include/univ.i:
+ Fix Bug#58643 InnoDB: too long table name
+
+2011-01-06 The InnoDB Team
* handler/i_s.cc, include/trx0i_s.h, trx/trx0i_s.c:
Fix Bug#55397 cannot select from innodb_trx when trx_query contains
blobs that aren't strings
diff --git a/storage/innodb_plugin/btr/btr0cur.c b/storage/innodb_plugin/btr/btr0cur.c
index 874db3066b5..704cc606a5f 100644
--- a/storage/innodb_plugin/btr/btr0cur.c
+++ b/storage/innodb_plugin/btr/btr0cur.c
@@ -186,7 +186,7 @@ static
ulint
btr_rec_get_externally_stored_len(
/*==============================*/
- rec_t* rec, /*!< in: record */
+ const rec_t* rec, /*!< in: record */
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
#endif /* !UNIV_HOTBACKUP */
@@ -1768,8 +1768,8 @@ btr_cur_update_in_place(
NOT call it if index is secondary */
if (!dict_index_is_clust(index)
- || row_upd_changes_ord_field_binary(NULL, NULL,
- index, update)) {
+ || row_upd_changes_ord_field_binary(index, update, thr,
+ NULL, NULL)) {
/* Remove possible hash index pointer to this record */
btr_search_update_hash_on_delete(cursor);
@@ -3484,34 +3484,62 @@ btr_estimate_number_of_different_key_vals(
/*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/
/***********************************************************//**
+Gets the offset of the pointer to the externally stored part of a field.
+@return offset of the pointer to the externally stored part */
+static
+ulint
+btr_rec_get_field_ref_offs(
+/*=======================*/
+ const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
+ ulint n) /*!< in: index of the external field */
+{
+ ulint field_ref_offs;
+ ulint local_len;
+
+ ut_a(rec_offs_nth_extern(offsets, n));
+ field_ref_offs = rec_get_nth_field_offs(offsets, n, &local_len);
+ ut_a(local_len != UNIV_SQL_NULL);
+ ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
+
+ return(field_ref_offs + local_len - BTR_EXTERN_FIELD_REF_SIZE);
+}
+
+/** Gets a pointer to the externally stored part of a field.
+@param rec record
+@param offsets rec_get_offsets(rec)
+@param n index of the externally stored field
+@return pointer to the externally stored part */
+#define btr_rec_get_field_ref(rec, offsets, n) \
+ ((rec) + btr_rec_get_field_ref_offs(offsets, n))
+
+/***********************************************************//**
Gets the externally stored size of a record, in units of a database page.
@return externally stored part, in units of a database page */
static
ulint
btr_rec_get_externally_stored_len(
/*==============================*/
- rec_t* rec, /*!< in: record */
+ const rec_t* rec, /*!< in: record */
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
{
ulint n_fields;
- byte* data;
- ulint local_len;
- ulint extern_len;
ulint total_extern_len = 0;
ulint i;
ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec));
+
+ if (!rec_offs_any_extern(offsets)) {
+ return(0);
+ }
+
n_fields = rec_offs_n_fields(offsets);
for (i = 0; i < n_fields; i++) {
if (rec_offs_nth_extern(offsets, i)) {
- data = rec_get_nth_field(rec, offsets, i, &local_len);
-
- local_len -= BTR_EXTERN_FIELD_REF_SIZE;
-
- extern_len = mach_read_from_4(data + local_len
- + BTR_EXTERN_LEN + 4);
+ ulint extern_len = mach_read_from_4(
+ btr_rec_get_field_ref(rec, offsets, i)
+ + BTR_EXTERN_LEN + 4);
total_extern_len += ut_calc_align(extern_len,
UNIV_PAGE_SIZE);
@@ -3541,7 +3569,7 @@ btr_cur_set_ownership_of_extern_field(
ulint byte_val;
data = rec_get_nth_field(rec, offsets, i, &local_len);
-
+ ut_ad(rec_offs_nth_extern(offsets, i));
ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
@@ -3551,6 +3579,9 @@ btr_cur_set_ownership_of_extern_field(
if (val) {
byte_val = byte_val & (~BTR_EXTERN_OWNER_FLAG);
} else {
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!(byte_val & BTR_EXTERN_OWNER_FLAG));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
byte_val = byte_val | BTR_EXTERN_OWNER_FLAG;
}
@@ -3788,8 +3819,8 @@ file segment of the index tree.
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
UNIV_INTERN
ulint
-btr_store_big_rec_extern_fields(
-/*============================*/
+btr_store_big_rec_extern_fields_func(
+/*=================================*/
dict_index_t* index, /*!< in: index of rec; the index tree
MUST be X-latched */
buf_block_t* rec_block, /*!< in/out: block containing rec */
@@ -3798,11 +3829,17 @@ btr_store_big_rec_extern_fields(
the "external storage" flags in offsets
will not correspond to rec when
this function returns */
- big_rec_t* big_rec_vec, /*!< in: vector containing fields
+#ifdef UNIV_DEBUG
+ mtr_t* local_mtr, /*!< in: mtr containing the
+ latch to rec and to the tree */
+#endif /* UNIV_DEBUG */
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ 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* local_mtr __attribute__((unused))) /*!< in: mtr
- containing the latch to rec and to the
- tree */
+
{
ulint rec_page_no;
byte* field_ref;
@@ -3820,6 +3857,7 @@ btr_store_big_rec_extern_fields(
z_stream c_stream;
ut_ad(rec_offs_validate(rec, index, offsets));
+ ut_ad(rec_offs_any_extern(offsets));
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));
@@ -3851,21 +3889,37 @@ btr_store_big_rec_extern_fields(
ut_a(err == Z_OK);
}
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ /* All pointers to externally stored columns in the record
+ must either be zero or they must be pointers to inherited
+ columns, owned by this record or an earlier record version. */
+ for (i = 0; i < rec_offs_n_fields(offsets); i++) {
+ if (!rec_offs_nth_extern(offsets, i)) {
+ continue;
+ }
+ field_ref = btr_rec_get_field_ref(rec, offsets, i);
+
+ ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
+ /* Either this must be an update in place,
+ or the BLOB must be inherited, or the BLOB pointer
+ must be zero (will be written in this function). */
+ ut_a(update_in_place
+ || (field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_INHERITED_FLAG)
+ || !memcmp(field_ref, field_ref_zero,
+ BTR_EXTERN_FIELD_REF_SIZE));
+ }
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
/* We have to create a file segment to the tablespace
for each field and put the pointer to the field in rec */
for (i = 0; i < big_rec_vec->n_fields; i++) {
- ut_ad(rec_offs_nth_extern(offsets,
- big_rec_vec->fields[i].field_no));
- {
- ulint local_len;
- field_ref = rec_get_nth_field(
- rec, offsets, big_rec_vec->fields[i].field_no,
- &local_len);
- ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
- local_len -= BTR_EXTERN_FIELD_REF_SIZE;
- field_ref += local_len;
- }
+ field_ref = btr_rec_get_field_ref(
+ rec, offsets, big_rec_vec->fields[i].field_no);
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ /* A zero BLOB pointer should have been initially inserted. */
+ ut_a(!memcmp(field_ref, field_ref_zero,
+ BTR_EXTERN_FIELD_REF_SIZE));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
extern_len = big_rec_vec->fields[i].len;
UNIV_MEM_ASSERT_RW(big_rec_vec->fields[i].data,
extern_len);
@@ -4147,6 +4201,23 @@ next_zip_page:
mem_heap_free(heap);
}
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ /* All pointers to externally stored columns in the record
+ must be valid. */
+ for (i = 0; i < rec_offs_n_fields(offsets); i++) {
+ if (!rec_offs_nth_extern(offsets, i)) {
+ continue;
+ }
+
+ field_ref = btr_rec_get_field_ref(rec, offsets, i);
+
+ /* The pointer must not be zero. */
+ ut_a(0 != memcmp(field_ref, field_ref_zero,
+ BTR_EXTERN_FIELD_REF_SIZE));
+ /* The column must not be disowned by this record. */
+ ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
+ }
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
return(DB_SUCCESS);
}
@@ -4169,6 +4240,7 @@ btr_check_blob_fil_page_type(
if (UNIV_UNLIKELY(type != FIL_PAGE_TYPE_BLOB)) {
ulint flags = fil_space_get_flags(space_id);
+#ifndef UNIV_DEBUG /* Improve debug test coverage */
if (UNIV_LIKELY
((flags & DICT_TF_FORMAT_MASK) == DICT_TF_FORMAT_51)) {
/* Old versions of InnoDB did not initialize
@@ -4177,6 +4249,7 @@ btr_check_blob_fil_page_type(
a BLOB page that is in Antelope format.*/
return;
}
+#endif /* !UNIV_DEBUG */
ut_print_timestamp(stderr);
fprintf(stderr,
@@ -4226,23 +4299,13 @@ btr_free_externally_stored_field(
ulint page_no;
ulint next_page_no;
mtr_t mtr;
-#ifdef UNIV_DEBUG
+
ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index),
MTR_MEMO_X_LOCK));
ut_ad(mtr_memo_contains_page(local_mtr, field_ref,
MTR_MEMO_PAGE_X_FIX));
ut_ad(!rec || rec_offs_validate(rec, index, offsets));
-
- if (rec) {
- ulint local_len;
- const byte* f = rec_get_nth_field(rec, offsets,
- i, &local_len);
- ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
- local_len -= BTR_EXTERN_FIELD_REF_SIZE;
- f += local_len;
- ut_ad(f == field_ref);
- }
-#endif /* UNIV_DEBUG */
+ ut_ad(!rec || field_ref == btr_rec_get_field_ref(rec, offsets, i));
if (UNIV_UNLIKELY(!memcmp(field_ref, field_ref_zero,
BTR_EXTERN_FIELD_REF_SIZE))) {
@@ -4407,13 +4470,8 @@ btr_rec_free_externally_stored_fields(
for (i = 0; i < n_fields; i++) {
if (rec_offs_nth_extern(offsets, i)) {
- ulint len;
- byte* data
- = rec_get_nth_field(rec, offsets, i, &len);
- ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
-
btr_free_externally_stored_field(
- index, data + len - BTR_EXTERN_FIELD_REF_SIZE,
+ index, btr_rec_get_field_ref(rec, offsets, i),
rec, offsets, page_zip, i, rb_ctx, mtr);
}
}
diff --git a/storage/innodb_plugin/buf/buf0buf.c b/storage/innodb_plugin/buf/buf0buf.c
index 6e76e4c65be..6bbd5565c58 100644
--- a/storage/innodb_plugin/buf/buf0buf.c
+++ b/storage/innodb_plugin/buf/buf0buf.c
@@ -657,9 +657,9 @@ buf_block_init(
block->modify_clock = 0;
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
block->page.file_page_was_freed = FALSE;
-#endif /* UNIV_DEBUG_FILE_ACCESSES */
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
block->check_index_page_at_flush = FALSE;
block->index = NULL;
@@ -1600,7 +1600,7 @@ buf_page_peek_if_search_hashed(
return(is_hashed);
}
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
/********************************************************************//**
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
@@ -1621,6 +1621,8 @@ buf_page_set_file_page_was_freed(
bpage = buf_page_hash_get(space, offset);
if (bpage) {
+ /* bpage->file_page_was_freed can already hold
+ when this code is invoked from dict_drop_index_tree() */
bpage->file_page_was_freed = TRUE;
}
@@ -1656,7 +1658,7 @@ buf_page_reset_file_page_was_freed(
return(bpage);
}
-#endif /* UNIV_DEBUG_FILE_ACCESSES */
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
/********************************************************************//**
Get read access to a compressed page (usually of type
@@ -1753,7 +1755,7 @@ got_block:
buf_page_set_accessed_make_young(bpage, access_time);
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(!bpage->file_page_was_freed);
#endif
@@ -2321,7 +2323,7 @@ wait_until_unfixed:
buf_page_set_accessed_make_young(&block->page, access_time);
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(!block->page.file_page_was_freed);
#endif
@@ -2479,7 +2481,7 @@ buf_page_optimistic_get(
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(block->page.file_page_was_freed == FALSE);
#endif
if (UNIV_UNLIKELY(!access_time)) {
@@ -2587,7 +2589,7 @@ buf_page_get_known_nowait(
ut_a(block->page.buf_fix_count > 0);
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(block->page.file_page_was_freed == FALSE);
#endif
@@ -2670,9 +2672,9 @@ buf_page_try_get_func(
ut_a(block->page.buf_fix_count > 0);
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(block->page.file_page_was_freed == FALSE);
-#endif /* UNIV_DEBUG_FILE_ACCESSES */
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
buf_pool->stat.n_page_gets++;
@@ -2701,9 +2703,9 @@ buf_page_init_low(
bpage->newest_modification = 0;
bpage->oldest_modification = 0;
HASH_INVALIDATE(bpage, hash);
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
bpage->file_page_was_freed = FALSE;
-#endif /* UNIV_DEBUG_FILE_ACCESSES */
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
}
/********************************************************************//**
@@ -3009,9 +3011,9 @@ buf_page_create(
#ifdef UNIV_IBUF_COUNT_DEBUG
ut_a(ibuf_count_get(space, offset) == 0);
#endif
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
block->page.file_page_was_freed = FALSE;
-#endif /* UNIV_DEBUG_FILE_ACCESSES */
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
/* Page can be found in buf_pool */
buf_pool_mutex_exit();
diff --git a/storage/innodb_plugin/dict/dict0dict.c b/storage/innodb_plugin/dict/dict0dict.c
index ff56e9cb76a..a8787bbda61 100644
--- a/storage/innodb_plugin/dict/dict0dict.c
+++ b/storage/innodb_plugin/dict/dict0dict.c
@@ -932,7 +932,7 @@ dict_table_rename_in_cache(
dict_foreign_t* foreign;
dict_index_t* index;
ulint fold;
- char old_name[MAX_TABLE_NAME_LEN + 1];
+ char old_name[MAX_FULL_NAME_LEN + 1];
ut_ad(table);
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -944,7 +944,7 @@ dict_table_rename_in_cache(
ut_print_timestamp(stderr);
fprintf(stderr, "InnoDB: too long table name: '%s', "
"max length is %d\n", table->name,
- MAX_TABLE_NAME_LEN);
+ MAX_FULL_NAME_LEN);
ut_error;
}
@@ -994,11 +994,11 @@ dict_table_rename_in_cache(
ut_fold_string(old_name), table);
if (strlen(new_name) > strlen(table->name)) {
- /* We allocate MAX_TABLE_NAME_LEN+1 bytes here to avoid
+ /* We allocate MAX_FULL_NAME_LEN + 1 bytes here to avoid
memory fragmentation, we assume a repeated calls of
ut_realloc() with the same size do not cause fragmentation */
- ut_a(strlen(new_name) <= MAX_TABLE_NAME_LEN);
- table->name = ut_realloc(table->name, MAX_TABLE_NAME_LEN + 1);
+ ut_a(strlen(new_name) <= MAX_FULL_NAME_LEN);
+ table->name = ut_realloc(table->name, MAX_FULL_NAME_LEN + 1);
}
memcpy(table->name, new_name, strlen(new_name) + 1);
diff --git a/storage/innodb_plugin/fsp/fsp0fsp.c b/storage/innodb_plugin/fsp/fsp0fsp.c
index e9d24b8fdf6..d091a14c474 100644
--- a/storage/innodb_plugin/fsp/fsp0fsp.c
+++ b/storage/innodb_plugin/fsp/fsp0fsp.c
@@ -3444,9 +3444,9 @@ fseg_free_page(
fseg_free_page_low(seg_inode, space, zip_size, page, mtr);
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
buf_page_set_file_page_was_freed(space, page);
-#endif
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
}
/**********************************************************************//**
@@ -3513,13 +3513,13 @@ fseg_free_extent(
fsp_free_extent(space, zip_size, page, mtr);
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
for (i = 0; i < FSP_EXTENT_SIZE; i++) {
buf_page_set_file_page_was_freed(space,
first_page_in_extent + i);
}
-#endif
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
}
/**********************************************************************//**
diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc
index 2d60c7397b0..dda2fbaa4d2 100644
--- a/storage/innodb_plugin/handler/ha_innodb.cc
+++ b/storage/innodb_plugin/handler/ha_innodb.cc
@@ -6028,6 +6028,16 @@ create_table_def(
DBUG_RETURN(HA_ERR_GENERIC);
}
+ /* MySQL does the name length check. But we do additional check
+ on the name length here */
+ if (strlen(table_name) > MAX_FULL_NAME_LEN) {
+ push_warning_printf(
+ (THD*) trx->mysql_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TABLE_NAME,
+ "InnoDB: Table Name or Database Name is too long");
+ DBUG_RETURN(ER_TABLE_NAME);
+ }
+
n_cols = form->s->fields;
/* We pass 0 as the space id, and determine at a lower level the space
diff --git a/storage/innodb_plugin/handler/i_s.cc b/storage/innodb_plugin/handler/i_s.cc
index 24996496b0c..b0149967e9b 100644
--- a/storage/innodb_plugin/handler/i_s.cc
+++ b/storage/innodb_plugin/handler/i_s.cc
@@ -587,16 +587,7 @@ fill_innodb_locks_from_cache(
for (i = 0; i < rows_num; i++) {
i_s_locks_row_t* row;
-
- /* note that the decoded database or table name is
- never expected to be longer than NAME_LEN;
- NAME_LEN for database name
- 2 for surrounding quotes around database name
- NAME_LEN for table name
- 2 for surrounding quotes around table name
- 1 for the separating dot (.)
- 9 for the #mysql50# prefix */
- char buf[2 * NAME_LEN + 14];
+ char buf[MAX_FULL_NAME_LEN + 1];
const char* bufend;
char lock_trx_id[TRX_ID_MAX_LEN + 1];
diff --git a/storage/innodb_plugin/ibuf/ibuf0ibuf.c b/storage/innodb_plugin/ibuf/ibuf0ibuf.c
index 701e8f0ef04..23981ac388e 100644
--- a/storage/innodb_plugin/ibuf/ibuf0ibuf.c
+++ b/storage/innodb_plugin/ibuf/ibuf0ibuf.c
@@ -1878,9 +1878,9 @@ ibuf_remove_free_page(void)
fseg_free_page(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
IBUF_SPACE_ID, page_no, &mtr);
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
buf_page_reset_file_page_was_freed(IBUF_SPACE_ID, page_no);
-#endif
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
ibuf_enter();
@@ -1922,9 +1922,9 @@ ibuf_remove_free_page(void)
ibuf_bitmap_page_set_bits(
bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, FALSE, &mtr);
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
buf_page_set_file_page_was_freed(IBUF_SPACE_ID, page_no);
-#endif
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
mtr_commit(&mtr);
mutex_exit(&ibuf_mutex);
diff --git a/storage/innodb_plugin/include/btr0cur.h b/storage/innodb_plugin/include/btr0cur.h
index cb8cb399715..ece3621fa97 100644
--- a/storage/innodb_plugin/include/btr0cur.h
+++ b/storage/innodb_plugin/include/btr0cur.h
@@ -512,8 +512,8 @@ file segment of the index tree.
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
UNIV_INTERN
ulint
-btr_store_big_rec_extern_fields(
-/*============================*/
+btr_store_big_rec_extern_fields_func(
+/*=================================*/
dict_index_t* index, /*!< in: index of rec; the index tree
MUST be X-latched */
buf_block_t* rec_block, /*!< in/out: block containing rec */
@@ -522,10 +522,42 @@ btr_store_big_rec_extern_fields(
the "external storage" flags in offsets
will not correspond to rec when
this function returns */
- big_rec_t* big_rec_vec, /*!< in: vector containing fields
+#ifdef UNIV_DEBUG
+ mtr_t* local_mtr, /*!< in: mtr containing the
+ latch to rec and to the tree */
+#endif /* UNIV_DEBUG */
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ 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* local_mtr); /*!< in: mtr containing the latch to
- rec and to the tree */
+ __attribute__((nonnull));
+
+/** 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.
+The fields are stored on pages allocated from leaf node
+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);
+ the "external storage" flags in offsets will not be adjusted
+@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
+@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)
+#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)
+#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)
+#endif
+
/*******************************************************************//**
Frees the space in an externally stored field to the file space
management if the field in data is owned the externally stored field,
diff --git a/storage/innodb_plugin/include/buf0buf.h b/storage/innodb_plugin/include/buf0buf.h
index d903b443920..a16de67aa3a 100644
--- a/storage/innodb_plugin/include/buf0buf.h
+++ b/storage/innodb_plugin/include/buf0buf.h
@@ -368,7 +368,7 @@ buf_reset_check_index_page_at_flush(
/*================================*/
ulint space, /*!< in: space id */
ulint offset);/*!< in: page number */
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
/********************************************************************//**
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
@@ -393,7 +393,7 @@ buf_page_reset_file_page_was_freed(
/*===============================*/
ulint space, /*!< in: space id */
ulint offset); /*!< in: page number */
-#endif /* UNIV_DEBUG_FILE_ACCESSES */
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
/********************************************************************//**
Reads the freed_page_clock of a buffer block.
@return freed_page_clock */
@@ -1135,11 +1135,11 @@ struct buf_page_struct{
0 if the block was never accessed
in the buffer pool */
/* @} */
-# ifdef UNIV_DEBUG_FILE_ACCESSES
+# if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ibool file_page_was_freed;
/*!< this is set to TRUE when fsp
frees a page in buffer pool */
-# endif /* UNIV_DEBUG_FILE_ACCESSES */
+# endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
#endif /* !UNIV_HOTBACKUP */
};
diff --git a/storage/innodb_plugin/include/row0upd.h b/storage/innodb_plugin/include/row0upd.h
index b61e6b6dca1..97b7ec49a17 100644
--- a/storage/innodb_plugin/include/row0upd.h
+++ b/storage/innodb_plugin/include/row0upd.h
@@ -280,19 +280,29 @@ NOTE: we compare the fields as binary strings!
@return TRUE if update vector changes an ordering field in the index record */
UNIV_INTERN
ibool
-row_upd_changes_ord_field_binary(
-/*=============================*/
+row_upd_changes_ord_field_binary_func(
+/*==================================*/
+ dict_index_t* index, /*!< in: index of the record */
+ const upd_t* update, /*!< in: update vector for the row; NOTE: the
+ field numbers in this MUST be clustered index
+ positions! */
+#ifdef UNIV_DEBUG
+ const que_thr_t*thr, /*!< in: query thread */
+#endif /* UNIV_DEBUG */
const dtuple_t* row, /*!< in: old value of row, or NULL if the
row and the data values in update are not
known when this function is called, e.g., at
compile time */
- const row_ext_t*ext, /*!< NULL, or prefixes of the externally
+ const row_ext_t*ext) /*!< NULL, or prefixes of the externally
stored columns in the old row */
- dict_index_t* index, /*!< in: index of the record */
- const upd_t* update) /*!< in: update vector for the row; NOTE: the
- field numbers in this MUST be clustered index
- positions! */
- __attribute__((nonnull(3,4), warn_unused_result));
+ __attribute__((nonnull(1,2), warn_unused_result));
+#ifdef UNIV_DEBUG
+# define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \
+ row_upd_changes_ord_field_binary_func(index,update,thr,row,ext)
+#else /* UNIV_DEBUG */
+# define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \
+ row_upd_changes_ord_field_binary_func(index,update,row,ext)
+#endif /* UNIV_DEBUG */
/***********************************************************//**
Checks if an update vector changes an ordering field of an index record.
This function is fast if the update vector is short or the number of ordering
diff --git a/storage/innodb_plugin/include/univ.i b/storage/innodb_plugin/include/univ.i
index 4425950748b..9a719872c50 100644
--- a/storage/innodb_plugin/include/univ.i
+++ b/storage/innodb_plugin/include/univ.i
@@ -177,14 +177,15 @@ command. Not tested on Windows. */
debugging without UNIV_DEBUG */
#define UNIV_BUF_DEBUG /* Enable buffer pool
debugging without UNIV_DEBUG */
+#define UNIV_BLOB_LIGHT_DEBUG /* Enable off-page column
+ debugging without UNIV_DEBUG */
#define UNIV_DEBUG /* Enable ut_ad() assertions
and disable UNIV_INLINE */
#define UNIV_DEBUG_LOCK_VALIDATE /* Enable
ut_ad(lock_rec_validate_page())
assertions. */
-#define UNIV_DEBUG_FILE_ACCESSES /* Debug .ibd file access
- (field file_page_was_freed
- in buf_page_t) */
+#define UNIV_DEBUG_FILE_ACCESSES /* Enable freed block access
+ debugging without UNIV_DEBUG */
#define UNIV_LRU_DEBUG /* debug the buffer pool LRU */
#define UNIV_HASH_DEBUG /* debug HASH_ macros */
#define UNIV_LIST_DEBUG /* debug UT_LIST_ macros */
@@ -296,6 +297,18 @@ number does not include a terminating '\0'. InnoDB probably can handle
longer names internally */
#define MAX_TABLE_NAME_LEN 192
+/* The maximum length of a database name. Like MAX_TABLE_NAME_LEN this is
+the MySQL's NAME_LEN, see check_and_convert_db_name(). */
+#define MAX_DATABASE_NAME_LEN MAX_TABLE_NAME_LEN
+
+/* MAX_FULL_NAME_LEN defines the full name path including the
+database name and table name. In addition, 14 bytes is added for:
+ 2 for surrounding quotes around table name
+ 1 for the separating dot (.)
+ 9 for the #mysql50# prefix */
+#define MAX_FULL_NAME_LEN \
+ (MAX_TABLE_NAME_LEN + MAX_DATABASE_NAME_LEN + 14)
+
/*
UNIVERSAL TYPE DEFINITIONS
==========================
diff --git a/storage/innodb_plugin/include/ut0vec.h b/storage/innodb_plugin/include/ut0vec.h
index a770f671cfc..0f8b955b098 100644
--- a/storage/innodb_plugin/include/ut0vec.h
+++ b/storage/innodb_plugin/include/ut0vec.h
@@ -94,6 +94,25 @@ ib_vector_get(
ulint n); /*!< in: element index to get */
/****************************************************************//**
+Get last element. The vector must not be empty.
+@return last element */
+UNIV_INLINE
+void*
+ib_vector_get_last(
+/*===============*/
+ ib_vector_t* vec); /*!< in: vector */
+
+/****************************************************************//**
+Set the n'th element. */
+UNIV_INLINE
+void
+ib_vector_set(
+/*==========*/
+ ib_vector_t* vec, /*!< in/out: vector */
+ ulint n, /*!< in: element index to set */
+ void* elem); /*!< in: data element */
+
+/****************************************************************//**
Remove the last element from the vector. */
UNIV_INLINE
void*
diff --git a/storage/innodb_plugin/include/ut0vec.ic b/storage/innodb_plugin/include/ut0vec.ic
index 02e881f9bca..34c858868ce 100644
--- a/storage/innodb_plugin/include/ut0vec.ic
+++ b/storage/innodb_plugin/include/ut0vec.ic
@@ -51,6 +51,35 @@ ib_vector_get(
}
/****************************************************************//**
+Get last element. The vector must not be empty.
+@return last element */
+UNIV_INLINE
+void*
+ib_vector_get_last(
+/*===============*/
+ ib_vector_t* vec) /*!< in: vector */
+{
+ ut_a(vec->used > 0);
+
+ return(vec->data[vec->used - 1]);
+}
+
+/****************************************************************//**
+Set the n'th element. */
+UNIV_INLINE
+void
+ib_vector_set(
+/*==========*/
+ ib_vector_t* vec, /*!< in/out: vector */
+ ulint n, /*!< in: element index to set */
+ void* elem) /*!< in: data element */
+{
+ ut_a(n < vec->used);
+
+ vec->data[n] = elem;
+}
+
+/****************************************************************//**
Remove the last element from the vector.
@return last vector element */
UNIV_INLINE
diff --git a/storage/innodb_plugin/lock/lock0lock.c b/storage/innodb_plugin/lock/lock0lock.c
index 77d69d11a2d..c8bbc5c02bd 100644
--- a/storage/innodb_plugin/lock/lock0lock.c
+++ b/storage/innodb_plugin/lock/lock0lock.c
@@ -3625,6 +3625,80 @@ lock_table_create(
}
/*************************************************************//**
+Pops autoinc lock requests from the transaction's autoinc_locks. We
+handle the case where there are gaps in the array and they need to
+be popped off the stack. */
+UNIV_INLINE
+void
+lock_table_pop_autoinc_locks(
+/*=========================*/
+ trx_t* trx) /*!< in/out: transaction that owns the AUTOINC locks */
+{
+ ut_ad(mutex_own(&kernel_mutex));
+ ut_ad(!ib_vector_is_empty(trx->autoinc_locks));
+
+ /* Skip any gaps, gaps are NULL lock entries in the
+ trx->autoinc_locks vector. */
+
+ do {
+ ib_vector_pop(trx->autoinc_locks);
+
+ if (ib_vector_is_empty(trx->autoinc_locks)) {
+ return;
+ }
+
+ } while (ib_vector_get_last(trx->autoinc_locks) == NULL);
+}
+
+/*************************************************************//**
+Removes an autoinc lock request from the transaction's autoinc_locks. */
+UNIV_INLINE
+void
+lock_table_remove_autoinc_lock(
+/*===========================*/
+ lock_t* lock, /*!< in: table lock */
+ trx_t* trx) /*!< in/out: transaction that owns the lock */
+{
+ lock_t* autoinc_lock;
+ lint i = ib_vector_size(trx->autoinc_locks) - 1;
+
+ ut_ad(mutex_own(&kernel_mutex));
+ ut_ad(lock_get_mode(lock) == LOCK_AUTO_INC);
+ ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
+ ut_ad(!ib_vector_is_empty(trx->autoinc_locks));
+
+ /* With stored functions and procedures the user may drop
+ a table within the same "statement". This special case has
+ to be handled by deleting only those AUTOINC locks that were
+ held by the table being dropped. */
+
+ autoinc_lock = ib_vector_get(trx->autoinc_locks, i);
+
+ /* This is the default fast case. */
+
+ if (autoinc_lock == lock) {
+ lock_table_pop_autoinc_locks(trx);
+ } else {
+ /* The last element should never be NULL */
+ ut_a(autoinc_lock != NULL);
+
+ /* Handle freeing the locks from within the stack. */
+
+ while (--i >= 0) {
+ autoinc_lock = ib_vector_get(trx->autoinc_locks, i);
+
+ if (UNIV_LIKELY(autoinc_lock == lock)) {
+ ib_vector_set(trx->autoinc_locks, i, NULL);
+ return;
+ }
+ }
+
+ /* Must find the autoinc lock. */
+ ut_error;
+ }
+}
+
+/*************************************************************//**
Removes a table lock request from the queue and the trx list of locks;
this is a low-level function which does NOT check if waiting requests
can now be granted. */
@@ -3663,10 +3737,8 @@ lock_table_remove_low(
if (!lock_get_wait(lock)
&& !ib_vector_is_empty(trx->autoinc_locks)) {
- lock_t* autoinc_lock;
- autoinc_lock = ib_vector_pop(trx->autoinc_locks);
- ut_a(autoinc_lock == lock);
+ lock_table_remove_autoinc_lock(lock, trx);
}
ut_a(table->n_waiting_or_granted_auto_inc_locks > 0);
diff --git a/storage/innodb_plugin/row/row0ins.c b/storage/innodb_plugin/row/row0ins.c
index 298c601c7e3..8050c099751 100644
--- a/storage/innodb_plugin/row/row0ins.c
+++ b/storage/innodb_plugin/row/row0ins.c
@@ -2130,7 +2130,7 @@ function_exit:
err = btr_store_big_rec_extern_fields(
index, btr_cur_get_block(&cursor),
- rec, offsets, big_rec, &mtr);
+ rec, offsets, &mtr, FALSE, big_rec);
if (modify) {
dtuple_big_rec_free(big_rec);
diff --git a/storage/innodb_plugin/row/row0merge.c b/storage/innodb_plugin/row/row0merge.c
index 160edd32fbf..647d0031635 100644
--- a/storage/innodb_plugin/row/row0merge.c
+++ b/storage/innodb_plugin/row/row0merge.c
@@ -2341,7 +2341,7 @@ row_merge_rename_tables(
{
ulint err = DB_ERROR;
pars_info_t* info;
- char old_name[MAX_TABLE_NAME_LEN + 1];
+ char old_name[MAX_FULL_NAME_LEN + 1];
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_ad(old_table != new_table);
@@ -2356,7 +2356,7 @@ row_merge_rename_tables(
ut_print_timestamp(stderr);
fprintf(stderr, "InnoDB: too long table name: '%s', "
"max length is %d\n", old_table->name,
- MAX_TABLE_NAME_LEN);
+ MAX_FULL_NAME_LEN);
ut_error;
}
diff --git a/storage/innodb_plugin/row/row0purge.c b/storage/innodb_plugin/row/row0purge.c
index 8bf2ae0f458..752a2ec9e83 100644
--- a/storage/innodb_plugin/row/row0purge.c
+++ b/storage/innodb_plugin/row/row0purge.c
@@ -387,8 +387,11 @@ Purges an update of an existing record. Also purges an update of a delete
marked record if that record contained an externally stored field. */
static
void
-row_purge_upd_exist_or_extern(
-/*==========================*/
+row_purge_upd_exist_or_extern_func(
+/*===============================*/
+#ifdef UNIV_DEBUG
+ const que_thr_t*thr, /*!< in: query thread */
+#endif /* UNIV_DEBUG */
purge_node_t* node) /*!< in: row purge node */
{
mem_heap_t* heap;
@@ -413,8 +416,8 @@ row_purge_upd_exist_or_extern(
while (node->index != NULL) {
index = node->index;
- if (row_upd_changes_ord_field_binary(NULL, NULL, node->index,
- node->update)) {
+ if (row_upd_changes_ord_field_binary(node->index, node->update,
+ thr, NULL, NULL)) {
/* Build the older version of the index entry */
entry = row_build_index_entry(node->row, NULL,
index, heap);
@@ -496,6 +499,14 @@ skip_secondaries:
}
}
+#ifdef UNIV_DEBUG
+# define row_purge_upd_exist_or_extern(thr,node) \
+ row_purge_upd_exist_or_extern_func(thr,node)
+#else /* UNIV_DEBUG */
+# define row_purge_upd_exist_or_extern(thr,node) \
+ row_purge_upd_exist_or_extern_func(node)
+#endif /* UNIV_DEBUG */
+
/***********************************************************//**
Parses the row reference and other info in a modify undo log record.
@return TRUE if purge operation required: NOTE that then the CALLER
@@ -602,47 +613,32 @@ err_exit:
/***********************************************************//**
Fetches an undo log record and does the purge for the recorded operation.
If none left, or the current purge completed, returns the control to the
-parent node, which is always a query thread node.
-@return DB_SUCCESS if operation successfully completed, else error code */
-static
-ulint
+parent node, which is always a query thread node. */
+static __attribute__((nonnull))
+void
row_purge(
/*======*/
purge_node_t* node, /*!< in: row purge node */
que_thr_t* thr) /*!< in: query thread */
{
- roll_ptr_t roll_ptr;
- ibool purge_needed;
ibool updated_extern;
- trx_t* trx;
- ut_ad(node && thr);
-
- trx = thr_get_trx(thr);
+ ut_ad(node);
+ ut_ad(thr);
- node->undo_rec = trx_purge_fetch_next_rec(&roll_ptr,
- &(node->reservation),
+ node->undo_rec = trx_purge_fetch_next_rec(&node->roll_ptr,
+ &node->reservation,
node->heap);
if (!node->undo_rec) {
/* Purge completed for this query thread */
thr->run_node = que_node_get_parent(node);
- return(DB_SUCCESS);
- }
-
- node->roll_ptr = roll_ptr;
-
- if (node->undo_rec == &trx_purge_dummy_rec) {
- purge_needed = FALSE;
- } else {
- purge_needed = row_purge_parse_undo_rec(node, &updated_extern,
- thr);
- /* If purge_needed == TRUE, we must also remember to unfreeze
- data dictionary! */
+ return;
}
- if (purge_needed) {
+ if (node->undo_rec != &trx_purge_dummy_rec
+ && row_purge_parse_undo_rec(node, &updated_extern, thr)) {
node->found_clust = FALSE;
node->index = dict_table_get_next_index(
@@ -654,14 +650,14 @@ row_purge(
} else if (updated_extern
|| node->rec_type == TRX_UNDO_UPD_EXIST_REC) {
- row_purge_upd_exist_or_extern(node);
+ row_purge_upd_exist_or_extern(thr, node);
}
if (node->found_clust) {
btr_pcur_close(&(node->pcur));
}
- row_mysql_unfreeze_data_dictionary(trx);
+ row_mysql_unfreeze_data_dictionary(thr_get_trx(thr));
}
/* Do some cleanup */
@@ -669,8 +665,6 @@ row_purge(
mem_heap_empty(node->heap);
thr->run_node = node;
-
- return(DB_SUCCESS);
}
/***********************************************************//**
@@ -684,9 +678,6 @@ row_purge_step(
que_thr_t* thr) /*!< in: query thread */
{
purge_node_t* node;
-#ifdef UNIV_DEBUG
- ulint err;
-#endif /* UNIV_DEBUG */
ut_ad(thr);
@@ -694,12 +685,7 @@ row_purge_step(
ut_ad(que_node_get_type(node) == QUE_NODE_PURGE);
-#ifdef UNIV_DEBUG
- err =
-#endif /* UNIV_DEBUG */
row_purge(node, thr);
- ut_ad(err == DB_SUCCESS);
-
return(thr);
}
diff --git a/storage/innodb_plugin/row/row0umod.c b/storage/innodb_plugin/row/row0umod.c
index 562f8093c38..5202a498eed 100644
--- a/storage/innodb_plugin/row/row0umod.c
+++ b/storage/innodb_plugin/row/row0umod.c
@@ -173,40 +173,26 @@ row_undo_mod_remove_clust_low(
mtr_t* mtr, /*!< in: mtr */
ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
{
- btr_pcur_t* pcur;
btr_cur_t* btr_cur;
ulint err;
- ibool success;
ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC);
- pcur = &(node->pcur);
- btr_cur = btr_pcur_get_btr_cur(pcur);
- success = btr_pcur_restore_position(mode, pcur, mtr);
+ /* Find out if the record has been purged already
+ or if we can remove it. */
- if (!success) {
+ if (!btr_pcur_restore_position(mode, &node->pcur, mtr)
+ || row_vers_must_preserve_del_marked(node->new_trx_id, mtr)) {
return(DB_SUCCESS);
}
- /* Find out if we can remove the whole clustered index record */
-
- if (node->rec_type == TRX_UNDO_UPD_DEL_REC
- && !row_vers_must_preserve_del_marked(node->new_trx_id, mtr)) {
-
- /* Ok, we can remove */
- } else {
- return(DB_SUCCESS);
- }
+ btr_cur = btr_pcur_get_btr_cur(&node->pcur);
if (mode == BTR_MODIFY_LEAF) {
- success = btr_cur_optimistic_delete(btr_cur, mtr);
-
- if (success) {
- err = DB_SUCCESS;
- } else {
- err = DB_FAIL;
- }
+ err = btr_cur_optimistic_delete(btr_cur, mtr)
+ ? DB_SUCCESS
+ : DB_FAIL;
} else {
ut_ad(mode == BTR_MODIFY_TREE);
@@ -668,8 +654,9 @@ row_undo_mod_upd_exist_sec(
while (node->index != NULL) {
index = node->index;
- if (row_upd_changes_ord_field_binary(
- node->row, node->ext, node->index, node->update)) {
+ if (row_upd_changes_ord_field_binary(node->index, node->update,
+ thr,
+ node->row, node->ext)) {
/* Build the newest version of the index entry */
entry = row_build_index_entry(node->row, node->ext,
diff --git a/storage/innodb_plugin/row/row0upd.c b/storage/innodb_plugin/row/row0upd.c
index 691d263e6ed..9ded3d68018 100644
--- a/storage/innodb_plugin/row/row0upd.c
+++ b/storage/innodb_plugin/row/row0upd.c
@@ -1192,25 +1192,31 @@ NOTE: we compare the fields as binary strings!
@return TRUE if update vector changes an ordering field in the index record */
UNIV_INTERN
ibool
-row_upd_changes_ord_field_binary(
-/*=============================*/
+row_upd_changes_ord_field_binary_func(
+/*==================================*/
+ dict_index_t* index, /*!< in: index of the record */
+ const upd_t* update, /*!< in: update vector for the row; NOTE: the
+ field numbers in this MUST be clustered index
+ positions! */
+#ifdef UNIV_DEBUG
+ const que_thr_t*thr, /*!< in: query thread */
+#endif /* UNIV_DEBUG */
const dtuple_t* row, /*!< in: old value of row, or NULL if the
row and the data values in update are not
known when this function is called, e.g., at
compile time */
- const row_ext_t*ext, /*!< NULL, or prefixes of the externally
+ const row_ext_t*ext) /*!< NULL, or prefixes of the externally
stored columns in the old row */
- dict_index_t* index, /*!< in: index of the record */
- const upd_t* update) /*!< in: update vector for the row; NOTE: the
- field numbers in this MUST be clustered index
- positions! */
{
ulint n_unique;
ulint i;
const dict_index_t* clust_index;
- ut_ad(update);
ut_ad(index);
+ ut_ad(update);
+ ut_ad(thr);
+ ut_ad(thr->graph);
+ ut_ad(thr->graph->trx);
n_unique = dict_index_get_n_unique(index);
@@ -1263,9 +1269,14 @@ row_upd_changes_ord_field_binary(
if (UNIV_LIKELY_NULL(buf)) {
if (UNIV_UNLIKELY(buf == field_ref_zero)) {
- /* This should never happen, but
- we try to fail safe here. */
- ut_ad(0);
+ /* The externally stored field
+ was not written yet. This
+ record should only be seen by
+ recv_recovery_rollback_active(),
+ when the server had crashed before
+ storing the field. */
+ ut_ad(thr->graph->trx->is_recovered);
+ ut_ad(trx_is_recv(thr->graph->trx));
return(TRUE);
}
@@ -1612,8 +1623,8 @@ row_upd_sec_step(
ut_ad(!dict_index_is_clust(node->index));
if (node->state == UPD_NODE_UPDATE_ALL_SEC
- || row_upd_changes_ord_field_binary(node->row, node->ext,
- node->index, node->update)) {
+ || row_upd_changes_ord_field_binary(node->index, node->update,
+ thr, node->row, node->ext)) {
return(row_upd_sec_index_entry(node, thr));
}
@@ -1941,7 +1952,7 @@ row_upd_clust_rec(
index, btr_cur_get_block(btr_cur), rec,
rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
- big_rec, mtr);
+ mtr, TRUE, big_rec);
mtr_commit(mtr);
}
@@ -2140,8 +2151,8 @@ exit_func:
row_upd_store_row(node);
- if (row_upd_changes_ord_field_binary(node->row, node->ext, index,
- node->update)) {
+ if (row_upd_changes_ord_field_binary(index, node->update, thr,
+ node->row, node->ext)) {
/* Update causes an ordering field (ordering fields within
the B-tree) of the clustered index record to change: perform
diff --git a/storage/innodb_plugin/trx/trx0roll.c b/storage/innodb_plugin/trx/trx0roll.c
index 1a43e419214..a4bbf7fd652 100644
--- a/storage/innodb_plugin/trx/trx0roll.c
+++ b/storage/innodb_plugin/trx/trx0roll.c
@@ -48,8 +48,8 @@ Created 3/26/1996 Heikki Tuuri
rollback */
#define TRX_ROLL_TRUNC_THRESHOLD 1
-/** In crash recovery, the current trx to be rolled back */
-static trx_t* trx_roll_crash_recv_trx = NULL;
+/** In crash recovery, the current trx to be rolled back; NULL otherwise */
+static const trx_t* trx_roll_crash_recv_trx = NULL;
/** In crash recovery we set this to the undo n:o of the current trx to be
rolled back. Then we can print how many % the rollback has progressed. */