Auto-merge from mysql-next-mr.
This commit is contained in:
commit
fca241584f
@ -1,4 +1,4 @@
|
||||
[MYSQL]
|
||||
post_commit_to = "commits@lists.mysql.com"
|
||||
post_push_to = "commits@lists.mysql.com"
|
||||
tree_name = "mysql-5.5-next-mr-bugfixing"
|
||||
tree_name = "mysql-next-mr-bugfixing"
|
||||
|
@ -3072,6 +3072,9 @@ libmysqld/rpl_handler.cc
|
||||
libmysqld/debug_sync.cc
|
||||
libmysqld/rpl_handler.cc
|
||||
dbug/tests
|
||||
libmysqld/mdl.cc
|
||||
client/transaction.h
|
||||
libmysqld/transaction.cc
|
||||
libmysqld/sys_vars.cc
|
||||
libmysqld/keycaches.cc
|
||||
client/dtoa.c
|
||||
|
@ -107,8 +107,9 @@ sql_src=log_event.h mysql_priv.h rpl_constants.h \
|
||||
rpl_tblmap.h rpl_tblmap.cc \
|
||||
log_event.cc my_decimal.h my_decimal.cc \
|
||||
log_event_old.h log_event_old.cc \
|
||||
rpl_record_old.h rpl_record_old.cc \
|
||||
rpl_utility.h rpl_utility.cc \
|
||||
rpl_record_old.h rpl_record_old.cc
|
||||
transaction.h
|
||||
strings_src=decimal.c dtoa.c
|
||||
|
||||
link_sources:
|
||||
|
@ -67,6 +67,7 @@
|
||||
#define MAX_COLUMNS 256
|
||||
#define MAX_EMBEDDED_SERVER_ARGS 64
|
||||
#define MAX_DELIMITER_LENGTH 16
|
||||
#define DEFAULT_MAX_CONN 128
|
||||
|
||||
/* Flags controlling send and reap */
|
||||
#define QUERY_SEND_FLAG 1
|
||||
@ -79,8 +80,8 @@
|
||||
enum {
|
||||
OPT_SKIP_SAFEMALLOC=OPT_MAX_CLIENT_OPTION,
|
||||
OPT_PS_PROTOCOL, OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
|
||||
OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES,
|
||||
OPT_RESULT_FORMAT_VERSION
|
||||
OPT_MAX_CONNECT_RETRIES, OPT_MAX_CONNECTIONS, OPT_MARK_PROGRESS,
|
||||
OPT_LOG_DIR, OPT_TAIL_LINES, OPT_RESULT_FORMAT_VERSION,
|
||||
};
|
||||
|
||||
static int record= 0, opt_sleep= -1;
|
||||
@ -94,6 +95,7 @@ const char *opt_include= 0, *opt_charsets_dir;
|
||||
static int opt_port= 0;
|
||||
static int opt_max_connect_retries;
|
||||
static int opt_result_format_version;
|
||||
static int opt_max_connections= DEFAULT_MAX_CONN;
|
||||
static my_bool opt_compress= 0, silent= 0, verbose= 0;
|
||||
static my_bool debug_info_flag= 0, debug_check_flag= 0;
|
||||
static my_bool tty_password= 0;
|
||||
@ -103,7 +105,7 @@ static my_bool sp_protocol= 0, sp_protocol_enabled= 0;
|
||||
static my_bool view_protocol= 0, view_protocol_enabled= 0;
|
||||
static my_bool cursor_protocol= 0, cursor_protocol_enabled= 0;
|
||||
static my_bool parsing_disabled= 0;
|
||||
static my_bool display_result_vertically= FALSE,
|
||||
static my_bool display_result_vertically= FALSE, display_result_lower= FALSE,
|
||||
display_metadata= FALSE, display_result_sorted= FALSE;
|
||||
static my_bool disable_query_log= 0, disable_result_log= 0;
|
||||
static my_bool disable_warnings= 0;
|
||||
@ -140,6 +142,7 @@ struct st_block
|
||||
int line; /* Start line of block */
|
||||
my_bool ok; /* Should block be executed */
|
||||
enum block_cmd cmd; /* Command owning the block */
|
||||
char delim[MAX_DELIMITER_LENGTH]; /* Delimiter before block */
|
||||
};
|
||||
|
||||
static struct st_block block_stack[32];
|
||||
@ -235,6 +238,8 @@ struct st_connection
|
||||
char *name;
|
||||
size_t name_len;
|
||||
MYSQL_STMT* stmt;
|
||||
/* Set after send to disallow other queries before reap */
|
||||
my_bool pending;
|
||||
|
||||
#ifdef EMBEDDED_LIBRARY
|
||||
const char *cur_query;
|
||||
@ -244,7 +249,8 @@ struct st_connection
|
||||
int query_done;
|
||||
#endif /*EMBEDDED_LIBRARY*/
|
||||
};
|
||||
struct st_connection connections[128];
|
||||
|
||||
struct st_connection *connections= NULL;
|
||||
struct st_connection* cur_con= NULL, *next_con, *connections_end;
|
||||
|
||||
/*
|
||||
@ -278,6 +284,7 @@ enum enum_commands {
|
||||
Q_DISABLE_ABORT_ON_ERROR, Q_ENABLE_ABORT_ON_ERROR,
|
||||
Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
|
||||
Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL, Q_SORTED_RESULT,
|
||||
Q_LOWERCASE,
|
||||
Q_START_TIMER, Q_END_TIMER,
|
||||
Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
|
||||
Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
|
||||
@ -290,7 +297,7 @@ enum enum_commands {
|
||||
Q_LIST_FILES, Q_LIST_FILES_WRITE_FILE, Q_LIST_FILES_APPEND_FILE,
|
||||
Q_SEND_SHUTDOWN, Q_SHUTDOWN_SERVER,
|
||||
Q_RESULT_FORMAT_VERSION,
|
||||
Q_MOVE_FILE, Q_SEND_EVAL,
|
||||
Q_MOVE_FILE, Q_REMOVE_FILES_WILDCARD, Q_SEND_EVAL,
|
||||
Q_UNKNOWN, /* Unknown command. */
|
||||
Q_COMMENT, /* Comments, ignored. */
|
||||
Q_COMMENT_WITH_COMMAND,
|
||||
@ -350,6 +357,7 @@ const char *command_names[]=
|
||||
"query_vertical",
|
||||
"query_horizontal",
|
||||
"sorted_result",
|
||||
"lowercase_result",
|
||||
"start_timer",
|
||||
"end_timer",
|
||||
"character_set",
|
||||
@ -386,6 +394,7 @@ const char *command_names[]=
|
||||
"shutdown_server",
|
||||
"result_format",
|
||||
"move_file",
|
||||
"remove_files_wildcard",
|
||||
"send_eval",
|
||||
|
||||
0
|
||||
@ -490,6 +499,8 @@ void free_replace();
|
||||
void do_get_replace_regex(struct st_command *command);
|
||||
void free_replace_regex();
|
||||
|
||||
/* Used by sleep */
|
||||
void check_eol_junk_line(const char *eol);
|
||||
|
||||
void free_all_replace(){
|
||||
free_replace();
|
||||
@ -1036,7 +1047,7 @@ void check_command_args(struct st_command *command,
|
||||
}
|
||||
/* Check for too many arguments passed */
|
||||
ptr= command->last_argument;
|
||||
while(ptr <= command->end)
|
||||
while(ptr <= command->end && *ptr != '#')
|
||||
{
|
||||
if (*ptr && *ptr != ' ')
|
||||
die("Extra argument '%s' passed to '%.*s'",
|
||||
@ -1094,6 +1105,7 @@ void close_connections()
|
||||
mysql_close(next_con->util_mysql);
|
||||
my_free(next_con->name, MYF(MY_ALLOW_ZERO_PTR));
|
||||
}
|
||||
my_free(connections, MYF(MY_WME));
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
@ -1120,7 +1132,7 @@ void close_files()
|
||||
if (cur_file->file && cur_file->file != stdin)
|
||||
{
|
||||
DBUG_PRINT("info", ("closing file: %s", cur_file->file_name));
|
||||
my_fclose(cur_file->file, MYF(0));
|
||||
fclose(cur_file->file);
|
||||
}
|
||||
my_free((uchar*) cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
|
||||
cur_file->file_name= 0;
|
||||
@ -1134,7 +1146,8 @@ void free_used_memory()
|
||||
uint i;
|
||||
DBUG_ENTER("free_used_memory");
|
||||
|
||||
close_connections();
|
||||
if (connections)
|
||||
close_connections();
|
||||
close_files();
|
||||
my_hash_free(&var_hash);
|
||||
|
||||
@ -2495,7 +2508,7 @@ int open_file(const char *name)
|
||||
if (cur_file == file_stack_end)
|
||||
die("Source directives are nesting too deep");
|
||||
cur_file++;
|
||||
if (!(cur_file->file = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
|
||||
if (!(cur_file->file = fopen(buff, "rb")))
|
||||
{
|
||||
cur_file--;
|
||||
die("Could not open '%s' for reading, errno: %d", buff, errno);
|
||||
@ -2707,6 +2720,10 @@ void do_exec(struct st_command *command)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* exec command is interpreted externally and will not take newlines */
|
||||
while(replace(&ds_cmd, "\n", 1, " ", 1) == 0)
|
||||
;
|
||||
|
||||
DBUG_PRINT("info", ("Executing '%s' as '%s'",
|
||||
command->first_argument, ds_cmd.str));
|
||||
|
||||
@ -2930,6 +2947,81 @@ void do_remove_file(struct st_command *command)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
SYNOPSIS
|
||||
do_remove_files_wildcard
|
||||
command called command
|
||||
|
||||
DESCRIPTION
|
||||
remove_files_wildcard <directory> [<file_name_pattern>]
|
||||
Remove the files in <directory> optionally matching <file_name_pattern>
|
||||
*/
|
||||
|
||||
void do_remove_files_wildcard(struct st_command *command)
|
||||
{
|
||||
int error= 0;
|
||||
uint i;
|
||||
MY_DIR *dir_info;
|
||||
FILEINFO *file;
|
||||
char dir_separator[2];
|
||||
static DYNAMIC_STRING ds_directory;
|
||||
static DYNAMIC_STRING ds_wild;
|
||||
static DYNAMIC_STRING ds_file_to_remove;
|
||||
char dirname[FN_REFLEN];
|
||||
|
||||
const struct command_arg rm_args[] = {
|
||||
{ "directory", ARG_STRING, TRUE, &ds_directory,
|
||||
"Directory containing files to delete" },
|
||||
{ "filename", ARG_STRING, FALSE, &ds_wild, "File pattern to delete" }
|
||||
};
|
||||
DBUG_ENTER("do_remove_files_wildcard");
|
||||
|
||||
check_command_args(command, command->first_argument,
|
||||
rm_args, sizeof(rm_args)/sizeof(struct command_arg),
|
||||
' ');
|
||||
fn_format(dirname, ds_directory.str, "", "", MY_UNPACK_FILENAME);
|
||||
|
||||
DBUG_PRINT("info", ("listing directory: %s", dirname));
|
||||
/* Note that my_dir sorts the list if not given any flags */
|
||||
if (!(dir_info= my_dir(dirname, MYF(MY_DONT_SORT | MY_WANT_STAT))))
|
||||
{
|
||||
error= 1;
|
||||
goto end;
|
||||
}
|
||||
init_dynamic_string(&ds_file_to_remove, dirname, 1024, 1024);
|
||||
dir_separator[0]= FN_LIBCHAR;
|
||||
dir_separator[1]= 0;
|
||||
dynstr_append(&ds_file_to_remove, dir_separator);
|
||||
for (i= 0; i < (uint) dir_info->number_off_files; i++)
|
||||
{
|
||||
file= dir_info->dir_entry + i;
|
||||
/* Remove only regular files, i.e. no directories etc. */
|
||||
/* if (!MY_S_ISREG(file->mystat->st_mode)) */
|
||||
/* MY_S_ISREG does not work here on Windows, just skip directories */
|
||||
if (MY_S_ISDIR(file->mystat->st_mode))
|
||||
continue;
|
||||
if (ds_wild.length &&
|
||||
wild_compare(file->name, ds_wild.str, 0))
|
||||
continue;
|
||||
ds_file_to_remove.length= ds_directory.length + 1;
|
||||
ds_file_to_remove.str[ds_directory.length + 1]= 0;
|
||||
dynstr_append(&ds_file_to_remove, file->name);
|
||||
DBUG_PRINT("info", ("removing file: %s", ds_file_to_remove.str));
|
||||
error= my_delete(ds_file_to_remove.str, MYF(0)) != 0;
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
my_dirend(dir_info);
|
||||
|
||||
end:
|
||||
handle_command_error(command, error);
|
||||
dynstr_free(&ds_directory);
|
||||
dynstr_free(&ds_wild);
|
||||
dynstr_free(&ds_file_to_remove);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
SYNOPSIS
|
||||
do_copy_file
|
||||
@ -3690,49 +3782,58 @@ void do_perl(struct st_command *command)
|
||||
sizeof(perl_args)/sizeof(struct command_arg),
|
||||
' ');
|
||||
|
||||
/* If no delimiter was provided, use EOF */
|
||||
if (ds_delimiter.length == 0)
|
||||
dynstr_set(&ds_delimiter, "EOF");
|
||||
|
||||
init_dynamic_string(&ds_script, "", 1024, 1024);
|
||||
read_until_delimiter(&ds_script, &ds_delimiter);
|
||||
|
||||
DBUG_PRINT("info", ("Executing perl: %s", ds_script.str));
|
||||
|
||||
/* Create temporary file name */
|
||||
if ((fd= create_temp_file(temp_file_path, getenv("MYSQLTEST_VARDIR"),
|
||||
"tmp", O_CREAT | O_SHARE | O_RDWR,
|
||||
MYF(MY_WME))) < 0)
|
||||
die("Failed to create temporary file for perl command");
|
||||
my_close(fd, MYF(0));
|
||||
|
||||
str_to_file(temp_file_path, ds_script.str, ds_script.length);
|
||||
|
||||
/* Format the "perl <filename>" command */
|
||||
my_snprintf(buf, sizeof(buf), "perl %s", temp_file_path);
|
||||
|
||||
if (!(res_file= popen(buf, "r")) && command->abort_on_error)
|
||||
die("popen(\"%s\", \"r\") failed", buf);
|
||||
|
||||
while (fgets(buf, sizeof(buf), res_file))
|
||||
ds_script= command->content;
|
||||
/* If it hasn't been done already by a loop iteration, fill it in */
|
||||
if (! ds_script.str)
|
||||
{
|
||||
if (disable_result_log)
|
||||
{
|
||||
buf[strlen(buf)-1]=0;
|
||||
DBUG_PRINT("exec_result",("%s", buf));
|
||||
}
|
||||
else
|
||||
{
|
||||
replace_dynstr_append(&ds_res, buf);
|
||||
}
|
||||
/* If no delimiter was provided, use EOF */
|
||||
if (ds_delimiter.length == 0)
|
||||
dynstr_set(&ds_delimiter, "EOF");
|
||||
|
||||
init_dynamic_string(&ds_script, "", 1024, 1024);
|
||||
read_until_delimiter(&ds_script, &ds_delimiter);
|
||||
command->content= ds_script;
|
||||
}
|
||||
error= pclose(res_file);
|
||||
|
||||
/* Remove the temporary file */
|
||||
my_delete(temp_file_path, MYF(0));
|
||||
/* This function could be called even if "false", so check before doing */
|
||||
if (cur_block->ok)
|
||||
{
|
||||
DBUG_PRINT("info", ("Executing perl: %s", ds_script.str));
|
||||
|
||||
handle_command_error(command, WEXITSTATUS(error));
|
||||
dynstr_free(&ds_script);
|
||||
/* Create temporary file name */
|
||||
if ((fd= create_temp_file(temp_file_path, getenv("MYSQLTEST_VARDIR"),
|
||||
"tmp", O_CREAT | O_SHARE | O_RDWR,
|
||||
MYF(MY_WME))) < 0)
|
||||
die("Failed to create temporary file for perl command");
|
||||
my_close(fd, MYF(0));
|
||||
|
||||
str_to_file(temp_file_path, ds_script.str, ds_script.length);
|
||||
|
||||
/* Format the "perl <filename>" command */
|
||||
my_snprintf(buf, sizeof(buf), "perl %s", temp_file_path);
|
||||
|
||||
if (!(res_file= popen(buf, "r")) && command->abort_on_error)
|
||||
die("popen(\"%s\", \"r\") failed", buf);
|
||||
|
||||
while (fgets(buf, sizeof(buf), res_file))
|
||||
{
|
||||
if (disable_result_log)
|
||||
{
|
||||
buf[strlen(buf)-1]=0;
|
||||
DBUG_PRINT("exec_result",("%s", buf));
|
||||
}
|
||||
else
|
||||
{
|
||||
replace_dynstr_append(&ds_res, buf);
|
||||
}
|
||||
}
|
||||
error= pclose(res_file);
|
||||
|
||||
/* Remove the temporary file */
|
||||
my_delete(temp_file_path, MYF(0));
|
||||
|
||||
handle_command_error(command, WEXITSTATUS(error));
|
||||
}
|
||||
dynstr_free(&ds_delimiter);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
@ -4140,10 +4241,19 @@ void do_let(struct st_command *command)
|
||||
int do_sleep(struct st_command *command, my_bool real_sleep)
|
||||
{
|
||||
int error= 0;
|
||||
char *p= command->first_argument;
|
||||
char *sleep_start, *sleep_end= command->end;
|
||||
char *sleep_start, *sleep_end;
|
||||
double sleep_val;
|
||||
char *p;
|
||||
static DYNAMIC_STRING ds_sleep;
|
||||
const struct command_arg sleep_args[] = {
|
||||
{ "sleep_delay", ARG_STRING, TRUE, &ds_sleep, "Number of seconds to sleep." }
|
||||
};
|
||||
check_command_args(command, command->first_argument, sleep_args,
|
||||
sizeof(sleep_args)/sizeof(struct command_arg),
|
||||
' ');
|
||||
|
||||
p= ds_sleep.str;
|
||||
sleep_end= ds_sleep.str + ds_sleep.length;
|
||||
while (my_isspace(charset_info, *p))
|
||||
p++;
|
||||
if (!*p)
|
||||
@ -4152,11 +4262,13 @@ int do_sleep(struct st_command *command, my_bool real_sleep)
|
||||
/* Check that arg starts with a digit, not handled by my_strtod */
|
||||
if (!my_isdigit(charset_info, *sleep_start))
|
||||
die("Invalid argument to %.*s \"%s\"", command->first_word_len,
|
||||
command->query,command->first_argument);
|
||||
command->query, sleep_start);
|
||||
sleep_val= my_strtod(sleep_start, &sleep_end, &error);
|
||||
check_eol_junk_line(sleep_end);
|
||||
if (error)
|
||||
die("Invalid argument to %.*s \"%s\"", command->first_word_len,
|
||||
command->query, command->first_argument);
|
||||
dynstr_free(&ds_sleep);
|
||||
|
||||
/* Fixed sleep time selected by --sleep option */
|
||||
if (opt_sleep >= 0 && !real_sleep)
|
||||
@ -4165,7 +4277,6 @@ int do_sleep(struct st_command *command, my_bool real_sleep)
|
||||
DBUG_PRINT("info", ("sleep_val: %f", sleep_val));
|
||||
if (sleep_val)
|
||||
my_sleep((ulong) (sleep_val * 1000000L));
|
||||
command->last_argument= sleep_end;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4703,7 +4814,8 @@ void do_close_connection(struct st_command *command)
|
||||
if (con->util_mysql)
|
||||
mysql_close(con->util_mysql);
|
||||
con->util_mysql= 0;
|
||||
|
||||
con->pending= FALSE;
|
||||
|
||||
my_free(con->name, MYF(0));
|
||||
|
||||
/*
|
||||
@ -5037,7 +5149,7 @@ void do_connect(struct st_command *command)
|
||||
{
|
||||
if (!(con_slot= find_connection_by_name("-closed_connection-")))
|
||||
die("Connection limit exhausted, you can have max %d connections",
|
||||
(int) (sizeof(connections)/sizeof(struct st_connection)));
|
||||
opt_max_connections);
|
||||
}
|
||||
|
||||
#ifdef EMBEDDED_LIBRARY
|
||||
@ -5156,6 +5268,12 @@ int do_done(struct st_command *command)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*cur_block->delim)
|
||||
{
|
||||
/* Restore "old" delimiter after false if block */
|
||||
strcpy (delimiter, cur_block->delim);
|
||||
delimiter_length= strlen(delimiter);
|
||||
}
|
||||
/* Pop block from stack, goto next line */
|
||||
cur_block--;
|
||||
parser.current_line++;
|
||||
@ -5214,6 +5332,7 @@ void do_block(enum block_cmd cmd, struct st_command* command)
|
||||
cur_block++;
|
||||
cur_block->cmd= cmd;
|
||||
cur_block->ok= FALSE;
|
||||
cur_block->delim[0]= '\0';
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
@ -5250,6 +5369,15 @@ void do_block(enum block_cmd cmd, struct st_command* command)
|
||||
if (not_expr)
|
||||
cur_block->ok = !cur_block->ok;
|
||||
|
||||
if (cur_block->ok)
|
||||
{
|
||||
cur_block->delim[0]= '\0';
|
||||
} else
|
||||
{
|
||||
/* Remember "old" delimiter if entering a false if block */
|
||||
strcpy (cur_block->delim, delimiter);
|
||||
}
|
||||
|
||||
DBUG_PRINT("info", ("OK: %d", cur_block->ok));
|
||||
|
||||
var_free(&v);
|
||||
@ -5352,7 +5480,7 @@ int read_line(char *buf, int size)
|
||||
found_eof:
|
||||
if (cur_file->file != stdin)
|
||||
{
|
||||
my_fclose(cur_file->file, MYF(0));
|
||||
fclose(cur_file->file);
|
||||
cur_file->file= 0;
|
||||
}
|
||||
my_free((uchar*) cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
|
||||
@ -5792,6 +5920,10 @@ static struct my_option my_long_options[] =
|
||||
"Max number of connection attempts when connecting to server",
|
||||
(uchar**) &opt_max_connect_retries, (uchar**) &opt_max_connect_retries, 0,
|
||||
GET_INT, REQUIRED_ARG, 500, 1, 10000, 0, 0, 0},
|
||||
{"max-connections", OPT_MAX_CONNECTIONS,
|
||||
"Max number of open connections to server",
|
||||
(uchar**) &opt_max_connections, (uchar**) &opt_max_connections, 0,
|
||||
GET_INT, REQUIRED_ARG, 128, 8, 5120, 0, 0, 0},
|
||||
{"password", 'p', "Password to use when connecting to server.",
|
||||
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"port", 'P', "Port number to use for connection or 0 for default to, in "
|
||||
@ -5964,7 +6096,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
||||
fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
|
||||
DBUG_ASSERT(cur_file == file_stack && cur_file->file == 0);
|
||||
if (!(cur_file->file=
|
||||
my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
|
||||
fopen(buff, "rb")))
|
||||
die("Could not open '%s' for reading, errno: %d", buff, errno);
|
||||
cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
|
||||
cur_file->lineno= 1;
|
||||
@ -6583,8 +6715,11 @@ void run_query_normal(struct st_connection *cn, struct st_command *command,
|
||||
wait_query_thread_end(cn);
|
||||
#endif /*EMBEDDED_LIBRARY*/
|
||||
if (!(flags & QUERY_REAP_FLAG))
|
||||
{
|
||||
cn->pending= TRUE;
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/*
|
||||
@ -6668,6 +6803,7 @@ void run_query_normal(struct st_connection *cn, struct st_command *command,
|
||||
|
||||
end:
|
||||
|
||||
cn->pending= FALSE;
|
||||
/*
|
||||
We save the return code (mysql_errno(mysql)) from the last call sent
|
||||
to the server into the mysqltest builtin variable $mysql_errno. This
|
||||
@ -7144,6 +7280,9 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
|
||||
|
||||
init_dynamic_string(&ds_warnings, NULL, 0, 256);
|
||||
|
||||
if (cn->pending && (flags & QUERY_SEND_FLAG))
|
||||
die ("Cannot run query on connection between send and reap");
|
||||
|
||||
/*
|
||||
Evaluate query if this is an eval command
|
||||
*/
|
||||
@ -7666,12 +7805,6 @@ int main(int argc, char **argv)
|
||||
/* Init expected errors */
|
||||
memset(&saved_expected_errors, 0, sizeof(saved_expected_errors));
|
||||
|
||||
/* Init connections */
|
||||
memset(connections, 0, sizeof(connections));
|
||||
connections_end= connections +
|
||||
(sizeof(connections)/sizeof(struct st_connection)) - 1;
|
||||
next_con= connections + 1;
|
||||
|
||||
#ifdef EMBEDDED_LIBRARY
|
||||
/* set appropriate stack for the 'query' threads */
|
||||
(void) pthread_attr_init(&cn_thd_attrib);
|
||||
@ -7698,7 +7831,14 @@ int main(int argc, char **argv)
|
||||
1024, 0, 0, get_var_key, var_free, MYF(0)))
|
||||
die("Variable hash initialization failed");
|
||||
|
||||
var_set_string("$MYSQL_SERVER_VERSION", MYSQL_SERVER_VERSION);
|
||||
var_set_string("MYSQL_SERVER_VERSION", MYSQL_SERVER_VERSION);
|
||||
var_set_string("MYSQL_SYSTEM_TYPE", SYSTEM_TYPE);
|
||||
var_set_string("MYSQL_MACHINE_TYPE", MACHINE_TYPE);
|
||||
if (sizeof(void *) == 8) {
|
||||
var_set_string("MYSQL_SYSTEM_ARCHITECTURE", "64");
|
||||
} else {
|
||||
var_set_string("MYSQL_SYSTEM_ARCHITECTURE", "32");
|
||||
}
|
||||
|
||||
memset(&master_pos, 0, sizeof(master_pos));
|
||||
|
||||
@ -7726,6 +7866,13 @@ int main(int argc, char **argv)
|
||||
verbose_msg("Tracing progress in '%s'.", progress_file.file_name());
|
||||
}
|
||||
|
||||
/* Init connections, allocate 1 extra as buffer + 1 for default */
|
||||
connections= (struct st_connection*)
|
||||
my_malloc((opt_max_connections+2) * sizeof(struct st_connection),
|
||||
MYF(MY_WME | MY_ZEROFILL));
|
||||
connections_end= connections + opt_max_connections +1;
|
||||
next_con= connections + 1;
|
||||
|
||||
var_set_int("$PS_PROTOCOL", ps_protocol);
|
||||
var_set_int("$SP_PROTOCOL", sp_protocol);
|
||||
var_set_int("$VIEW_PROTOCOL", view_protocol);
|
||||
@ -7829,7 +7976,8 @@ int main(int argc, char **argv)
|
||||
command->type= Q_COMMENT;
|
||||
}
|
||||
|
||||
my_bool ok_to_do= cur_block->ok;
|
||||
/* delimiter needs to be executed so we can continue to parse */
|
||||
my_bool ok_to_do= cur_block->ok || command->type == Q_DELIMITER;
|
||||
/*
|
||||
Some commands need to be "done" the first time if they may get
|
||||
re-iterated over in a true context. This can only happen if there's
|
||||
@ -7887,6 +8035,7 @@ int main(int argc, char **argv)
|
||||
case Q_ECHO: do_echo(command); command_executed++; break;
|
||||
case Q_SYSTEM: do_system(command); break;
|
||||
case Q_REMOVE_FILE: do_remove_file(command); break;
|
||||
case Q_REMOVE_FILES_WILDCARD: do_remove_files_wildcard(command); break;
|
||||
case Q_MKDIR: do_mkdir(command); break;
|
||||
case Q_RMDIR: do_rmdir(command); break;
|
||||
case Q_LIST_FILES: do_list_files(command); break;
|
||||
@ -7924,6 +8073,13 @@ int main(int argc, char **argv)
|
||||
*/
|
||||
display_result_sorted= TRUE;
|
||||
break;
|
||||
case Q_LOWERCASE:
|
||||
/*
|
||||
Turn on lowercasing of result, will be reset after next
|
||||
command
|
||||
*/
|
||||
display_result_lower= TRUE;
|
||||
break;
|
||||
case Q_LET: do_let(command); break;
|
||||
case Q_EVAL_RESULT:
|
||||
die("'eval_result' command is deprecated");
|
||||
@ -8168,8 +8324,9 @@ int main(int argc, char **argv)
|
||||
*/
|
||||
free_all_replace();
|
||||
|
||||
/* Also reset "sorted_result" */
|
||||
/* Also reset "sorted_result" and "lowercase"*/
|
||||
display_result_sorted= FALSE;
|
||||
display_result_lower= FALSE;
|
||||
}
|
||||
last_command_executed= command_executed;
|
||||
|
||||
@ -9509,7 +9666,7 @@ int insert_pointer_name(reg1 POINTER_ARRAY *pa,char * name)
|
||||
if (pa->length+length >= pa->max_length)
|
||||
{
|
||||
if (!(new_pos= (uchar*) my_realloc((uchar*) pa->str,
|
||||
(uint) (pa->max_length+PS_MALLOC),
|
||||
(uint) (pa->length+length+PS_MALLOC),
|
||||
MYF(MY_WME))))
|
||||
DBUG_RETURN(1);
|
||||
if (new_pos != pa->str)
|
||||
@ -9520,7 +9677,7 @@ int insert_pointer_name(reg1 POINTER_ARRAY *pa,char * name)
|
||||
char*);
|
||||
pa->str=new_pos;
|
||||
}
|
||||
pa->max_length+=PS_MALLOC;
|
||||
pa->max_length= pa->length+length+PS_MALLOC;
|
||||
}
|
||||
if (pa->typelib.count >= pa->max_count-1)
|
||||
{
|
||||
@ -9573,6 +9730,18 @@ void replace_dynstr_append_mem(DYNAMIC_STRING *ds,
|
||||
fix_win_paths(val, len);
|
||||
#endif
|
||||
|
||||
if (display_result_lower)
|
||||
{
|
||||
/* Convert to lower case, and do this first */
|
||||
char lower[512];
|
||||
char *c= lower;
|
||||
for (const char *v= val; *v; v++)
|
||||
*c++= my_tolower(charset_info, *v);
|
||||
*c= '\0';
|
||||
/* Copy from this buffer instead */
|
||||
val= lower;
|
||||
}
|
||||
|
||||
if (glob_replace_regex)
|
||||
{
|
||||
/* Regex replace */
|
||||
|
@ -38,6 +38,23 @@ extern "C" {
|
||||
|
||||
#define my_wc_t ulong
|
||||
|
||||
|
||||
/*
|
||||
On i386 we store Unicode->CS conversion tables for
|
||||
some character sets using Big-endian order,
|
||||
to copy two bytes at onces.
|
||||
This gives some performance improvement.
|
||||
*/
|
||||
#ifdef __i386__
|
||||
#define MB2(x) (((x) >> 8) + (((x) & 0xFF) << 8))
|
||||
#define MY_PUT_MB2(s, code) { *((uint16*)(s))= (code); }
|
||||
#else
|
||||
#define MB2(x) (x)
|
||||
#define MY_PUT_MB2(s, code) { (s)[0]= code >> 8; (s)[1]= code & 0xFF; }
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
typedef struct unicase_info_st
|
||||
{
|
||||
uint32 toupper;
|
||||
|
@ -191,10 +191,11 @@ enum ha_extra_function {
|
||||
/* Inform handler that we will do a rename */
|
||||
HA_EXTRA_PREPARE_FOR_RENAME,
|
||||
/*
|
||||
Orders MERGE handler to attach or detach its child tables. Used at
|
||||
begin and end of a statement.
|
||||
Special actions for MERGE tables.
|
||||
*/
|
||||
HA_EXTRA_ADD_CHILDREN_LIST,
|
||||
HA_EXTRA_ATTACH_CHILDREN,
|
||||
HA_EXTRA_IS_ATTACHED_CHILDREN,
|
||||
HA_EXTRA_DETACH_CHILDREN
|
||||
};
|
||||
|
||||
|
@ -1598,7 +1598,7 @@ inline void operator delete[](void*, void*) { /* Do nothing */ }
|
||||
#if !defined(max)
|
||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
#endif
|
||||
/*
|
||||
Only Linux is known to need an explicit sync of the directory to make sure a
|
||||
file creation/deletion/renaming in(from,to) this directory durable.
|
||||
@ -1611,6 +1611,25 @@ inline void operator delete[](void*, void*) { /* Do nothing */ }
|
||||
#define bool In_C_you_should_use_my_bool_instead()
|
||||
#endif
|
||||
|
||||
/* Provide __func__ macro definition for platforms that miss it. */
|
||||
#if __STDC_VERSION__ < 199901L
|
||||
# if __GNUC__ >= 2
|
||||
# define __func__ __FUNCTION__
|
||||
# else
|
||||
# define __func__ "<unknown>"
|
||||
# endif
|
||||
#elif defined(_MSC_VER)
|
||||
# if _MSC_VER < 1300
|
||||
# define __func__ "<unknown>"
|
||||
# else
|
||||
# define __func__ __FUNCTION__
|
||||
# endif
|
||||
#elif defined(__BORLANDC__)
|
||||
# define __func__ __FUNC__
|
||||
#else
|
||||
# define __func__ "<unknown>"
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_RINT
|
||||
/**
|
||||
All integers up to this number can be represented exactly as double precision
|
||||
|
@ -102,6 +102,19 @@ struct timespec {
|
||||
(ABSTIME).max_timeout_msec= (long)((NSEC)/1000000); \
|
||||
}
|
||||
|
||||
/**
|
||||
Compare two timespec structs.
|
||||
|
||||
@retval 1 If TS1 ends after TS2.
|
||||
|
||||
@retval 0 If TS1 is equal to TS2.
|
||||
|
||||
@retval -1 If TS1 ends before TS2.
|
||||
*/
|
||||
#define cmp_timespec(TS1, TS2) \
|
||||
((TS1.tv.i64 > TS2.tv.i64) ? 1 : \
|
||||
((TS1.tv.i64 < TS2.tv.i64) ? -1 : 0))
|
||||
|
||||
|
||||
int win_pthread_mutex_trylock(pthread_mutex_t *mutex);
|
||||
int pthread_create(pthread_t *, const pthread_attr_t *, pthread_handler, void *);
|
||||
@ -412,6 +425,33 @@ int my_pthread_mutex_trylock(pthread_mutex_t *mutex);
|
||||
(ABSTIME).tv_nsec= (long) (now % ULL(10000000) * 100 + ((NSEC) % 100)); \
|
||||
}
|
||||
#endif /* !set_timespec_nsec */
|
||||
#endif /* HAVE_TIMESPEC_TS_SEC */
|
||||
|
||||
/**
|
||||
Compare two timespec structs.
|
||||
|
||||
@retval 1 If TS1 ends after TS2.
|
||||
|
||||
@retval 0 If TS1 is equal to TS2.
|
||||
|
||||
@retval -1 If TS1 ends before TS2.
|
||||
*/
|
||||
#ifdef HAVE_TIMESPEC_TS_SEC
|
||||
#ifndef cmp_timespec
|
||||
#define cmp_timespec(TS1, TS2) \
|
||||
((TS1.ts_sec > TS2.ts_sec || \
|
||||
(TS1.ts_sec == TS2.ts_sec && TS1.ts_nsec > TS2.ts_nsec)) ? 1 : \
|
||||
((TS1.ts_sec < TS2.ts_sec || \
|
||||
(TS1.ts_sec == TS2.ts_sec && TS1.ts_nsec < TS2.ts_nsec)) ? -1 : 0))
|
||||
#endif /* !cmp_timespec */
|
||||
#else
|
||||
#ifndef cmp_timespec
|
||||
#define cmp_timespec(TS1, TS2) \
|
||||
((TS1.tv_sec > TS2.tv_sec || \
|
||||
(TS1.tv_sec == TS2.tv_sec && TS1.tv_nsec > TS2.tv_nsec)) ? 1 : \
|
||||
((TS1.tv_sec < TS2.tv_sec || \
|
||||
(TS1.tv_sec == TS2.tv_sec && TS1.tv_nsec < TS2.tv_nsec)) ? -1 : 0))
|
||||
#endif /* !cmp_timespec */
|
||||
#endif /* HAVE_TIMESPEC_TS_SEC */
|
||||
|
||||
/* safe_mutex adds checking to mutex for easier debugging */
|
||||
|
@ -235,6 +235,9 @@ extern void (*fatal_error_handler_hook)(uint my_err, const char *str,
|
||||
extern uint my_file_limit;
|
||||
extern ulong my_thread_stack_size;
|
||||
|
||||
extern const char *(*proc_info_hook)(void *, const char *, const char *,
|
||||
const char *, const unsigned int);
|
||||
|
||||
#ifdef HAVE_LARGE_PAGES
|
||||
extern my_bool my_use_large_pages;
|
||||
extern uint my_large_page_size;
|
||||
|
@ -83,7 +83,6 @@ enum enum_thr_lock_result { THR_LOCK_SUCCESS= 0, THR_LOCK_ABORTED= 1,
|
||||
|
||||
|
||||
extern ulong max_write_lock_count;
|
||||
extern ulong table_lock_wait_timeout;
|
||||
extern my_bool thr_lock_inited;
|
||||
extern enum thr_lock_type thr_upgraded_concurrent_insert_lock;
|
||||
|
||||
@ -156,19 +155,25 @@ void thr_lock_data_init(THR_LOCK *lock,THR_LOCK_DATA *data,
|
||||
void *status_param);
|
||||
enum enum_thr_lock_result thr_lock(THR_LOCK_DATA *data,
|
||||
THR_LOCK_OWNER *owner,
|
||||
enum thr_lock_type lock_type);
|
||||
enum thr_lock_type lock_type,
|
||||
ulong lock_wait_timeout);
|
||||
void thr_unlock(THR_LOCK_DATA *data);
|
||||
enum enum_thr_lock_result thr_multi_lock(THR_LOCK_DATA **data,
|
||||
uint count, THR_LOCK_OWNER *owner);
|
||||
uint count, THR_LOCK_OWNER *owner,
|
||||
ulong lock_wait_timeout);
|
||||
void thr_multi_unlock(THR_LOCK_DATA **data,uint count);
|
||||
void
|
||||
thr_lock_merge_status(THR_LOCK_DATA **data, uint count);
|
||||
void thr_abort_locks(THR_LOCK *lock, my_bool upgrade_lock);
|
||||
my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread);
|
||||
void thr_print_locks(void); /* For debugging */
|
||||
my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data,
|
||||
enum thr_lock_type new_lock_type);
|
||||
enum thr_lock_type new_lock_type,
|
||||
ulong lock_wait_timeout);
|
||||
void thr_downgrade_write_lock(THR_LOCK_DATA *data,
|
||||
enum thr_lock_type new_lock_type);
|
||||
my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data);
|
||||
my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data,
|
||||
ulong lock_wait_timeout);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -135,6 +135,7 @@ SET(LIBMYSQLD_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
|
||||
../sql/scheduler.cc ../sql/sql_audit.cc
|
||||
../sql/event_parse_data.cc
|
||||
../sql/sql_signal.cc ../sql/rpl_handler.cc
|
||||
../sql/mdl.cc ../sql/transaction.cc
|
||||
${GEN_SOURCES}
|
||||
${LIB_SOURCES})
|
||||
|
||||
|
@ -75,11 +75,10 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
|
||||
sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \
|
||||
parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
|
||||
rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
|
||||
debug_sync.cc \
|
||||
sql_tablespace.cc \
|
||||
debug_sync.cc sql_tablespace.cc transaction.cc \
|
||||
rpl_injector.cc my_user.c partition_info.cc \
|
||||
sql_servers.cc sql_audit.cc event_parse_data.cc \
|
||||
sql_signal.cc rpl_handler.cc keycaches.cc
|
||||
sql_servers.cc event_parse_data.cc sql_signal.cc \
|
||||
rpl_handler.cc mdl.cc keycaches.cc sql_audit.cc
|
||||
|
||||
libmysqld_int_a_SOURCES= $(libmysqld_sources)
|
||||
nodist_libmysqld_int_a_SOURCES= $(libmysqlsources) $(sqlsources)
|
||||
|
34
mysql-test/extra/binlog_tests/drop_table.test
Normal file
34
mysql-test/extra/binlog_tests/drop_table.test
Normal file
@ -0,0 +1,34 @@
|
||||
#
|
||||
# Bug#989: If DROP TABLE while there's an active transaction, wrong binlog order
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
--enable_warnings
|
||||
|
||||
connect (con1,localhost,root,,);
|
||||
connect (con2,localhost,root,,);
|
||||
|
||||
connection con1;
|
||||
RESET MASTER;
|
||||
CREATE TABLE t1 (a INT);
|
||||
SET AUTOCOMMIT=OFF;
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(1);
|
||||
|
||||
connection con2;
|
||||
--send DROP TABLE t1;
|
||||
|
||||
connection con1;
|
||||
COMMIT;
|
||||
|
||||
connection con2;
|
||||
--reap
|
||||
|
||||
connection default;
|
||||
|
||||
--disconnect con1
|
||||
--disconnect con2
|
||||
|
||||
let $VERSION=`select version()`;
|
||||
source include/show_binlog_events.inc;
|
@ -205,6 +205,10 @@ select (@after:=unix_timestamp())*0; # always give repeatable output
|
||||
# the bug, the reap would return immediately after the insert into t2.
|
||||
select (@after-@before) >= 2;
|
||||
|
||||
connection con3;
|
||||
commit;
|
||||
|
||||
connection con2;
|
||||
drop table t1,t2;
|
||||
commit;
|
||||
|
||||
|
@ -118,6 +118,71 @@ connection master;
|
||||
FLUSH LOGS;
|
||||
|
||||
DROP DATABASE mysqltest1;
|
||||
-- source include/master-slave-end.inc
|
||||
|
||||
--echo End of 5.1 tests
|
||||
|
||||
--echo #
|
||||
--echo # Bug#39675 rename tables on innodb tables with pending
|
||||
--echo # transactions causes slave data issue.
|
||||
--echo #
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
DROP TABLE IF EXISTS t3;
|
||||
--enable_warnings
|
||||
|
||||
CREATE TABLE t1 (
|
||||
id INT PRIMARY KEY auto_increment,
|
||||
b INT DEFAULT NULL
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE t2 (
|
||||
id INT PRIMARY KEY auto_increment,
|
||||
b INT DEFAULT NULL
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
INSERT INTO t1 (b) VALUES (1),(2),(3);
|
||||
|
||||
BEGIN;
|
||||
INSERT INTO t1(b) VALUES (4);
|
||||
|
||||
--echo -------- switch to master1 --------
|
||||
connection master1;
|
||||
--send RENAME TABLE t1 TO t3, t2 TO t1;
|
||||
|
||||
--echo -------- switch to master --------
|
||||
connection master;
|
||||
# Need to wait until RENAME is received
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
||||
WHERE info = "RENAME TABLE t1 TO t3, t2 TO t1" and
|
||||
state = "Waiting for table";
|
||||
--source include/wait_condition.inc
|
||||
|
||||
COMMIT;
|
||||
|
||||
--echo -------- switch to master1 --------
|
||||
connection master1;
|
||||
--reap
|
||||
|
||||
--echo -------- switch to master --------
|
||||
connection master;
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t3;
|
||||
|
||||
sync_slave_with_master;
|
||||
|
||||
--echo -------- switch to slave --------
|
||||
connection slave;
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t3;
|
||||
|
||||
--echo -------- switch to master --------
|
||||
connection master;
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t3;
|
||||
|
||||
--echo End of 6.0 tests
|
||||
|
||||
--source include/master-slave-end.inc
|
||||
|
@ -729,15 +729,15 @@ call p_verify_status_increment(2, 0, 4, 4);
|
||||
alter table t3 add column (b int);
|
||||
call p_verify_status_increment(2, 0, 2, 0);
|
||||
alter table t3 rename t4;
|
||||
call p_verify_status_increment(1, 0, 1, 0);
|
||||
call p_verify_status_increment(2, 0, 2, 0);
|
||||
rename table t4 to t3;
|
||||
call p_verify_status_increment(1, 0, 1, 0);
|
||||
call p_verify_status_increment(0, 0, 0, 0);
|
||||
truncate table t3;
|
||||
call p_verify_status_increment(2, 0, 2, 0);
|
||||
create view v1 as select * from t2;
|
||||
call p_verify_status_increment(1, 0, 1, 0);
|
||||
call p_verify_status_increment(2, 0, 2, 0);
|
||||
check table t1;
|
||||
call p_verify_status_increment(3, 0, 3, 0);
|
||||
call p_verify_status_increment(2, 0, 2, 0);
|
||||
--echo # Sic: after this bug is fixed, CHECK leaves no pending transaction
|
||||
commit;
|
||||
call p_verify_status_increment(0, 0, 0, 0);
|
||||
|
44
mysql-test/include/ctype_utf8_table.inc
Normal file
44
mysql-test/include/ctype_utf8_table.inc
Normal file
@ -0,0 +1,44 @@
|
||||
CREATE TABLE t1 (a CHAR(1)) CHARACTER SET utf8;
|
||||
INSERT INTO t1 VALUES ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7');
|
||||
INSERT INTO t1 VALUES ('8'),('9'),('A'),('B'),('C'),('D'),('E'),('F');
|
||||
#
|
||||
# Populate tables head and tail with values '00'-'FF'
|
||||
#
|
||||
CREATE TEMPORARY TABLE head AS SELECT concat(b1.a, b2.a) AS head FROM t1 b1, t1 b2;
|
||||
CREATE TEMPORARY TABLE tail AS SELECT concat(b1.a, b2.a) AS tail FROM t1 b1, t1 b2;
|
||||
CREATE TEMPORARY TABLE middle AS SELECT concat(b1.a, b2.a) AS middle FROM t1 b1, t1 b2;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a varchar(1)) CHARACTER SET utf8;
|
||||
|
||||
#
|
||||
# Populate single byte characters
|
||||
#
|
||||
|
||||
INSERT INTO t1 SELECT UNHEX(head)
|
||||
FROM head WHERE (head BETWEEN '00' AND '7F') ORDER BY head;
|
||||
|
||||
#
|
||||
# Populate 2-byte byte characters: U+80..U+7FF: [C2-DF][80-BF]
|
||||
#
|
||||
INSERT INTO t1
|
||||
SELECT UNHEX(CONCAT(head,tail))
|
||||
FROM head, tail
|
||||
WHERE (head BETWEEN 'C2' AND 'DF') AND (tail BETWEEN '80' AND 'BF')
|
||||
ORDER BY head, tail;
|
||||
|
||||
|
||||
#
|
||||
# Populate 3-byte characters: U+800..U+FFFF: [E0-EF][80-BF][80-BF]
|
||||
# excluding overlong [E0][80-9F][80-BF]
|
||||
#
|
||||
INSERT INTO t1
|
||||
SELECT UNHEX(CONCAT(head, middle, tail))
|
||||
FROM head, middle, tail
|
||||
WHERE (head BETWEEN 'E0' AND 'EF')
|
||||
AND (middle BETWEEN '80' AND 'BF')
|
||||
AND (tail BETWEEN '80' AND 'BF')
|
||||
AND NOT (head='E0' AND middle BETWEEN '80' AND '9F')
|
||||
ORDER BY head, middle, tail;
|
||||
|
||||
SELECT count(*) FROM t1;
|
File diff suppressed because it is too large
Load Diff
5
mysql-test/include/implicit_commit_helper.inc
Normal file
5
mysql-test/include/implicit_commit_helper.inc
Normal file
@ -0,0 +1,5 @@
|
||||
INSERT INTO db1.trans (a) VALUES (1);
|
||||
--disable_result_log
|
||||
eval $statement;
|
||||
--enable_result_log
|
||||
CALL db1.test_if_commit();
|
@ -899,6 +899,8 @@ CREATE PROCEDURE p1 ()
|
||||
BEGIN
|
||||
DECLARE i INT DEFAULT 50;
|
||||
DECLARE cnt INT;
|
||||
# Continue even in the presence of ER_LOCK_DEADLOCK.
|
||||
DECLARE CONTINUE HANDLER FOR 1213 BEGIN END;
|
||||
START TRANSACTION;
|
||||
ALTER TABLE t1 ENGINE=InnoDB;
|
||||
COMMIT;
|
||||
@ -1392,6 +1394,7 @@ SELECT * FROM t1;
|
||||
connection con2;
|
||||
--reap
|
||||
SELECT * FROM t1;
|
||||
COMMIT;
|
||||
|
||||
--echo # Switch to connection con1
|
||||
connection con1;
|
||||
|
@ -1994,6 +1994,7 @@ commit;
|
||||
connection b;
|
||||
set autocommit = 0;
|
||||
update t1 set b = 5 where a = 2;
|
||||
commit;
|
||||
connection a;
|
||||
delimiter |;
|
||||
create trigger t1t before insert on t1 for each row begin set NEW.b = NEW.a * 10 + 5, NEW.c = NEW.a / 10; end |
|
||||
@ -2056,6 +2057,7 @@ update t2 set b = b + 5 where a = 1;
|
||||
update t3 set b = b + 5 where a = 1;
|
||||
update t4 set b = b + 5 where a = 1;
|
||||
insert into t5(a) values(20);
|
||||
commit;
|
||||
connection b;
|
||||
set autocommit = 0;
|
||||
insert into t1(a) values(7);
|
||||
|
@ -194,6 +194,35 @@ INSERT INTO global_suppressions VALUES
|
||||
("Slave I/O: Get master COLLATION_SERVER failed with error:.*"),
|
||||
("Slave I/O: Get master TIME_ZONE failed with error:.*"),
|
||||
|
||||
/* Messages from valgrind */
|
||||
("==[0-9]*== Memcheck,"),
|
||||
("==[0-9]*== Copyright"),
|
||||
("==[0-9]*== Using"),
|
||||
("==[0-9]*== For more details"),
|
||||
/* This comes with innodb plugin tests */
|
||||
("==[0-9]*== Warning: set address range perms: large range"),
|
||||
|
||||
/* valgrind warnings: invalid file descriptor -1 in syscall
|
||||
write()/read(). Bug #50414 */
|
||||
("==[0-9]*== Warning: invalid file descriptor -1 in syscall write()"),
|
||||
("==[0-9]*== Warning: invalid file descriptor -1 in syscall read()"),
|
||||
|
||||
/*
|
||||
Transient network failures that cause warnings on reconnect.
|
||||
BUG#47743 and BUG#47983.
|
||||
*/
|
||||
("Slave I/O: Get master SERVER_ID failed with error:.*"),
|
||||
("Slave I/O: Get master clock failed with error:.*"),
|
||||
("Slave I/O: Get master COLLATION_SERVER failed with error:.*"),
|
||||
("Slave I/O: Get master TIME_ZONE failed with error:.*"),
|
||||
/*
|
||||
BUG#42147 - Concurrent DML and LOCK TABLE ... READ for InnoDB
|
||||
table cause warnings in errlog
|
||||
Note: This is a temporary suppression until Bug#42147 can be
|
||||
fixed properly. See bug page for more information.
|
||||
*/
|
||||
("Found lock of type 6 that is write and read locked"),
|
||||
|
||||
("THE_LAST_SUPPRESSION")||
|
||||
|
||||
|
||||
|
@ -81,24 +81,28 @@ sub is_child {
|
||||
}
|
||||
|
||||
|
||||
# Find the safe process binary or script
|
||||
my @safe_process_cmd;
|
||||
my $safe_kill;
|
||||
if (IS_WIN32PERL or IS_CYGWIN){
|
||||
# Use my_safe_process.exe
|
||||
my $exe= my_find_bin(".", ["lib/My/SafeProcess", "My/SafeProcess"],
|
||||
"my_safe_process");
|
||||
push(@safe_process_cmd, $exe);
|
||||
|
||||
# Use my_safe_kill.exe
|
||||
$safe_kill= my_find_bin(".", "lib/My/SafeProcess", "my_safe_kill");
|
||||
}
|
||||
else
|
||||
{
|
||||
# Use my_safe_process
|
||||
my $exe= my_find_bin(".", ["lib/My/SafeProcess", "My/SafeProcess"],
|
||||
"my_safe_process");
|
||||
push(@safe_process_cmd, $exe);
|
||||
# Find the safe process binary or script
|
||||
sub find_bin {
|
||||
if (IS_WIN32PERL or IS_CYGWIN)
|
||||
{
|
||||
# Use my_safe_process.exe
|
||||
my $exe= my_find_bin(".", ["lib/My/SafeProcess", "My/SafeProcess"],
|
||||
"my_safe_process");
|
||||
push(@safe_process_cmd, $exe);
|
||||
|
||||
# Use my_safe_kill.exe
|
||||
$safe_kill= my_find_bin(".", "lib/My/SafeProcess", "my_safe_kill");
|
||||
}
|
||||
else
|
||||
{
|
||||
# Use my_safe_process
|
||||
my $exe= my_find_bin(".", ["lib/My/SafeProcess", "My/SafeProcess"],
|
||||
"my_safe_process");
|
||||
push(@safe_process_cmd, $exe);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -183,63 +187,6 @@ sub run {
|
||||
return $proc->exit_status();
|
||||
}
|
||||
|
||||
#
|
||||
# Start a process that returns after "duration" seconds
|
||||
# or when it's parent process does not exist anymore
|
||||
#
|
||||
sub timer {
|
||||
my $class= shift;
|
||||
my $duration= shift or croak "duration required";
|
||||
my $parent_pid= $$;
|
||||
|
||||
my $pid= My::SafeProcess::Base::_safe_fork();
|
||||
if ($pid){
|
||||
# Parent
|
||||
my $proc= bless
|
||||
({
|
||||
SAFE_PID => $pid,
|
||||
SAFE_NAME => "timer",
|
||||
PARENT => $$,
|
||||
}, $class);
|
||||
|
||||
# Put the new process in list of running
|
||||
$running{$pid}= $proc;
|
||||
return $proc;
|
||||
}
|
||||
|
||||
# Child, install signal handlers and sleep for "duration"
|
||||
$SIG{INT}= 'IGNORE';
|
||||
|
||||
$SIG{TERM}= sub {
|
||||
#print STDERR "timer $$: woken up, exiting!\n";
|
||||
exit(0);
|
||||
};
|
||||
|
||||
$0= "safe_timer($duration)";
|
||||
|
||||
if (IS_WIN32PERL){
|
||||
# Just a thread in same process
|
||||
sleep($duration);
|
||||
print STDERR "timer $$: expired after $duration seconds\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
my $count_down= $duration;
|
||||
while($count_down--){
|
||||
|
||||
# Check that parent is still alive
|
||||
if (kill(0, $parent_pid) == 0){
|
||||
#print STDERR "timer $$: parent gone, exiting!\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
print STDERR "timer $$: expired after $duration seconds\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Shutdown process nicely, and wait for shutdown_timeout seconds
|
||||
# If processes hasn't shutdown, kill them hard and wait for return
|
||||
@ -338,12 +285,12 @@ sub start_kill {
|
||||
$ret= system($safe_kill, $winpid) >> 8;
|
||||
|
||||
if ($ret == 3){
|
||||
print "Couldn't open the winpid: $winpid ",
|
||||
print "Couldn't open the winpid: $winpid ".
|
||||
"for pid: $pid, try one more time\n";
|
||||
sleep(1);
|
||||
$winpid= _winpid($pid);
|
||||
$ret= system($safe_kill, $winpid) >> 8;
|
||||
print "Couldn't open the winpid: $winpid ",
|
||||
print "Couldn't open the winpid: $winpid ".
|
||||
"for pid: $pid, continue and see what happens...\n";
|
||||
}
|
||||
}
|
||||
@ -537,6 +484,40 @@ sub wait_any {
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Wait for any process to exit, or a timeout
|
||||
#
|
||||
# Returns a reference to the SafeProcess that
|
||||
# exited or a pseudo-process with $proc->{timeout} == 1
|
||||
#
|
||||
|
||||
sub wait_any_timeout {
|
||||
my $class= shift;
|
||||
my $timeout= shift;
|
||||
my $proc;
|
||||
my $millis=10;
|
||||
|
||||
do {
|
||||
::mtr_milli_sleep($millis);
|
||||
# Slowly increse interval up to max. 1 second
|
||||
$millis++ if $millis < 1000;
|
||||
# Return a "fake" process for timeout
|
||||
if (::has_expired($timeout)) {
|
||||
$proc= bless
|
||||
({
|
||||
SAFE_PID => 0,
|
||||
SAFE_NAME => "timer",
|
||||
timeout => 1,
|
||||
}, $class);
|
||||
} else {
|
||||
$proc= check_any();
|
||||
}
|
||||
} while (! $proc);
|
||||
|
||||
return $proc;
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Wait for all processes to exit
|
||||
#
|
||||
@ -594,7 +575,7 @@ sub self2str {
|
||||
|
||||
sub _verbose {
|
||||
return unless $_verbose;
|
||||
print STDERR " ## ", @_, "\n";
|
||||
print STDERR " ## ". @_. "\n";
|
||||
}
|
||||
|
||||
|
||||
|
@ -186,14 +186,20 @@ int main(int argc, const char** argv )
|
||||
die("No real args -> nothing to do");
|
||||
/* Copy the remaining args to child_arg */
|
||||
for (int j= i+1; j < argc; j++) {
|
||||
if (strchr (argv[j], ' ')) {
|
||||
/* Protect with "" if this arg contains a space */
|
||||
to+= _snprintf(to, child_args + sizeof(child_args) - to,
|
||||
"\"%s\" ", argv[j]);
|
||||
} else {
|
||||
to+= _snprintf(to, child_args + sizeof(child_args) - to,
|
||||
"%s ", argv[j]);
|
||||
}
|
||||
arg= argv[j];
|
||||
if (strchr (arg, ' ') &&
|
||||
arg[0] != '\"' &&
|
||||
arg[strlen(arg)] != '\"')
|
||||
{
|
||||
/* Quote arg that contains spaces and are not quoted already */
|
||||
to+= _snprintf(to, child_args + sizeof(child_args) - to,
|
||||
"\"%s\" ", arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
to+= _snprintf(to, child_args + sizeof(child_args) - to,
|
||||
"%s ", arg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
|
@ -40,7 +40,6 @@ our $default_storage_engine;
|
||||
our $opt_with_ndbcluster_only;
|
||||
our $defaults_file;
|
||||
our $defaults_extra_file;
|
||||
our $reorder= 1;
|
||||
our $quick_collect;
|
||||
|
||||
sub collect_option {
|
||||
@ -99,7 +98,8 @@ sub init_pattern {
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
sub collect_test_cases ($$) {
|
||||
sub collect_test_cases ($$$) {
|
||||
my $opt_reorder= shift; # True if we're reordering tests
|
||||
my $suites= shift; # Semicolon separated list of test suites
|
||||
my $opt_cases= shift;
|
||||
my $cases= []; # Array of hash(one hash for each testcase)
|
||||
@ -118,10 +118,16 @@ sub collect_test_cases ($$) {
|
||||
!(IS_WINDOWS && $::opt_embedded_server) &&
|
||||
$lib_innodb_plugin);
|
||||
|
||||
foreach my $suite (split(",", $suites))
|
||||
# If not reordering, we also shouldn't group by suites, unless
|
||||
# no test cases were named.
|
||||
# This also effects some logic in the loop following this.
|
||||
if ($opt_reorder or !@$opt_cases)
|
||||
{
|
||||
push(@$cases, collect_one_suite($suite, $opt_cases));
|
||||
last if $some_test_found;
|
||||
foreach my $suite (split(",", $suites))
|
||||
{
|
||||
push(@$cases, collect_one_suite($suite, $opt_cases));
|
||||
last if $some_test_found;
|
||||
}
|
||||
}
|
||||
|
||||
if ( @$opt_cases )
|
||||
@ -135,6 +141,7 @@ sub collect_test_cases ($$) {
|
||||
my ($sname, $tname, $extension)= split_testname($test_name_spec);
|
||||
foreach my $test ( @$cases )
|
||||
{
|
||||
last unless $opt_reorder;
|
||||
# test->{name} is always in suite.name format
|
||||
if ( $test->{name} =~ /.*\.$tname/ )
|
||||
{
|
||||
@ -144,12 +151,13 @@ sub collect_test_cases ($$) {
|
||||
}
|
||||
if ( not $found )
|
||||
{
|
||||
$sname= "main" if !$opt_reorder and !$sname;
|
||||
mtr_error("Could not find '$tname' in '$suites' suite(s)") unless $sname;
|
||||
# If suite was part of name, find it there
|
||||
my ($this_case) = collect_one_suite($sname, [ $tname ]);
|
||||
if ($this_case)
|
||||
# If suite was part of name, find it there, may come with combinations
|
||||
my @this_case = collect_one_suite($sname, [ $tname ]);
|
||||
if (@this_case)
|
||||
{
|
||||
push (@$cases, $this_case);
|
||||
push (@$cases, @this_case);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -159,7 +167,7 @@ sub collect_test_cases ($$) {
|
||||
}
|
||||
}
|
||||
|
||||
if ( $reorder && !$quick_collect)
|
||||
if ( $opt_reorder && !$quick_collect)
|
||||
{
|
||||
# Reorder the test cases in an order that will make them faster to run
|
||||
my %sort_criteria;
|
||||
|
@ -20,43 +20,20 @@
|
||||
|
||||
use strict;
|
||||
|
||||
# These are not to be prefixed with "mtr_"
|
||||
sub gprof_collect ($@) {
|
||||
my ($exe_mysqld, @gprof_dirs)= @_;
|
||||
|
||||
sub gprof_prepare ();
|
||||
sub gprof_collect ();
|
||||
print ("Collecting gprof reports.....\n");
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
#
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
sub gprof_prepare () {
|
||||
|
||||
rmtree($::opt_gprof_dir);
|
||||
mkdir($::opt_gprof_dir);
|
||||
}
|
||||
|
||||
# FIXME what about master1 and slave1?!
|
||||
sub gprof_collect () {
|
||||
|
||||
if ( -f "$::master->[0]->{'path_myddir'}/gmon.out" )
|
||||
foreach my $datadir (@gprof_dirs)
|
||||
{
|
||||
# FIXME check result code?!
|
||||
mtr_run("gprof",
|
||||
[$::exe_master_mysqld,
|
||||
"$::master->[0]->{'path_myddir'}/gmon.out"],
|
||||
$::opt_gprof_master, "", "", "");
|
||||
print "Master execution profile has been saved in $::opt_gprof_master\n";
|
||||
}
|
||||
if ( -f "$::slave->[0]->{'path_myddir'}/gmon.out" )
|
||||
{
|
||||
# FIXME check result code?!
|
||||
mtr_run("gprof",
|
||||
[$::exe_slave_mysqld,
|
||||
"$::slave->[0]->{'path_myddir'}/gmon.out"],
|
||||
$::opt_gprof_slave, "", "", "");
|
||||
print "Slave execution profile has been saved in $::opt_gprof_slave\n";
|
||||
my $gprof_msg= "$datadir/gprof.msg";
|
||||
my $gprof_err= "$datadir/gprof.err";
|
||||
if ( -f "$datadir/gmon.out" )
|
||||
{
|
||||
system("gprof $exe_mysqld $datadir/gmon.out 2>$gprof_err >$gprof_msg");
|
||||
print ("GPROF output in $gprof_msg, errors in $gprof_err\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,9 @@ sub mtr_script_exists(@);
|
||||
sub mtr_file_exists(@);
|
||||
sub mtr_exe_exists(@);
|
||||
sub mtr_exe_maybe_exists(@);
|
||||
|
||||
sub mtr_milli_sleep($);
|
||||
sub start_timer($);
|
||||
sub has_expired($);
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@ -167,11 +169,18 @@ sub mtr_exe_exists (@) {
|
||||
}
|
||||
|
||||
|
||||
sub mtr_milli_sleep {
|
||||
sub mtr_milli_sleep ($) {
|
||||
die "usage: mtr_milli_sleep(milliseconds)" unless @_ == 1;
|
||||
my ($millis)= @_;
|
||||
|
||||
select(undef, undef, undef, ($millis/1000));
|
||||
}
|
||||
|
||||
# Simple functions to start and check timers (have to be actively polled)
|
||||
# Timer can be "killed" by setting it to 0
|
||||
|
||||
sub start_timer ($) { return time + $_[0]; }
|
||||
|
||||
sub has_expired ($) { return $_[0] && time gt $_[0]; }
|
||||
|
||||
1;
|
||||
|
@ -69,7 +69,7 @@ sub _mtr_report_test_name ($) {
|
||||
$tname.= " '$tinfo->{combination}'"
|
||||
if defined $tinfo->{combination};
|
||||
|
||||
print _name(), _timestamp();
|
||||
print _name(). _timestamp();
|
||||
printf "%-40s ", $tname;
|
||||
my $worker = $tinfo->{worker};
|
||||
printf "w$worker " if $worker;
|
||||
@ -222,8 +222,8 @@ sub mtr_report_test ($) {
|
||||
}
|
||||
|
||||
|
||||
sub mtr_report_stats ($;$) {
|
||||
my ($tests, $dont_error)= @_;
|
||||
sub mtr_report_stats ($$;$) {
|
||||
my ($prefix, $tests, $dont_error)= @_;
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Find out how we where doing
|
||||
@ -328,6 +328,9 @@ sub mtr_report_stats ($;$) {
|
||||
}
|
||||
}
|
||||
|
||||
# Print summary line prefix
|
||||
print "$prefix: ";
|
||||
|
||||
# Print a list of testcases that failed
|
||||
if ( $tot_failed != 0 )
|
||||
{
|
||||
@ -387,13 +390,13 @@ sub mtr_report_stats ($;$) {
|
||||
##############################################################################
|
||||
|
||||
sub mtr_print_line () {
|
||||
print '-' x 60, "\n";
|
||||
print '-' x 60 . "\n";
|
||||
}
|
||||
|
||||
|
||||
sub mtr_print_thick_line {
|
||||
my $char= shift || '=';
|
||||
print $char x 78, "\n";
|
||||
print $char x 78 . "\n";
|
||||
}
|
||||
|
||||
|
||||
@ -451,7 +454,7 @@ sub _timestamp {
|
||||
|
||||
# Always print message to screen
|
||||
sub mtr_print (@) {
|
||||
print _name(), join(" ", @_), "\n";
|
||||
print _name(). join(" ", @_). "\n";
|
||||
}
|
||||
|
||||
|
||||
@ -459,22 +462,22 @@ sub mtr_print (@) {
|
||||
sub mtr_report (@) {
|
||||
if (defined $verbose)
|
||||
{
|
||||
print _name(), join(" ", @_), "\n";
|
||||
print _name(). join(" ", @_). "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Print warning to screen
|
||||
sub mtr_warning (@) {
|
||||
print STDERR _name(), _timestamp(),
|
||||
"mysql-test-run: WARNING: ", join(" ", @_), "\n";
|
||||
print STDERR _name(). _timestamp().
|
||||
"mysql-test-run: WARNING: ". join(" ", @_). "\n";
|
||||
}
|
||||
|
||||
|
||||
# Print error to screen and then exit
|
||||
sub mtr_error (@) {
|
||||
print STDERR _name(), _timestamp(),
|
||||
"mysql-test-run: *** ERROR: ", join(" ", @_), "\n";
|
||||
print STDERR _name(). _timestamp().
|
||||
"mysql-test-run: *** ERROR: ". join(" ", @_). "\n";
|
||||
if (IS_WINDOWS)
|
||||
{
|
||||
POSIX::_exit(1);
|
||||
@ -489,8 +492,8 @@ sub mtr_error (@) {
|
||||
sub mtr_debug (@) {
|
||||
if ( $verbose > 2 )
|
||||
{
|
||||
print STDERR _name(),
|
||||
_timestamp(), "####: ", join(" ", @_), "\n";
|
||||
print STDERR _name().
|
||||
_timestamp(). "####: ". join(" ", @_). "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@ -498,8 +501,8 @@ sub mtr_debug (@) {
|
||||
sub mtr_verbose (@) {
|
||||
if ( $verbose )
|
||||
{
|
||||
print STDERR _name(), _timestamp(),
|
||||
"> ",join(" ", @_),"\n";
|
||||
print STDERR _name(). _timestamp().
|
||||
"> ".join(" ", @_)."\n";
|
||||
}
|
||||
}
|
||||
|
||||
@ -509,8 +512,8 @@ sub mtr_verbose_restart (@) {
|
||||
my $proc= $server->{proc};
|
||||
if ( $verbose_restart )
|
||||
{
|
||||
print STDERR _name(),_timestamp(),
|
||||
"> Restart $proc - ",join(" ", @args),"\n";
|
||||
print STDERR _name()._timestamp().
|
||||
"> Restart $proc - ".join(" ", @args)."\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,7 @@ sub run_stress_test ()
|
||||
mtr_add_arg($args, "--verbose");
|
||||
mtr_add_arg($args, "--cleanup");
|
||||
mtr_add_arg($args, "--log-error-details");
|
||||
mtr_add_arg($args, "--abort-on-error");
|
||||
mtr_add_arg($args, "--abort-on-error=1");
|
||||
|
||||
if ( $::opt_stress_init_file )
|
||||
{
|
||||
|
@ -376,6 +376,9 @@ sub mtr_report_stats ($) {
|
||||
/Slave: Can't DROP 'c7'.* 1091/ or
|
||||
/Slave: Key column 'c6'.* 1072/ or
|
||||
|
||||
# Warnings generated until bug#42147 is properly resolved
|
||||
/Found lock of type 6 that is write and read locked/ or
|
||||
|
||||
# rpl_idempotency.test produces warnings for the slave.
|
||||
($testname eq 'rpl.rpl_idempotency' and
|
||||
(/Slave: Can\'t find record in \'t1\' Error_code: 1032/ or
|
||||
|
@ -150,7 +150,7 @@ sub run_stress_test ()
|
||||
mtr_add_arg($args, "--verbose");
|
||||
mtr_add_arg($args, "--cleanup");
|
||||
mtr_add_arg($args, "--log-error-details");
|
||||
mtr_add_arg($args, "--abort-on-error");
|
||||
mtr_add_arg($args, "--abort-on-error=1");
|
||||
|
||||
if ( $::opt_stress_init_file )
|
||||
{
|
||||
|
@ -905,6 +905,11 @@ sub command_line_setup () {
|
||||
mtr_report("Using default engine '$used_default_engine'")
|
||||
if defined $used_default_engine;
|
||||
|
||||
if ($glob_win32 and defined $opt_mem) {
|
||||
mtr_report("--mem not supported on Windows, ignored");
|
||||
$opt_mem= undef;
|
||||
}
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Check if we should speed up tests by trying to run on tmpfs
|
||||
# --------------------------------------------------------------------------
|
||||
|
@ -102,6 +102,7 @@ use IO::Select;
|
||||
require "lib/mtr_process.pl";
|
||||
require "lib/mtr_io.pl";
|
||||
require "lib/mtr_gcov.pl";
|
||||
require "lib/mtr_gprof.pl";
|
||||
require "lib/mtr_misc.pl";
|
||||
|
||||
$SIG{INT}= sub { mtr_error("Got ^C signal"); };
|
||||
@ -186,6 +187,9 @@ our $opt_gcov_exe= "gcov";
|
||||
our $opt_gcov_err= "mysql-test-gcov.msg";
|
||||
our $opt_gcov_msg= "mysql-test-gcov.err";
|
||||
|
||||
our $opt_gprof;
|
||||
our %gprof_dirs;
|
||||
|
||||
our $glob_debugger= 0;
|
||||
our $opt_gdb;
|
||||
our $opt_client_gdb;
|
||||
@ -204,7 +208,9 @@ our $opt_experimental;
|
||||
our $experimental_test_cases;
|
||||
|
||||
my $baseport;
|
||||
# $opt_build_thread may later be set from $opt_port_base
|
||||
my $opt_build_thread= $ENV{'MTR_BUILD_THREAD'} || "auto";
|
||||
my $opt_port_base= $ENV{'MTR_PORT_BASE'} || "auto";
|
||||
my $build_thread= 0;
|
||||
|
||||
my $opt_record;
|
||||
@ -214,6 +220,7 @@ my $opt_skip_core;
|
||||
|
||||
our $opt_check_testcases= 1;
|
||||
my $opt_mark_progress;
|
||||
my $opt_max_connections;
|
||||
|
||||
my $opt_sleep;
|
||||
|
||||
@ -233,6 +240,7 @@ my $opt_wait_all;
|
||||
my $opt_repeat= 1;
|
||||
my $opt_retry= 3;
|
||||
my $opt_retry_failure= env_or_val(MTR_RETRY_FAILURE => 2);
|
||||
my $opt_reorder= 1;
|
||||
|
||||
my $opt_strace_client;
|
||||
|
||||
@ -245,6 +253,7 @@ my @default_valgrind_args= ("--show-reachable=yes");
|
||||
my @valgrind_args;
|
||||
my $opt_valgrind_path;
|
||||
my $opt_callgrind;
|
||||
my %mysqld_logs;
|
||||
my $opt_debug_sync_timeout= 300; # Default timeout for WAIT_FOR actions.
|
||||
|
||||
our $opt_warnings= 1;
|
||||
@ -284,6 +293,9 @@ sub main {
|
||||
|
||||
command_line_setup();
|
||||
|
||||
# --help will not reach here, so now it's safe to assume we have binaries
|
||||
My::SafeProcess::find_bin();
|
||||
|
||||
if ( $opt_gcov ) {
|
||||
gcov_prepare($basedir);
|
||||
}
|
||||
@ -313,7 +325,7 @@ sub main {
|
||||
}
|
||||
|
||||
mtr_report("Collecting tests...");
|
||||
my $tests= collect_test_cases($opt_suites, \@opt_cases);
|
||||
my $tests= collect_test_cases($opt_reorder, $opt_suites, \@opt_cases);
|
||||
|
||||
if ( $opt_report_features ) {
|
||||
# Put "report features" as the first test to run
|
||||
@ -430,7 +442,7 @@ sub main {
|
||||
$opt_gcov_msg, $opt_gcov_err);
|
||||
}
|
||||
|
||||
mtr_report_stats($completed);
|
||||
mtr_report_stats("Completed", $completed);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
@ -454,7 +466,7 @@ sub run_test_server ($$$) {
|
||||
my $result;
|
||||
my $exe_mysqld= find_mysqld($basedir) || ""; # Used as hint to CoreDump
|
||||
|
||||
my $suite_timeout_proc= My::SafeProcess->timer(suite_timeout());
|
||||
my $suite_timeout= start_timer(suite_timeout());
|
||||
|
||||
my $s= IO::Select->new();
|
||||
$s->add($server);
|
||||
@ -475,7 +487,6 @@ sub run_test_server ($$$) {
|
||||
mtr_verbose("Child closed socket");
|
||||
$s->remove($sock);
|
||||
if (--$childs == 0){
|
||||
$suite_timeout_proc->kill();
|
||||
return $completed;
|
||||
}
|
||||
next;
|
||||
@ -544,15 +555,13 @@ sub run_test_server ($$$) {
|
||||
|
||||
if ( !$opt_force ) {
|
||||
# Test has failed, force is off
|
||||
$suite_timeout_proc->kill();
|
||||
push(@$completed, $result);
|
||||
return $completed;
|
||||
}
|
||||
elsif ($opt_max_test_fail > 0 and
|
||||
$num_failed_test >= $opt_max_test_fail) {
|
||||
$suite_timeout_proc->kill();
|
||||
push(@$completed, $result);
|
||||
mtr_report_stats($completed, 1);
|
||||
mtr_report_stats("Too many failed", $completed, 1);
|
||||
mtr_report("Too many tests($num_failed_test) failed!",
|
||||
"Terminating...");
|
||||
return undef;
|
||||
@ -639,9 +648,9 @@ sub run_test_server ($$$) {
|
||||
next;
|
||||
}
|
||||
|
||||
# Prefer same configuration
|
||||
if (defined $result and
|
||||
$result->{template_path} eq $t->{template_path})
|
||||
# Prefer same configuration, or just use next if --noreorder
|
||||
if (!$opt_reorder or (defined $result and
|
||||
$result->{template_path} eq $t->{template_path}))
|
||||
{
|
||||
#mtr_report("Test uses same config => good match");
|
||||
# Test uses same config => good match
|
||||
@ -682,9 +691,9 @@ sub run_test_server ($$$) {
|
||||
# ----------------------------------------------------
|
||||
# Check if test suite timer expired
|
||||
# ----------------------------------------------------
|
||||
if ( ! $suite_timeout_proc->wait_one(0) )
|
||||
if ( has_expired($suite_timeout) )
|
||||
{
|
||||
mtr_report_stats($completed, 1);
|
||||
mtr_report_stats("Timeout", $completed, 1);
|
||||
mtr_report("Test suite timeout! Terminating...");
|
||||
return undef;
|
||||
}
|
||||
@ -760,6 +769,12 @@ sub run_worker ($) {
|
||||
elsif ($line eq 'BYE'){
|
||||
mtr_report("Server said BYE");
|
||||
stop_all_servers($opt_shutdown_timeout);
|
||||
if ($opt_valgrind_mysqld) {
|
||||
valgrind_exit_reports();
|
||||
}
|
||||
if ( $opt_gprof ) {
|
||||
gprof_collect (find_mysqld($basedir), keys %gprof_dirs);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
else {
|
||||
@ -840,9 +855,11 @@ sub command_line_setup {
|
||||
'combination=s' => \@opt_combinations,
|
||||
'skip-combinations' => \&collect_option,
|
||||
'experimental=s' => \$opt_experimental,
|
||||
'skip-im' => \&ignore_option,
|
||||
|
||||
# Specify ports
|
||||
'build-thread|mtr-build-thread=i' => \$opt_build_thread,
|
||||
'port-base|mtr-port-base=i' => \$opt_port_base,
|
||||
|
||||
# Test case authoring
|
||||
'record' => \$opt_record,
|
||||
@ -873,6 +890,7 @@ sub command_line_setup {
|
||||
|
||||
# Coverage, profiling etc
|
||||
'gcov' => \$opt_gcov,
|
||||
'gprof' => \$opt_gprof,
|
||||
'valgrind|valgrind-all' => \$opt_valgrind,
|
||||
'valgrind-mysqltest' => \$opt_valgrind_mysqltest,
|
||||
'valgrind-mysqld' => \$opt_valgrind_mysqld,
|
||||
@ -903,7 +921,7 @@ sub command_line_setup {
|
||||
'report-features' => \$opt_report_features,
|
||||
'comment=s' => \$opt_comment,
|
||||
'fast' => \$opt_fast,
|
||||
'reorder!' => \&collect_option,
|
||||
'reorder!' => \$opt_reorder,
|
||||
'enable-disabled' => \&collect_option,
|
||||
'verbose+' => \$opt_verbose,
|
||||
'verbose-restart' => \&report_option,
|
||||
@ -923,6 +941,7 @@ sub command_line_setup {
|
||||
'warnings!' => \$opt_warnings,
|
||||
'timestamp' => \&report_option,
|
||||
'timediff' => \&report_option,
|
||||
'max-connections=i' => \$opt_max_connections,
|
||||
|
||||
'help|h' => \$opt_usage,
|
||||
'list-options' => \$opt_list_options,
|
||||
@ -947,6 +966,11 @@ sub command_line_setup {
|
||||
|
||||
# Find the absolute path to the test directory
|
||||
$glob_mysql_test_dir= cwd();
|
||||
if ($glob_mysql_test_dir =~ / /)
|
||||
{
|
||||
die("Working directory \"$glob_mysql_test_dir\" contains space\n".
|
||||
"Bailing out, cannot function properly with space in path");
|
||||
}
|
||||
if (IS_CYGWIN)
|
||||
{
|
||||
# Use mixed path format i.e c:/path/to/
|
||||
@ -1099,6 +1123,21 @@ sub command_line_setup {
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_WINDOWS and defined $opt_mem) {
|
||||
mtr_report("--mem not supported on Windows, ignored");
|
||||
$opt_mem= undef;
|
||||
}
|
||||
|
||||
if ($opt_port_base ne "auto")
|
||||
{
|
||||
if (my $rem= $opt_port_base % 10)
|
||||
{
|
||||
mtr_warning ("Port base $opt_port_base rounded down to multiple of 10");
|
||||
$opt_port_base-= $rem;
|
||||
}
|
||||
$opt_build_thread= $opt_port_base / 10 - 1000;
|
||||
}
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Check if we should speed up tests by trying to run on tmpfs
|
||||
# --------------------------------------------------------------------------
|
||||
@ -1264,7 +1303,7 @@ sub command_line_setup {
|
||||
# --------------------------------------------------------------------------
|
||||
# Gcov flag
|
||||
# --------------------------------------------------------------------------
|
||||
if ( $opt_gcov and ! $source_dist )
|
||||
if ( ($opt_gcov or $opt_gprof) and ! $source_dist )
|
||||
{
|
||||
mtr_error("Coverage test needs the source - please use source dist");
|
||||
}
|
||||
@ -1363,8 +1402,7 @@ sub command_line_setup {
|
||||
push(@valgrind_args, @default_valgrind_args)
|
||||
unless @valgrind_args;
|
||||
|
||||
# Make valgrind run in quiet mode so it only print errors
|
||||
push(@valgrind_args, "--quiet" );
|
||||
# Don't add --quiet; you will loose the summary reports.
|
||||
|
||||
mtr_report("Running valgrind with options \"",
|
||||
join(" ", @valgrind_args), "\"");
|
||||
@ -1469,6 +1507,12 @@ sub collect_mysqld_features {
|
||||
mtr_add_arg($args, "--verbose");
|
||||
mtr_add_arg($args, "--help");
|
||||
|
||||
# Need --user=root if running as *nix root user
|
||||
if (!IS_WINDOWS and $> == 0)
|
||||
{
|
||||
mtr_add_arg($args, "--user=root");
|
||||
}
|
||||
|
||||
my $exe_mysqld= find_mysqld($basedir);
|
||||
my $cmd= join(" ", $exe_mysqld, @$args);
|
||||
my $list= `$cmd`;
|
||||
@ -1787,11 +1831,11 @@ sub environment_setup {
|
||||
{
|
||||
push(@ld_library_paths, "$basedir/libmysql/.libs/",
|
||||
"$basedir/libmysql_r/.libs/",
|
||||
"$basedir/zlib.libs/");
|
||||
"$basedir/zlib/.libs/");
|
||||
}
|
||||
else
|
||||
{
|
||||
push(@ld_library_paths, "$basedir/lib");
|
||||
push(@ld_library_paths, "$basedir/lib", "$basedir/lib/mysql");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2580,6 +2624,7 @@ sub create_config_file_for_extern {
|
||||
# binlog reads from [client] and [mysqlbinlog]
|
||||
[mysqlbinlog]
|
||||
character-sets-dir= $path_charsetsdir
|
||||
local-load= $opt_tmpdir
|
||||
|
||||
# mysql_fix_privilege_tables.sh don't read from [client]
|
||||
[mysql_fix_privilege_tables]
|
||||
@ -3009,11 +3054,11 @@ sub check_testcase($$)
|
||||
# Return immediately if no check proceess was started
|
||||
return 0 unless ( keys %started );
|
||||
|
||||
my $timeout_proc= My::SafeProcess->timer(check_timeout());
|
||||
my $timeout= start_timer(check_timeout());
|
||||
|
||||
while (1){
|
||||
my $result;
|
||||
my $proc= My::SafeProcess->wait_any();
|
||||
my $proc= My::SafeProcess->wait_any_timeout($timeout);
|
||||
mtr_report("Got $proc");
|
||||
|
||||
if ( delete $started{$proc->pid()} ) {
|
||||
@ -3037,9 +3082,6 @@ sub check_testcase($$)
|
||||
|
||||
if ( keys(%started) == 0){
|
||||
# All checks completed
|
||||
|
||||
$timeout_proc->kill();
|
||||
|
||||
return 0;
|
||||
}
|
||||
# Wait for next process to exit
|
||||
@ -3080,10 +3122,9 @@ test case was executed:\n";
|
||||
|
||||
}
|
||||
}
|
||||
elsif ( $proc eq $timeout_proc ) {
|
||||
$tinfo->{comment}.= "Timeout $timeout_proc for ".
|
||||
"'check-testcase' expired after ".check_timeout().
|
||||
" seconds";
|
||||
elsif ( $proc->{timeout} ) {
|
||||
$tinfo->{comment}.= "Timeout for 'check-testcase' expired after "
|
||||
.check_timeout()." seconds";
|
||||
$result= 4;
|
||||
}
|
||||
else {
|
||||
@ -3098,8 +3139,6 @@ test case was executed:\n";
|
||||
# Kill any check processes still running
|
||||
map($_->kill(), values(%started));
|
||||
|
||||
$timeout_proc->kill();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@ -3171,11 +3210,11 @@ sub run_on_all($$)
|
||||
# Return immediately if no check proceess was started
|
||||
return 0 unless ( keys %started );
|
||||
|
||||
my $timeout_proc= My::SafeProcess->timer(check_timeout());
|
||||
my $timeout= start_timer(check_timeout());
|
||||
|
||||
while (1){
|
||||
my $result;
|
||||
my $proc= My::SafeProcess->wait_any();
|
||||
my $proc= My::SafeProcess->wait_any_timeout($timeout);
|
||||
mtr_report("Got $proc");
|
||||
|
||||
if ( delete $started{$proc->pid()} ) {
|
||||
@ -3194,17 +3233,15 @@ sub run_on_all($$)
|
||||
|
||||
if ( keys(%started) == 0){
|
||||
# All completed
|
||||
$timeout_proc->kill();
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Wait for next process to exit
|
||||
next;
|
||||
}
|
||||
elsif ( $proc eq $timeout_proc ) {
|
||||
$tinfo->{comment}.= "Timeout $timeout_proc for '$run' ".
|
||||
"expired after ". check_timeout().
|
||||
" seconds";
|
||||
elsif ($proc->{timeout}) {
|
||||
$tinfo->{comment}.= "Timeout for '$run' expired after "
|
||||
.check_timeout()." seconds";
|
||||
}
|
||||
else {
|
||||
# Unknown process returned, most likley a crash, abort everything
|
||||
@ -3216,8 +3253,6 @@ sub run_on_all($$)
|
||||
# Kill any check processes still running
|
||||
map($_->kill(), values(%started));
|
||||
|
||||
$timeout_proc->kill();
|
||||
|
||||
return 1;
|
||||
}
|
||||
mtr_error("INTERNAL_ERROR: run_on_all");
|
||||
@ -3324,9 +3359,11 @@ sub run_testcase ($) {
|
||||
|
||||
mtr_verbose("Running test:", $tinfo->{name});
|
||||
|
||||
# Allow only alpanumerics pluss _ - + . in combination names
|
||||
# Allow only alpanumerics pluss _ - + . in combination names,
|
||||
# or anything beginning with -- (the latter comes from --combination)
|
||||
my $combination= $tinfo->{combination};
|
||||
if ($combination && $combination !~ /^\w[-\w\.\+]+$/)
|
||||
if ($combination && $combination !~ /^\w[-\w\.\+]+$/
|
||||
&& $combination !~ /^--/)
|
||||
{
|
||||
mtr_error("Combination '$combination' contains illegal characters");
|
||||
}
|
||||
@ -3447,7 +3484,7 @@ sub run_testcase ($) {
|
||||
}
|
||||
}
|
||||
|
||||
my $test_timeout_proc= My::SafeProcess->timer(testcase_timeout());
|
||||
my $test_timeout= start_timer(testcase_timeout());
|
||||
|
||||
do_before_run_mysqltest($tinfo);
|
||||
|
||||
@ -3455,9 +3492,6 @@ sub run_testcase ($) {
|
||||
# Failed to record state of server or server crashed
|
||||
report_failure_and_restart($tinfo);
|
||||
|
||||
# Stop the test case timer
|
||||
$test_timeout_proc->kill();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -3475,20 +3509,20 @@ sub run_testcase ($) {
|
||||
if ($proc)
|
||||
{
|
||||
mtr_verbose ("Found exited process $proc");
|
||||
# If that was the timeout, cancel waiting
|
||||
if ( $proc eq $test_timeout_proc )
|
||||
{
|
||||
$keep_waiting_proc = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$proc = $keep_waiting_proc;
|
||||
# Also check if timer has expired, if so cancel waiting
|
||||
if ( has_expired($test_timeout) )
|
||||
{
|
||||
$keep_waiting_proc = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (! $keep_waiting_proc)
|
||||
{
|
||||
$proc= My::SafeProcess->wait_any();
|
||||
$proc= My::SafeProcess->wait_any_timeout($test_timeout);
|
||||
}
|
||||
|
||||
# Will be restored if we need to keep waiting
|
||||
@ -3505,9 +3539,6 @@ sub run_testcase ($) {
|
||||
# ----------------------------------------------------
|
||||
if ($proc eq $test)
|
||||
{
|
||||
# Stop the test case timer
|
||||
$test_timeout_proc->kill();
|
||||
|
||||
my $res= $test->exit_status();
|
||||
|
||||
if ($res == 0 and $opt_warnings and check_warnings($tinfo) )
|
||||
@ -3564,6 +3595,14 @@ sub run_testcase ($) {
|
||||
run_on_all($tinfo, "analyze-$analyze");
|
||||
}
|
||||
|
||||
# Wait a bit and see if a server died, if so report that instead
|
||||
mtr_milli_sleep(100);
|
||||
my $srvproc= My::SafeProcess::check_any();
|
||||
if ($srvproc && grep($srvproc eq $_, started(all_servers()))) {
|
||||
$proc= $srvproc;
|
||||
goto SRVDIED;
|
||||
}
|
||||
|
||||
# Test case failure reported by mysqltest
|
||||
report_failure_and_restart($tinfo);
|
||||
}
|
||||
@ -3571,7 +3610,7 @@ sub run_testcase ($) {
|
||||
{
|
||||
# mysqltest failed, probably crashed
|
||||
$tinfo->{comment}=
|
||||
"mysqltest failed with unexpected return code $res";
|
||||
"mysqltest failed with unexpected return code $res\n";
|
||||
report_failure_and_restart($tinfo);
|
||||
}
|
||||
|
||||
@ -3589,6 +3628,7 @@ sub run_testcase ($) {
|
||||
# ----------------------------------------------------
|
||||
# Check if it was an expected crash
|
||||
# ----------------------------------------------------
|
||||
SRVDIED:
|
||||
my $check_crash = check_expected_crash_and_restart($proc);
|
||||
if ($check_crash)
|
||||
{
|
||||
@ -3601,7 +3641,7 @@ sub run_testcase ($) {
|
||||
# ----------------------------------------------------
|
||||
# Stop the test case timer
|
||||
# ----------------------------------------------------
|
||||
$test_timeout_proc->kill();
|
||||
$test_timeout= 0;
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Check if it was a server that died
|
||||
@ -3640,7 +3680,7 @@ sub run_testcase ($) {
|
||||
# ----------------------------------------------------
|
||||
# Check if testcase timer expired
|
||||
# ----------------------------------------------------
|
||||
if ( $proc eq $test_timeout_proc )
|
||||
if ( $proc->{timeout} )
|
||||
{
|
||||
my $log_file_name= $opt_vardir."/log/".$tinfo->{shortname}.".log";
|
||||
$tinfo->{comment}=
|
||||
@ -3762,16 +3802,24 @@ sub extract_warning_lines ($$) {
|
||||
(
|
||||
qr/^Warning:|mysqld: Warning|\[Warning\]/,
|
||||
qr/^Error:|\[ERROR\]/,
|
||||
qr/^==\d*==/, # valgrind errors
|
||||
qr/^==\d+==\s+\S/, # valgrind errors
|
||||
qr/InnoDB: Warning|InnoDB: Error/,
|
||||
qr/^safe_mutex:|allocated at line/,
|
||||
qr/missing DBUG_RETURN/,
|
||||
qr/Attempting backtrace/,
|
||||
qr/Assertion .* failed/,
|
||||
);
|
||||
my $skip_valgrind= 0;
|
||||
|
||||
foreach my $line ( @lines )
|
||||
{
|
||||
if ($opt_valgrind_mysqld) {
|
||||
# Skip valgrind summary from tests where server has been restarted
|
||||
# Should this contain memory leaks, the final report will find it
|
||||
$skip_valgrind= 1 if $line =~ /^==\d+== ERROR SUMMARY:/;
|
||||
$skip_valgrind= 0 unless $line =~ /^==\d+==/;
|
||||
next if $skip_valgrind;
|
||||
}
|
||||
foreach my $pat ( @patterns )
|
||||
{
|
||||
if ( $line =~ /$pat/ )
|
||||
@ -3811,7 +3859,6 @@ sub start_check_warnings ($$) {
|
||||
|
||||
mtr_add_arg($args, "--loose-skip-safemalloc");
|
||||
mtr_add_arg($args, "--test-file=%s", "include/check-warnings.test");
|
||||
mtr_add_arg($args, "--verbose");
|
||||
|
||||
if ( $opt_embedded_server )
|
||||
{
|
||||
@ -3874,11 +3921,11 @@ sub check_warnings ($) {
|
||||
# Return immediately if no check proceess was started
|
||||
return 0 unless ( keys %started );
|
||||
|
||||
my $timeout_proc= My::SafeProcess->timer(check_timeout());
|
||||
my $timeout= start_timer(check_timeout());
|
||||
|
||||
while (1){
|
||||
my $result= 0;
|
||||
my $proc= My::SafeProcess->wait_any();
|
||||
my $proc= My::SafeProcess->wait_any_timeout($timeout);
|
||||
mtr_report("Got $proc");
|
||||
|
||||
if ( delete $started{$proc->pid()} ) {
|
||||
@ -3907,9 +3954,6 @@ sub check_warnings ($) {
|
||||
|
||||
if ( keys(%started) == 0){
|
||||
# All checks completed
|
||||
|
||||
$timeout_proc->kill();
|
||||
|
||||
return $result;
|
||||
}
|
||||
# Wait for next process to exit
|
||||
@ -3926,10 +3970,9 @@ sub check_warnings ($) {
|
||||
$result= 2;
|
||||
}
|
||||
}
|
||||
elsif ( $proc eq $timeout_proc ) {
|
||||
$tinfo->{comment}.= "Timeout $timeout_proc for ".
|
||||
"'check warnings' expired after ".check_timeout().
|
||||
" seconds";
|
||||
elsif ( $proc->{timeout} ) {
|
||||
$tinfo->{comment}.= "Timeout for 'check warnings' expired after "
|
||||
.check_timeout()." seconds";
|
||||
$result= 4;
|
||||
}
|
||||
else {
|
||||
@ -3943,8 +3986,6 @@ sub check_warnings ($) {
|
||||
# Kill any check processes still running
|
||||
map($_->kill(), values(%started));
|
||||
|
||||
$timeout_proc->kill();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@ -3962,7 +4003,7 @@ sub check_expected_crash_and_restart {
|
||||
|
||||
foreach my $mysqld ( mysqlds() )
|
||||
{
|
||||
next unless ( $mysqld->{proc} eq $proc );
|
||||
next unless ( $mysqld->{proc} and $mysqld->{proc} eq $proc );
|
||||
|
||||
# Check if crash expected by looking at the .expect file
|
||||
# in var/tmp
|
||||
@ -4160,6 +4201,20 @@ sub report_failure_and_restart ($) {
|
||||
# about what failed has been saved to file. Save the report
|
||||
# in tinfo
|
||||
$tinfo->{logfile}= mtr_fromfile($logfile);
|
||||
# If no newlines in the test log:
|
||||
# (it will contain the CURRENT_TEST written by mtr, so is not empty)
|
||||
if ($tinfo->{logfile} !~ /\n/)
|
||||
{
|
||||
# Show how far it got before suddenly failing
|
||||
$tinfo->{comment}.= "mysqltest failed but provided no output\n";
|
||||
my $log_file_name= $opt_vardir."/log/".$tinfo->{shortname}.".log";
|
||||
if (-e $log_file_name) {
|
||||
$tinfo->{comment}.=
|
||||
"The result from queries just before the failure was:".
|
||||
"\n< snip >\n".
|
||||
mtr_lastlinesfromfile($log_file_name, 20)."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4369,6 +4424,10 @@ sub mysqld_start ($$) {
|
||||
# see the exact location where valgrind complains
|
||||
$output= "$opt_vardir/log/".$mysqld->name().".trace";
|
||||
}
|
||||
# Remember this log file for valgrind error report search
|
||||
$mysqld_logs{$output}= 1 if $opt_valgrind;
|
||||
# Remember data dir for gmon.out files if using gprof
|
||||
$gprof_dirs{$mysqld->value('datadir')}= 1 if $opt_gprof;
|
||||
|
||||
if ( defined $exe )
|
||||
{
|
||||
@ -4918,6 +4977,10 @@ sub start_mysqltest ($) {
|
||||
mtr_add_arg($args, "--ssl");
|
||||
}
|
||||
|
||||
if ( $opt_max_connections ) {
|
||||
mtr_add_arg($args, "--max-connections=%d", $opt_max_connections);
|
||||
}
|
||||
|
||||
if ( $opt_embedded_server )
|
||||
{
|
||||
|
||||
@ -5146,7 +5209,7 @@ sub debugger_arguments {
|
||||
{
|
||||
# vc[express] /debugexe exe arg1 .. argn
|
||||
|
||||
# Add /debugexe and name of the exe before args
|
||||
# Add name of the exe and /debugexe before args
|
||||
unshift(@$$args, "$$exe");
|
||||
unshift(@$$args, "/debugexe");
|
||||
|
||||
@ -5221,6 +5284,66 @@ sub valgrind_arguments {
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Search server logs for valgrind reports printed at mysqld termination
|
||||
#
|
||||
|
||||
sub valgrind_exit_reports() {
|
||||
foreach my $log_file (keys %mysqld_logs)
|
||||
{
|
||||
my @culprits= ();
|
||||
my $valgrind_rep= "";
|
||||
my $found_report= 0;
|
||||
my $err_in_report= 0;
|
||||
|
||||
my $LOGF = IO::File->new($log_file)
|
||||
or mtr_error("Could not open file '$log_file' for reading: $!");
|
||||
|
||||
while ( my $line = <$LOGF> )
|
||||
{
|
||||
if ($line =~ /^CURRENT_TEST: (.+)$/)
|
||||
{
|
||||
my $testname= $1;
|
||||
# If we have a report, report it if needed and start new list of tests
|
||||
if ($found_report)
|
||||
{
|
||||
if ($err_in_report)
|
||||
{
|
||||
mtr_print ("Valgrind report from $log_file after tests:\n",
|
||||
@culprits);
|
||||
mtr_print_line();
|
||||
print ("$valgrind_rep\n");
|
||||
$err_in_report= 0;
|
||||
}
|
||||
# Make ready to collect new report
|
||||
@culprits= ();
|
||||
$found_report= 0;
|
||||
$valgrind_rep= "";
|
||||
}
|
||||
push (@culprits, $testname);
|
||||
next;
|
||||
}
|
||||
# This line marks the start of a valgrind report
|
||||
$found_report= 1 if $line =~ /ERROR SUMMARY:/;
|
||||
|
||||
if ($found_report) {
|
||||
$line=~ s/^==\d+== //;
|
||||
$valgrind_rep .= $line;
|
||||
$err_in_report= 1 if $line =~ /ERROR SUMMARY: [1-9]/;
|
||||
$err_in_report= 1 if $line =~ /definitely lost: [1-9]/;
|
||||
$err_in_report= 1 if $line =~ /possibly lost: [1-9]/;
|
||||
}
|
||||
}
|
||||
|
||||
$LOGF= undef;
|
||||
|
||||
if ($err_in_report) {
|
||||
mtr_print ("Valgrind report from $log_file after tests:\n", @culprits);
|
||||
mtr_print_line();
|
||||
print ("$valgrind_rep\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Usage
|
||||
@ -5300,6 +5423,11 @@ Options to control what test suites or cases to run
|
||||
|
||||
Options that specify ports
|
||||
|
||||
mtr-port-base=# Base for port numbers, ports from this number to
|
||||
port-base=# number+9 are reserved. Should be divisible by 10;
|
||||
if not it will be rounded down. May be set with
|
||||
environment variable MTR_PORT_BASE. If this value is
|
||||
set and is not "auto", it overrides build-thread.
|
||||
mtr-build-thread=# Specify unique number to calculate port number(s) from.
|
||||
build-thread=# Can be set in environment variable MTR_BUILD_THREAD.
|
||||
Set MTR_BUILD_THREAD="auto" to automatically aquire
|
||||
@ -5411,6 +5539,7 @@ Misc options
|
||||
timestamp Print timestamp before each test report line
|
||||
timediff With --timestamp, also print time passed since
|
||||
*previous* test started
|
||||
max-connections=N Max number of open connection to server in mysqltest
|
||||
|
||||
HERE
|
||||
exit(1);
|
||||
|
@ -842,11 +842,11 @@ call p_verify_status_increment(2, 0, 2, 0);
|
||||
SUCCESS
|
||||
|
||||
alter table t3 rename t4;
|
||||
call p_verify_status_increment(1, 0, 1, 0);
|
||||
call p_verify_status_increment(2, 0, 2, 0);
|
||||
SUCCESS
|
||||
|
||||
rename table t4 to t3;
|
||||
call p_verify_status_increment(1, 0, 1, 0);
|
||||
call p_verify_status_increment(0, 0, 0, 0);
|
||||
SUCCESS
|
||||
|
||||
truncate table t3;
|
||||
@ -854,13 +854,13 @@ call p_verify_status_increment(2, 0, 2, 0);
|
||||
SUCCESS
|
||||
|
||||
create view v1 as select * from t2;
|
||||
call p_verify_status_increment(1, 0, 1, 0);
|
||||
call p_verify_status_increment(2, 0, 2, 0);
|
||||
SUCCESS
|
||||
|
||||
check table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
call p_verify_status_increment(3, 0, 3, 0);
|
||||
call p_verify_status_increment(2, 0, 2, 0);
|
||||
SUCCESS
|
||||
|
||||
# Sic: after this bug is fixed, CHECK leaves no pending transaction
|
||||
|
@ -785,7 +785,7 @@ drop table t1;
|
||||
create table t1 select * from t2;
|
||||
ERROR 42S02: Table 'test.t2' doesn't exist
|
||||
create table t1 select * from t1;
|
||||
ERROR HY000: You can't specify target table 't1' for update in FROM clause
|
||||
ERROR 42S02: Table 'test.t1' doesn't exist
|
||||
create table t1 select coalesce('a' collate latin1_swedish_ci,'b' collate latin1_bin);
|
||||
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation 'coalesce'
|
||||
create table t1 (primary key(a)) select "b" as b;
|
||||
@ -805,6 +805,11 @@ Note 1050 Table 't1' already exists
|
||||
select * from t1;
|
||||
i
|
||||
1
|
||||
create table if not exists t1 select * from t1;
|
||||
ERROR HY000: You can't specify target table 't1' for update in FROM clause
|
||||
select * from t1;
|
||||
i
|
||||
1
|
||||
create table t1 select coalesce('a' collate latin1_swedish_ci,'b' collate latin1_bin);
|
||||
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation 'coalesce'
|
||||
select * from t1;
|
||||
@ -1953,3 +1958,22 @@ END ;|
|
||||
ERROR 42000: This version of MySQL doesn't yet support 'multiple triggers with the same action time and event for one table'
|
||||
DROP TABLE t1;
|
||||
DROP TABLE B;
|
||||
#
|
||||
# Bug #47107 assert in notify_shared_lock on incorrect
|
||||
# CREATE TABLE , HANDLER
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(f1 integer);
|
||||
# The following CREATE TABLEs before gave an assert.
|
||||
HANDLER t1 OPEN AS A;
|
||||
CREATE TABLE t1 SELECT 1 AS f2;
|
||||
ERROR 42S01: Table 't1' already exists
|
||||
HANDLER t1 OPEN AS A;
|
||||
CREATE TABLE t1(f1 integer);
|
||||
ERROR 42S01: Table 't1' already exists
|
||||
CREATE TABLE t2(f1 integer);
|
||||
HANDLER t1 OPEN AS A;
|
||||
CREATE TABLE t1 LIKE t2;
|
||||
ERROR 42S01: Table 't1' already exists
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -263,7 +263,7 @@ DROP TABLE t1;
|
||||
SET DEBUG_SYNC= 'RESET';
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (c1 INT);
|
||||
LOCK TABLE t1 WRITE;
|
||||
LOCK TABLE t1 READ;
|
||||
connection con1
|
||||
SET DEBUG_SYNC= 'wait_for_lock SIGNAL locked EXECUTE 2';
|
||||
INSERT INTO t1 VALUES (1);
|
||||
|
@ -79,8 +79,8 @@ drop table t1;
|
||||
drop database if exists mysqltest;
|
||||
drop table if exists t1;
|
||||
create table t1 (i int);
|
||||
lock tables t1 read;
|
||||
create database mysqltest;
|
||||
lock tables t1 read;
|
||||
drop table t1;
|
||||
show open tables;
|
||||
drop database mysqltest;
|
||||
|
@ -7,12 +7,16 @@ DROP DATABASE IF EXISTS mysql_test;
|
||||
|
||||
CREATE DATABASE mysql_test;
|
||||
CREATE TABLE mysql_test.t1(a INT);
|
||||
CREATE TABLE mysql_test.t2(b INT);
|
||||
CREATE TABLE mysql_test.t3(c INT);
|
||||
|
||||
SET SESSION DEBUG = "+d,bug43138";
|
||||
|
||||
DROP DATABASE mysql_test;
|
||||
Warnings:
|
||||
Error 1051 Unknown table 't1'
|
||||
Error 1051 Unknown table 't2'
|
||||
Error 1051 Unknown table 't3'
|
||||
|
||||
SET SESSION DEBUG = "-d,bug43138";
|
||||
|
||||
|
@ -33,6 +33,9 @@ flush tables with read lock;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
lock table t1 read;
|
||||
flush tables with read lock;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
unlock tables;
|
||||
flush tables with read lock;
|
||||
lock table t1 write;
|
||||
ERROR HY000: Can't execute the query because you have a conflicting read lock
|
||||
lock table t1 read;
|
||||
@ -46,6 +49,7 @@ flush tables with read lock;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
lock table t1 read, t2 read, t3 read;
|
||||
flush tables with read lock;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
unlock tables;
|
||||
drop table t1, t2, t3;
|
||||
create table t1 (c1 int);
|
||||
@ -69,6 +73,7 @@ ERROR HY000: Can't execute the given command because you have active locked tabl
|
||||
unlock tables;
|
||||
lock tables t1 read;
|
||||
flush tables with read lock;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
unlock tables;
|
||||
drop table t1, t2;
|
||||
set session low_priority_updates=default;
|
||||
@ -89,3 +94,20 @@ unlock tables;
|
||||
set global general_log= @old_general_log;
|
||||
set global read_only= @old_read_only;
|
||||
End of 5.1 tests
|
||||
#
|
||||
# Additional test for bug #51136 "Crash in pthread_rwlock_rdlock
|
||||
# on TEMPORARY + HANDLER + LOCK + SP".
|
||||
# Also see the main test for this bug in include/handler.inc.
|
||||
#
|
||||
drop tables if exists t1, t2;
|
||||
create table t1 (i int);
|
||||
create temporary table t2 (j int);
|
||||
flush tables with read lock;
|
||||
lock table t2 read;
|
||||
# This commit should not release any MDL locks.
|
||||
commit;
|
||||
# The below statement crashed before the bug fix as it
|
||||
# has attempted to release global shared metadata lock
|
||||
# which was already released by commit.
|
||||
unlock tables;
|
||||
drop tables t1, t2;
|
||||
|
@ -1,3 +1,4 @@
|
||||
# Save the initial number of concurrent sessions
|
||||
# Establish connection con1 (user=root)
|
||||
# Establish connection con2 (user=root)
|
||||
# Establish connection con3 (user=root)
|
||||
@ -8,15 +9,17 @@ BEGIN;
|
||||
INSERT INTO t1 VALUES(1);
|
||||
# Switch to connection con2
|
||||
FLUSH TABLES WITH READ LOCK;
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
# Switch to connection con1
|
||||
# Sending:
|
||||
COMMIT;
|
||||
# Switch to connection con2
|
||||
# Wait until COMMIT gets blocked.
|
||||
# Verify that 'con1' was blocked and data did not move.
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
UNLOCK TABLES;
|
||||
# Switch to connection con1
|
||||
# Reaping COMMIT
|
||||
# Switch to connection con1
|
||||
BEGIN;
|
||||
SELECT * FROM t1 FOR UPDATE;
|
||||
@ -32,6 +35,7 @@ COMMIT;
|
||||
# Switch to connection con2
|
||||
a
|
||||
1
|
||||
COMMIT;
|
||||
# Switch to connection con3
|
||||
UNLOCK TABLES;
|
||||
# Switch to connection con2
|
||||
@ -40,8 +44,6 @@ COMMIT;
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(10);
|
||||
FLUSH TABLES WITH READ LOCK;
|
||||
COMMIT;
|
||||
UNLOCK TABLES;
|
||||
# Switch to connection con2
|
||||
FLUSH TABLES WITH READ LOCK;
|
||||
UNLOCK TABLES;
|
||||
@ -53,5 +55,11 @@ a
|
||||
SHOW CREATE DATABASE test;
|
||||
Database Create Database
|
||||
test CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET latin1 */
|
||||
DROP TABLE t1;
|
||||
COMMIT;
|
||||
# Cleanup
|
||||
# Switch to connection default and close connections con1, con2, con3
|
||||
# We commit open transactions when we disconnect: only then we can
|
||||
# drop the table.
|
||||
DROP TABLE t1;
|
||||
# End of 4.1 tests
|
||||
# Wait till all disconnects are completed
|
||||
|
@ -1,17 +1,20 @@
|
||||
# Save the initial number of concurrent sessions
|
||||
# Establish connection con1 (user=root)
|
||||
# Establish connection con2 (user=root)
|
||||
# Switch to connection con1
|
||||
CREATE TABLE t1 (a INT) ENGINE=innodb;
|
||||
RESET MASTER;
|
||||
SET AUTOCOMMIT=0;
|
||||
INSERT t1 VALUES (1);
|
||||
SELECT 1;
|
||||
1
|
||||
1
|
||||
# Switch to connection con2
|
||||
FLUSH TABLES WITH READ LOCK;
|
||||
SHOW MASTER STATUS;
|
||||
File Position Binlog_Do_DB Binlog_Ignore_DB
|
||||
master-bin.000001 107
|
||||
# Switch to connection con1
|
||||
COMMIT;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
# Switch to connection con2
|
||||
SHOW MASTER STATUS;
|
||||
File Position Binlog_Do_DB Binlog_Ignore_DB
|
||||
@ -20,4 +23,12 @@ UNLOCK TABLES;
|
||||
# Switch to connection con1
|
||||
DROP TABLE t1;
|
||||
SET AUTOCOMMIT=1;
|
||||
create table t1 (a int) engine=innodb;
|
||||
flush tables with read lock;
|
||||
begin;
|
||||
insert into t1 values (1);;
|
||||
unlock tables;
|
||||
commit;
|
||||
drop table t1;
|
||||
# Switch to connection default and close connections con1 and con2
|
||||
# Wait till all disconnects are completed
|
||||
|
@ -3,21 +3,14 @@ create table t1 (a int not null auto_increment primary key);
|
||||
insert into t1 values(0);
|
||||
lock table t1 read;
|
||||
flush table t1;
|
||||
ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
|
||||
unlock tables;
|
||||
lock table t1 write;
|
||||
flush table t1;
|
||||
check table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
unlock tables;
|
||||
lock table t1 read;
|
||||
lock table t1 read;
|
||||
flush table t1;
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
unlock tables;
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
unlock tables;
|
||||
lock table t1 write;
|
||||
lock table t1 read;
|
||||
flush table t1;
|
||||
@ -26,7 +19,7 @@ a
|
||||
1
|
||||
unlock tables;
|
||||
unlock tables;
|
||||
lock table t1 read;
|
||||
lock table t1 write;
|
||||
lock table t1 write;
|
||||
flush table t1;
|
||||
select * from t1;
|
||||
|
@ -548,6 +548,7 @@ c1
|
||||
1
|
||||
connection: flush
|
||||
flush tables;;
|
||||
connection: waiter
|
||||
connection: default
|
||||
handler t2 open;
|
||||
handler t2 read first;
|
||||
@ -559,23 +560,36 @@ c1
|
||||
handler t1 close;
|
||||
handler t2 close;
|
||||
drop table t1,t2;
|
||||
drop table if exists t1,t2;
|
||||
drop table if exists t1, t0;
|
||||
create table t1 (c1 int);
|
||||
connection: default
|
||||
handler t1 open;
|
||||
handler t1 read first;
|
||||
c1
|
||||
connection: flush
|
||||
rename table t1 to t2;;
|
||||
rename table t1 to t0;;
|
||||
connection: waiter
|
||||
connection: default
|
||||
handler t2 open;
|
||||
handler t2 read first;
|
||||
c1
|
||||
#
|
||||
# RENAME placed two pending locks and waits.
|
||||
# When HANDLER t0 OPEN does open_tables(), it calls
|
||||
# mysql_ha_flush(), which in turn closes the open HANDLER for t1.
|
||||
# RENAME TABLE gets unblocked. If it gets scheduled quickly
|
||||
# and manages to complete before open_tables()
|
||||
# of HANDLER t0 OPEN, open_tables() and therefore the whole
|
||||
# HANDLER t0 OPEN succeeds. Otherwise open_tables()
|
||||
# notices a pending or active exclusive metadata lock on t2
|
||||
# and the whole HANDLER t0 OPEN fails with ER_LOCK_DEADLOCK
|
||||
# error.
|
||||
#
|
||||
handler t0 open;
|
||||
handler t0 close;
|
||||
connection: flush
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Table 'test.t1' doesn't exist
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
handler t1 close;
|
||||
handler t2 close;
|
||||
drop table t2;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
drop table t0;
|
||||
drop table if exists t1;
|
||||
create temporary table t1 (a int, b char(1), key a(a), key b(a,b));
|
||||
insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"),
|
||||
@ -731,15 +745,943 @@ drop table t1;
|
||||
handler t1 read a next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
drop table if exists t1;
|
||||
# First test case which is supposed trigger the execution
|
||||
# path on which problem was discovered.
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1);
|
||||
handler t1 open;
|
||||
lock table t1 write;
|
||||
alter table t1 engine=memory;
|
||||
handler t1 read a next;
|
||||
ERROR HY000: Table storage engine for 't1' doesn't have this option
|
||||
handler t1 close;
|
||||
unlock tables;
|
||||
drop table t1;
|
||||
# Now test case which was reported originally but which no longer
|
||||
# triggers execution path which has caused the problem.
|
||||
create table t1 (a int, key(a));
|
||||
insert into t1 values (1);
|
||||
handler t1 open;
|
||||
alter table t1 engine=memory;
|
||||
# Since S metadata lock was already acquired at HANDLER OPEN time
|
||||
# and TL_READ lock requested by HANDLER READ is compatible with
|
||||
# ALTER's TL_WRITE_ALLOW_READ the below statement should succeed
|
||||
# without waiting. The old version of table should be used in it.
|
||||
handler t1 read a next;
|
||||
a
|
||||
1
|
||||
handler t1 close;
|
||||
drop table t1;
|
||||
USE information_schema;
|
||||
HANDLER COLUMNS OPEN;
|
||||
ERROR HY000: Incorrect usage of HANDLER OPEN and information_schema
|
||||
USE test;
|
||||
#
|
||||
# Add test coverage for HANDLER and LOCK TABLES, HANDLER and DDL.
|
||||
#
|
||||
drop table if exists t1, t2, t3;
|
||||
create table t1 (a int, key a (a));
|
||||
insert into t1 (a) values (1), (2), (3), (4), (5);
|
||||
create table t2 (a int, key a (a)) select * from t1;
|
||||
create temporary table t3 (a int, key a (a)) select * from t2;
|
||||
handler t1 open;
|
||||
handler t2 open;
|
||||
handler t3 open;
|
||||
#
|
||||
# No HANDLER sql is allowed under LOCK TABLES.
|
||||
# But it does not implicitly closes all handlers.
|
||||
#
|
||||
lock table t1 read;
|
||||
handler t1 open;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
handler t1 read next;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
handler t2 close;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
handler t3 open;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
# After UNLOCK TABLES handlers should be around and
|
||||
# we should be able to continue reading through them.
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
a
|
||||
1
|
||||
handler t1 close;
|
||||
handler t2 read next;
|
||||
a
|
||||
1
|
||||
handler t2 close;
|
||||
handler t3 read next;
|
||||
a
|
||||
1
|
||||
handler t3 close;
|
||||
drop temporary table t3;
|
||||
#
|
||||
# Other operations that implicitly close handler:
|
||||
#
|
||||
# TRUNCATE
|
||||
#
|
||||
handler t1 open;
|
||||
truncate table t1;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
handler t1 open;
|
||||
#
|
||||
# CREATE TRIGGER
|
||||
#
|
||||
create trigger t1_ai after insert on t1 for each row set @a=1;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# DROP TRIGGER
|
||||
#
|
||||
handler t1 open;
|
||||
drop trigger t1_ai;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# ALTER TABLE
|
||||
#
|
||||
handler t1 open;
|
||||
alter table t1 add column b int;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# ANALYZE TABLE
|
||||
#
|
||||
handler t1 open;
|
||||
analyze table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status OK
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# OPTIMIZE TABLE
|
||||
#
|
||||
handler t1 open;
|
||||
optimize table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
|
||||
test.t1 optimize status OK
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# REPAIR TABLE
|
||||
#
|
||||
handler t1 open;
|
||||
repair table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 repair note The storage engine for the table doesn't support repair
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# DROP TABLE, naturally.
|
||||
#
|
||||
handler t1 open;
|
||||
drop table t1;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
create table t1 (a int, b int, key a (a)) select a from t2;
|
||||
#
|
||||
# RENAME TABLE, naturally
|
||||
#
|
||||
handler t1 open;
|
||||
rename table t1 to t3;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# CREATE TABLE (even with IF NOT EXISTS clause,
|
||||
# and the table exists).
|
||||
#
|
||||
handler t2 open;
|
||||
create table if not exists t2 (a int);
|
||||
Warnings:
|
||||
Note 1050 Table 't2' already exists
|
||||
handler t2 read next;
|
||||
ERROR 42S02: Unknown table 't2' in HANDLER
|
||||
rename table t3 to t1;
|
||||
drop table t2;
|
||||
#
|
||||
# FLUSH TABLE doesn't close the table but loses the position
|
||||
#
|
||||
handler t1 open;
|
||||
handler t1 read a prev;
|
||||
b a
|
||||
NULL 5
|
||||
flush table t1;
|
||||
handler t1 read a prev;
|
||||
b a
|
||||
NULL 5
|
||||
handler t1 close;
|
||||
#
|
||||
# FLUSH TABLES WITH READ LOCK behaves like FLUSH TABLE.
|
||||
#
|
||||
handler t1 open;
|
||||
handler t1 read a prev;
|
||||
b a
|
||||
NULL 5
|
||||
flush tables with read lock;
|
||||
handler t1 read a prev;
|
||||
b a
|
||||
NULL 5
|
||||
handler t1 close;
|
||||
unlock tables;
|
||||
#
|
||||
# Let us also check that these operations behave in similar
|
||||
# way under LOCK TABLES.
|
||||
#
|
||||
# TRUNCATE under LOCK TABLES.
|
||||
#
|
||||
handler t1 open;
|
||||
lock tables t1 write;
|
||||
truncate table t1;
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
handler t1 open;
|
||||
#
|
||||
# CREATE TRIGGER under LOCK TABLES.
|
||||
#
|
||||
lock tables t1 write;
|
||||
create trigger t1_ai after insert on t1 for each row set @a=1;
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# DROP TRIGGER under LOCK TABLES.
|
||||
#
|
||||
handler t1 open;
|
||||
lock tables t1 write;
|
||||
drop trigger t1_ai;
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# ALTER TABLE under LOCK TABLES.
|
||||
#
|
||||
handler t1 open;
|
||||
lock tables t1 write;
|
||||
alter table t1 drop column b;
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# ANALYZE TABLE under LOCK TABLES.
|
||||
#
|
||||
handler t1 open;
|
||||
lock tables t1 write;
|
||||
analyze table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status OK
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# OPTIMIZE TABLE under LOCK TABLES.
|
||||
#
|
||||
handler t1 open;
|
||||
lock tables t1 write;
|
||||
optimize table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
|
||||
test.t1 optimize status OK
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# REPAIR TABLE under LOCK TABLES.
|
||||
#
|
||||
handler t1 open;
|
||||
lock tables t1 write;
|
||||
repair table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 repair note The storage engine for the table doesn't support repair
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# DROP TABLE under LOCK TABLES, naturally.
|
||||
#
|
||||
handler t1 open;
|
||||
lock tables t1 write;
|
||||
drop table t1;
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
create table t1 (a int, b int, key a (a));
|
||||
insert into t1 (a) values (1), (2), (3), (4), (5);
|
||||
#
|
||||
# FLUSH TABLE doesn't close the table but loses the position
|
||||
#
|
||||
handler t1 open;
|
||||
handler t1 read a prev;
|
||||
a b
|
||||
5 NULL
|
||||
lock tables t1 write;
|
||||
flush table t1;
|
||||
unlock tables;
|
||||
handler t1 read a prev;
|
||||
a b
|
||||
5 NULL
|
||||
handler t1 close;
|
||||
#
|
||||
# Explore the effect of HANDLER locks on concurrent DDL
|
||||
#
|
||||
handler t1 open;
|
||||
# Establishing auxiliary connections con1, con2, con3
|
||||
# --> connection con1;
|
||||
# Sending:
|
||||
drop table t1 ;
|
||||
# We can't use connection 'default' as wait_condition will
|
||||
# autoclose handlers.
|
||||
# --> connection con2
|
||||
# Waitng for 'drop table t1' to get blocked...
|
||||
# --> connection default
|
||||
handler t1 read a prev;
|
||||
a b
|
||||
5 NULL
|
||||
handler t1 read a prev;
|
||||
a b
|
||||
4 NULL
|
||||
handler t1 close;
|
||||
# --> connection con1
|
||||
# Reaping 'drop table t1'...
|
||||
# --> connection default
|
||||
#
|
||||
# Explore the effect of HANDLER locks in parallel with SELECT
|
||||
#
|
||||
create table t1 (a int, key a (a));
|
||||
insert into t1 (a) values (1), (2), (3), (4), (5);
|
||||
begin;
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
handler t1 open;
|
||||
handler t1 read a prev;
|
||||
a
|
||||
5
|
||||
handler t1 read a prev;
|
||||
a
|
||||
4
|
||||
handler t1 close;
|
||||
# --> connection con1;
|
||||
# Sending:
|
||||
drop table t1 ;
|
||||
# --> connection con2
|
||||
# Waiting for 'drop table t1' to get blocked...
|
||||
# --> connection default
|
||||
# We can still use the table, it's part of the transaction
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
# Such are the circumstances that t1 is a part of transaction,
|
||||
# thus we can reopen it in the handler
|
||||
handler t1 open;
|
||||
# We can commit the transaction, it doesn't close the handler
|
||||
# and doesn't let DROP to proceed.
|
||||
commit;
|
||||
handler t1 read a prev;
|
||||
a
|
||||
5
|
||||
handler t1 read a prev;
|
||||
a
|
||||
4
|
||||
handler t1 read a prev;
|
||||
a
|
||||
3
|
||||
handler t1 close;
|
||||
# --> connection con1
|
||||
# Now drop can proceed
|
||||
# Reaping 'drop table t1'...
|
||||
# --> connection default
|
||||
#
|
||||
# Demonstrate that HANDLER locks and transaction locks
|
||||
# reside in the same context, and we don't back-off
|
||||
# when have transaction or handler locks.
|
||||
#
|
||||
create table t1 (a int, key a (a));
|
||||
insert into t1 (a) values (1), (2), (3), (4), (5);
|
||||
create table t0 (a int, key a (a));
|
||||
insert into t0 (a) values (1), (2), (3), (4), (5);
|
||||
begin;
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
# --> connection con2
|
||||
# Sending:
|
||||
rename table t0 to t3, t1 to t0, t3 to t1;
|
||||
# --> connection con1
|
||||
# Waiting for 'rename table ...' to get blocked...
|
||||
# --> connection default
|
||||
handler t0 open;
|
||||
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
||||
select * from t0;
|
||||
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
||||
handler t1 open;
|
||||
commit;
|
||||
handler t1 close;
|
||||
# --> connection con2
|
||||
# Reaping 'rename table ...'...
|
||||
# --> connection default
|
||||
handler t1 open;
|
||||
handler t1 read a prev;
|
||||
a
|
||||
5
|
||||
handler t1 close;
|
||||
drop table t0;
|
||||
#
|
||||
# Originally there was a deadlock error in this test.
|
||||
# With implementation of deadlock detector
|
||||
# we no longer deadlock, but block and wait on a lock.
|
||||
# The HANDLER is auto-closed as soon as the connection
|
||||
# sees a pending conflicting lock against it.
|
||||
#
|
||||
create table t2 (a int, key a (a));
|
||||
handler t1 open;
|
||||
# --> connection con1
|
||||
lock tables t2 read;
|
||||
# --> connection con2
|
||||
# Sending 'drop table t2'...
|
||||
drop table t2;
|
||||
# --> connection con1
|
||||
# Waiting for 'drop table t2' to get blocked...
|
||||
# --> connection default
|
||||
# Sending 'select * from t2'
|
||||
select * from t2;
|
||||
# --> connection con1
|
||||
# Waiting for 'select * from t2' to get blocked...
|
||||
unlock tables;
|
||||
# --> connection con2
|
||||
# Reaping 'drop table t2'...
|
||||
# --> connection default
|
||||
# Reaping 'select * from t2'
|
||||
ERROR 42S02: Table 'test.t2' doesn't exist
|
||||
handler t1 close;
|
||||
#
|
||||
# ROLLBACK TO SAVEPOINT releases transactional locks,
|
||||
# but has no effect on open HANDLERs
|
||||
#
|
||||
create table t2 like t1;
|
||||
create table t3 like t1;
|
||||
begin;
|
||||
# Have something before the savepoint
|
||||
select * from t3;
|
||||
a
|
||||
savepoint sv;
|
||||
handler t1 open;
|
||||
handler t1 read a first;
|
||||
a
|
||||
1
|
||||
handler t1 read a next;
|
||||
a
|
||||
2
|
||||
select * from t2;
|
||||
a
|
||||
# --> connection con1
|
||||
# Sending:
|
||||
drop table t1;
|
||||
# --> connection con2
|
||||
# Sending:
|
||||
drop table t2;
|
||||
# --> connection default
|
||||
# Let DROP TABLE statements sync in. We must use
|
||||
# a separate connection for that, because otherwise SELECT
|
||||
# will auto-close the HANDLERs, becaues there are pending
|
||||
# exclusive locks against them.
|
||||
# --> connection con3
|
||||
# Waiting for 'drop table t1' to get blocked...
|
||||
# Waiting for 'drop table t2' to get blocked...
|
||||
# Demonstrate that t2 lock was released and t2 was dropped
|
||||
# after ROLLBACK TO SAVEPOINT
|
||||
# --> connection default
|
||||
rollback to savepoint sv;
|
||||
# --> connection con2
|
||||
# Reaping 'drop table t2'...
|
||||
# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
|
||||
# lock.
|
||||
# --> connection default
|
||||
handler t1 read a next;
|
||||
a
|
||||
3
|
||||
handler t1 read a next;
|
||||
a
|
||||
4
|
||||
# Demonstrate that the drop will go through as soon as we close the
|
||||
# HANDLER
|
||||
handler t1 close;
|
||||
# connection con1
|
||||
# Reaping 'drop table t1'...
|
||||
# --> connection default
|
||||
commit;
|
||||
drop table t3;
|
||||
#
|
||||
# A few special cases when using SAVEPOINT/ROLLBACK TO
|
||||
# SAVEPOINT and HANDLER.
|
||||
#
|
||||
# Show that rollback to the savepoint taken in the beginning
|
||||
# of the transaction doesn't release mdl lock on
|
||||
# the HANDLER that was opened later.
|
||||
#
|
||||
create table t1 (a int, key a(a));
|
||||
insert into t1 (a) values (1), (2), (3), (4), (5);
|
||||
create table t2 like t1;
|
||||
begin;
|
||||
savepoint sv;
|
||||
handler t1 open;
|
||||
handler t1 read a first;
|
||||
a
|
||||
1
|
||||
handler t1 read a next;
|
||||
a
|
||||
2
|
||||
select * from t2;
|
||||
a
|
||||
# --> connection con1
|
||||
# Sending:
|
||||
drop table t1;
|
||||
# --> connection con2
|
||||
# Sending:
|
||||
drop table t2;
|
||||
# --> connection default
|
||||
# Let DROP TABLE statements sync in. We must use
|
||||
# a separate connection for that, because otherwise SELECT
|
||||
# will auto-close the HANDLERs, becaues there are pending
|
||||
# exclusive locks against them.
|
||||
# --> connection con3
|
||||
# Waiting for 'drop table t1' to get blocked...
|
||||
# Waiting for 'drop table t2' to get blocked...
|
||||
# Demonstrate that t2 lock was released and t2 was dropped
|
||||
# after ROLLBACK TO SAVEPOINT
|
||||
# --> connection default
|
||||
rollback to savepoint sv;
|
||||
# --> connection con2
|
||||
# Reaping 'drop table t2'...
|
||||
# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
|
||||
# lock.
|
||||
# --> connection default
|
||||
handler t1 read a next;
|
||||
a
|
||||
3
|
||||
handler t1 read a next;
|
||||
a
|
||||
4
|
||||
# Demonstrate that the drop will go through as soon as we close the
|
||||
# HANDLER
|
||||
handler t1 close;
|
||||
# connection con1
|
||||
# Reaping 'drop table t1'...
|
||||
# --> connection default
|
||||
commit;
|
||||
#
|
||||
# Show that rollback to the savepoint taken in the beginning
|
||||
# of the transaction works properly (no valgrind warnins, etc),
|
||||
# even though it's done after the HANDLER mdl lock that was there
|
||||
# at the beginning is released and added again.
|
||||
#
|
||||
create table t1 (a int, key a(a));
|
||||
insert into t1 (a) values (1), (2), (3), (4), (5);
|
||||
create table t2 like t1;
|
||||
create table t3 like t1;
|
||||
insert into t3 (a) select a from t1;
|
||||
begin;
|
||||
handler t1 open;
|
||||
savepoint sv;
|
||||
handler t1 read a first;
|
||||
a
|
||||
1
|
||||
select * from t2;
|
||||
a
|
||||
handler t1 close;
|
||||
handler t3 open;
|
||||
handler t3 read a first;
|
||||
a
|
||||
1
|
||||
rollback to savepoint sv;
|
||||
# --> connection con1
|
||||
drop table t1, t2;
|
||||
# Sending:
|
||||
drop table t3;
|
||||
# Let DROP TABLE statement sync in.
|
||||
# --> connection con2
|
||||
# Waiting for 'drop table t3' to get blocked...
|
||||
# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
|
||||
# lock.
|
||||
# --> connection default
|
||||
handler t3 read a next;
|
||||
a
|
||||
2
|
||||
# Demonstrate that the drop will go through as soon as we close the
|
||||
# HANDLER
|
||||
handler t3 close;
|
||||
# connection con1
|
||||
# Reaping 'drop table t3'...
|
||||
# --> connection default
|
||||
commit;
|
||||
#
|
||||
# If we have to wait on an exclusive locks while having
|
||||
# an open HANDLER, ER_LOCK_DEADLOCK is reported.
|
||||
#
|
||||
create table t1 (a int, key a(a));
|
||||
create table t2 like t1;
|
||||
handler t1 open;
|
||||
# --> connection con1
|
||||
lock table t1 write, t2 write;
|
||||
# --> connection default
|
||||
drop table t2;
|
||||
# --> connection con2
|
||||
# Waiting for 'drop table t2' to get blocked...
|
||||
# --> connection con1
|
||||
drop table t1;
|
||||
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
||||
unlock tables;
|
||||
# --> connection default
|
||||
# Demonstrate that there is no deadlock with FLUSH TABLE,
|
||||
# even though it is waiting for the other table to go away
|
||||
create table t2 like t1;
|
||||
# Sending:
|
||||
flush table t2;
|
||||
# --> connection con2
|
||||
drop table t1;
|
||||
# --> connection con1
|
||||
unlock tables;
|
||||
# --> connection default
|
||||
# Reaping 'flush table t2'...
|
||||
drop table t2;
|
||||
#
|
||||
# Bug #46224 HANDLER statements within a transaction might
|
||||
# lead to deadlocks
|
||||
#
|
||||
create table t1 (a int, key a(a));
|
||||
insert into t1 values (1), (2);
|
||||
# --> connection default
|
||||
begin;
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
2
|
||||
handler t1 open;
|
||||
# --> connection con1
|
||||
# Sending:
|
||||
lock tables t1 write;
|
||||
# --> connection con2
|
||||
# Check that 'lock tables t1 write' waits until transaction which
|
||||
# has read from the table commits.
|
||||
# --> connection default
|
||||
# The below 'handler t1 read ...' should not be blocked as
|
||||
# 'lock tables t1 write' has not succeeded yet.
|
||||
handler t1 read a next;
|
||||
a
|
||||
1
|
||||
# Unblock 'lock tables t1 write'.
|
||||
commit;
|
||||
# --> connection con1
|
||||
# Reap 'lock tables t1 write'.
|
||||
# --> connection default
|
||||
# Sending:
|
||||
handler t1 read a next;
|
||||
# --> connection con1
|
||||
# Waiting for 'handler t1 read a next' to get blocked...
|
||||
# The below 'drop table t1' should be able to proceed without
|
||||
# waiting as it will force HANDLER to be closed.
|
||||
drop table t1;
|
||||
unlock tables;
|
||||
# --> connection default
|
||||
# Reaping 'handler t1 read a next'...
|
||||
ERROR 42S02: Table 'test.t1' doesn't exist
|
||||
handler t1 close;
|
||||
# --> connection con1
|
||||
# --> connection con2
|
||||
# --> connection con3
|
||||
#
|
||||
# A temporary table test.
|
||||
# Check that we don't loose positions of HANDLER opened
|
||||
# against a temporary table.
|
||||
#
|
||||
create table t1 (a int, b int, key a (a));
|
||||
insert into t1 (a) values (1), (2), (3), (4), (5);
|
||||
create temporary table t2 (a int, b int, key a (a));
|
||||
insert into t2 (a) select a from t1;
|
||||
handler t1 open;
|
||||
handler t1 read a next;
|
||||
a b
|
||||
1 NULL
|
||||
handler t2 open;
|
||||
handler t2 read a next;
|
||||
a b
|
||||
1 NULL
|
||||
flush table t1;
|
||||
handler t2 read a next;
|
||||
a b
|
||||
2 NULL
|
||||
# Sic: the position is lost
|
||||
handler t1 read a next;
|
||||
a b
|
||||
1 NULL
|
||||
select * from t1;
|
||||
a b
|
||||
1 NULL
|
||||
2 NULL
|
||||
3 NULL
|
||||
4 NULL
|
||||
5 NULL
|
||||
# Sic: the position is not lost
|
||||
handler t2 read a next;
|
||||
a b
|
||||
3 NULL
|
||||
select * from t2;
|
||||
ERROR HY000: Can't reopen table: 't2'
|
||||
handler t2 read a next;
|
||||
a b
|
||||
4 NULL
|
||||
drop table t1;
|
||||
drop temporary table t2;
|
||||
#
|
||||
# A test for lock_table_names()/unlock_table_names() function.
|
||||
# It should work properly in presence of open HANDLER.
|
||||
#
|
||||
create table t1 (a int, b int, key a (a));
|
||||
create table t2 like t1;
|
||||
create table t3 like t1;
|
||||
create table t4 like t1;
|
||||
handler t1 open;
|
||||
handler t2 open;
|
||||
rename table t4 to t5, t3 to t4, t5 to t3;
|
||||
handler t1 read first;
|
||||
a b
|
||||
handler t2 read first;
|
||||
a b
|
||||
drop table t1, t2, t3, t4;
|
||||
#
|
||||
# A test for FLUSH TABLES WITH READ LOCK and HANDLER statements.
|
||||
#
|
||||
set autocommit=0;
|
||||
create table t1 (a int, b int, key a (a));
|
||||
insert into t1 (a, b) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 5);
|
||||
create table t2 like t1;
|
||||
insert into t2 (a, b) select a, b from t1;
|
||||
create table t3 like t1;
|
||||
insert into t3 (a, b) select a, b from t1;
|
||||
commit;
|
||||
flush tables with read lock;
|
||||
handler t1 open;
|
||||
lock table t1 read;
|
||||
handler t1 read next;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
# This implicitly leaves LOCK TABLES but doesn't drop the GLR
|
||||
lock table not_exists_write read;
|
||||
ERROR 42S02: Table 'test.not_exists_write' doesn't exist
|
||||
# We still have the read lock.
|
||||
drop table t1;
|
||||
ERROR HY000: Can't execute the query because you have a conflicting read lock
|
||||
handler t1 read next;
|
||||
a b
|
||||
1 1
|
||||
handler t1 close;
|
||||
handler t1 open;
|
||||
select a from t2;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
handler t1 read next;
|
||||
a b
|
||||
1 1
|
||||
flush tables with read lock;
|
||||
handler t2 open;
|
||||
flush tables with read lock;
|
||||
handler t1 read next;
|
||||
a b
|
||||
1 1
|
||||
select a from t3;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
handler t2 read next;
|
||||
a b
|
||||
1 1
|
||||
handler t1 close;
|
||||
rollback;
|
||||
handler t2 close;
|
||||
drop table t1;
|
||||
ERROR HY000: Can't execute the query because you have a conflicting read lock
|
||||
commit;
|
||||
flush tables;
|
||||
drop table t1;
|
||||
ERROR HY000: Can't execute the query because you have a conflicting read lock
|
||||
unlock tables;
|
||||
drop table t1;
|
||||
set autocommit=default;
|
||||
drop table t2, t3;
|
||||
#
|
||||
# HANDLER statement and operation-type aware metadata locks.
|
||||
# Check that when we clone a ticket for HANDLER we downrade
|
||||
# the lock.
|
||||
#
|
||||
# Establish an auxiliary connection con1.
|
||||
# -> connection default
|
||||
create table t1 (a int, b int, key a (a));
|
||||
insert into t1 (a, b) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 5);
|
||||
begin;
|
||||
insert into t1 (a, b) values (6, 6);
|
||||
handler t1 open;
|
||||
handler t1 read a last;
|
||||
a b
|
||||
6 6
|
||||
insert into t1 (a, b) values (7, 7);
|
||||
handler t1 read a last;
|
||||
a b
|
||||
7 7
|
||||
commit;
|
||||
# -> connection con1
|
||||
# Demonstrate that the HANDLER doesn't hold MDL_SHARED_WRITE.
|
||||
lock table t1 write;
|
||||
unlock tables;
|
||||
# -> connection default
|
||||
handler t1 read a prev;
|
||||
a b
|
||||
6 6
|
||||
handler t1 close;
|
||||
# Cleanup.
|
||||
drop table t1;
|
||||
# -> connection con1
|
||||
# -> connection default
|
||||
#
|
||||
# A test for Bug#50555 "handler commands crash server in
|
||||
# my_hash_first()".
|
||||
#
|
||||
handler no_such_table read no_such_index first;
|
||||
ERROR 42S02: Unknown table 'no_such_table' in HANDLER
|
||||
handler no_such_table close;
|
||||
ERROR 42S02: Unknown table 'no_such_table' in HANDLER
|
||||
#
|
||||
# Bug#50907 Assertion `hash_tables->table->next == __null' on
|
||||
# HANDLER OPEN
|
||||
#
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
CREATE TEMPORARY TABLE t1 (i INT);
|
||||
CREATE TEMPORARY TABLE t2 (i INT);
|
||||
HANDLER t2 OPEN;
|
||||
HANDLER t2 READ FIRST;
|
||||
i
|
||||
HANDLER t2 CLOSE;
|
||||
DROP TABLE t1, t2;
|
||||
#
|
||||
# Bug#50912 Assertion `ticket->m_type >= mdl_request->type'
|
||||
# failed on HANDLER + I_S
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (id INT);
|
||||
HANDLER t1 OPEN;
|
||||
SELECT table_name, table_comment FROM information_schema.tables
|
||||
WHERE table_schema= 'test' AND table_name= 't1';
|
||||
table_name table_comment
|
||||
t1
|
||||
HANDLER t1 CLOSE;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Test for bug #50908 "Assertion `handler_tables_hash.records == 0'
|
||||
# failed in enter_locked_tables_mode".
|
||||
#
|
||||
drop tables if exists t1, t2;
|
||||
drop function if exists f1;
|
||||
create table t1 (i int);
|
||||
insert into t1 values (1), (2);
|
||||
create table t2 (j int);
|
||||
insert into t2 values (1);
|
||||
create function f1() returns int return (select count(*) from t2);
|
||||
# Check that open HANDLER survives statement executed in
|
||||
# prelocked mode.
|
||||
handler t1 open;
|
||||
handler t1 read next;
|
||||
i
|
||||
1
|
||||
# The below statement were aborted due to an assertion failure.
|
||||
select f1() from t2;
|
||||
f1()
|
||||
1
|
||||
handler t1 read next;
|
||||
i
|
||||
2
|
||||
handler t1 close;
|
||||
# Check that the same happens under GLOBAL READ LOCK.
|
||||
flush tables with read lock;
|
||||
handler t1 open;
|
||||
handler t1 read next;
|
||||
i
|
||||
1
|
||||
select f1() from t2;
|
||||
f1()
|
||||
1
|
||||
handler t1 read next;
|
||||
i
|
||||
2
|
||||
unlock tables;
|
||||
handler t1 close;
|
||||
# Now, check that the same happens if LOCK TABLES is executed.
|
||||
handler t1 open;
|
||||
handler t1 read next;
|
||||
i
|
||||
1
|
||||
lock table t2 read;
|
||||
select * from t2;
|
||||
j
|
||||
1
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
i
|
||||
2
|
||||
handler t1 close;
|
||||
# Finally, check scenario with GRL and LOCK TABLES.
|
||||
flush tables with read lock;
|
||||
handler t1 open;
|
||||
handler t1 read next;
|
||||
i
|
||||
1
|
||||
lock table t2 read;
|
||||
select * from t2;
|
||||
j
|
||||
1
|
||||
# This unlocks both tables and GRL.
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
i
|
||||
2
|
||||
handler t1 close;
|
||||
# Clean-up.
|
||||
drop function f1;
|
||||
drop tables t1, t2;
|
||||
#
|
||||
# Test for bug #51136 "Crash in pthread_rwlock_rdlock on TEMPORARY +
|
||||
# HANDLER + LOCK + SP".
|
||||
# Also see additional coverage for this bug in flush.test.
|
||||
#
|
||||
drop tables if exists t1, t2;
|
||||
create table t1 (i int);
|
||||
create temporary table t2 (j int);
|
||||
handler t1 open;
|
||||
lock table t2 read;
|
||||
# This commit should not release any MDL locks.
|
||||
commit;
|
||||
unlock tables;
|
||||
# The below statement crashed before the bug fix as it
|
||||
# has attempted to release metadata lock which was
|
||||
# already released by commit.
|
||||
handler t1 close;
|
||||
drop tables t1, t2;
|
||||
|
@ -547,6 +547,7 @@ c1
|
||||
1
|
||||
connection: flush
|
||||
flush tables;;
|
||||
connection: waiter
|
||||
connection: default
|
||||
handler t2 open;
|
||||
handler t2 read first;
|
||||
@ -558,23 +559,36 @@ c1
|
||||
handler t1 close;
|
||||
handler t2 close;
|
||||
drop table t1,t2;
|
||||
drop table if exists t1,t2;
|
||||
drop table if exists t1, t0;
|
||||
create table t1 (c1 int);
|
||||
connection: default
|
||||
handler t1 open;
|
||||
handler t1 read first;
|
||||
c1
|
||||
connection: flush
|
||||
rename table t1 to t2;;
|
||||
rename table t1 to t0;;
|
||||
connection: waiter
|
||||
connection: default
|
||||
handler t2 open;
|
||||
handler t2 read first;
|
||||
c1
|
||||
#
|
||||
# RENAME placed two pending locks and waits.
|
||||
# When HANDLER t0 OPEN does open_tables(), it calls
|
||||
# mysql_ha_flush(), which in turn closes the open HANDLER for t1.
|
||||
# RENAME TABLE gets unblocked. If it gets scheduled quickly
|
||||
# and manages to complete before open_tables()
|
||||
# of HANDLER t0 OPEN, open_tables() and therefore the whole
|
||||
# HANDLER t0 OPEN succeeds. Otherwise open_tables()
|
||||
# notices a pending or active exclusive metadata lock on t2
|
||||
# and the whole HANDLER t0 OPEN fails with ER_LOCK_DEADLOCK
|
||||
# error.
|
||||
#
|
||||
handler t0 open;
|
||||
handler t0 close;
|
||||
connection: flush
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Table 'test.t1' doesn't exist
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
handler t1 close;
|
||||
handler t2 close;
|
||||
drop table t2;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
drop table t0;
|
||||
drop table if exists t1;
|
||||
create temporary table t1 (a int, b char(1), key a(a), key b(a,b));
|
||||
insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"),
|
||||
@ -729,19 +743,945 @@ drop table t1;
|
||||
handler t1 read a next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
drop table if exists t1;
|
||||
# First test case which is supposed trigger the execution
|
||||
# path on which problem was discovered.
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1);
|
||||
handler t1 open;
|
||||
lock table t1 write;
|
||||
alter table t1 engine=memory;
|
||||
handler t1 read a next;
|
||||
ERROR HY000: Table storage engine for 't1' doesn't have this option
|
||||
handler t1 close;
|
||||
unlock tables;
|
||||
drop table t1;
|
||||
# Now test case which was reported originally but which no longer
|
||||
# triggers execution path which has caused the problem.
|
||||
create table t1 (a int, key(a));
|
||||
insert into t1 values (1);
|
||||
handler t1 open;
|
||||
alter table t1 engine=memory;
|
||||
# Since S metadata lock was already acquired at HANDLER OPEN time
|
||||
# and TL_READ lock requested by HANDLER READ is compatible with
|
||||
# ALTER's TL_WRITE_ALLOW_READ the below statement should succeed
|
||||
# without waiting. The old version of table should be used in it.
|
||||
handler t1 read a next;
|
||||
a
|
||||
1
|
||||
handler t1 close;
|
||||
drop table t1;
|
||||
USE information_schema;
|
||||
HANDLER COLUMNS OPEN;
|
||||
ERROR HY000: Incorrect usage of HANDLER OPEN and information_schema
|
||||
USE test;
|
||||
#
|
||||
# Add test coverage for HANDLER and LOCK TABLES, HANDLER and DDL.
|
||||
#
|
||||
drop table if exists t1, t2, t3;
|
||||
create table t1 (a int, key a (a));
|
||||
insert into t1 (a) values (1), (2), (3), (4), (5);
|
||||
create table t2 (a int, key a (a)) select * from t1;
|
||||
create temporary table t3 (a int, key a (a)) select * from t2;
|
||||
handler t1 open;
|
||||
handler t2 open;
|
||||
handler t3 open;
|
||||
#
|
||||
# No HANDLER sql is allowed under LOCK TABLES.
|
||||
# But it does not implicitly closes all handlers.
|
||||
#
|
||||
lock table t1 read;
|
||||
handler t1 open;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
handler t1 read next;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
handler t2 close;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
handler t3 open;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
# After UNLOCK TABLES handlers should be around and
|
||||
# we should be able to continue reading through them.
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
a
|
||||
1
|
||||
handler t1 close;
|
||||
handler t2 read next;
|
||||
a
|
||||
1
|
||||
handler t2 close;
|
||||
handler t3 read next;
|
||||
a
|
||||
1
|
||||
handler t3 close;
|
||||
drop temporary table t3;
|
||||
#
|
||||
# Other operations that implicitly close handler:
|
||||
#
|
||||
# TRUNCATE
|
||||
#
|
||||
handler t1 open;
|
||||
truncate table t1;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
handler t1 open;
|
||||
#
|
||||
# CREATE TRIGGER
|
||||
#
|
||||
create trigger t1_ai after insert on t1 for each row set @a=1;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# DROP TRIGGER
|
||||
#
|
||||
handler t1 open;
|
||||
drop trigger t1_ai;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# ALTER TABLE
|
||||
#
|
||||
handler t1 open;
|
||||
alter table t1 add column b int;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# ANALYZE TABLE
|
||||
#
|
||||
handler t1 open;
|
||||
analyze table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Table is already up to date
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# OPTIMIZE TABLE
|
||||
#
|
||||
handler t1 open;
|
||||
optimize table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 optimize status OK
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# REPAIR TABLE
|
||||
#
|
||||
handler t1 open;
|
||||
repair table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 repair status OK
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# DROP TABLE, naturally.
|
||||
#
|
||||
handler t1 open;
|
||||
drop table t1;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
create table t1 (a int, b int, key a (a)) select a from t2;
|
||||
#
|
||||
# RENAME TABLE, naturally
|
||||
#
|
||||
handler t1 open;
|
||||
rename table t1 to t3;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# CREATE TABLE (even with IF NOT EXISTS clause,
|
||||
# and the table exists).
|
||||
#
|
||||
handler t2 open;
|
||||
create table if not exists t2 (a int);
|
||||
Warnings:
|
||||
Note 1050 Table 't2' already exists
|
||||
handler t2 read next;
|
||||
ERROR 42S02: Unknown table 't2' in HANDLER
|
||||
rename table t3 to t1;
|
||||
drop table t2;
|
||||
#
|
||||
# FLUSH TABLE doesn't close the table but loses the position
|
||||
#
|
||||
handler t1 open;
|
||||
handler t1 read a prev;
|
||||
b a
|
||||
NULL 5
|
||||
flush table t1;
|
||||
handler t1 read a prev;
|
||||
b a
|
||||
NULL 5
|
||||
handler t1 close;
|
||||
#
|
||||
# FLUSH TABLES WITH READ LOCK behaves like FLUSH TABLE.
|
||||
#
|
||||
handler t1 open;
|
||||
handler t1 read a prev;
|
||||
b a
|
||||
NULL 5
|
||||
flush tables with read lock;
|
||||
handler t1 read a prev;
|
||||
b a
|
||||
NULL 5
|
||||
handler t1 close;
|
||||
unlock tables;
|
||||
#
|
||||
# Let us also check that these operations behave in similar
|
||||
# way under LOCK TABLES.
|
||||
#
|
||||
# TRUNCATE under LOCK TABLES.
|
||||
#
|
||||
handler t1 open;
|
||||
lock tables t1 write;
|
||||
truncate table t1;
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
handler t1 open;
|
||||
#
|
||||
# CREATE TRIGGER under LOCK TABLES.
|
||||
#
|
||||
lock tables t1 write;
|
||||
create trigger t1_ai after insert on t1 for each row set @a=1;
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# DROP TRIGGER under LOCK TABLES.
|
||||
#
|
||||
handler t1 open;
|
||||
lock tables t1 write;
|
||||
drop trigger t1_ai;
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# ALTER TABLE under LOCK TABLES.
|
||||
#
|
||||
handler t1 open;
|
||||
lock tables t1 write;
|
||||
alter table t1 drop column b;
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# ANALYZE TABLE under LOCK TABLES.
|
||||
#
|
||||
handler t1 open;
|
||||
lock tables t1 write;
|
||||
analyze table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Table is already up to date
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# OPTIMIZE TABLE under LOCK TABLES.
|
||||
#
|
||||
handler t1 open;
|
||||
lock tables t1 write;
|
||||
optimize table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 optimize status OK
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# REPAIR TABLE under LOCK TABLES.
|
||||
#
|
||||
handler t1 open;
|
||||
lock tables t1 write;
|
||||
repair table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 repair status OK
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
#
|
||||
# DROP TABLE under LOCK TABLES, naturally.
|
||||
#
|
||||
handler t1 open;
|
||||
lock tables t1 write;
|
||||
drop table t1;
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
create table t1 (a int, b int, key a (a));
|
||||
insert into t1 (a) values (1), (2), (3), (4), (5);
|
||||
#
|
||||
# FLUSH TABLE doesn't close the table but loses the position
|
||||
#
|
||||
handler t1 open;
|
||||
handler t1 read a prev;
|
||||
a b
|
||||
5 NULL
|
||||
lock tables t1 write;
|
||||
flush table t1;
|
||||
unlock tables;
|
||||
handler t1 read a prev;
|
||||
a b
|
||||
5 NULL
|
||||
handler t1 close;
|
||||
#
|
||||
# Explore the effect of HANDLER locks on concurrent DDL
|
||||
#
|
||||
handler t1 open;
|
||||
# Establishing auxiliary connections con1, con2, con3
|
||||
# --> connection con1;
|
||||
# Sending:
|
||||
drop table t1 ;
|
||||
# We can't use connection 'default' as wait_condition will
|
||||
# autoclose handlers.
|
||||
# --> connection con2
|
||||
# Waitng for 'drop table t1' to get blocked...
|
||||
# --> connection default
|
||||
handler t1 read a prev;
|
||||
a b
|
||||
5 NULL
|
||||
handler t1 read a prev;
|
||||
a b
|
||||
4 NULL
|
||||
handler t1 close;
|
||||
# --> connection con1
|
||||
# Reaping 'drop table t1'...
|
||||
# --> connection default
|
||||
#
|
||||
# Explore the effect of HANDLER locks in parallel with SELECT
|
||||
#
|
||||
create table t1 (a int, key a (a));
|
||||
insert into t1 (a) values (1), (2), (3), (4), (5);
|
||||
begin;
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
handler t1 open;
|
||||
handler t1 read a prev;
|
||||
a
|
||||
5
|
||||
handler t1 read a prev;
|
||||
a
|
||||
4
|
||||
handler t1 close;
|
||||
# --> connection con1;
|
||||
# Sending:
|
||||
drop table t1 ;
|
||||
# --> connection con2
|
||||
# Waiting for 'drop table t1' to get blocked...
|
||||
# --> connection default
|
||||
# We can still use the table, it's part of the transaction
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
# Such are the circumstances that t1 is a part of transaction,
|
||||
# thus we can reopen it in the handler
|
||||
handler t1 open;
|
||||
# We can commit the transaction, it doesn't close the handler
|
||||
# and doesn't let DROP to proceed.
|
||||
commit;
|
||||
handler t1 read a prev;
|
||||
a
|
||||
5
|
||||
handler t1 read a prev;
|
||||
a
|
||||
4
|
||||
handler t1 read a prev;
|
||||
a
|
||||
3
|
||||
handler t1 close;
|
||||
# --> connection con1
|
||||
# Now drop can proceed
|
||||
# Reaping 'drop table t1'...
|
||||
# --> connection default
|
||||
#
|
||||
# Demonstrate that HANDLER locks and transaction locks
|
||||
# reside in the same context, and we don't back-off
|
||||
# when have transaction or handler locks.
|
||||
#
|
||||
create table t1 (a int, key a (a));
|
||||
insert into t1 (a) values (1), (2), (3), (4), (5);
|
||||
create table t0 (a int, key a (a));
|
||||
insert into t0 (a) values (1), (2), (3), (4), (5);
|
||||
begin;
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
# --> connection con2
|
||||
# Sending:
|
||||
rename table t0 to t3, t1 to t0, t3 to t1;
|
||||
# --> connection con1
|
||||
# Waiting for 'rename table ...' to get blocked...
|
||||
# --> connection default
|
||||
handler t0 open;
|
||||
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
||||
select * from t0;
|
||||
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
||||
handler t1 open;
|
||||
commit;
|
||||
handler t1 close;
|
||||
# --> connection con2
|
||||
# Reaping 'rename table ...'...
|
||||
# --> connection default
|
||||
handler t1 open;
|
||||
handler t1 read a prev;
|
||||
a
|
||||
5
|
||||
handler t1 close;
|
||||
drop table t0;
|
||||
#
|
||||
# Originally there was a deadlock error in this test.
|
||||
# With implementation of deadlock detector
|
||||
# we no longer deadlock, but block and wait on a lock.
|
||||
# The HANDLER is auto-closed as soon as the connection
|
||||
# sees a pending conflicting lock against it.
|
||||
#
|
||||
create table t2 (a int, key a (a));
|
||||
handler t1 open;
|
||||
# --> connection con1
|
||||
lock tables t2 read;
|
||||
# --> connection con2
|
||||
# Sending 'drop table t2'...
|
||||
drop table t2;
|
||||
# --> connection con1
|
||||
# Waiting for 'drop table t2' to get blocked...
|
||||
# --> connection default
|
||||
# Sending 'select * from t2'
|
||||
select * from t2;
|
||||
# --> connection con1
|
||||
# Waiting for 'select * from t2' to get blocked...
|
||||
unlock tables;
|
||||
# --> connection con2
|
||||
# Reaping 'drop table t2'...
|
||||
# --> connection default
|
||||
# Reaping 'select * from t2'
|
||||
ERROR 42S02: Table 'test.t2' doesn't exist
|
||||
handler t1 close;
|
||||
#
|
||||
# ROLLBACK TO SAVEPOINT releases transactional locks,
|
||||
# but has no effect on open HANDLERs
|
||||
#
|
||||
create table t2 like t1;
|
||||
create table t3 like t1;
|
||||
begin;
|
||||
# Have something before the savepoint
|
||||
select * from t3;
|
||||
a
|
||||
savepoint sv;
|
||||
handler t1 open;
|
||||
handler t1 read a first;
|
||||
a
|
||||
1
|
||||
handler t1 read a next;
|
||||
a
|
||||
2
|
||||
select * from t2;
|
||||
a
|
||||
# --> connection con1
|
||||
# Sending:
|
||||
drop table t1;
|
||||
# --> connection con2
|
||||
# Sending:
|
||||
drop table t2;
|
||||
# --> connection default
|
||||
# Let DROP TABLE statements sync in. We must use
|
||||
# a separate connection for that, because otherwise SELECT
|
||||
# will auto-close the HANDLERs, becaues there are pending
|
||||
# exclusive locks against them.
|
||||
# --> connection con3
|
||||
# Waiting for 'drop table t1' to get blocked...
|
||||
# Waiting for 'drop table t2' to get blocked...
|
||||
# Demonstrate that t2 lock was released and t2 was dropped
|
||||
# after ROLLBACK TO SAVEPOINT
|
||||
# --> connection default
|
||||
rollback to savepoint sv;
|
||||
# --> connection con2
|
||||
# Reaping 'drop table t2'...
|
||||
# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
|
||||
# lock.
|
||||
# --> connection default
|
||||
handler t1 read a next;
|
||||
a
|
||||
3
|
||||
handler t1 read a next;
|
||||
a
|
||||
4
|
||||
# Demonstrate that the drop will go through as soon as we close the
|
||||
# HANDLER
|
||||
handler t1 close;
|
||||
# connection con1
|
||||
# Reaping 'drop table t1'...
|
||||
# --> connection default
|
||||
commit;
|
||||
drop table t3;
|
||||
#
|
||||
# A few special cases when using SAVEPOINT/ROLLBACK TO
|
||||
# SAVEPOINT and HANDLER.
|
||||
#
|
||||
# Show that rollback to the savepoint taken in the beginning
|
||||
# of the transaction doesn't release mdl lock on
|
||||
# the HANDLER that was opened later.
|
||||
#
|
||||
create table t1 (a int, key a(a));
|
||||
insert into t1 (a) values (1), (2), (3), (4), (5);
|
||||
create table t2 like t1;
|
||||
begin;
|
||||
savepoint sv;
|
||||
handler t1 open;
|
||||
handler t1 read a first;
|
||||
a
|
||||
1
|
||||
handler t1 read a next;
|
||||
a
|
||||
2
|
||||
select * from t2;
|
||||
a
|
||||
# --> connection con1
|
||||
# Sending:
|
||||
drop table t1;
|
||||
# --> connection con2
|
||||
# Sending:
|
||||
drop table t2;
|
||||
# --> connection default
|
||||
# Let DROP TABLE statements sync in. We must use
|
||||
# a separate connection for that, because otherwise SELECT
|
||||
# will auto-close the HANDLERs, becaues there are pending
|
||||
# exclusive locks against them.
|
||||
# --> connection con3
|
||||
# Waiting for 'drop table t1' to get blocked...
|
||||
# Waiting for 'drop table t2' to get blocked...
|
||||
# Demonstrate that t2 lock was released and t2 was dropped
|
||||
# after ROLLBACK TO SAVEPOINT
|
||||
# --> connection default
|
||||
rollback to savepoint sv;
|
||||
# --> connection con2
|
||||
# Reaping 'drop table t2'...
|
||||
# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
|
||||
# lock.
|
||||
# --> connection default
|
||||
handler t1 read a next;
|
||||
a
|
||||
3
|
||||
handler t1 read a next;
|
||||
a
|
||||
4
|
||||
# Demonstrate that the drop will go through as soon as we close the
|
||||
# HANDLER
|
||||
handler t1 close;
|
||||
# connection con1
|
||||
# Reaping 'drop table t1'...
|
||||
# --> connection default
|
||||
commit;
|
||||
#
|
||||
# Show that rollback to the savepoint taken in the beginning
|
||||
# of the transaction works properly (no valgrind warnins, etc),
|
||||
# even though it's done after the HANDLER mdl lock that was there
|
||||
# at the beginning is released and added again.
|
||||
#
|
||||
create table t1 (a int, key a(a));
|
||||
insert into t1 (a) values (1), (2), (3), (4), (5);
|
||||
create table t2 like t1;
|
||||
create table t3 like t1;
|
||||
insert into t3 (a) select a from t1;
|
||||
begin;
|
||||
handler t1 open;
|
||||
savepoint sv;
|
||||
handler t1 read a first;
|
||||
a
|
||||
1
|
||||
select * from t2;
|
||||
a
|
||||
handler t1 close;
|
||||
handler t3 open;
|
||||
handler t3 read a first;
|
||||
a
|
||||
1
|
||||
rollback to savepoint sv;
|
||||
# --> connection con1
|
||||
drop table t1, t2;
|
||||
# Sending:
|
||||
drop table t3;
|
||||
# Let DROP TABLE statement sync in.
|
||||
# --> connection con2
|
||||
# Waiting for 'drop table t3' to get blocked...
|
||||
# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
|
||||
# lock.
|
||||
# --> connection default
|
||||
handler t3 read a next;
|
||||
a
|
||||
2
|
||||
# Demonstrate that the drop will go through as soon as we close the
|
||||
# HANDLER
|
||||
handler t3 close;
|
||||
# connection con1
|
||||
# Reaping 'drop table t3'...
|
||||
# --> connection default
|
||||
commit;
|
||||
#
|
||||
# If we have to wait on an exclusive locks while having
|
||||
# an open HANDLER, ER_LOCK_DEADLOCK is reported.
|
||||
#
|
||||
create table t1 (a int, key a(a));
|
||||
create table t2 like t1;
|
||||
handler t1 open;
|
||||
# --> connection con1
|
||||
lock table t1 write, t2 write;
|
||||
# --> connection default
|
||||
drop table t2;
|
||||
# --> connection con2
|
||||
# Waiting for 'drop table t2' to get blocked...
|
||||
# --> connection con1
|
||||
drop table t1;
|
||||
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
||||
unlock tables;
|
||||
# --> connection default
|
||||
# Demonstrate that there is no deadlock with FLUSH TABLE,
|
||||
# even though it is waiting for the other table to go away
|
||||
create table t2 like t1;
|
||||
# Sending:
|
||||
flush table t2;
|
||||
# --> connection con2
|
||||
drop table t1;
|
||||
# --> connection con1
|
||||
unlock tables;
|
||||
# --> connection default
|
||||
# Reaping 'flush table t2'...
|
||||
drop table t2;
|
||||
#
|
||||
# Bug #46224 HANDLER statements within a transaction might
|
||||
# lead to deadlocks
|
||||
#
|
||||
create table t1 (a int, key a(a));
|
||||
insert into t1 values (1), (2);
|
||||
# --> connection default
|
||||
begin;
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
2
|
||||
handler t1 open;
|
||||
# --> connection con1
|
||||
# Sending:
|
||||
lock tables t1 write;
|
||||
# --> connection con2
|
||||
# Check that 'lock tables t1 write' waits until transaction which
|
||||
# has read from the table commits.
|
||||
# --> connection default
|
||||
# The below 'handler t1 read ...' should not be blocked as
|
||||
# 'lock tables t1 write' has not succeeded yet.
|
||||
handler t1 read a next;
|
||||
a
|
||||
1
|
||||
# Unblock 'lock tables t1 write'.
|
||||
commit;
|
||||
# --> connection con1
|
||||
# Reap 'lock tables t1 write'.
|
||||
# --> connection default
|
||||
# Sending:
|
||||
handler t1 read a next;
|
||||
# --> connection con1
|
||||
# Waiting for 'handler t1 read a next' to get blocked...
|
||||
# The below 'drop table t1' should be able to proceed without
|
||||
# waiting as it will force HANDLER to be closed.
|
||||
drop table t1;
|
||||
unlock tables;
|
||||
# --> connection default
|
||||
# Reaping 'handler t1 read a next'...
|
||||
ERROR 42S02: Table 'test.t1' doesn't exist
|
||||
handler t1 close;
|
||||
# --> connection con1
|
||||
# --> connection con2
|
||||
# --> connection con3
|
||||
#
|
||||
# A temporary table test.
|
||||
# Check that we don't loose positions of HANDLER opened
|
||||
# against a temporary table.
|
||||
#
|
||||
create table t1 (a int, b int, key a (a));
|
||||
insert into t1 (a) values (1), (2), (3), (4), (5);
|
||||
create temporary table t2 (a int, b int, key a (a));
|
||||
insert into t2 (a) select a from t1;
|
||||
handler t1 open;
|
||||
handler t1 read a next;
|
||||
a b
|
||||
1 NULL
|
||||
handler t2 open;
|
||||
handler t2 read a next;
|
||||
a b
|
||||
1 NULL
|
||||
flush table t1;
|
||||
handler t2 read a next;
|
||||
a b
|
||||
2 NULL
|
||||
# Sic: the position is lost
|
||||
handler t1 read a next;
|
||||
a b
|
||||
1 NULL
|
||||
select * from t1;
|
||||
a b
|
||||
1 NULL
|
||||
2 NULL
|
||||
3 NULL
|
||||
4 NULL
|
||||
5 NULL
|
||||
# Sic: the position is not lost
|
||||
handler t2 read a next;
|
||||
a b
|
||||
3 NULL
|
||||
select * from t2;
|
||||
ERROR HY000: Can't reopen table: 't2'
|
||||
handler t2 read a next;
|
||||
a b
|
||||
4 NULL
|
||||
drop table t1;
|
||||
drop temporary table t2;
|
||||
#
|
||||
# A test for lock_table_names()/unlock_table_names() function.
|
||||
# It should work properly in presence of open HANDLER.
|
||||
#
|
||||
create table t1 (a int, b int, key a (a));
|
||||
create table t2 like t1;
|
||||
create table t3 like t1;
|
||||
create table t4 like t1;
|
||||
handler t1 open;
|
||||
handler t2 open;
|
||||
rename table t4 to t5, t3 to t4, t5 to t3;
|
||||
handler t1 read first;
|
||||
a b
|
||||
handler t2 read first;
|
||||
a b
|
||||
drop table t1, t2, t3, t4;
|
||||
#
|
||||
# A test for FLUSH TABLES WITH READ LOCK and HANDLER statements.
|
||||
#
|
||||
set autocommit=0;
|
||||
create table t1 (a int, b int, key a (a));
|
||||
insert into t1 (a, b) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 5);
|
||||
create table t2 like t1;
|
||||
insert into t2 (a, b) select a, b from t1;
|
||||
create table t3 like t1;
|
||||
insert into t3 (a, b) select a, b from t1;
|
||||
commit;
|
||||
flush tables with read lock;
|
||||
handler t1 open;
|
||||
lock table t1 read;
|
||||
handler t1 read next;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
# This implicitly leaves LOCK TABLES but doesn't drop the GLR
|
||||
lock table not_exists_write read;
|
||||
ERROR 42S02: Table 'test.not_exists_write' doesn't exist
|
||||
# We still have the read lock.
|
||||
drop table t1;
|
||||
ERROR HY000: Can't execute the query because you have a conflicting read lock
|
||||
handler t1 read next;
|
||||
a b
|
||||
1 1
|
||||
handler t1 close;
|
||||
handler t1 open;
|
||||
select a from t2;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
handler t1 read next;
|
||||
a b
|
||||
1 1
|
||||
flush tables with read lock;
|
||||
handler t2 open;
|
||||
flush tables with read lock;
|
||||
handler t1 read next;
|
||||
a b
|
||||
1 1
|
||||
select a from t3;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
handler t2 read next;
|
||||
a b
|
||||
1 1
|
||||
handler t1 close;
|
||||
rollback;
|
||||
handler t2 close;
|
||||
drop table t1;
|
||||
ERROR HY000: Can't execute the query because you have a conflicting read lock
|
||||
commit;
|
||||
flush tables;
|
||||
drop table t1;
|
||||
ERROR HY000: Can't execute the query because you have a conflicting read lock
|
||||
unlock tables;
|
||||
drop table t1;
|
||||
set autocommit=default;
|
||||
drop table t2, t3;
|
||||
#
|
||||
# HANDLER statement and operation-type aware metadata locks.
|
||||
# Check that when we clone a ticket for HANDLER we downrade
|
||||
# the lock.
|
||||
#
|
||||
# Establish an auxiliary connection con1.
|
||||
# -> connection default
|
||||
create table t1 (a int, b int, key a (a));
|
||||
insert into t1 (a, b) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 5);
|
||||
begin;
|
||||
insert into t1 (a, b) values (6, 6);
|
||||
handler t1 open;
|
||||
handler t1 read a last;
|
||||
a b
|
||||
6 6
|
||||
insert into t1 (a, b) values (7, 7);
|
||||
handler t1 read a last;
|
||||
a b
|
||||
7 7
|
||||
commit;
|
||||
# -> connection con1
|
||||
# Demonstrate that the HANDLER doesn't hold MDL_SHARED_WRITE.
|
||||
lock table t1 write;
|
||||
unlock tables;
|
||||
# -> connection default
|
||||
handler t1 read a prev;
|
||||
a b
|
||||
6 6
|
||||
handler t1 close;
|
||||
# Cleanup.
|
||||
drop table t1;
|
||||
# -> connection con1
|
||||
# -> connection default
|
||||
#
|
||||
# A test for Bug#50555 "handler commands crash server in
|
||||
# my_hash_first()".
|
||||
#
|
||||
handler no_such_table read no_such_index first;
|
||||
ERROR 42S02: Unknown table 'no_such_table' in HANDLER
|
||||
handler no_such_table close;
|
||||
ERROR 42S02: Unknown table 'no_such_table' in HANDLER
|
||||
#
|
||||
# Bug#50907 Assertion `hash_tables->table->next == __null' on
|
||||
# HANDLER OPEN
|
||||
#
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
CREATE TEMPORARY TABLE t1 (i INT);
|
||||
CREATE TEMPORARY TABLE t2 (i INT);
|
||||
HANDLER t2 OPEN;
|
||||
HANDLER t2 READ FIRST;
|
||||
i
|
||||
HANDLER t2 CLOSE;
|
||||
DROP TABLE t1, t2;
|
||||
#
|
||||
# Bug#50912 Assertion `ticket->m_type >= mdl_request->type'
|
||||
# failed on HANDLER + I_S
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (id INT);
|
||||
HANDLER t1 OPEN;
|
||||
SELECT table_name, table_comment FROM information_schema.tables
|
||||
WHERE table_schema= 'test' AND table_name= 't1';
|
||||
table_name table_comment
|
||||
t1
|
||||
HANDLER t1 CLOSE;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Test for bug #50908 "Assertion `handler_tables_hash.records == 0'
|
||||
# failed in enter_locked_tables_mode".
|
||||
#
|
||||
drop tables if exists t1, t2;
|
||||
drop function if exists f1;
|
||||
create table t1 (i int);
|
||||
insert into t1 values (1), (2);
|
||||
create table t2 (j int);
|
||||
insert into t2 values (1);
|
||||
create function f1() returns int return (select count(*) from t2);
|
||||
# Check that open HANDLER survives statement executed in
|
||||
# prelocked mode.
|
||||
handler t1 open;
|
||||
handler t1 read next;
|
||||
i
|
||||
1
|
||||
# The below statement were aborted due to an assertion failure.
|
||||
select f1() from t2;
|
||||
f1()
|
||||
1
|
||||
handler t1 read next;
|
||||
i
|
||||
2
|
||||
handler t1 close;
|
||||
# Check that the same happens under GLOBAL READ LOCK.
|
||||
flush tables with read lock;
|
||||
handler t1 open;
|
||||
handler t1 read next;
|
||||
i
|
||||
1
|
||||
select f1() from t2;
|
||||
f1()
|
||||
1
|
||||
handler t1 read next;
|
||||
i
|
||||
2
|
||||
unlock tables;
|
||||
handler t1 close;
|
||||
# Now, check that the same happens if LOCK TABLES is executed.
|
||||
handler t1 open;
|
||||
handler t1 read next;
|
||||
i
|
||||
1
|
||||
lock table t2 read;
|
||||
select * from t2;
|
||||
j
|
||||
1
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
i
|
||||
2
|
||||
handler t1 close;
|
||||
# Finally, check scenario with GRL and LOCK TABLES.
|
||||
flush tables with read lock;
|
||||
handler t1 open;
|
||||
handler t1 read next;
|
||||
i
|
||||
1
|
||||
lock table t2 read;
|
||||
select * from t2;
|
||||
j
|
||||
1
|
||||
# This unlocks both tables and GRL.
|
||||
unlock tables;
|
||||
handler t1 read next;
|
||||
i
|
||||
2
|
||||
handler t1 close;
|
||||
# Clean-up.
|
||||
drop function f1;
|
||||
drop tables t1, t2;
|
||||
#
|
||||
# Test for bug #51136 "Crash in pthread_rwlock_rdlock on TEMPORARY +
|
||||
# HANDLER + LOCK + SP".
|
||||
# Also see additional coverage for this bug in flush.test.
|
||||
#
|
||||
drop tables if exists t1, t2;
|
||||
create table t1 (i int);
|
||||
create temporary table t2 (j int);
|
||||
handler t1 open;
|
||||
lock table t2 read;
|
||||
# This commit should not release any MDL locks.
|
||||
commit;
|
||||
unlock tables;
|
||||
# The below statement crashed before the bug fix as it
|
||||
# has attempted to release metadata lock which was
|
||||
# already released by commit.
|
||||
handler t1 close;
|
||||
drop tables t1, t2;
|
||||
#
|
||||
# BUG #46456: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash
|
||||
#
|
||||
CREATE TABLE t1 AS SELECT 1 AS f1;
|
||||
|
1061
mysql-test/r/implicit_commit.result
Normal file
1061
mysql-test/r/implicit_commit.result
Normal file
File diff suppressed because it is too large
Load Diff
@ -1682,6 +1682,57 @@ DROP USER nonpriv;
|
||||
DROP TABLE db1.t1;
|
||||
DROP DATABASE db1;
|
||||
End of 5.1 tests.
|
||||
#
|
||||
# Additional test for WL#3726 "DDL locking for all metadata objects"
|
||||
# To avoid possible deadlocks process of filling of I_S tables should
|
||||
# use high-priority metadata lock requests when opening tables.
|
||||
# Below we just test that we really use high-priority lock request
|
||||
# since reproducing a deadlock will require much more complex test.
|
||||
#
|
||||
drop tables if exists t1, t2, t3;
|
||||
create table t1 (i int);
|
||||
create table t2 (j int primary key auto_increment);
|
||||
# Switching to connection 'con3726_1'
|
||||
lock table t2 read;
|
||||
# Switching to connection 'con3726_2'
|
||||
# RENAME below will be blocked by 'lock table t2 read' above but
|
||||
# will add two pending requests for exclusive metadata locks.
|
||||
rename table t2 to t3;
|
||||
# Switching to connection 'default'
|
||||
# These statements should not be blocked by pending lock requests
|
||||
select table_name, column_name, data_type from information_schema.columns
|
||||
where table_schema = 'test' and table_name in ('t1', 't2');
|
||||
table_name column_name data_type
|
||||
t1 i int
|
||||
t2 j int
|
||||
select table_name, auto_increment from information_schema.tables
|
||||
where table_schema = 'test' and table_name in ('t1', 't2');
|
||||
table_name auto_increment
|
||||
t1 NULL
|
||||
t2 1
|
||||
# Switching to connection 'con3726_1'
|
||||
unlock tables;
|
||||
# Switching to connection 'con3726_2'
|
||||
# Switching to connection 'default'
|
||||
drop tables t1, t3;
|
||||
EXPLAIN SELECT * FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE KEY_COLUMN_USAGE ALL NULL NULL NULL NULL NULL Open_full_table; Scanned all databases
|
||||
EXPLAIN SELECT * FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE PARTITIONS ALL NULL TABLE_NAME NULL NULL NULL Using where; Open_full_table; Scanned 1 database
|
||||
EXPLAIN SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
|
||||
WHERE CONSTRAINT_SCHEMA='test';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE REFERENTIAL_CONSTRAINTS ALL NULL CONSTRAINT_SCHEMA NULL NULL NULL Using where; Open_full_table; Scanned 1 database
|
||||
EXPLAIN SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
|
||||
WHERE TABLE_NAME='t1' and TABLE_SCHEMA='test';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE TABLE_CONSTRAINTS ALL NULL TABLE_SCHEMA,TABLE_NAME NULL NULL NULL Using where; Open_full_table; Scanned 0 databases
|
||||
EXPLAIN SELECT * FROM INFORMATION_SCHEMA.TRIGGERS
|
||||
WHERE EVENT_OBJECT_SCHEMA='test';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE TRIGGERS ALL NULL EVENT_OBJECT_SCHEMA NULL NULL NULL Using where; Open_frm_only; Scanned 1 database
|
||||
create table information_schema.t1 (f1 INT);
|
||||
ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
|
||||
drop table information_schema.t1;
|
||||
@ -1720,28 +1771,10 @@ ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_
|
||||
LOCK TABLES t1 READ, information_schema.tables READ;
|
||||
ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
|
||||
DROP TABLE t1;
|
||||
EXPLAIN SELECT * FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE KEY_COLUMN_USAGE ALL NULL NULL NULL NULL NULL Open_full_table; Scanned all databases
|
||||
EXPLAIN SELECT * FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE PARTITIONS ALL NULL TABLE_NAME NULL NULL NULL Using where; Open_full_table; Scanned 1 database
|
||||
EXPLAIN SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
|
||||
WHERE CONSTRAINT_SCHEMA='test';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE REFERENTIAL_CONSTRAINTS ALL NULL CONSTRAINT_SCHEMA NULL NULL NULL Using where; Open_full_table; Scanned 1 database
|
||||
EXPLAIN SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
|
||||
WHERE TABLE_NAME='t1' and TABLE_SCHEMA='test';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE TABLE_CONSTRAINTS ALL NULL TABLE_SCHEMA,TABLE_NAME NULL NULL NULL Using where; Open_full_table; Scanned 0 databases
|
||||
EXPLAIN SELECT * FROM INFORMATION_SCHEMA.TRIGGERS
|
||||
WHERE EVENT_OBJECT_SCHEMA='test';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE TRIGGERS ALL NULL EVENT_OBJECT_SCHEMA NULL NULL NULL Using where; Open_frm_only; Scanned 1 database
|
||||
SELECT *
|
||||
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
|
||||
LEFT JOIN INFORMATION_SCHEMA.COLUMNS
|
||||
USING (TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME)
|
||||
WHERE COLUMNS.TABLE_SCHEMA = 'test'
|
||||
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
|
||||
LEFT JOIN INFORMATION_SCHEMA.COLUMNS
|
||||
USING (TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME)
|
||||
WHERE COLUMNS.TABLE_SCHEMA = 'test'
|
||||
AND COLUMNS.TABLE_NAME = 't1';
|
||||
TABLE_SCHEMA TABLE_NAME COLUMN_NAME CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG ORDINAL_POSITION POSITION_IN_UNIQUE_CONSTRAINT REFERENCED_TABLE_SCHEMA REFERENCED_TABLE_NAME REFERENCED_COLUMN_NAME TABLE_CATALOG ORDINAL_POSITION COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA PRIVILEGES COLUMN_COMMENT
|
||||
|
@ -25,6 +25,12 @@ id x
|
||||
0 2
|
||||
commit;
|
||||
drop table t1;
|
||||
#
|
||||
# Old lock method (where LOCK TABLE was ignored by InnoDB) no longer
|
||||
# works due to fix for bugs #46272 "MySQL 5.4.4, new MDL: unnecessary
|
||||
# deadlock" and bug #37346 "innodb does not detect deadlock between
|
||||
# update and alter table".
|
||||
#
|
||||
set @@innodb_table_locks=0;
|
||||
create table t1 (id integer primary key, x integer) engine=INNODB;
|
||||
insert into t1 values(0, 0),(1,1),(2,2);
|
||||
@ -32,26 +38,27 @@ commit;
|
||||
SELECT * from t1 where id = 0 FOR UPDATE;
|
||||
id x
|
||||
0 0
|
||||
# Connection 'con2'.
|
||||
set autocommit=0;
|
||||
set @@innodb_table_locks=0;
|
||||
lock table t1 write;
|
||||
update t1 set x=10 where id = 2;
|
||||
SELECT * from t1 where id = 2;
|
||||
id x
|
||||
2 2
|
||||
UPDATE t1 set x=3 where id = 2;
|
||||
commit;
|
||||
SELECT * from t1;
|
||||
id x
|
||||
0 0
|
||||
1 1
|
||||
2 3
|
||||
commit;
|
||||
unlock tables;
|
||||
commit;
|
||||
# The following statement should block because SQL-level lock
|
||||
# is taken on t1 which will wait until concurrent transaction
|
||||
# is commited.
|
||||
# Sending:
|
||||
lock table t1 write;;
|
||||
# Connection 'con1'.
|
||||
# Wait until LOCK TABLE is blocked on SQL-level lock.
|
||||
# We should be able to do UPDATEs and SELECTs within transaction.
|
||||
update t1 set x=1 where id = 0;
|
||||
select * from t1;
|
||||
id x
|
||||
0 0
|
||||
0 1
|
||||
1 1
|
||||
2 10
|
||||
2 2
|
||||
# Unblock LOCK TABLE.
|
||||
commit;
|
||||
# Connection 'con2'.
|
||||
# Reap LOCK TABLE.
|
||||
unlock tables;
|
||||
# Connection 'con1'.
|
||||
drop table t1;
|
||||
|
@ -2834,10 +2834,10 @@ t2 CREATE TABLE `t2` (
|
||||
DROP TABLE t2,t1;
|
||||
create table t1(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
|
||||
insert into t1(a) values (1),(2),(3);
|
||||
create trigger t1t before insert on t1 for each row begin set NEW.b = NEW.a * 10 + 5, NEW.c = NEW.a / 10; end |
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
update t1 set b = 5 where a = 2;
|
||||
create trigger t1t before insert on t1 for each row begin set NEW.b = NEW.a * 10 + 5, NEW.c = NEW.a / 10; end |
|
||||
set autocommit = 0;
|
||||
insert into t1(a) values (10),(20),(30),(40),(50),(60),(70),(80),(90),(100),
|
||||
(11),(21),(31),(41),(51),(61),(71),(81),(91),(101),
|
||||
@ -2885,6 +2885,7 @@ insert into t2(a) values(8);
|
||||
delete from t2 where a = 3;
|
||||
update t4 set b = b + 1 where a = 3;
|
||||
commit;
|
||||
commit;
|
||||
drop trigger t1t;
|
||||
drop trigger t2t;
|
||||
drop trigger t3t;
|
||||
|
@ -1105,6 +1105,8 @@ CREATE PROCEDURE p1 ()
|
||||
BEGIN
|
||||
DECLARE i INT DEFAULT 50;
|
||||
DECLARE cnt INT;
|
||||
# Continue even in the presence of ER_LOCK_DEADLOCK.
|
||||
DECLARE CONTINUE HANDLER FOR 1213 BEGIN END;
|
||||
START TRANSACTION;
|
||||
ALTER TABLE t1 ENGINE=InnoDB;
|
||||
COMMIT;
|
||||
@ -1618,6 +1620,7 @@ a b
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 init+con1+con2
|
||||
COMMIT;
|
||||
# Switch to connection con1
|
||||
# 3. test for updated key column:
|
||||
TRUNCATE t1;
|
||||
|
88
mysql-test/r/innodb_mysql_lock.result
Normal file
88
mysql-test/r/innodb_mysql_lock.result
Normal file
@ -0,0 +1,88 @@
|
||||
#
|
||||
# Bug #22876 Four-way deadlock
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
# Connection 1
|
||||
set @@autocommit=0;
|
||||
CREATE TABLE t1(s1 INT UNIQUE) ENGINE=innodb;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
# Connection 2
|
||||
set @@autocommit=0;
|
||||
INSERT INTO t1 VALUES (2);
|
||||
INSERT INTO t1 VALUES (1);
|
||||
# Connection 3
|
||||
set @@autocommit=0;
|
||||
DROP TABLE t1;
|
||||
# Connection 1
|
||||
# Connection 1 is now holding the lock.
|
||||
# Issuing insert from connection 1 while connection 2&3
|
||||
# is waiting for the lock should give a deadlock error.
|
||||
INSERT INTO t1 VALUES (2);
|
||||
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
||||
# Cleanup
|
||||
commit;
|
||||
set @@autocommit=1;
|
||||
commit;
|
||||
set @@autocommit=1;
|
||||
set @@autocommit=1;
|
||||
#
|
||||
# Test for bug #37346 "innodb does not detect deadlock between update
|
||||
# and alter table".
|
||||
#
|
||||
drop table if exists t1;
|
||||
create table t1 (c1 int primary key, c2 int, c3 int) engine=InnoDB;
|
||||
insert into t1 values (1,1,0),(2,2,0),(3,3,0),(4,4,0),(5,5,0);
|
||||
begin;
|
||||
# Run statement which acquires X-lock on one of table's rows.
|
||||
update t1 set c3=c3+1 where c2=3;
|
||||
#
|
||||
# Switching to connection 'con37346'.
|
||||
# The below ALTER TABLE statement should wait till transaction
|
||||
# in connection 'default' is complete and then succeed.
|
||||
# It should not deadlock or fail with ER_LOCK_DEADLOCK error.
|
||||
# Sending:
|
||||
alter table t1 add column c4 int;;
|
||||
#
|
||||
# Switching to connection 'default'.
|
||||
# Wait until the above ALTER TABLE gets blocked because this
|
||||
# connection holds SW metadata lock on table to be altered.
|
||||
# The below statement should succeed. It should not
|
||||
# deadlock or end with ER_LOCK_DEADLOCK error.
|
||||
update t1 set c3=c3+1 where c2=4;
|
||||
# Unblock ALTER TABLE by committing transaction.
|
||||
commit;
|
||||
#
|
||||
# Switching to connection 'con37346'.
|
||||
# Reaping ALTER TABLE.
|
||||
#
|
||||
# Switching to connection 'default'.
|
||||
drop table t1;
|
||||
#
|
||||
# Bug #42147 Concurrent DML and LOCK TABLE ... READ for InnoDB
|
||||
# table cause warnings in errlog
|
||||
#
|
||||
#
|
||||
# Note that this test for now relies on a global suppression of
|
||||
# the warning "Found lock of type 6 that is write and read locked"
|
||||
# This suppression rule can be removed once Bug#42147 is properly
|
||||
# fixed. See bug page for more info.
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (i INT) engine= innodb;
|
||||
# Connection 2
|
||||
# Get user-level lock
|
||||
SELECT get_lock('bug42147_lock', 60);
|
||||
get_lock('bug42147_lock', 60)
|
||||
1
|
||||
# Connection 1
|
||||
INSERT INTO t1 SELECT get_lock('bug42147_lock', 60);
|
||||
# Connection 2
|
||||
LOCK TABLES t1 READ;
|
||||
SELECT release_lock('bug42147_lock');
|
||||
release_lock('bug42147_lock')
|
||||
1
|
||||
# Connection 1
|
||||
# Connection 2
|
||||
UNLOCK TABLES;
|
||||
# Connection 1
|
||||
DROP TABLE t1;
|
26
mysql-test/r/innodb_mysql_sync.result
Normal file
26
mysql-test/r/innodb_mysql_sync.result
Normal file
@ -0,0 +1,26 @@
|
||||
#
|
||||
# Bug 42074 concurrent optimize table and
|
||||
# alter table = Assertion failed: thd->is_error()
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
# Create InnoDB table
|
||||
CREATE TABLE t1 (id INT) engine=innodb;
|
||||
# Connection 1
|
||||
# Start optimizing table
|
||||
SET DEBUG_SYNC='ha_admin_try_alter SIGNAL optimize_started WAIT_FOR table_altered';
|
||||
OPTIMIZE TABLE t1;
|
||||
# Connection 2
|
||||
# Change table to engine=memory
|
||||
SET DEBUG_SYNC='now WAIT_FOR optimize_started';
|
||||
ALTER TABLE t1 engine=memory;
|
||||
SET DEBUG_SYNC='now SIGNAL table_altered';
|
||||
# Connection 1
|
||||
# Complete optimization
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
|
||||
test.t1 optimize error Got error -1 from storage engine
|
||||
test.t1 optimize status Operation failed
|
||||
Warnings:
|
||||
Error 1030 Got error -1 from storage engine
|
||||
DROP TABLE t1;
|
||||
SET DEBUG_SYNC='RESET';
|
@ -138,4 +138,107 @@ KILL CONNECTION_ID();
|
||||
# of close of the connection socket
|
||||
SELECT 1;
|
||||
Got one of the listed errors
|
||||
#
|
||||
# Additional test for WL#3726 "DDL locking for all metadata objects"
|
||||
# Check that DDL and DML statements waiting for metadata locks can
|
||||
# be killed. Note that we don't cover all situations here since it
|
||||
# can be tricky to write test case for some of them (e.g. REPAIR or
|
||||
# ALTER and other statements under LOCK TABLES).
|
||||
#
|
||||
drop tables if exists t1, t2, t3;
|
||||
create table t1 (i int primary key);
|
||||
# Test for RENAME TABLE
|
||||
# Switching to connection 'blocker'
|
||||
lock table t1 read;
|
||||
# Switching to connection 'ddl'
|
||||
rename table t1 to t2;
|
||||
# Switching to connection 'default'
|
||||
kill query ID;
|
||||
# Switching to connection 'ddl'
|
||||
ERROR 70100: Query execution was interrupted
|
||||
# Test for DROP TABLE
|
||||
drop table t1;
|
||||
# Switching to connection 'default'
|
||||
kill query ID;
|
||||
# Switching to connection 'ddl'
|
||||
ERROR 70100: Query execution was interrupted
|
||||
# Test for CREATE TRIGGER
|
||||
create trigger t1_bi before insert on t1 for each row set @a:=1;
|
||||
# Switching to connection 'default'
|
||||
kill query ID;
|
||||
# Switching to connection 'ddl'
|
||||
ERROR 70100: Query execution was interrupted
|
||||
#
|
||||
# Tests for various kinds of ALTER TABLE
|
||||
#
|
||||
# Full-blown ALTER which should copy table
|
||||
alter table t1 add column j int;
|
||||
# Switching to connection 'default'
|
||||
kill query ID;
|
||||
# Switching to connection 'ddl'
|
||||
ERROR 70100: Query execution was interrupted
|
||||
# Two kinds of simple ALTER
|
||||
alter table t1 rename to t2;
|
||||
# Switching to connection 'default'
|
||||
kill query ID;
|
||||
# Switching to connection 'ddl'
|
||||
ERROR 70100: Query execution was interrupted
|
||||
alter table t1 disable keys;
|
||||
# Switching to connection 'default'
|
||||
kill query ID;
|
||||
# Switching to connection 'ddl'
|
||||
ERROR 70100: Query execution was interrupted
|
||||
# Fast ALTER
|
||||
alter table t1 alter column i set default 100;
|
||||
# Switching to connection 'default'
|
||||
kill query ID;
|
||||
# Switching to connection 'ddl'
|
||||
ERROR 70100: Query execution was interrupted
|
||||
# Special case which is triggered only for MERGE tables.
|
||||
# Switching to connection 'blocker'
|
||||
unlock tables;
|
||||
create table t2 (i int primary key) engine=merge union=(t1);
|
||||
lock tables t2 read;
|
||||
# Switching to connection 'ddl'
|
||||
alter table t2 alter column i set default 100;
|
||||
# Switching to connection 'default'
|
||||
kill query ID;
|
||||
# Switching to connection 'ddl'
|
||||
ERROR 70100: Query execution was interrupted
|
||||
# Test for DML waiting for meta-data lock
|
||||
# Switching to connection 'blocker'
|
||||
unlock tables;
|
||||
drop table t2;
|
||||
create table t2 (k int);
|
||||
lock tables t1 read;
|
||||
# Switching to connection 'ddl'
|
||||
rename tables t1 to t3, t2 to t1;
|
||||
# Switching to connection 'dml'
|
||||
insert into t2 values (1);
|
||||
# Switching to connection 'default'
|
||||
kill query ID2;
|
||||
# Switching to connection 'dml'
|
||||
ERROR 70100: Query execution was interrupted
|
||||
# Switching to connection 'blocker'
|
||||
unlock tables;
|
||||
# Switching to connection 'ddl'
|
||||
# Test for DML waiting for tables to be flushed
|
||||
# Switching to connection 'blocker'
|
||||
lock tables t1 read;
|
||||
# Switching to connection 'ddl'
|
||||
# Let us mark locked table t1 as old
|
||||
flush tables;
|
||||
# Switching to connection 'dml'
|
||||
select * from t1;
|
||||
# Switching to connection 'default'
|
||||
kill query ID2;
|
||||
# Switching to connection 'dml'
|
||||
ERROR 70100: Query execution was interrupted
|
||||
# Switching to connection 'blocker'
|
||||
unlock tables;
|
||||
# Switching to connection 'ddl'
|
||||
# Cleanup.
|
||||
# Switching to connection 'default'
|
||||
drop table t3;
|
||||
drop table t1;
|
||||
set @@global.concurrent_insert= @old_concurrent_insert;
|
||||
|
@ -1,4 +1,4 @@
|
||||
drop table if exists t1,t2;
|
||||
drop table if exists t1,t2,t3;
|
||||
CREATE TABLE t1 ( `id` int(11) NOT NULL default '0', `id2` int(11) NOT NULL default '0', `id3` int(11) NOT NULL default '0', `dummy1` char(30) default NULL, PRIMARY KEY (`id`,`id2`), KEY `index_id3` (`id3`)) ENGINE=MyISAM;
|
||||
insert into t1 (id,id2) values (1,1),(1,2),(1,3);
|
||||
LOCK TABLE t1 WRITE;
|
||||
@ -41,7 +41,7 @@ lock tables t1 write;
|
||||
check table t2;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t2 check Error Table 't2' was not locked with LOCK TABLES
|
||||
test.t2 check error Corrupt
|
||||
test.t2 check status Operation failed
|
||||
insert into t1 select index1,nr from t1;
|
||||
ERROR HY000: Table 't1' was not locked with LOCK TABLES
|
||||
unlock tables;
|
||||
@ -128,13 +128,14 @@ select * from v_bug5719;
|
||||
1
|
||||
1
|
||||
drop view v_bug5719;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
|
||||
sic: did not left LOCK TABLES mode automatically
|
||||
|
||||
select * from t1;
|
||||
ERROR HY000: Table 't1' was not locked with LOCK TABLES
|
||||
unlock tables;
|
||||
create view v_bug5719 as select * from t1;
|
||||
create or replace view v_bug5719 as select * from t1;
|
||||
lock tables v_bug5719 write;
|
||||
select * from v_bug5719;
|
||||
a
|
||||
@ -150,6 +151,12 @@ select * from t2;
|
||||
a
|
||||
select * from t3;
|
||||
ERROR HY000: Table 't3' was not locked with LOCK TABLES
|
||||
Dropping of implicitly locked table is disallowed.
|
||||
drop table t1;
|
||||
ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
|
||||
unlock tables;
|
||||
Now let us also lock table explicitly and drop it.
|
||||
lock tables t1 write, v_bug5719 write;
|
||||
drop table t1;
|
||||
|
||||
sic: left LOCK TABLES mode
|
||||
@ -200,3 +207,266 @@ ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE t1,t2;
|
||||
End of 5.1 tests.
|
||||
#
|
||||
# Ensure that FLUSH TABLES doesn't substitute a base locked table
|
||||
# with a temporary one.
|
||||
#
|
||||
drop table if exists t1, t2;
|
||||
create table t1 (a int);
|
||||
create table t2 (a int);
|
||||
lock table t1 write, t2 write;
|
||||
create temporary table t1 (a int);
|
||||
flush table t1;
|
||||
drop temporary table t1;
|
||||
select * from t1;
|
||||
a
|
||||
unlock tables;
|
||||
drop table t1, t2;
|
||||
#
|
||||
# Ensure that REPAIR .. USE_FRM works under LOCK TABLES.
|
||||
#
|
||||
drop table if exists t1, t2;
|
||||
create table t1 (a int);
|
||||
create table t2 (a int);
|
||||
lock table t1 write, t2 write;
|
||||
repair table t1 use_frm;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 repair status OK
|
||||
repair table t1 use_frm;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 repair status OK
|
||||
select * from t1;
|
||||
a
|
||||
select * from t2;
|
||||
a
|
||||
repair table t2 use_frm;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t2 repair status OK
|
||||
repair table t2 use_frm;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t2 repair status OK
|
||||
select * from t1;
|
||||
a
|
||||
unlock tables;
|
||||
drop table t1, t2;
|
||||
#
|
||||
# Ensure that mi_copy_status is called for two instances
|
||||
# of the same table when it is reopened after a flush.
|
||||
#
|
||||
drop table if exists t1;
|
||||
drop view if exists v1;
|
||||
create table t1 (c1 int);
|
||||
create view v1 as select * from t1;
|
||||
lock tables t1 write, v1 write;
|
||||
flush table t1;
|
||||
insert into t1 values (33);
|
||||
flush table t1;
|
||||
select * from t1;
|
||||
c1
|
||||
33
|
||||
unlock tables;
|
||||
drop table t1;
|
||||
drop view v1;
|
||||
#
|
||||
# WL#4284: Transactional DDL locking
|
||||
#
|
||||
drop table if exists t1;
|
||||
create table t1 (a int);
|
||||
set autocommit= 0;
|
||||
insert into t1 values (1);
|
||||
lock table t1 write;
|
||||
# Disconnect
|
||||
# Ensure that metadata locks will be released if there is an open
|
||||
# transaction (autocommit=off) in conjunction with lock tables.
|
||||
drop table t1;
|
||||
# Same problem but now for BEGIN
|
||||
drop table if exists t1;
|
||||
create table t1 (a int);
|
||||
begin;
|
||||
insert into t1 values (1);
|
||||
# Disconnect
|
||||
# Ensure that metadata locks held by the transaction are released.
|
||||
drop table t1;
|
||||
#
|
||||
# Coverage for situations when we try to execute DDL on tables
|
||||
# which are locked by LOCK TABLES only implicitly.
|
||||
#
|
||||
drop tables if exists t1, t2;
|
||||
drop view if exists v1;
|
||||
drop function if exists f1;
|
||||
create table t1 (i int);
|
||||
create table t2 (j int);
|
||||
#
|
||||
# Try to perform DDL on table which is locked through view.
|
||||
create view v1 as select * from t2;
|
||||
lock tables t1 write, v1 write;
|
||||
flush table t2;
|
||||
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
|
||||
drop table t2;
|
||||
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
|
||||
alter table t2 add column k int;
|
||||
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
|
||||
create trigger t2_bi before insert on t2 for each row set @a:=1;
|
||||
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
|
||||
# Repair produces error as part of its result set.
|
||||
repair table t2;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t2 repair Error Table 't2' was locked with a READ lock and can't be updated
|
||||
test.t2 repair status Operation failed
|
||||
unlock tables;
|
||||
drop view v1;
|
||||
#
|
||||
# Now, try DDL on table which is locked through routine.
|
||||
create function f1 () returns int
|
||||
begin
|
||||
insert into t2 values (1);
|
||||
return 0;
|
||||
end|
|
||||
create view v1 as select f1() from t1;
|
||||
lock tables v1 read;
|
||||
flush table t2;
|
||||
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
|
||||
drop table t2;
|
||||
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
|
||||
alter table t2 add column k int;
|
||||
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
|
||||
create trigger t2_bi before insert on t2 for each row set @a:=1;
|
||||
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
|
||||
# Repair produces error as part of its result set.
|
||||
repair table t2;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t2 repair Error Table 't2' was locked with a READ lock and can't be updated
|
||||
test.t2 repair status Operation failed
|
||||
unlock tables;
|
||||
drop view v1;
|
||||
drop function f1;
|
||||
#
|
||||
# Finally, try DDL on table which is locked thanks to trigger.
|
||||
create trigger t1_ai after insert on t1 for each row insert into t2 values (1);
|
||||
lock tables t1 write;
|
||||
flush table t2;
|
||||
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
|
||||
drop table t2;
|
||||
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
|
||||
alter table t2 add column k int;
|
||||
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
|
||||
create trigger t2_bi before insert on t2 for each row set @a:=1;
|
||||
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
|
||||
# Repair produces error as part of its result set.
|
||||
repair table t2;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t2 repair Error Table 't2' was locked with a READ lock and can't be updated
|
||||
test.t2 repair status Operation failed
|
||||
unlock tables;
|
||||
drop trigger t1_ai;
|
||||
drop tables t1, t2;
|
||||
#
|
||||
# Bug#45035 " Altering table under LOCK TABLES results in
|
||||
# "Error 1213 Deadlock found..."
|
||||
#
|
||||
# When reopening tables under LOCK TABLES after ALTER TABLE,
|
||||
# 6.0 used to be taking thr_lock locks one by one, and
|
||||
# that would lead to a lock conflict.
|
||||
# Check that taking all locks at once works.
|
||||
#
|
||||
drop table if exists t1;
|
||||
create table t1 (i int);
|
||||
lock tables t1 write, t1 as a read, t1 as b read;
|
||||
alter table t1 add column j int;
|
||||
unlock tables;
|
||||
drop table t1;
|
||||
create temporary table t1 (i int);
|
||||
#
|
||||
# This is just for test coverage purposes,
|
||||
# when this is allowed, remove the --error.
|
||||
#
|
||||
lock tables t1 write, t1 as a read, t1 as b read;
|
||||
ERROR HY000: Can't reopen table: 't1'
|
||||
alter table t1 add column j int;
|
||||
unlock tables;
|
||||
drop table t1;
|
||||
#
|
||||
# Separate case for partitioned tables is important
|
||||
# because each partition has an own thr_lock object.
|
||||
#
|
||||
create table t1 (i int) partition by list (i)
|
||||
(partition p0 values in (1),
|
||||
partition p1 values in (2,3),
|
||||
partition p2 values in (4,5));
|
||||
lock tables t1 write, t1 as a read, t1 as b read;
|
||||
alter table t1 add column j int;
|
||||
unlock tables;
|
||||
drop table t1;
|
||||
#
|
||||
# Bug #43272 HANDLER SQL command does not work under LOCK TABLES
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (a INT);
|
||||
LOCK TABLE t1 WRITE;
|
||||
# HANDLER commands are not allowed in LOCK TABLES mode
|
||||
HANDLER t1 OPEN;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
HANDLER t1 READ FIRST;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
HANDLER t1 CLOSE;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug#45066 FLUSH TABLES WITH READ LOCK deadlocks against
|
||||
# LOCK TABLE
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a INT);
|
||||
LOCK TABLE t1 READ;
|
||||
FLUSH TABLES;
|
||||
ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
|
||||
LOCK TABLE t1 WRITE;
|
||||
FLUSH TABLES;
|
||||
#
|
||||
# If you allow the next combination, you reintroduce bug Bug#45066
|
||||
#
|
||||
LOCK TABLE t1 READ;
|
||||
FLUSH TABLES WITH READ LOCK;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
LOCK TABLE t1 WRITE;
|
||||
FLUSH TABLES WITH READ LOCK;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Simplified test for bug #48538 "Assertion in thr_lock() on LOAD DATA
|
||||
# CONCURRENT INFILE".
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (f1 INT, f2 INT) ENGINE = MEMORY;
|
||||
CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW
|
||||
UPDATE LOW_PRIORITY t1 SET f2 = 7;
|
||||
# Statement below should fail with ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
|
||||
# error instead of failing on assertion in table-level locking subsystem.
|
||||
INSERT INTO t1(f1) VALUES(0);
|
||||
ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug#43685 Lock table affects other non-related tables
|
||||
#
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
CREATE TABLE t1 (id INT);
|
||||
CREATE TABLE t2 (id INT);
|
||||
# Connection default
|
||||
LOCK TABLE t1 WRITE;
|
||||
ANALYZE TABLE t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Table is already up to date
|
||||
# Connection con2
|
||||
LOCK TABLE t2 WRITE;
|
||||
# This used to hang until the first connection
|
||||
# unlocked t1.
|
||||
FLUSH TABLE t2;
|
||||
UNLOCK TABLES;
|
||||
# Connection default
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE t1, t2;
|
||||
#
|
||||
# End of 6.0 tests.
|
||||
#
|
||||
|
@ -1,21 +1,39 @@
|
||||
drop table if exists t1,t2;
|
||||
create table t1(n int);
|
||||
insert into t1 values (1);
|
||||
lock tables t1 write;
|
||||
select get_lock("mysqltest_lock", 100);
|
||||
get_lock("mysqltest_lock", 100)
|
||||
1
|
||||
update t1 set n = 2 and get_lock('mysqltest_lock', 100);
|
||||
update low_priority t1 set n = 4;
|
||||
select n from t1;
|
||||
unlock tables;
|
||||
select release_lock("mysqltest_lock");
|
||||
release_lock("mysqltest_lock")
|
||||
1
|
||||
select release_lock("mysqltest_lock");
|
||||
release_lock("mysqltest_lock")
|
||||
1
|
||||
n
|
||||
4
|
||||
drop table t1;
|
||||
create table t1(n int);
|
||||
insert into t1 values (1);
|
||||
lock tables t1 read;
|
||||
select get_lock("mysqltest_lock", 100);
|
||||
get_lock("mysqltest_lock", 100)
|
||||
1
|
||||
select n from t1 where get_lock('mysqltest_lock', 100);
|
||||
update low_priority t1 set n = 4;
|
||||
select n from t1;
|
||||
n
|
||||
1
|
||||
unlock tables;
|
||||
select release_lock("mysqltest_lock");
|
||||
release_lock("mysqltest_lock")
|
||||
1
|
||||
n
|
||||
1
|
||||
select release_lock("mysqltest_lock");
|
||||
release_lock("mysqltest_lock")
|
||||
1
|
||||
drop table t1;
|
||||
create table t1 (a int, b int);
|
||||
create table t2 (c int, d int);
|
||||
@ -35,6 +53,7 @@ create table t2 (a int);
|
||||
lock table t1 write, t2 write;
|
||||
insert t1 select * from t2;
|
||||
drop table t2;
|
||||
unlock tables;
|
||||
ERROR 42S02: Table 'test.t2' doesn't exist
|
||||
drop table t1;
|
||||
create table t1 (a int);
|
||||
@ -42,6 +61,7 @@ create table t2 (a int);
|
||||
lock table t1 write, t2 write, t1 as t1_2 write, t2 as t2_2 write;
|
||||
insert t1 select * from t2;
|
||||
drop table t2;
|
||||
unlock tables;
|
||||
ERROR 42S02: Table 'test.t2' doesn't exist
|
||||
drop table t1;
|
||||
End of 4.1 tests
|
||||
@ -72,9 +92,10 @@ CREATE TABLE t1 (c1 int);
|
||||
LOCK TABLE t1 WRITE;
|
||||
FLUSH TABLES WITH READ LOCK;
|
||||
CREATE TABLE t2 (c1 int);
|
||||
ERROR HY000: Table 't2' was not locked with LOCK TABLES
|
||||
UNLOCK TABLES;
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE t1, t2;
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (c1 int);
|
||||
LOCK TABLE t1 WRITE;
|
||||
FLUSH TABLES WITH READ LOCK;
|
||||
@ -203,7 +224,7 @@ drop table if exists t1,t2;
|
||||
create table t1 (a int);
|
||||
flush status;
|
||||
lock tables t1 read;
|
||||
insert into t1 values(1);;
|
||||
insert into t1 values(1);
|
||||
unlock tables;
|
||||
drop table t1;
|
||||
select @tlwa < @tlwb;
|
||||
@ -219,3 +240,225 @@ flush tables with read lock;;
|
||||
connection: default
|
||||
flush tables;
|
||||
drop table t1;
|
||||
#
|
||||
# Test for bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock".
|
||||
#
|
||||
drop table if exists t1;
|
||||
create table t1 (c1 int primary key, c2 int, c3 int);
|
||||
insert into t1 values (1,1,0),(2,2,0),(3,3,0),(4,4,0),(5,5,0);
|
||||
begin;
|
||||
update t1 set c3=c3+1 where c2=3;
|
||||
#
|
||||
# Switching to connection 'con46272'.
|
||||
# The below ALTER TABLE statement should wait till transaction
|
||||
# in connection 'default' is complete and then succeed.
|
||||
# It should not deadlock or fail with ER_LOCK_DEADLOCK error.
|
||||
# Sending:
|
||||
alter table t1 add column c4 int;;
|
||||
#
|
||||
# Switching to connection 'default'.
|
||||
# Wait until the above ALTER TABLE gets blocked because this
|
||||
# connection holds SW metadata lock on table to be altered.
|
||||
# The below statement should succeed. It should not
|
||||
# deadlock or end with ER_LOCK_DEADLOCK error.
|
||||
update t1 set c3=c3+1 where c2=4;
|
||||
# Unblock ALTER TABLE by committing transaction.
|
||||
commit;
|
||||
#
|
||||
# Switching to connection 'con46272'.
|
||||
# Reaping ALTER TABLE.
|
||||
#
|
||||
# Switching to connection 'default'.
|
||||
drop table t1;
|
||||
#
|
||||
# Bug#47249 assert in MDL_global_lock::is_lock_type_compatible
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP VIEW IF EXISTS v1;
|
||||
#
|
||||
# Test 1: LOCK TABLES v1 WRITE, t1 READ;
|
||||
#
|
||||
# Thanks to the fact that we no longer allow DDL on tables
|
||||
# which are locked for write implicitly, the exact scenario
|
||||
# in which assert was failing is no longer repeatable.
|
||||
CREATE TABLE t1 ( f1 integer );
|
||||
CREATE VIEW v1 AS SELECT f1 FROM t1 ;
|
||||
LOCK TABLES v1 WRITE, t1 READ;
|
||||
FLUSH TABLE t1;
|
||||
ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE t1;
|
||||
DROP VIEW v1;
|
||||
#
|
||||
# Test 2: LOCK TABLES t1 WRITE, v1 READ;
|
||||
#
|
||||
CREATE TABLE t1 ( f1 integer );
|
||||
CREATE VIEW v1 AS SELECT f1 FROM t1 ;
|
||||
# Connection 2
|
||||
LOCK TABLES t1 WRITE, v1 READ;
|
||||
FLUSH TABLE t1;
|
||||
# Connection 1
|
||||
LOCK TABLES t1 WRITE;
|
||||
FLUSH TABLE t1;
|
||||
DROP TABLE t1;
|
||||
DROP VIEW v1;
|
||||
#
|
||||
# Test for bug #50913 "Deadlock between open_and_lock_tables_derived
|
||||
# and MDL". Also see additional coverage in mdl_sync.test.
|
||||
#
|
||||
drop table if exists t1;
|
||||
drop view if exists v1;
|
||||
create table t1 (i int);
|
||||
create view v1 as select i from t1;
|
||||
begin;
|
||||
select * from t1;
|
||||
i
|
||||
# Switching to connection 'con50913'.
|
||||
# Sending:
|
||||
alter table t1 add column j int;
|
||||
# Switching to connection 'default'.
|
||||
# Wait until ALTER TABLE gets blocked.
|
||||
# The below statement should try to acquire SW lock on 't1'
|
||||
# and therefore should get ER_LOCK_DEADLOCK error. Before
|
||||
# bug fix it acquired SR lock and hung on thr_lock.c lock.
|
||||
delete a from t1 as a where i = 1;
|
||||
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
||||
# Unblock ALTER TABLE.
|
||||
commit;
|
||||
# Switching to connection 'con50913'.
|
||||
# Reaping ALTER TABLE;
|
||||
# Switching to connection 'default'.
|
||||
begin;
|
||||
select * from v1;
|
||||
i
|
||||
# Switching to connection 'con50913'.
|
||||
# Sending:
|
||||
alter table t1 drop column j;
|
||||
# Switching to connection 'default'.
|
||||
# Wait until ALTER TABLE gets blocked.
|
||||
# The below statement should try to acquire SW lock on 't1'
|
||||
# and therefore should get ER_LOCK_DEADLOCK error. Before
|
||||
# bug fix it acquired SR lock and hung on thr_lock.c lock.
|
||||
insert into v1 values (1);
|
||||
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
||||
# Unblock ALTER TABLE.
|
||||
commit;
|
||||
# Switching to connection 'con50913'.
|
||||
# Reaping ALTER TABLE;
|
||||
# Switching to connection 'default'.
|
||||
drop view v1;
|
||||
drop table t1;
|
||||
#
|
||||
# Bug#45225 Locking: hang if drop table with no timeout
|
||||
#
|
||||
# These tests also provide function coverage for the
|
||||
# lock_wait_timeout server variable.
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (id int);
|
||||
SET SESSION lock_wait_timeout= 1;
|
||||
#
|
||||
# Test 1: acquire exclusive lock
|
||||
#
|
||||
# Connection default
|
||||
START TRANSACTION;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
# Connection 2
|
||||
DROP TABLE t1;
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
# Connection default
|
||||
COMMIT;
|
||||
#
|
||||
# Test 2: upgrade shared lock
|
||||
#
|
||||
# Connection default
|
||||
START TRANSACTION;
|
||||
SELECT * FROM t1;
|
||||
id
|
||||
1
|
||||
# Connection 2
|
||||
ALTER TABLE t1 RENAME TO t2;
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
# Connection default
|
||||
COMMIT;
|
||||
#
|
||||
# Test 3: acquire shared lock
|
||||
#
|
||||
# Connection default
|
||||
LOCK TABLE t1 WRITE;
|
||||
# Connection 2
|
||||
INSERT INTO t1(id) VALUES (2);
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
# Connection default
|
||||
UNLOCK TABLES;
|
||||
#
|
||||
# Test 4: table level locks
|
||||
#
|
||||
# Connection default
|
||||
LOCK TABLE t1 READ;
|
||||
# Connection 2
|
||||
INSERT INTO t1(id) VALUES(4);
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
# Connection default
|
||||
UNLOCK TABLES;
|
||||
#
|
||||
# Test 5: Waiting on Table Definition Cache (TDC)
|
||||
#
|
||||
# Connection default
|
||||
LOCK TABLE t1 READ;
|
||||
# Connection con3
|
||||
# Sending:
|
||||
FLUSH TABLES;
|
||||
# Connection con2
|
||||
SELECT * FROM t1;
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
# Connection default
|
||||
UNLOCK TABLES;
|
||||
# Connection con3
|
||||
# Reaping: FLUSH TABLES
|
||||
#
|
||||
# Test 6: Timeouts in I_S queries
|
||||
#
|
||||
# Connection default
|
||||
CREATE TABLE t2 (id INT);
|
||||
LOCK TABLE t2 WRITE;
|
||||
# Connection con3
|
||||
# Sending:
|
||||
DROP TABLE t1, t2;
|
||||
# Connection con2
|
||||
SELECT table_name, table_comment FROM information_schema.tables
|
||||
WHERE table_schema= 'test' AND table_name= 't1';
|
||||
table_name table_comment
|
||||
t1 Lock wait timeout exceeded; try restarting transaction
|
||||
# Connection default
|
||||
UNLOCK TABLES;
|
||||
# Connection con3
|
||||
# Reaping: DROP TABLE t1, t2
|
||||
# Connection default
|
||||
# Cleanup
|
||||
#
|
||||
# Test for bug #51134 "Crash in MDL_lock::destroy on a concurrent
|
||||
# DDL workload".
|
||||
#
|
||||
drop tables if exists t1, t2, t3;
|
||||
create table t3 (i int);
|
||||
# Switching to connection 'con1'
|
||||
# Lock 't3' so upcoming RENAME is blocked.
|
||||
lock table t3 read;
|
||||
# Switching to connection 'con2'
|
||||
# Remember ID for this connection.
|
||||
# Start statement which will try to acquire two instances
|
||||
# of X metadata lock on the same object.
|
||||
# Sending:
|
||||
rename tables t1 to t2, t2 to t3;;
|
||||
# Switching to connection 'default'
|
||||
# Wait until RENAME TABLE is blocked on table 't3'.
|
||||
# Kill RENAME TABLE.
|
||||
kill query ID;
|
||||
# Switching to connection 'con2'
|
||||
# RENAME TABLE should be aborted but should not crash.
|
||||
ERROR 70100: Query execution was interrupted
|
||||
# Switching to connection 'con1'
|
||||
unlock tables;
|
||||
# Switching to connection 'default'
|
||||
drop table t3;
|
||||
|
@ -6,6 +6,7 @@
|
||||
# statements which tried to acquire stronger write lock (TL_WRITE,
|
||||
# TL_WRITE_ALLOW_READ) on this table might have led to deadlock.
|
||||
drop table if exists t1;
|
||||
drop view if exists v1;
|
||||
# Create auxiliary connections used through the test.
|
||||
# Reset DEBUG_SYNC facility before using it.
|
||||
set debug_sync= 'RESET';
|
||||
@ -14,6 +15,9 @@ set debug_sync= 'RESET';
|
||||
set @old_general_log = @@global.general_log;
|
||||
set @@global.general_log= OFF;
|
||||
create table t1 (i int) engine=InnoDB;
|
||||
# We have to use view in order to make LOCK TABLES avoid
|
||||
# acquiring SNRW metadata lock on table.
|
||||
create view v1 as select * from t1;
|
||||
insert into t1 values (1);
|
||||
# Prepare user lock which will be used for resuming execution of
|
||||
# the first statement after it acquires TL_WRITE_ALLOW_WRITE lock.
|
||||
@ -36,7 +40,7 @@ select count(*) > 0 from t1 as a, t1 as b for update;;
|
||||
# acquiring lock for the the first instance of 't1'.
|
||||
set debug_sync= 'now WAIT_FOR parked';
|
||||
# Send LOCK TABLE statement which will try to get TL_WRITE lock on 't1':
|
||||
lock table t1 write;;
|
||||
lock table v1 write;;
|
||||
# Switch to connection 'default'.
|
||||
# Wait until this LOCK TABLES statement starts waiting for table lock.
|
||||
# Allow SELECT ... FOR UPDATE to resume.
|
||||
@ -56,6 +60,9 @@ release_lock("lock_bug45143_wait")
|
||||
1
|
||||
# Switch to connection 'con_bug45143_1'.
|
||||
# Reap INSERT statement.
|
||||
# In Statement and Mixed replication mode we get here "Unsafe
|
||||
# for binlog" warnings. In row mode there are no warnings.
|
||||
# Hide the discrepancy.
|
||||
# Switch to connection 'con_bug45143_3'.
|
||||
# Reap LOCK TABLES statement.
|
||||
unlock tables;
|
||||
@ -63,4 +70,25 @@ unlock tables;
|
||||
# Do clean-up.
|
||||
set debug_sync= 'RESET';
|
||||
set @@global.general_log= @old_general_log;
|
||||
drop view v1;
|
||||
drop table t1;
|
||||
#
|
||||
# Bug#50821 Deadlock between LOCK TABLES and ALTER TABLE
|
||||
#
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
CREATE TABLE t1(id INT);
|
||||
CREATE TABLE t2(id INT);
|
||||
# Connection con2
|
||||
START TRANSACTION;
|
||||
SELECT * FROM t1;
|
||||
id
|
||||
# Connection default
|
||||
# Sending:
|
||||
ALTER TABLE t1 ADD COLUMN j INT;
|
||||
# Connection con2
|
||||
# This used to cause a deadlock.
|
||||
INSERT INTO t2 SELECT * FROM t1;
|
||||
COMMIT;
|
||||
# Connection default
|
||||
# Reaping ALTER TABLE t1 ADD COLUMN j INT
|
||||
DROP TABLE t1, t2;
|
||||
|
@ -226,10 +226,9 @@ drop table t_bug44738_UPPERCASE;
|
||||
create table t_bug44738_UPPERCASE (i int);
|
||||
drop table t_bug44738_UPPERCASE;
|
||||
# Finally, let us check that another issue which was exposed by
|
||||
# the original test case is solved. I.e. that fuse in CREATE TABLE
|
||||
# which ensures that table is not created if there is an entry for
|
||||
# it in TDC even though it was removed from disk uses normalized
|
||||
# version of the table name.
|
||||
# the original test case is solved. I.e. that the table is not
|
||||
# created if there is an entry for it in TDC even though it was
|
||||
# removed from disk.
|
||||
create table t_bug44738_UPPERCASE (i int) engine = myisam;
|
||||
# Load table definition in TDC.
|
||||
select table_schema, table_name, table_comment from information_schema.tables
|
||||
@ -237,10 +236,13 @@ where table_schema = 'test' and table_name like 't_bug44738_%';
|
||||
table_schema table_name table_comment
|
||||
test t_bug44738_UPPERCASE
|
||||
# Simulate manual removal of the table.
|
||||
# After manual removal of table still there should be an entry for table
|
||||
# in TDC so attempt to create table with the same name should fail.
|
||||
# Check that still there is an entry for table in TDC.
|
||||
show open tables like 't_bug44738_%';
|
||||
Database Table In_use Name_locked
|
||||
test t_bug44738_uppercase 0 0
|
||||
# So attempt to create table with the same name should fail.
|
||||
create table t_bug44738_UPPERCASE (i int);
|
||||
ERROR 42S01: Table 't_bug44738_uppercase' already exists
|
||||
ERROR HY000: Can't find file: 't_bug44738_uppercase' (errno: 2)
|
||||
# And should succeed after FLUSH TABLES.
|
||||
flush tables;
|
||||
create table t_bug44738_UPPERCASE (i int);
|
||||
|
2377
mysql-test/r/mdl_sync.result
Normal file
2377
mysql-test/r/mdl_sync.result
Normal file
File diff suppressed because it is too large
Load Diff
@ -578,23 +578,23 @@ select max(b) from t1 where a = 2;
|
||||
max(b)
|
||||
1
|
||||
drop table t3,t1,t2;
|
||||
create table t1 (a int not null);
|
||||
create table t2 (a int not null);
|
||||
insert into t1 values (1);
|
||||
insert into t2 values (2);
|
||||
create temporary table t3 (a int not null) ENGINE=MERGE UNION=(t1,t2);
|
||||
select * from t3;
|
||||
CREATE TABLE t1 (c1 INT NOT NULL);
|
||||
CREATE TABLE t2 (c1 INT NOT NULL);
|
||||
INSERT INTO t1 VALUES (1);
|
||||
INSERT INTO t2 VALUES (2);
|
||||
CREATE TEMPORARY TABLE t3 (c1 INT NOT NULL) ENGINE=MRG_MYISAM UNION=(t1,t2);
|
||||
SELECT * FROM t3;
|
||||
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
|
||||
create temporary table t4 (a int not null);
|
||||
create temporary table t5 (a int not null);
|
||||
insert into t4 values (1);
|
||||
insert into t5 values (2);
|
||||
create temporary table t6 (a int not null) ENGINE=MERGE UNION=(t4,t5);
|
||||
select * from t6;
|
||||
a
|
||||
1
|
||||
2
|
||||
drop table t6, t3, t1, t2, t4, t5;
|
||||
CREATE TEMPORARY TABLE t4 (c1 INT NOT NULL);
|
||||
CREATE TEMPORARY TABLE t5 (c1 INT NOT NULL);
|
||||
INSERT INTO t4 VALUES (4);
|
||||
INSERT INTO t5 VALUES (5);
|
||||
CREATE TEMPORARY TABLE t6 (c1 INT NOT NULL) ENGINE=MRG_MYISAM UNION=(t4,t5);
|
||||
SELECT * FROM t6;
|
||||
c1
|
||||
4
|
||||
5
|
||||
DROP TABLE t6, t3, t1, t2, t4, t5;
|
||||
create temporary table t1 (a int not null);
|
||||
create temporary table t2 (a int not null);
|
||||
insert into t1 values (1);
|
||||
@ -1046,18 +1046,21 @@ c1
|
||||
LOCK TABLE t1 WRITE, t2 WRITE, t3 WRITE;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
TRUNCATE TABLE t3;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
SELECT * FROM t3;
|
||||
c1
|
||||
1
|
||||
2
|
||||
UNLOCK TABLES;
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
SELECT * FROM t2;
|
||||
c1
|
||||
#
|
||||
# Truncate child table under locked tables.
|
||||
LOCK TABLE t1 WRITE, t2 WRITE, t3 WRITE;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
INSERT INTO t2 VALUES (2);
|
||||
TRUNCATE TABLE t1;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
SELECT * FROM t3;
|
||||
c1
|
||||
1
|
||||
2
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE t1, t2, t3;
|
||||
@ -1089,18 +1092,24 @@ INSERT INTO t1 VALUES (1);
|
||||
CREATE TABLE t4 (c1 INT, INDEX(c1));
|
||||
LOCK TABLE t4 WRITE;
|
||||
TRUNCATE TABLE t3;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
SELECT * FROM t3;
|
||||
c1
|
||||
1
|
||||
2
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
SELECT * FROM t2;
|
||||
c1
|
||||
#
|
||||
# Truncate temporary child table under locked tables.
|
||||
INSERT INTO t1 VALUES (1);
|
||||
INSERT INTO t2 VALUES (2);
|
||||
TRUNCATE TABLE t1;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
SELECT * FROM t3;
|
||||
c1
|
||||
1
|
||||
2
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
SELECT * FROM t2;
|
||||
c1
|
||||
2
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE t1, t2, t3, t4;
|
||||
@ -1149,7 +1158,8 @@ SHOW CREATE TABLE t3;
|
||||
ERROR 42S02: Table 'test.t3' doesn't exist
|
||||
DROP TABLE t1, t2;
|
||||
#
|
||||
# CREATE ... LIKE
|
||||
# Bug#37371 "CREATE TABLE LIKE merge loses UNION parameter"
|
||||
# Demonstrate that this is no longer the case.
|
||||
#
|
||||
# 1. Create like.
|
||||
CREATE TABLE t1 (c1 INT);
|
||||
@ -1164,26 +1174,26 @@ SHOW CREATE TABLE t4;
|
||||
Table Create Table
|
||||
t4 CREATE TABLE `t4` (
|
||||
`c1` int(11) DEFAULT NULL
|
||||
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1
|
||||
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t1`,`t2`)
|
||||
INSERT INTO t4 VALUES (4);
|
||||
ERROR HY000: Table 't4' is read only
|
||||
DROP TABLE t4;
|
||||
#
|
||||
# 1. Create like with locked tables.
|
||||
LOCK TABLES t3 WRITE, t2 WRITE, t1 WRITE;
|
||||
CREATE TABLE t4 LIKE t3;
|
||||
ERROR HY000: Table 't4' was not locked with LOCK TABLES
|
||||
SHOW CREATE TABLE t4;
|
||||
ERROR HY000: Table 't4' was not locked with LOCK TABLES
|
||||
INSERT INTO t4 VALUES (4);
|
||||
ERROR HY000: Table 't4' was not locked with LOCK TABLES
|
||||
CREATE TEMPORARY TABLE t4 LIKE t3;
|
||||
SHOW CREATE TABLE t4;
|
||||
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
|
||||
INSERT INTO t4 VALUES (4);
|
||||
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
|
||||
UNLOCK TABLES;
|
||||
SHOW CREATE TABLE t4;
|
||||
Table Create Table
|
||||
t4 CREATE TABLE `t4` (
|
||||
`c1` int(11) DEFAULT NULL
|
||||
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1
|
||||
INSERT INTO t4 VALUES (4);
|
||||
ERROR HY000: Table 't4' is read only
|
||||
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
|
||||
DROP TABLE t4;
|
||||
#
|
||||
# Rename child.
|
||||
@ -1210,6 +1220,7 @@ c1
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
RENAME TABLE t2 TO t5;
|
||||
SELECT * FROM t3 ORDER BY c1;
|
||||
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
|
||||
@ -1219,6 +1230,7 @@ c1
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
#
|
||||
# 3. Normal rename with locked tables.
|
||||
LOCK TABLES t1 WRITE, t2 WRITE, t3 WRITE;
|
||||
@ -1227,6 +1239,7 @@ c1
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
RENAME TABLE t2 TO t5;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
SELECT * FROM t3 ORDER BY c1;
|
||||
@ -1234,6 +1247,7 @@ c1
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
RENAME TABLE t5 TO t2;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
SELECT * FROM t3 ORDER BY c1;
|
||||
@ -1241,6 +1255,7 @@ c1
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
UNLOCK TABLES;
|
||||
#
|
||||
# 4. Alter table rename.
|
||||
@ -1253,12 +1268,13 @@ c1
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
#
|
||||
# 5. Alter table rename with locked tables.
|
||||
LOCK TABLES t1 WRITE, t2 WRITE, t3 WRITE;
|
||||
ALTER TABLE t2 RENAME TO t5;
|
||||
SELECT * FROM t3 ORDER BY c1;
|
||||
ERROR HY000: Table 't3' was not locked with LOCK TABLES
|
||||
ERROR HY000: Table 't2' was not locked with LOCK TABLES
|
||||
ALTER TABLE t5 RENAME TO t2;
|
||||
ERROR HY000: Table 't5' was not locked with LOCK TABLES
|
||||
UNLOCK TABLES;
|
||||
@ -1268,6 +1284,7 @@ c1
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
#
|
||||
# Rename parent.
|
||||
#
|
||||
@ -1278,6 +1295,7 @@ c1
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
RENAME TABLE t3 TO t5;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
SELECT * FROM t3 ORDER BY c1;
|
||||
@ -1285,6 +1303,7 @@ c1
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
RENAME TABLE t5 TO t3;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
SELECT * FROM t3 ORDER BY c1;
|
||||
@ -1292,6 +1311,7 @@ c1
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
#
|
||||
# 5. Alter table rename with locked tables.
|
||||
ALTER TABLE t3 RENAME TO t5;
|
||||
@ -1306,6 +1326,7 @@ c1
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
DROP TABLE t1, t2, t3;
|
||||
#
|
||||
# Drop locked tables.
|
||||
@ -1330,9 +1351,9 @@ LOCK TABLES t1 WRITE, t2 WRITE;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
DROP TABLE t1;
|
||||
SELECT * FROM t2;
|
||||
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
|
||||
ERROR HY000: Table 't1' was not locked with LOCK TABLES
|
||||
SELECT * FROM t1;
|
||||
ERROR 42S02: Table 'test.t1' doesn't exist
|
||||
ERROR HY000: Table 't1' was not locked with LOCK TABLES
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE t2;
|
||||
#
|
||||
@ -2256,3 +2277,332 @@ deallocate prepare stmt;
|
||||
#
|
||||
drop table t_parent;
|
||||
set @@global.table_definition_cache=@save_table_definition_cache;
|
||||
DROP DATABASE IF EXISTS mysql_test1;
|
||||
CREATE DATABASE mysql_test1;
|
||||
CREATE TABLE t1 ... DATA DIRECTORY=... INDEX DIRECTORY=...
|
||||
CREATE TABLE mysql_test1.t2 ... DATA DIRECTORY=... INDEX DIRECTORY=...
|
||||
CREATE TABLE m1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,mysql_test1.t2)
|
||||
INSERT_METHOD=LAST;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
INSERT INTO mysql_test1.t2 VALUES (2);
|
||||
SELECT * FROM m1;
|
||||
c1
|
||||
1
|
||||
2
|
||||
DROP TABLE t1, mysql_test1.t2, m1;
|
||||
DROP DATABASE mysql_test1;
|
||||
CREATE TABLE t1 (c1 INT);
|
||||
CREATE TABLE t2 (c1 INT);
|
||||
INSERT INTO t1 (c1) VALUES (1);
|
||||
CREATE TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2) INSERT_METHOD=FIRST;
|
||||
CREATE TABLE t3 (c1 INT);
|
||||
INSERT INTO t3 (c1) VALUES (1);
|
||||
CREATE FUNCTION f1() RETURNS INT RETURN (SELECT MAX(c1) FROM t3);
|
||||
CREATE VIEW v1 AS SELECT foo.c1 c1, f1() c2, bar.c1 c3, f1() c4
|
||||
FROM tm1 foo, tm1 bar, t3;
|
||||
SELECT * FROM v1;
|
||||
c1 c2 c3 c4
|
||||
1 1 1 1
|
||||
DROP FUNCTION f1;
|
||||
DROP VIEW v1;
|
||||
DROP TABLE tm1, t1, t2, t3;
|
||||
CREATE TEMPORARY TABLE t1 (c1 INT);
|
||||
CREATE TEMPORARY TABLE t2 (c1 INT);
|
||||
CREATE TEMPORARY TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2)
|
||||
INSERT_METHOD=FIRST;
|
||||
CREATE FUNCTION f1() RETURNS INT RETURN (SELECT MAX(c1) FROM tm1);
|
||||
INSERT INTO tm1 (c1) VALUES (1);
|
||||
SELECT f1() FROM (SELECT 1) AS c1;
|
||||
f1()
|
||||
1
|
||||
DROP FUNCTION f1;
|
||||
DROP TABLE tm1, t1, t2;
|
||||
CREATE FUNCTION f1() RETURNS INT
|
||||
BEGIN
|
||||
CREATE TEMPORARY TABLE t1 (c1 INT);
|
||||
CREATE TEMPORARY TABLE t2 (c1 INT);
|
||||
CREATE TEMPORARY TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2);
|
||||
INSERT INTO t1 (c1) VALUES (1);
|
||||
RETURN (SELECT MAX(c1) FROM tm1);
|
||||
END|
|
||||
SELECT f1() FROM (SELECT 1 UNION SELECT 1) c1;
|
||||
f1()
|
||||
1
|
||||
DROP FUNCTION f1;
|
||||
DROP TABLE tm1, t1, t2;
|
||||
CREATE TEMPORARY TABLE t1 (c1 INT);
|
||||
INSERT INTO t1 (c1) VALUES (1);
|
||||
CREATE TEMPORARY TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1);
|
||||
CREATE FUNCTION f1() RETURNS INT
|
||||
BEGIN
|
||||
CREATE TEMPORARY TABLE t2 (c1 INT);
|
||||
ALTER TEMPORARY TABLE tm1 UNION=(t1,t2);
|
||||
INSERT INTO t2 (c1) VALUES (2);
|
||||
RETURN (SELECT MAX(c1) FROM tm1);
|
||||
END|
|
||||
ERROR 0A000: ALTER VIEW is not allowed in stored procedures
|
||||
DROP TABLE tm1, t1;
|
||||
CREATE TABLE t1 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST;
|
||||
INSERT INTO tm1 VALUES (1);
|
||||
SELECT * FROM tm1;
|
||||
c1
|
||||
1
|
||||
DROP TABLE tm1, t1;
|
||||
CREATE FUNCTION f1() RETURNS INT
|
||||
BEGIN
|
||||
INSERT INTO tm1 VALUES (1);
|
||||
RETURN (SELECT MAX(c1) FROM tm1);
|
||||
END|
|
||||
CREATE TABLE t1 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST;
|
||||
SELECT f1();
|
||||
f1()
|
||||
1
|
||||
DROP FUNCTION f1;
|
||||
DROP TABLE tm1, t1;
|
||||
CREATE TABLE t1 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST;
|
||||
LOCK TABLE tm1 WRITE;
|
||||
INSERT INTO tm1 VALUES (1);
|
||||
SELECT * FROM tm1;
|
||||
c1
|
||||
1
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE tm1, t1;
|
||||
CREATE FUNCTION f1() RETURNS INT
|
||||
BEGIN
|
||||
INSERT INTO tm1 VALUES (1);
|
||||
RETURN (SELECT MAX(c1) FROM tm1);
|
||||
END|
|
||||
CREATE TABLE t1 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST;
|
||||
LOCK TABLE tm1 WRITE;
|
||||
SELECT f1();
|
||||
f1()
|
||||
1
|
||||
UNLOCK TABLES;
|
||||
DROP FUNCTION f1;
|
||||
DROP TABLE tm1, t1;
|
||||
CREATE TABLE t1 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TABLE t2 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST;
|
||||
CREATE TRIGGER t2_ai AFTER INSERT ON t2
|
||||
FOR EACH ROW INSERT INTO tm1 VALUES(11);
|
||||
LOCK TABLE t2 WRITE;
|
||||
INSERT INTO t2 VALUES (2);
|
||||
SELECT * FROM tm1;
|
||||
c1
|
||||
11
|
||||
SELECT * FROM t2;
|
||||
c1
|
||||
2
|
||||
UNLOCK TABLES;
|
||||
DROP TRIGGER t2_ai;
|
||||
DROP TABLE tm1, t1, t2;
|
||||
CREATE TEMPORARY TABLE t1 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TEMPORARY TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1)
|
||||
INSERT_METHOD=LAST;
|
||||
INSERT INTO tm1 VALUES (1);
|
||||
SELECT * FROM tm1;
|
||||
c1
|
||||
1
|
||||
DROP TABLE tm1, t1;
|
||||
CREATE FUNCTION f1() RETURNS INT
|
||||
BEGIN
|
||||
INSERT INTO tm1 VALUES (1);
|
||||
RETURN (SELECT MAX(c1) FROM tm1);
|
||||
END|
|
||||
CREATE TEMPORARY TABLE t1 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TEMPORARY TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1)
|
||||
INSERT_METHOD=LAST;
|
||||
SELECT f1();
|
||||
f1()
|
||||
1
|
||||
DROP FUNCTION f1;
|
||||
DROP TABLE tm1, t1;
|
||||
CREATE TEMPORARY TABLE t1 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TEMPORARY TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1)
|
||||
INSERT_METHOD=LAST;
|
||||
CREATE TABLE t9 (c1 INT) ENGINE=MyISAM;
|
||||
LOCK TABLE t9 WRITE;
|
||||
INSERT INTO tm1 VALUES (1);
|
||||
SELECT * FROM tm1;
|
||||
c1
|
||||
1
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE tm1, t1, t9;
|
||||
CREATE FUNCTION f1() RETURNS INT
|
||||
BEGIN
|
||||
INSERT INTO tm1 VALUES (1);
|
||||
RETURN (SELECT MAX(c1) FROM tm1);
|
||||
END|
|
||||
CREATE TEMPORARY TABLE t1 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TEMPORARY TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1)
|
||||
INSERT_METHOD=LAST;
|
||||
CREATE TABLE t9 (c1 INT) ENGINE=MyISAM;
|
||||
LOCK TABLE t9 WRITE;
|
||||
SELECT f1();
|
||||
f1()
|
||||
1
|
||||
UNLOCK TABLES;
|
||||
DROP FUNCTION f1;
|
||||
DROP TABLE tm1, t1, t9;
|
||||
CREATE TEMPORARY TABLE t1 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TEMPORARY TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1)
|
||||
INSERT_METHOD=LAST;
|
||||
CREATE TABLE t2 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TRIGGER t2_ai AFTER INSERT ON t2
|
||||
FOR EACH ROW INSERT INTO tm1 VALUES(11);
|
||||
LOCK TABLE t2 WRITE;
|
||||
INSERT INTO t2 VALUES (2);
|
||||
SELECT * FROM tm1;
|
||||
c1
|
||||
11
|
||||
SELECT * FROM t2;
|
||||
c1
|
||||
2
|
||||
UNLOCK TABLES;
|
||||
DROP TRIGGER t2_ai;
|
||||
DROP TABLE tm1, t1, t2;
|
||||
#
|
||||
# Don't allow an update of a MERGE child in a trigger
|
||||
# if the table's already being modified by the main
|
||||
# statement.
|
||||
#
|
||||
CREATE TABLE t1 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1)
|
||||
INSERT_METHOD=LAST;
|
||||
CREATE TRIGGER tm1_ai AFTER INSERT ON tm1
|
||||
FOR EACH ROW INSERT INTO t1 VALUES(11);
|
||||
LOCK TABLE tm1 WRITE, t1 WRITE;
|
||||
INSERT INTO tm1 VALUES (1);
|
||||
ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
|
||||
SELECT * FROM tm1;
|
||||
c1
|
||||
1
|
||||
UNLOCK TABLES;
|
||||
LOCK TABLE t1 WRITE, tm1 WRITE;
|
||||
INSERT INTO tm1 VALUES (1);
|
||||
ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
|
||||
SELECT * FROM tm1;
|
||||
c1
|
||||
1
|
||||
1
|
||||
UNLOCK TABLES;
|
||||
DROP TRIGGER tm1_ai;
|
||||
DROP TABLE tm1, t1;
|
||||
#
|
||||
# Don't select MERGE child when trying to get a prelocked table.
|
||||
#
|
||||
# Due to a limitation demonstrated by the previous test
|
||||
# we can no longer use a write-locked prelocked table.
|
||||
# The test is kept for historical purposes.
|
||||
#
|
||||
CREATE TABLE t1 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1)
|
||||
INSERT_METHOD=LAST;
|
||||
CREATE TRIGGER tm1_ai AFTER INSERT ON tm1
|
||||
FOR EACH ROW SELECT max(c1) FROM t1 INTO @var;
|
||||
LOCK TABLE tm1 WRITE, t1 WRITE;
|
||||
INSERT INTO tm1 VALUES (1);
|
||||
SELECT * FROM tm1;
|
||||
c1
|
||||
1
|
||||
UNLOCK TABLES;
|
||||
LOCK TABLE t1 WRITE, tm1 WRITE;
|
||||
INSERT INTO tm1 VALUES (1);
|
||||
SELECT * FROM tm1;
|
||||
c1
|
||||
1
|
||||
1
|
||||
UNLOCK TABLES;
|
||||
DROP TRIGGER tm1_ai;
|
||||
DROP TABLE tm1, t1;
|
||||
CREATE TABLE t1 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TABLE t2 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TABLE t3 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TABLE t4 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TABLE t5 (c1 INT) ENGINE=MyISAM;
|
||||
CREATE TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2,t3,t4,t5)
|
||||
INSERT_METHOD=LAST;
|
||||
CREATE TRIGGER t2_au AFTER UPDATE ON t2
|
||||
FOR EACH ROW SELECT MAX(c1) FROM t1 INTO @var;
|
||||
CREATE FUNCTION f1() RETURNS INT
|
||||
RETURN (SELECT MAX(c1) FROM t4);
|
||||
LOCK TABLE tm1 WRITE, t1 WRITE, t2 WRITE, t3 WRITE, t4 WRITE, t5 WRITE;
|
||||
INSERT INTO t1 VALUES(1);
|
||||
INSERT INTO t2 VALUES(2);
|
||||
INSERT INTO t3 VALUES(3);
|
||||
INSERT INTO t4 VALUES(4);
|
||||
INSERT INTO t5 VALUES(5);
|
||||
UPDATE t2, tm1 SET t2.c1=f1();
|
||||
FLUSH TABLES;
|
||||
FLUSH TABLES;
|
||||
UNLOCK TABLES;
|
||||
SELECT * FROM tm1;
|
||||
c1
|
||||
1
|
||||
4
|
||||
3
|
||||
4
|
||||
5
|
||||
DROP TRIGGER t2_au;
|
||||
DROP FUNCTION f1;
|
||||
DROP TABLE tm1, t1, t2, t3, t4, t5;
|
||||
#
|
||||
# Bug47098 assert in MDL_context::destroy on HANDLER
|
||||
# <damaged merge table> OPEN
|
||||
#
|
||||
# Test that merge tables are closed correctly when opened using
|
||||
# HANDLER ... OPEN.
|
||||
# The general case.
|
||||
DROP TABLE IF EXISTS t1, t2, t3;
|
||||
# Connection con1.
|
||||
CREATE TABLE t1 (c1 int);
|
||||
CREATE TABLE t2 (c1 int);
|
||||
CREATE TABLE t3 (c1 int) ENGINE = MERGE UNION (t1,t2);
|
||||
START TRANSACTION;
|
||||
HANDLER t3 OPEN;
|
||||
ERROR HY000: Table storage engine for 't3' doesn't have this option
|
||||
DROP TABLE t1, t2, t3;
|
||||
# Connection default.
|
||||
# Disconnecting con1, all mdl_tickets must have been released.
|
||||
# The bug-specific case.
|
||||
# Connection con1.
|
||||
CREATE TABLE t1 (c1 int);
|
||||
CREATE TABLE t2 (c1 int);
|
||||
CREATE TABLE t3 (c1 int) ENGINE = MERGE UNION (t1,t2);
|
||||
DROP TABLE t2;
|
||||
START TRANSACTION;
|
||||
HANDLER t3 OPEN;
|
||||
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
|
||||
DROP TABLE t1, t3;
|
||||
# Connection default.
|
||||
# Disconnecting con1, all mdl_tickets must have been released.
|
||||
#
|
||||
# A test case for Bug#47648 main.merge fails sporadically
|
||||
#
|
||||
# Make sure we correctly maintain lex->query_tables_last_own.
|
||||
#
|
||||
create table t1 (c1 int not null);
|
||||
create table t2 (c1 int not null);
|
||||
create table t3 (c1 int not null);
|
||||
create function f1 () returns int return (select max(c1) from t3);
|
||||
create table t4 (c1 int not null) engine=merge union=(t1,t2) insert_method=last ;
|
||||
select * from t4 where c1 < f1();
|
||||
c1
|
||||
prepare stmt from "select * from t4 where c1 < f1()";
|
||||
execute stmt;
|
||||
c1
|
||||
execute stmt;
|
||||
c1
|
||||
execute stmt;
|
||||
c1
|
||||
drop function f1;
|
||||
execute stmt;
|
||||
ERROR 42000: FUNCTION test.f1 does not exist
|
||||
execute stmt;
|
||||
ERROR 42000: FUNCTION test.f1 does not exist
|
||||
drop table t4, t3, t2, t1;
|
||||
End of 6.0 tests
|
||||
|
103
mysql-test/r/merge_recover.result
Normal file
103
mysql-test/r/merge_recover.result
Normal file
@ -0,0 +1,103 @@
|
||||
#
|
||||
# Test of MyISAM MRG tables with corrupted children.
|
||||
# Run with --myisam-recover=force option.
|
||||
#
|
||||
# Preparation: we need to make sure that the merge parent
|
||||
# is never left in the table cache when closed, since this may
|
||||
# have effect on merge children.
|
||||
# For that, we set the table cache to minimal size and populate it
|
||||
# in a concurrent connection.
|
||||
#
|
||||
# Switching to connection con1
|
||||
#
|
||||
#
|
||||
# Minimal values.
|
||||
#
|
||||
call mtr.add_suppression("Got an error from thread_id=.*ha_myisam.cc:");
|
||||
call mtr.add_suppression("MySQL thread id .*, query id .* localhost.*root Checking table");
|
||||
call mtr.add_suppression(" '\..test.t1'");
|
||||
set global table_open_cache=256;
|
||||
set global table_definition_cache=400;
|
||||
drop procedure if exists p_create;
|
||||
create procedure p_create()
|
||||
begin
|
||||
declare i int default 1;
|
||||
set @lock_table_stmt="lock table ";
|
||||
set @drop_table_stmt="drop table ";
|
||||
while i < @@global.table_definition_cache + 1 do
|
||||
set @table_name=concat("t_", i);
|
||||
set @opt_comma=if(i=1, "", ", ");
|
||||
set @lock_table_stmt=concat(@lock_table_stmt, @opt_comma,
|
||||
@table_name, " read");
|
||||
set @drop_table_stmt=concat(@drop_table_stmt, @opt_comma, @table_name);
|
||||
set @create_table_stmt=concat("create table if not exists ",
|
||||
@table_name, " (a int)");
|
||||
prepare stmt from @create_table_stmt;
|
||||
execute stmt;
|
||||
deallocate prepare stmt;
|
||||
set i= i+1;
|
||||
end while;
|
||||
end|
|
||||
call p_create();
|
||||
drop procedure p_create;
|
||||
#
|
||||
# Switching to connection 'default'
|
||||
#
|
||||
#
|
||||
# We have to disable the ps-protocol, to avoid
|
||||
# "Prepared statement needs to be re-prepared" errors
|
||||
# -- table def versions change all the time with full table cache.
|
||||
#
|
||||
drop table if exists t1, t1_mrg, t1_copy;
|
||||
#
|
||||
# Prepare a MERGE engine table, that refers to a corrupted
|
||||
# child.
|
||||
#
|
||||
create table t1 (a int, key(a)) engine=myisam;
|
||||
create table t1_mrg (a int) union (t1) engine=merge;
|
||||
#
|
||||
# Create a table with a corrupted index file:
|
||||
# save an old index file, insert more rows,
|
||||
# overwrite the new index file with the old one.
|
||||
#
|
||||
insert into t1 (a) values (1), (2), (3);
|
||||
flush table t1;
|
||||
insert into t1 (a) values (4), (5), (6);
|
||||
flush table t1;
|
||||
# check table is needed to mark the table as crashed.
|
||||
check table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check warning Size of datafile is: 42 Should be: 21
|
||||
test.t1 check error Record-count is not ok; is 6 Should be: 3
|
||||
test.t1 check warning Found 6 key parts. Should be: 3
|
||||
test.t1 check error Corrupt
|
||||
#
|
||||
# At this point we have a merge table t1_mrg pointing to t1,
|
||||
# and t1 is corrupted, and will be auto-repaired at open.
|
||||
# Check that this doesn't lead to memory corruption.
|
||||
#
|
||||
select * from t1_mrg;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
Warnings:
|
||||
Error 145 Table 't1' is marked as crashed and should be repaired
|
||||
Error 1194 Table 't1' is marked as crashed and should be repaired
|
||||
Error 1034 Number of rows changed from 3 to 6
|
||||
#
|
||||
# Cleanup
|
||||
#
|
||||
drop table t1, t1_mrg;
|
||||
#
|
||||
# Switching to connection con1
|
||||
#
|
||||
unlock tables;
|
||||
prepare stmt from @drop_table_stmt;
|
||||
execute stmt;
|
||||
deallocate prepare stmt;
|
||||
set @@global.table_definition_cache=default;
|
||||
set @@global.table_open_cache=default;
|
@ -2063,6 +2063,7 @@ insert into t1(a) values (1),(2),(3);
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
update t1 set b = 5 where a = 2;
|
||||
commit;
|
||||
create trigger t1t before insert on t1 for each row begin set NEW.b = NEW.a * 10 + 5, NEW.c = NEW.a / 10; end |
|
||||
set autocommit = 0;
|
||||
insert into t1(a) values (10),(20),(30),(40),(50),(60),(70),(80),(90),(100),
|
||||
@ -2105,6 +2106,7 @@ update t2 set b = b + 5 where a = 1;
|
||||
update t3 set b = b + 5 where a = 1;
|
||||
update t4 set b = b + 5 where a = 1;
|
||||
insert into t5(a) values(20);
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
insert into t1(a) values(7);
|
||||
insert into t2(a) values(8);
|
||||
|
@ -214,6 +214,9 @@ The following options may be given as the first argument:
|
||||
the week.
|
||||
--local-infile Enable LOAD DATA LOCAL INFILE
|
||||
(Defaults to on; use --skip-local-infile to disable.)
|
||||
--lock-wait-timeout=#
|
||||
Timeout in seconds to wait for a lock before returning an
|
||||
error.
|
||||
-l, --log[=name] Log connections and queries to file (deprecated option,
|
||||
use --general-log/--general-log-file instead).
|
||||
--log-bin[=name] Log update queries in binary format. Optional (but
|
||||
@ -682,10 +685,6 @@ The following options may be given as the first argument:
|
||||
--table-cache=# Deprecated; use --table-open-cache instead.
|
||||
--table-definition-cache=#
|
||||
The number of cached table definitions
|
||||
--table-lock-wait-timeout=#
|
||||
Timeout in seconds to wait for a table level lock before
|
||||
returning an error. Used only if the connection has
|
||||
active cursors
|
||||
--table-open-cache=#
|
||||
The number of cached open tables
|
||||
--tc-heuristic-recover=name
|
||||
@ -803,6 +802,7 @@ lc-messages en_US
|
||||
lc-messages-dir MYSQL_SHAREDIR/
|
||||
lc-time-names en_US
|
||||
local-infile TRUE
|
||||
lock-wait-timeout 31536000
|
||||
log-bin (No default value)
|
||||
log-bin-index (No default value)
|
||||
log-bin-trust-function-creators FALSE
|
||||
@ -941,7 +941,6 @@ sync-relay-log-info 0
|
||||
sysdate-is-now FALSE
|
||||
table-cache 400
|
||||
table-definition-cache 400
|
||||
table-lock-wait-timeout 50
|
||||
table-open-cache 400
|
||||
tc-heuristic-recover COMMIT
|
||||
thread-cache-size 0
|
||||
|
@ -213,6 +213,9 @@ The following options may be given as the first argument:
|
||||
the week.
|
||||
--local-infile Enable LOAD DATA LOCAL INFILE
|
||||
(Defaults to on; use --skip-local-infile to disable.)
|
||||
--lock-wait-timeout=#
|
||||
Timeout in seconds to wait for a lock before returning an
|
||||
error.
|
||||
-l, --log[=name] Log connections and queries to file (deprecated option,
|
||||
use --general-log/--general-log-file instead).
|
||||
--log-bin[=name] Log update queries in binary format. Optional (but
|
||||
@ -686,10 +689,6 @@ The following options may be given as the first argument:
|
||||
--table-cache=# Deprecated; use --table-open-cache instead.
|
||||
--table-definition-cache=#
|
||||
The number of cached table definitions
|
||||
--table-lock-wait-timeout=#
|
||||
Timeout in seconds to wait for a table level lock before
|
||||
returning an error. Used only if the connection has
|
||||
active cursors
|
||||
--table-open-cache=#
|
||||
The number of cached open tables
|
||||
--tc-heuristic-recover=name
|
||||
@ -806,6 +805,7 @@ lc-messages en_US
|
||||
lc-messages-dir MYSQL_SHAREDIR/
|
||||
lc-time-names en_US
|
||||
local-infile TRUE
|
||||
lock-wait-timeout 31536000
|
||||
log-bin (No default value)
|
||||
log-bin-index (No default value)
|
||||
log-bin-trust-function-creators FALSE
|
||||
@ -947,7 +947,6 @@ sync-relay-log-info 0
|
||||
sysdate-is-now FALSE
|
||||
table-cache 400
|
||||
table-definition-cache 400
|
||||
table-lock-wait-timeout 50
|
||||
table-open-cache 400
|
||||
tc-heuristic-recover COMMIT
|
||||
thread-cache-size 0
|
||||
|
@ -147,9 +147,10 @@ hello
|
||||
hello
|
||||
;;;;;;;;
|
||||
# MySQL: -- The
|
||||
mysqltest: At line 1: End of line junk detected: "6"
|
||||
mysqltest: At line 1: End of line junk detected: "6"
|
||||
mysqltest: At line 1: Missing delimiter
|
||||
mysqltest: At line 1: Extra argument '6' passed to 'sleep'
|
||||
mysqltest: At line 1: Extra argument '6' passed to 'sleep'
|
||||
mysqltest: At line 1: Extra argument 'A comment
|
||||
show status' passed to 'sleep'
|
||||
mysqltest: At line 1: End of line junk detected: "sleep 7
|
||||
# Another comment
|
||||
"
|
||||
@ -216,6 +217,12 @@ source database
|
||||
echo message echo message
|
||||
|
||||
mysqltest: At line 1: Missing argument in exec
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
X
|
||||
3
|
||||
MySQL
|
||||
"MySQL"
|
||||
MySQL: The
|
||||
@ -348,8 +355,10 @@ here is the sourced script
|
||||
here is the sourced script
|
||||
"hello"
|
||||
"hello"
|
||||
mysqltest: At line 1: Missing argument to sleep
|
||||
mysqltest: At line 1: Missing argument to real_sleep
|
||||
mysqltest: At line 2: Invalid argument to sleep "xyz"
|
||||
mysqltest: At line 2: Invalid argument to real_sleep "xyz"
|
||||
mysqltest: At line 1: Missing required argument 'sleep_delay' to command 'sleep'
|
||||
mysqltest: At line 1: Missing required argument 'sleep_delay' to command 'real_sleep'
|
||||
mysqltest: At line 1: Invalid argument to sleep "abc"
|
||||
mysqltest: At line 1: Invalid argument to real_sleep "abc"
|
||||
1
|
||||
@ -377,6 +386,10 @@ test
|
||||
test2
|
||||
test3
|
||||
test4
|
||||
outer
|
||||
true-inner
|
||||
true-inner again
|
||||
true-outer
|
||||
Counter is greater than 0, (counter=10)
|
||||
Counter is not 0, (counter=0)
|
||||
1
|
||||
@ -417,6 +430,9 @@ mysqltest: At line 1: Wrong number of arguments to replace_column in 'replace_co
|
||||
mysqltest: At line 1: Wrong column number to replace_column in 'replace_column a b'
|
||||
mysqltest: At line 1: Wrong column number to replace_column in 'replace_column a 1'
|
||||
mysqltest: At line 1: Wrong column number to replace_column in 'replace_column 1 b c '
|
||||
select "LONG_STRING" as x;
|
||||
x
|
||||
LONG_STRING
|
||||
mysqltest: At line 1: Invalid integer argument "10!"
|
||||
mysqltest: At line 1: Invalid integer argument "a"
|
||||
mysqltest: At line 1: Missing required argument 'connection name' to command 'connect'
|
||||
@ -523,7 +539,28 @@ a D
|
||||
1 1
|
||||
1 4
|
||||
drop table t1;
|
||||
create table t1 ( f1 char(10));
|
||||
insert into t1 values ("Abcd");
|
||||
select * from t1;
|
||||
f1
|
||||
Abcd
|
||||
select * from t2;;
|
||||
ERROR 42S02: Table 'test.t2' doesn't exist
|
||||
select * from t1;
|
||||
f1
|
||||
Abcd
|
||||
select * from t1;;
|
||||
Result coming up
|
||||
f1
|
||||
Abcd
|
||||
select * from t1;;
|
||||
f1
|
||||
Abcd
|
||||
mysqltest: At line 2: Cannot run query on connection between send and reap
|
||||
select * from t1;;
|
||||
drop table t1;
|
||||
mysqltest: At line 1: Missing required argument 'filename' to command 'remove_file'
|
||||
mysqltest: At line 1: Missing required argument 'directory' to command 'remove_files_wildcard'
|
||||
mysqltest: At line 1: Missing required argument 'filename' to command 'write_file'
|
||||
mysqltest: At line 1: End of file encountered before 'EOF' delimiter was found
|
||||
Content for test_file1
|
||||
@ -553,6 +590,8 @@ hello
|
||||
mysqltest: At line 1: Max delimiter length(16) exceeded
|
||||
hello
|
||||
hello
|
||||
val is 5
|
||||
val is 5
|
||||
mysqltest: At line 1: test of die
|
||||
Some output
|
||||
create table t1( a int, b char(255), c timestamp);
|
||||
@ -680,6 +719,29 @@ INSERT INTO t1 SELECT f1 - 256 FROM t1;
|
||||
INSERT INTO t1 SELECT f1 - 512 FROM t1;
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
select "500g blåbærsyltetøy" as "will be lower cased";
|
||||
will be lower cased
|
||||
500g blåbærsyltetøy
|
||||
SELECT "UPPER" AS "WILL NOT BE lower cased";
|
||||
WILL NOT BE lower cased
|
||||
UPPER
|
||||
UP
|
||||
SELECT 0 as "UP AGAIN";
|
||||
UP AGAIN
|
||||
0
|
||||
select "abcdef" as "uvwxyz";
|
||||
uvwxyz
|
||||
abcdef
|
||||
select "xyz" as name union select "abc" as name order by name desc;
|
||||
name
|
||||
abc
|
||||
xyz
|
||||
select 1 as "some new text";
|
||||
some new text
|
||||
1
|
||||
select 0 as "will not lower case ÄËÐ";
|
||||
will not lower case ÄËÐ
|
||||
0
|
||||
CREATE TABLE t1(
|
||||
a int, b varchar(255), c datetime
|
||||
);
|
||||
@ -726,6 +788,8 @@ mysqltest: At line 1: change user failed: Access denied for user 'root'@'localho
|
||||
file1.txt
|
||||
file1.txt
|
||||
file2.txt
|
||||
file11.txt
|
||||
dir-list.txt
|
||||
SELECT 'c:\\a.txt' AS col;
|
||||
col
|
||||
z
|
||||
|
@ -1,6 +1,16 @@
|
||||
select 1;
|
||||
1
|
||||
1
|
||||
call mtr.add_suppression("Can't open and lock privilege tables: Table 'host' was not locked with LOCK TABLES");
|
||||
SHOW VARIABLES like 'slave_skip_errors';
|
||||
Variable_name Value
|
||||
slave_skip_errors OFF
|
||||
#
|
||||
# WL#4284: Transactional DDL locking
|
||||
#
|
||||
# FLUSH PRIVILEGES should not implicitly unlock locked tables.
|
||||
#
|
||||
drop table if exists t1;
|
||||
create table t1 (c1 int);
|
||||
lock tables t1 read;
|
||||
flush privileges;
|
||||
ERROR HY000: Table 'host' was not locked with LOCK TABLES
|
||||
unlock tables;
|
||||
drop table t1;
|
||||
|
@ -78,6 +78,15 @@ show indexes from t1;
|
||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
||||
t1 1 a 1 a A 1 NULL NULL YES BTREE
|
||||
drop table t1;
|
||||
create table t1 (a int)
|
||||
partition by hash (a);
|
||||
create index i on t1 (a);
|
||||
insert into t1 values (1);
|
||||
insert into t1 select * from t1;
|
||||
create index i on t1 (a);
|
||||
ERROR 42000: Duplicate key name 'i'
|
||||
create index i2 on t1 (a);
|
||||
drop table t1;
|
||||
CREATE TABLE t1 (a INT, FOREIGN KEY (a) REFERENCES t0 (a))
|
||||
ENGINE=MyISAM
|
||||
PARTITION BY HASH (a);
|
||||
|
@ -56,11 +56,11 @@ insert into t1 values (2,5), (2,15), (2,25),
|
||||
insert into t1 select * from t1;
|
||||
explain partitions select * from t1 where a=2;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 p01,p02,p03,p11 ALL NULL NULL NULL NULL 13 Using where
|
||||
1 SIMPLE t1 p01,p02,p03,p11 ALL NULL NULL NULL NULL 8 Using where
|
||||
explain partitions select * from t1 where a=4;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 p11,p12,p13,p21 ALL NULL NULL NULL NULL 16 Using where
|
||||
1 SIMPLE t1 p11,p12,p13,p21 ALL NULL NULL NULL NULL 14 Using where
|
||||
explain partitions select * from t1 where a=2 and b < 22;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 p01,p02,p03 ALL NULL NULL NULL NULL 16 Using where
|
||||
1 SIMPLE t1 p01,p02,p03 ALL NULL NULL NULL NULL 14 Using where
|
||||
drop table t1;
|
||||
|
@ -304,47 +304,3 @@ CREATE TABLE t1 (a INT) ENGINE=InnoDB
|
||||
PARTITION BY list(a) (PARTITION p1 VALUES IN (1));
|
||||
CREATE INDEX i1 ON t1 (a);
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug#47343: InnoDB fails to clean-up after lock wait timeout on
|
||||
# REORGANIZE PARTITION
|
||||
#
|
||||
CREATE TABLE t1 (
|
||||
a INT,
|
||||
b DATE NOT NULL,
|
||||
PRIMARY KEY (a, b)
|
||||
) ENGINE=InnoDB
|
||||
PARTITION BY RANGE (a) (
|
||||
PARTITION pMAX VALUES LESS THAN MAXVALUE
|
||||
) ;
|
||||
INSERT INTO t1 VALUES (1, '2001-01-01'), (2, '2002-02-02'), (3, '2003-03-03');
|
||||
START TRANSACTION;
|
||||
SELECT * FROM t1 FOR UPDATE;
|
||||
a b
|
||||
1 2001-01-01
|
||||
2 2002-02-02
|
||||
3 2003-03-03
|
||||
# Connection con1
|
||||
ALTER TABLE t1 REORGANIZE PARTITION pMAX INTO
|
||||
(PARTITION p3 VALUES LESS THAN (3),
|
||||
PARTITION pMAX VALUES LESS THAN MAXVALUE);
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Error 1205 Lock wait timeout exceeded; try restarting transaction
|
||||
ALTER TABLE t1 REORGANIZE PARTITION pMAX INTO
|
||||
(PARTITION p3 VALUES LESS THAN (3),
|
||||
PARTITION pMAX VALUES LESS THAN MAXVALUE);
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Error 1205 Lock wait timeout exceeded; try restarting transaction
|
||||
t1.frm
|
||||
t1.par
|
||||
# Connection default
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 2001-01-01
|
||||
2 2002-02-02
|
||||
3 2003-03-03
|
||||
COMMIT;
|
||||
DROP TABLE t1;
|
||||
|
@ -102,7 +102,7 @@ a b
|
||||
# Switch to connection con1
|
||||
# 3. test for updated key column:
|
||||
TRUNCATE t1;
|
||||
TRUNCATE t2;
|
||||
DELETE FROM t2;
|
||||
INSERT INTO t1 VALUES (1,'init');
|
||||
BEGIN;
|
||||
UPDATE t1 SET a = 2, b = CONCAT(b, '+con1') WHERE a = 1;
|
||||
|
@ -2570,7 +2570,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
explain partitions
|
||||
select * from t1 X, t1 Y where X.a = Y.a and (X.a=1 or X.a=2);
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE X p1,p2 ALL a NULL NULL NULL 4 Using where
|
||||
1 SIMPLE X p1,p2 ALL a NULL NULL NULL 2 Using where
|
||||
1 SIMPLE Y p1,p2 ref a a 4 test.X.a 2
|
||||
drop table t1;
|
||||
create table t1 (a int) partition by hash(a) partitions 20;
|
||||
|
@ -23,3 +23,35 @@ a
|
||||
1
|
||||
# Connection 1
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug #46654 False deadlock on concurrent DML/DDL
|
||||
# with partitions, inconsistent behavior
|
||||
#
|
||||
DROP TABLE IF EXISTS tbl_with_partitions;
|
||||
CREATE TABLE tbl_with_partitions ( i INT )
|
||||
PARTITION BY HASH(i);
|
||||
INSERT INTO tbl_with_partitions VALUES (1);
|
||||
# Connection 3
|
||||
LOCK TABLE tbl_with_partitions READ;
|
||||
# Connection 1
|
||||
# Access table with disabled autocommit
|
||||
SET AUTOCOMMIT = 0;
|
||||
SELECT * FROM tbl_with_partitions;
|
||||
i
|
||||
1
|
||||
# Connection 2
|
||||
# Alter table, abort after prepare
|
||||
set session debug="+d,abort_copy_table";
|
||||
ALTER TABLE tbl_with_partitions ADD COLUMN f INT;
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
# Connection 1
|
||||
# Try accessing the table after Alter aborted.
|
||||
# This used to give ER_LOCK_DEADLOCK.
|
||||
SELECT * FROM tbl_with_partitions;
|
||||
i
|
||||
1
|
||||
# Connection 3
|
||||
UNLOCK TABLES;
|
||||
# Connection 1
|
||||
# Cleanup
|
||||
DROP TABLE tbl_with_partitions;
|
||||
|
@ -3152,5 +3152,29 @@ DROP PROCEDURE p1;
|
||||
DROP PROCEDURE p2;
|
||||
|
||||
# End of WL#4435.
|
||||
|
||||
End of 6.0 tests.
|
||||
#
|
||||
# WL#4284: Transactional DDL locking
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (a INT);
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
# Test that preparing a CREATE TABLE does not take a exclusive metdata lock.
|
||||
PREPARE stmt1 FROM "CREATE TABLE t1 AS SELECT 1";
|
||||
EXECUTE stmt1;
|
||||
ERROR 42S01: Table 't1' already exists
|
||||
DEALLOCATE PREPARE stmt1;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# WL#4284: Transactional DDL locking
|
||||
#
|
||||
# Test that metadata locks taken during prepare are released.
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (a INT);
|
||||
BEGIN;
|
||||
PREPARE stmt1 FROM "SELECT * FROM t1";
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 6.0 tests.
|
||||
|
@ -269,8 +269,6 @@ Part 7: TABLE -> TABLE (TRIGGER dependencies) transitions
|
||||
=====================================================================
|
||||
# Test 7-a: dependent PROCEDURE has changed
|
||||
#
|
||||
# Note, this scenario is not supported, subject of Bug#12093
|
||||
#
|
||||
create table t1 (a int);
|
||||
create trigger t1_ai after insert on t1 for each row
|
||||
call p1(new.a);
|
||||
@ -282,10 +280,9 @@ drop procedure p1;
|
||||
create procedure p1 (a int) begin end;
|
||||
set @var= 2;
|
||||
execute stmt using @var;
|
||||
ERROR 42000: PROCEDURE test.p1 does not exist
|
||||
# Cleanup
|
||||
drop procedure p1;
|
||||
call p_verify_reprepare_count(0);
|
||||
call p_verify_reprepare_count(1);
|
||||
SUCCESS
|
||||
|
||||
# Test 7-b: dependent FUNCTION has changed
|
||||
@ -361,11 +358,13 @@ set @var=8;
|
||||
# XXX: bug, the SQL statement in the trigger is still
|
||||
# pointing at table 't3', since the view was expanded
|
||||
# at first statement execution.
|
||||
# Since the view definition is inlined in the statement
|
||||
# at prepare, changing the view definition does not cause
|
||||
# repreparation.
|
||||
# Repreparation of the main statement doesn't cause repreparation
|
||||
# of trigger statements.
|
||||
execute stmt using @var;
|
||||
ERROR 42S02: Table 'test.t3' doesn't exist
|
||||
call p_verify_reprepare_count(1);
|
||||
call p_verify_reprepare_count(0);
|
||||
SUCCESS
|
||||
|
||||
#
|
||||
@ -382,6 +381,7 @@ select * from t3;
|
||||
a
|
||||
6
|
||||
7
|
||||
8
|
||||
flush table t1;
|
||||
set @var=9;
|
||||
execute stmt using @var;
|
||||
@ -396,6 +396,7 @@ select * from t3;
|
||||
a
|
||||
6
|
||||
7
|
||||
8
|
||||
drop view v1;
|
||||
drop table t1,t2,t3;
|
||||
# Test 7-d: dependent TABLE has changed
|
||||
@ -707,6 +708,9 @@ deallocate prepare stmt;
|
||||
=====================================================================
|
||||
Part 16: VIEW -> TEMPORARY TABLE transitions
|
||||
=====================================================================
|
||||
#
|
||||
# Test 1: Merged view
|
||||
#
|
||||
create table t2 (a int);
|
||||
insert into t2 (a) values (1);
|
||||
create view t1 as select * from t2;
|
||||
@ -720,16 +724,72 @@ SUCCESS
|
||||
create temporary table t1 (a int);
|
||||
execute stmt;
|
||||
a
|
||||
call p_verify_reprepare_count(1);
|
||||
1
|
||||
call p_verify_reprepare_count(0);
|
||||
SUCCESS
|
||||
|
||||
drop view t1;
|
||||
execute stmt;
|
||||
a
|
||||
ERROR 42S02: Table 'test.t1' doesn't exist
|
||||
call p_verify_reprepare_count(0);
|
||||
SUCCESS
|
||||
|
||||
drop table t2;
|
||||
drop temporary table t1;
|
||||
deallocate prepare stmt;
|
||||
#
|
||||
# Test 2: Materialized view
|
||||
#
|
||||
create table t2 (a int);
|
||||
insert into t2 (a) values (1);
|
||||
create algorithm = temptable view t1 as select * from t2;
|
||||
prepare stmt from "select * from t1";
|
||||
execute stmt;
|
||||
a
|
||||
1
|
||||
call p_verify_reprepare_count(0);
|
||||
SUCCESS
|
||||
|
||||
create temporary table t1 (a int);
|
||||
execute stmt;
|
||||
a
|
||||
1
|
||||
call p_verify_reprepare_count(0);
|
||||
SUCCESS
|
||||
|
||||
drop view t1;
|
||||
execute stmt;
|
||||
ERROR 42S02: Table 'test.t1' doesn't exist
|
||||
call p_verify_reprepare_count(0);
|
||||
SUCCESS
|
||||
|
||||
drop table t2;
|
||||
drop temporary table t1;
|
||||
deallocate prepare stmt;
|
||||
#
|
||||
# Test 3: View referencing an Information schema table
|
||||
#
|
||||
create view t1 as select table_name from information_schema.views;
|
||||
prepare stmt from "select * from t1";
|
||||
execute stmt;
|
||||
table_name
|
||||
t1
|
||||
call p_verify_reprepare_count(0);
|
||||
SUCCESS
|
||||
|
||||
create temporary table t1 (a int);
|
||||
execute stmt;
|
||||
table_name
|
||||
t1
|
||||
call p_verify_reprepare_count(0);
|
||||
SUCCESS
|
||||
|
||||
drop view t1;
|
||||
execute stmt;
|
||||
table_name
|
||||
call p_verify_reprepare_count(0);
|
||||
SUCCESS
|
||||
|
||||
drop temporary table t1;
|
||||
deallocate prepare stmt;
|
||||
=====================================================================
|
||||
@ -1695,7 +1755,7 @@ SUCCESS
|
||||
drop table t2;
|
||||
create temporary table t2 (a int);
|
||||
execute stmt;
|
||||
call p_verify_reprepare_count(1);
|
||||
call p_verify_reprepare_count(0);
|
||||
SUCCESS
|
||||
|
||||
execute stmt;
|
||||
@ -1711,7 +1771,7 @@ SUCCESS
|
||||
|
||||
drop table t2;
|
||||
execute stmt;
|
||||
call p_verify_reprepare_count(1);
|
||||
call p_verify_reprepare_count(0);
|
||||
SUCCESS
|
||||
|
||||
drop table t2;
|
||||
@ -1755,21 +1815,21 @@ SUCCESS
|
||||
|
||||
drop table t1;
|
||||
deallocate prepare stmt;
|
||||
# XXX: no validation of the first table in case of
|
||||
# CREATE TEMPORARY TABLE. This is a shortcoming of the current code,
|
||||
# but since validation is not strictly necessary, nothing is done
|
||||
# about it.
|
||||
# Will be fixed as part of work on Bug#21431 "Incomplete support of
|
||||
# temporary tables"
|
||||
create table t1 (a int);
|
||||
insert into t1 (a) values (1);
|
||||
prepare stmt from "create temporary table if not exists t2 as select * from t1";
|
||||
execute stmt;
|
||||
drop table t2;
|
||||
execute stmt;
|
||||
call p_verify_reprepare_count(0);
|
||||
SUCCESS
|
||||
|
||||
execute stmt;
|
||||
Warnings:
|
||||
Note 1050 Table 't2' already exists
|
||||
call p_verify_reprepare_count(1);
|
||||
SUCCESS
|
||||
|
||||
select * from t2;
|
||||
a
|
||||
1
|
||||
@ -1777,6 +1837,9 @@ a
|
||||
execute stmt;
|
||||
Warnings:
|
||||
Note 1050 Table 't2' already exists
|
||||
call p_verify_reprepare_count(0);
|
||||
SUCCESS
|
||||
|
||||
select * from t2;
|
||||
a
|
||||
1
|
||||
@ -1790,7 +1853,7 @@ Note 1050 Table 't2' already exists
|
||||
select * from t2;
|
||||
a
|
||||
1
|
||||
call p_verify_reprepare_count(0);
|
||||
call p_verify_reprepare_count(1);
|
||||
SUCCESS
|
||||
|
||||
drop table t1;
|
||||
|
@ -460,7 +460,7 @@ create schema mysqltest;
|
||||
end|
|
||||
execute stmt;
|
||||
ERROR 42000: PROCEDURE test.p1 does not exist
|
||||
call p_verify_reprepare_count(1);
|
||||
call p_verify_reprepare_count(0);
|
||||
SUCCESS
|
||||
|
||||
execute stmt;
|
||||
|
@ -157,3 +157,29 @@ REPAIR TABLE tt1 USE_FRM;
|
||||
Table Op Msg_type Msg_text
|
||||
tt1 repair error Cannot repair temporary table from .frm file
|
||||
DROP TABLE tt1;
|
||||
#
|
||||
# Bug #48248 assert in MDL_ticket::upgrade_shared_lock_to_exclusive
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a INT);
|
||||
LOCK TABLES t1 READ;
|
||||
REPAIR TABLE t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 repair Error Table 't1' was locked with a READ lock and can't be updated
|
||||
test.t1 repair status Operation failed
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Test for bug #50784 "MDL: Assertion `m_tickets.is_empty() ||
|
||||
# m_tickets.front() == m_trans_sentinel'"
|
||||
#
|
||||
drop tables if exists t1, t2;
|
||||
create table t1 (i int);
|
||||
create table t2 (j int);
|
||||
set @@autocommit= 0;
|
||||
repair table t1, t2;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 repair status OK
|
||||
test.t2 repair status OK
|
||||
set @@autocommit= default;
|
||||
drop tables t1, t2;
|
||||
|
@ -12,3 +12,39 @@ mysql
|
||||
performance_schema
|
||||
test
|
||||
drop schema foo;
|
||||
#
|
||||
# Bug #48940 MDL deadlocks against mysql_rm_db
|
||||
#
|
||||
DROP SCHEMA IF EXISTS schema1;
|
||||
# Connection default
|
||||
CREATE SCHEMA schema1;
|
||||
CREATE TABLE schema1.t1 (a INT);
|
||||
SET autocommit= FALSE;
|
||||
INSERT INTO schema1.t1 VALUES (1);
|
||||
# Connection 2
|
||||
DROP SCHEMA schema1;
|
||||
# Connection default
|
||||
ALTER SCHEMA schema1 DEFAULT CHARACTER SET utf8;
|
||||
Got one of the listed errors
|
||||
SET autocommit= TRUE;
|
||||
# Connection 2
|
||||
# Connection default
|
||||
#
|
||||
# Bug #49988 MDL deadlocks with mysql_create_db, reload_acl_and_cache
|
||||
#
|
||||
DROP SCHEMA IF EXISTS schema1;
|
||||
# Connection default
|
||||
CREATE SCHEMA schema1;
|
||||
CREATE TABLE schema1.t1 (id INT);
|
||||
LOCK TABLE schema1.t1 WRITE;
|
||||
# Connection con2
|
||||
DROP SCHEMA schema1;
|
||||
# Connection default
|
||||
# CREATE SCHEMA used to give a deadlock.
|
||||
# Now we prohibit CREATE SCHEMA in LOCK TABLES mode.
|
||||
CREATE SCHEMA IF NOT EXISTS schema1;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
# UNLOCK TABLES so DROP SCHEMA can continue.
|
||||
UNLOCK TABLES;
|
||||
# Connection con2
|
||||
# Connection default
|
||||
|
@ -512,7 +512,7 @@ select * from t1;
|
||||
end|
|
||||
lock table t1 read|
|
||||
alter procedure bug9566 comment 'Some comment'|
|
||||
ERROR HY000: Table 'proc' was not locked with LOCK TABLES
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
unlock tables|
|
||||
drop procedure bug9566|
|
||||
drop procedure if exists bug7299|
|
||||
@ -1687,6 +1687,17 @@ NULL
|
||||
SELECT non_existent (a) FROM t1 WHERE b = 999999;
|
||||
ERROR 42000: FUNCTION test.non_existent does not exist
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 ( f2 INTEGER, f3 INTEGER );
|
||||
INSERT INTO t1 VALUES ( 1, 1 );
|
||||
CREATE FUNCTION func_1 () RETURNS INTEGER
|
||||
BEGIN
|
||||
INSERT INTO t1 SELECT * FROM t1 ;
|
||||
RETURN 1 ;
|
||||
END|
|
||||
INSERT INTO t1 SELECT * FROM (SELECT 2 AS f1, 2 AS f2) AS A WHERE func_1() = 5;
|
||||
ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
|
||||
DROP FUNCTION func_1;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug #47788: Crash in TABLE_LIST::hide_view_error on UPDATE + VIEW +
|
||||
# SP + MERGE + ALTER
|
||||
|
697
mysql-test/r/sp-lock.result
Normal file
697
mysql-test/r/sp-lock.result
Normal file
@ -0,0 +1,697 @@
|
||||
#
|
||||
# Test coverage for changes performed by the fix
|
||||
# for Bug#30977 "Concurrent statement using stored function
|
||||
# and DROP FUNCTION breaks SBR.
|
||||
#
|
||||
#
|
||||
# 1) Verify that the preceding transaction is
|
||||
# (implicitly) committed before CREATE/ALTER/DROP
|
||||
# PROCEDURE. Note, that this is already tested
|
||||
# in implicit_commit.test, but here we use an alternative
|
||||
# approach.
|
||||
#
|
||||
# Start a transaction, create a savepoint,
|
||||
# then call a DDL operation on a procedure, and then check
|
||||
# that the savepoint is no longer present.
|
||||
drop table if exists t1;
|
||||
drop procedure if exists p1;
|
||||
drop procedure if exists p2;
|
||||
drop procedure if exists p3;
|
||||
drop procedure if exists p4;
|
||||
drop function if exists f1;
|
||||
create table t1 (a int);
|
||||
#
|
||||
# Test 'CREATE PROCEDURE'.
|
||||
#
|
||||
begin;
|
||||
savepoint sv;
|
||||
create procedure p1() begin end;
|
||||
rollback to savepoint sv;
|
||||
ERROR 42000: SAVEPOINT sv does not exist
|
||||
#
|
||||
# Test 'ALTER PROCEDURE'.
|
||||
#
|
||||
begin;
|
||||
savepoint sv;
|
||||
alter procedure p1 comment 'changed comment';
|
||||
rollback to savepoint sv;
|
||||
ERROR 42000: SAVEPOINT sv does not exist
|
||||
#
|
||||
# Test 'DROP PROCEDURE'.
|
||||
#
|
||||
begin;
|
||||
savepoint sv;
|
||||
drop procedure p1;
|
||||
rollback to savepoint sv;
|
||||
ERROR 42000: SAVEPOINT sv does not exist
|
||||
#
|
||||
# Test 'CREATE FUNCTION'.
|
||||
#
|
||||
begin;
|
||||
savepoint sv;
|
||||
create function f1() returns int return 1;
|
||||
rollback to savepoint sv;
|
||||
ERROR 42000: SAVEPOINT sv does not exist
|
||||
#
|
||||
# Test 'ALTER FUNCTION'.
|
||||
#
|
||||
begin;
|
||||
savepoint sv;
|
||||
alter function f1 comment 'new comment';
|
||||
rollback to savepoint sv;
|
||||
ERROR 42000: SAVEPOINT sv does not exist
|
||||
#
|
||||
# Test 'DROP FUNCTION'.
|
||||
#
|
||||
begin;
|
||||
savepoint sv;
|
||||
drop function f1;
|
||||
rollback to savepoint sv;
|
||||
ERROR 42000: SAVEPOINT sv does not exist
|
||||
#
|
||||
# 2) Verify that procedure DDL operations fail
|
||||
# under lock tables.
|
||||
#
|
||||
# Auxiliary routines to test ALTER.
|
||||
create procedure p1() begin end;
|
||||
create function f1() returns int return 1;
|
||||
lock table t1 write;
|
||||
create procedure p2() begin end;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
alter procedure p1 comment 'changed comment';
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
drop procedure p1;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
create function f2() returns int return 1;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
alter function f1 comment 'changed comment';
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
lock table t1 read;
|
||||
create procedure p2() begin end;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
alter procedure p1 comment 'changed comment';
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
drop procedure p1;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
create function f2() returns int return 1;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
alter function f1 comment 'changed comment';
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
unlock tables;
|
||||
#
|
||||
# Even if we locked a temporary table.
|
||||
# Todo: this is a restriction we could possibly lift.
|
||||
#
|
||||
drop table t1;
|
||||
create temporary table t1 (a int);
|
||||
lock table t1 read;
|
||||
create procedure p2() begin end;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
alter procedure p1 comment 'changed comment';
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
drop procedure p1;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
create function f2() returns int return 1;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
alter function f1 comment 'changed comment';
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
unlock tables;
|
||||
drop function f1;
|
||||
drop procedure p1;
|
||||
drop temporary table t1;
|
||||
#
|
||||
# 3) Verify that CREATE/ALTER/DROP routine grab an
|
||||
# exclusive lock.
|
||||
#
|
||||
# For that, start a transaction, use a routine. In a concurrent
|
||||
# connection, try to drop or alter the routine. It should place
|
||||
# a pending or exclusive lock and block. In another concurrnet
|
||||
# connection, try to use the routine.
|
||||
# That should block on the pending exclusive lock.
|
||||
#
|
||||
# Establish helper connections.
|
||||
#
|
||||
# Test DROP PROCEDURE.
|
||||
#
|
||||
# --> connection default
|
||||
create procedure p1() begin end;
|
||||
create function f1() returns int
|
||||
begin
|
||||
call p1();
|
||||
return 1;
|
||||
end|
|
||||
begin;
|
||||
select f1();
|
||||
f1()
|
||||
1
|
||||
# --> connection con1
|
||||
# Sending 'drop procedure p1'...
|
||||
drop procedure p1;
|
||||
# --> connection con2
|
||||
# Waitng for 'drop procedure t1' to get blocked on MDL lock...
|
||||
# Demonstrate that there is a pending exclusive lock.
|
||||
# Sending 'select f1()'...
|
||||
select f1();
|
||||
# --> connection con3
|
||||
# Waitng for 'select f1()' to get blocked by a pending MDL lock...
|
||||
# --> connection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
# Reaping 'drop procedure p1'...
|
||||
# --> connection con2
|
||||
# Reaping 'select f1()'
|
||||
ERROR 42000: PROCEDURE test.p1 does not exist
|
||||
# --> connection default
|
||||
#
|
||||
# Test CREATE PROCEDURE.
|
||||
#
|
||||
create procedure p1() begin end;
|
||||
begin;
|
||||
select f1();
|
||||
f1()
|
||||
1
|
||||
# --> connection con1
|
||||
# Sending 'create procedure p1'...
|
||||
create procedure p1() begin end;
|
||||
# --> connection con2
|
||||
# Waitng for 'create procedure t1' to get blocked on MDL lock...
|
||||
# Demonstrate that there is a pending exclusive lock.
|
||||
# Sending 'select f1()'...
|
||||
select f1();
|
||||
# --> connection con3
|
||||
# Waitng for 'select f1()' to get blocked by a pending MDL lock...
|
||||
# --> connection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
# Reaping 'create procedure p1'...
|
||||
ERROR 42000: PROCEDURE p1 already exists
|
||||
# --> connection con2
|
||||
# Reaping 'select f1()'
|
||||
f1()
|
||||
1
|
||||
#
|
||||
# Test ALTER PROCEDURE.
|
||||
#
|
||||
begin;
|
||||
select f1();
|
||||
f1()
|
||||
1
|
||||
# --> connection con1
|
||||
# Sending 'alter procedure p1'...
|
||||
alter procedure p1 contains sql;
|
||||
# --> connection con2
|
||||
# Waitng for 'alter procedure t1' to get blocked on MDL lock...
|
||||
# Demonstrate that there is a pending exclusive lock.
|
||||
# Sending 'select f1()'...
|
||||
select f1();
|
||||
# --> connection con3
|
||||
# Waitng for 'select f1()' to get blocked by a pending MDL lock...
|
||||
# --> connection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
# Reaping 'alter procedure p1'...
|
||||
# --> connection con2
|
||||
# Reaping 'select f1()'
|
||||
f1()
|
||||
1
|
||||
# --> connection default
|
||||
#
|
||||
# Test DROP FUNCTION.
|
||||
#
|
||||
begin;
|
||||
select f1();
|
||||
f1()
|
||||
1
|
||||
# --> connection con1
|
||||
# Sending 'drop function f1'...
|
||||
drop function f1;
|
||||
# --> connection con2
|
||||
# Waitng for 'drop function f1' to get blocked on MDL lock...
|
||||
# Demonstrate that there is a pending exclusive lock.
|
||||
# Sending 'select f1()'...
|
||||
select f1();
|
||||
# --> connection con3
|
||||
# Waitng for 'select f1()' to get blocked by a pending MDL lock...
|
||||
# --> connection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
# Reaping 'drop function f1'...
|
||||
# --> connection con2
|
||||
# Reaping 'select f1()'
|
||||
ERROR 42000: FUNCTION test.f1 does not exist
|
||||
# --> connection default
|
||||
#
|
||||
# Test CREATE FUNCTION.
|
||||
#
|
||||
create function f1() returns int return 1;
|
||||
begin;
|
||||
select f1();
|
||||
f1()
|
||||
1
|
||||
# --> connection con1
|
||||
# Sending 'create function f1'...
|
||||
create function f1() returns int return 2;
|
||||
# --> connection con2
|
||||
# Waitng for 'create function f1' to get blocked on MDL lock...
|
||||
# Demonstrate that there is a pending exclusive lock.
|
||||
# Sending 'select f1()'...
|
||||
select f1();
|
||||
# --> connection con3
|
||||
# Waitng for 'select f1()' to get blocked by a pending MDL lock...
|
||||
# --> connection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
# Reaping 'create function f1'...
|
||||
ERROR 42000: FUNCTION f1 already exists
|
||||
# --> connection con2
|
||||
# Reaping 'select f1()'
|
||||
f1()
|
||||
1
|
||||
# --> connection default
|
||||
#
|
||||
# Test ALTER FUNCTION.
|
||||
#
|
||||
begin;
|
||||
select f1();
|
||||
f1()
|
||||
1
|
||||
# --> connection con1
|
||||
# Sending 'alter function f1'...
|
||||
alter function f1 contains sql;
|
||||
# --> connection con2
|
||||
# Waitng for 'alter function f1' to get blocked on MDL lock...
|
||||
# Demonstrate that there is a pending exclusive lock.
|
||||
# Sending 'select f1()'...
|
||||
select f1();
|
||||
# --> connection con3
|
||||
# Waitng for 'select f1()' to get blocked by a pending MDL lock...
|
||||
# --> connection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
# Reaping 'alter function f1'...
|
||||
# --> connection con2
|
||||
# Reaping 'select f1()'
|
||||
f1()
|
||||
1
|
||||
# --> connection default
|
||||
drop function f1;
|
||||
drop procedure p1;
|
||||
#
|
||||
# 4) MDL lock should not be taken for
|
||||
# unrolled CALL statements.
|
||||
# The primary goal of metadata locks is a consistent binary log.
|
||||
# When a call statement is unrolled, it doesn't get to the
|
||||
# binary log, instead the statements that are contained
|
||||
# in the procedure body do. This can nest to any level.
|
||||
#
|
||||
create procedure p1() begin end;
|
||||
create procedure p2() begin end;
|
||||
create table t1 (a int);
|
||||
create procedure p3()
|
||||
begin
|
||||
call p1();
|
||||
call p1();
|
||||
call p2();
|
||||
end|
|
||||
create procedure p4()
|
||||
begin
|
||||
call p1();
|
||||
call p1();
|
||||
call p2();
|
||||
call p2();
|
||||
call p3();
|
||||
end|
|
||||
begin;
|
||||
select * from t1;
|
||||
a
|
||||
savepoint sv;
|
||||
call p4();
|
||||
# Prepared statement should not add any locks either.
|
||||
prepare stmt from "call p4()";
|
||||
execute stmt;
|
||||
execute stmt;
|
||||
# --> connection con1
|
||||
drop procedure p1;
|
||||
drop procedure p2;
|
||||
drop procedure p3;
|
||||
drop procedure p4;
|
||||
# --> connection default
|
||||
# This is to verify there was no implicit commit.
|
||||
rollback to savepoint sv;
|
||||
call p4();
|
||||
ERROR 42000: PROCEDURE test.p4 does not exist
|
||||
commit;
|
||||
drop table t1;
|
||||
#
|
||||
# 5) Locks should be taken on routines
|
||||
# used indirectly by views or triggers.
|
||||
#
|
||||
#
|
||||
# A function is used from a trigger.
|
||||
#
|
||||
create function f1() returns int return 1;
|
||||
create table t1 (a int);
|
||||
create table t2 (a int, b int);
|
||||
create trigger t1_ai after insert on t1 for each row
|
||||
insert into t2 (a, b) values (new.a, f1());
|
||||
begin;
|
||||
insert into t1 (a) values (1);
|
||||
# --> connection con1
|
||||
# Sending 'drop function f1'
|
||||
drop function f1;
|
||||
# --> connection con2
|
||||
# Waitng for 'drop function f1' to get blocked on MDL lock...
|
||||
# --> connnection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
# Reaping 'drop function f1'...
|
||||
# --> connection default
|
||||
#
|
||||
# A function is used from a view.
|
||||
#
|
||||
create function f1() returns int return 1;
|
||||
create view v1 as select f1() as a;
|
||||
begin;
|
||||
select * from v1;
|
||||
a
|
||||
1
|
||||
# --> connection con1
|
||||
# Sending 'drop function f1'
|
||||
drop function f1;
|
||||
# --> connection con2
|
||||
# Waitng for 'drop function f1' to get blocked on MDL lock...
|
||||
# --> connnection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
# Reaping 'drop function f1'...
|
||||
# --> connection default
|
||||
#
|
||||
# A procedure is used from a function.
|
||||
#
|
||||
create function f1() returns int
|
||||
begin
|
||||
declare v_out int;
|
||||
call p1(v_out);
|
||||
return v_out;
|
||||
end|
|
||||
create procedure p1(out v_out int) set v_out=3;
|
||||
begin;
|
||||
select * from v1;
|
||||
a
|
||||
3
|
||||
# --> connection con1
|
||||
# Sending 'drop procedure p1'
|
||||
drop procedure p1;
|
||||
# --> connection con2
|
||||
# Waitng for 'drop procedure p1' to get blocked on MDL lock...
|
||||
# --> connnection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
# Reaping 'drop procedure p1'...
|
||||
# --> connection default
|
||||
#
|
||||
# Deep nesting: a function is used from a procedure used
|
||||
# from a function used from a view used in a trigger.
|
||||
#
|
||||
create function f2() returns int return 4;
|
||||
create procedure p1(out v_out int) set v_out=f2();
|
||||
drop trigger t1_ai;
|
||||
create trigger t1_ai after insert on t1 for each row
|
||||
insert into t2 (a, b) values (new.a, (select max(a) from v1));
|
||||
begin;
|
||||
insert into t1 (a) values (3);
|
||||
# --> connection con1
|
||||
# Sending 'drop function f2'
|
||||
drop function f2;
|
||||
# --> connection con2
|
||||
# Waitng for 'drop function f2' to get blocked on MDL lock...
|
||||
# --> connnection default
|
||||
commit;
|
||||
# --> connection con1
|
||||
# Reaping 'drop function f2'...
|
||||
# --> connection default
|
||||
drop view v1;
|
||||
drop function f1;
|
||||
drop procedure p1;
|
||||
drop table t1, t2;
|
||||
#
|
||||
# 6) Check that ER_LOCK_DEADLOCK is reported if
|
||||
# acquisition of a shared lock fails during a transaction or
|
||||
# we need to back off to flush the sp cache.
|
||||
#
|
||||
# Sic: now this situation does not require a back off since we
|
||||
# flush the cache on the fly.
|
||||
#
|
||||
create function f1() returns int return 7;
|
||||
create table t1 (a int);
|
||||
begin;
|
||||
select * from t1;
|
||||
a
|
||||
select f1();
|
||||
f1()
|
||||
7
|
||||
commit;
|
||||
drop table t1;
|
||||
drop function f1;
|
||||
#
|
||||
# 7) Demonstrate that under LOCK TABLES we accumulate locks
|
||||
# on stored routines, and release metadata locks in
|
||||
# ROLLBACK TO SAVEPOINT. That is done only for those stored
|
||||
# routines that are not part of LOCK TABLES prelocking list.
|
||||
# Those stored routines that are part of LOCK TABLES
|
||||
# prelocking list are implicitly locked when entering
|
||||
# LOCK TABLES, and ROLLBACK TO SAVEPOINT has no effect on
|
||||
# them.
|
||||
#
|
||||
create function f1() returns varchar(20) return "f1()";
|
||||
create function f2() returns varchar(20) return "f2()";
|
||||
create view v1 as select f1() as a;
|
||||
set @@session.autocommit=0;
|
||||
lock table v1 read;
|
||||
select * from v1;
|
||||
a
|
||||
f1()
|
||||
savepoint sv;
|
||||
select f2();
|
||||
f2()
|
||||
f2()
|
||||
# --> connection con1
|
||||
# Sending 'drop function f1'...
|
||||
drop function f1;
|
||||
# --> connection con2
|
||||
# Waitng for 'drop function f1' to get blocked on MDL lock...
|
||||
# Sending 'drop function f2'...
|
||||
drop function f2;
|
||||
# --> connection default
|
||||
# Waitng for 'drop function f2' to get blocked on MDL lock...
|
||||
rollback to savepoint sv;
|
||||
# --> connection con2
|
||||
# Reaping 'drop function f2'...
|
||||
# --> connection default
|
||||
unlock tables;
|
||||
# --> connection con1
|
||||
# Reaping 'drop function f1'...
|
||||
# --> connection default
|
||||
drop function f1;
|
||||
ERROR 42000: FUNCTION test.f1 does not exist
|
||||
drop function f2;
|
||||
ERROR 42000: FUNCTION test.f2 does not exist
|
||||
drop view v1;
|
||||
set @@session.autocommit=default;
|
||||
#
|
||||
# 8) Check the situation when we're preparing or executing a
|
||||
# prepared statement, and as part of that try to flush the
|
||||
# session sp cache. However, one of the procedures that
|
||||
# needs a flush is in use. Verify that there is no infinite
|
||||
# reprepare loop and no crash.
|
||||
#
|
||||
create function f1() returns int return 1;
|
||||
#
|
||||
# We just mention p1() in the body of f2() to make
|
||||
# sure that p1() metadata is validated when validating
|
||||
# 'select f2()'.
|
||||
# Recursion is not allowed in stored functions, so
|
||||
# an attempt to just invoke p1() from f2() which is in turn
|
||||
# called from p1() would have given a run-time error.
|
||||
#
|
||||
create function f2() returns int
|
||||
begin
|
||||
if @var is null then
|
||||
call p1();
|
||||
end if;
|
||||
return 1;
|
||||
end|
|
||||
create procedure p1()
|
||||
begin
|
||||
select f1() into @var;
|
||||
execute stmt;
|
||||
end|
|
||||
# --> connection con2
|
||||
prepare stmt from "select f2()";
|
||||
# --> connection default
|
||||
begin;
|
||||
select f1();
|
||||
f1()
|
||||
1
|
||||
# --> connection con1
|
||||
# Sending 'alter function f1 ...'...
|
||||
alter function f1 comment "comment";
|
||||
# --> connection con2
|
||||
# Waitng for 'alter function f1 ...' to get blocked on MDL lock...
|
||||
# Sending 'call p1()'...
|
||||
call p1();
|
||||
# Waitng for 'call p1()' to get blocked on MDL lock on f1...
|
||||
# Let 'alter function f1 ...' go through...
|
||||
commit;
|
||||
# --> connection con1
|
||||
# Reaping 'alter function f1 ...'
|
||||
# --> connection con2
|
||||
# Reaping 'call p1()'...
|
||||
f2()
|
||||
1
|
||||
deallocate prepare stmt;
|
||||
# --> connection default
|
||||
drop function f1;
|
||||
drop function f2;
|
||||
drop procedure p1;
|
||||
#
|
||||
# 9) Check the situation when a stored function is invoked
|
||||
# from a stored procedure, and recursively invokes the
|
||||
# stored procedure that is in use. But for the second
|
||||
# invocation, a cache flush is requested. We can't
|
||||
# flush the procedure that's in use, and are forced
|
||||
# to use an old version. It is not a violation of
|
||||
# consistency, since we unroll top-level calls.
|
||||
# Just verify the code works.
|
||||
#
|
||||
create function f1() returns int return 1;
|
||||
begin;
|
||||
select f1();
|
||||
f1()
|
||||
1
|
||||
# --> connection con1
|
||||
# Sending 'alter function f1 ...'...
|
||||
alter function f1 comment "comment";
|
||||
# --> connection con2
|
||||
# Waitng for 'alter function f1 ...' to get blocked on MDL lock...
|
||||
#
|
||||
# We just mention p1() in the body of f2() to make
|
||||
# sure that p1() is prelocked for f2().
|
||||
# Recursion is not allowed in stored functions, so
|
||||
# an attempt to just invoke p1() from f2() which is in turn
|
||||
# called from p1() would have given a run-time error.
|
||||
#
|
||||
create function f2() returns int
|
||||
begin
|
||||
if @var is null then
|
||||
call p1();
|
||||
end if;
|
||||
return 1;
|
||||
end|
|
||||
create procedure p1()
|
||||
begin
|
||||
select f1() into @var;
|
||||
select f2() into @var;
|
||||
end|
|
||||
# Sending 'call p1()'...
|
||||
call p1();
|
||||
# Waitng for 'call p1()' to get blocked on MDL lock on f1...
|
||||
# Let 'alter function f1 ...' go through...
|
||||
commit;
|
||||
# --> connection con1
|
||||
# Reaping 'alter function f1 ...'
|
||||
# --> connection con2
|
||||
# Reaping 'call p1()'...
|
||||
# --> connection default
|
||||
drop function f1;
|
||||
drop function f2;
|
||||
drop procedure p1;
|
||||
#
|
||||
# 10) A select from information_schema.routines now
|
||||
# flushes the stored routines caches. Test that this
|
||||
# does not remove from the cache a stored routine
|
||||
# that is already prelocked.
|
||||
#
|
||||
create function f1() returns int return get_lock("30977", 100000);
|
||||
create function f2() returns int return 2;
|
||||
create function f3() returns varchar(255)
|
||||
begin
|
||||
declare res varchar(255);
|
||||
declare c cursor for select routine_name from
|
||||
information_schema.routines where routine_name='f1';
|
||||
select f1() into @var;
|
||||
open c;
|
||||
fetch c into res;
|
||||
close c;
|
||||
select f2() into @var;
|
||||
return res;
|
||||
end|
|
||||
# --> connection con1
|
||||
select get_lock("30977", 0);
|
||||
get_lock("30977", 0)
|
||||
1
|
||||
# --> connection default
|
||||
# Sending 'select f3()'...
|
||||
select f3();
|
||||
# --> connection con1
|
||||
# Waitng for 'select f3()' to get blocked on the user level lock...
|
||||
# Do something to change the cache version.
|
||||
create function f4() returns int return 4;
|
||||
drop function f4;
|
||||
select release_lock("30977");
|
||||
release_lock("30977")
|
||||
1
|
||||
# --> connection default
|
||||
# Reaping 'select f3()'...
|
||||
# Routine 'f2()' should exist and get executed successfully.
|
||||
f3()
|
||||
f1
|
||||
select @var;
|
||||
@var
|
||||
2
|
||||
drop function f1;
|
||||
drop function f2;
|
||||
drop function f3;
|
||||
# 11) Check the situation when the connection is flushing the
|
||||
# SP cache which contains a procedure that is being executed.
|
||||
#
|
||||
# Function f1() calls p1(). Procedure p1() has a DROP
|
||||
# VIEW statement, which, we know, invalidates the routines cache.
|
||||
# During cache flush p1() must not be flushed since it's in
|
||||
# use.
|
||||
#
|
||||
create function f1() returns int
|
||||
begin
|
||||
call p1();
|
||||
return 1;
|
||||
end|
|
||||
create procedure p1()
|
||||
begin
|
||||
create view v1 as select 1;
|
||||
drop view v1;
|
||||
select f1() into @var;
|
||||
set @exec_count=@exec_count+1;
|
||||
end|
|
||||
set @exec_count=0;
|
||||
call p1();
|
||||
ERROR HY000: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine p1
|
||||
select @exec_count;
|
||||
@exec_count
|
||||
0
|
||||
set @@session.max_sp_recursion_depth=5;
|
||||
set @exec_count=0;
|
||||
call p1();
|
||||
ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
|
||||
select @exec_count;
|
||||
@exec_count
|
||||
0
|
||||
drop procedure p1;
|
||||
drop function f1;
|
||||
set @@session.max_sp_recursion_depth=default;
|
||||
# --> connection con1
|
||||
# --> connection con2
|
||||
# --> connection con3
|
||||
# --> connection default
|
||||
#
|
||||
# End of 5.5 tests
|
||||
#
|
@ -35,7 +35,7 @@ call bug9486();
|
||||
show processlist;
|
||||
Id User Host db Command Time State Info
|
||||
# root localhost test Sleep # NULL
|
||||
# root localhost test Query # Locked update t1, t2 set val= 1 where id1=id2
|
||||
# root localhost test Query # Waiting for table update t1, t2 set val= 1 where id1=id2
|
||||
# root localhost test Query # NULL show processlist
|
||||
# root localhost test Sleep # NULL
|
||||
unlock tables;
|
||||
|
@ -1083,11 +1083,9 @@ select f0()|
|
||||
f0()
|
||||
100
|
||||
select * from v0|
|
||||
f0()
|
||||
100
|
||||
ERROR HY000: Table 'v0' was not locked with LOCK TABLES
|
||||
select *, f0() from v0, (select 123) as d1|
|
||||
f0() 123 f0()
|
||||
100 123 100
|
||||
ERROR HY000: Table 'v0' was not locked with LOCK TABLES
|
||||
select id, f3() from t1|
|
||||
ERROR HY000: Table 't1' was not locked with LOCK TABLES
|
||||
select f4()|
|
||||
@ -7149,3 +7147,62 @@ SELECT routine_comment FROM information_schema.routines WHERE routine_name = "p1
|
||||
routine_comment
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
DROP PROCEDURE p1;
|
||||
#
|
||||
# Bug #47313 assert in check_key_in_view during CALL procedure
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP VIEW IF EXISTS t1, t2_unrelated;
|
||||
DROP PROCEDURE IF EXISTS p1;
|
||||
CREATE PROCEDURE p1(IN x INT) INSERT INTO t1 VALUES (x);
|
||||
CREATE VIEW t1 AS SELECT 10 AS f1;
|
||||
# t1 refers to the view
|
||||
CALL p1(1);
|
||||
ERROR HY000: The target table t1 of the INSERT is not insertable-into
|
||||
CREATE TEMPORARY TABLE t1 (f1 INT);
|
||||
# t1 still refers to the view since it was inlined
|
||||
CALL p1(2);
|
||||
ERROR HY000: The target table t1 of the INSERT is not insertable-into
|
||||
DROP VIEW t1;
|
||||
# t1 now refers to the temporary table
|
||||
CALL p1(3);
|
||||
# Check which values were inserted into the temp table.
|
||||
SELECT * FROM t1;
|
||||
f1
|
||||
3
|
||||
DROP TEMPORARY TABLE t1;
|
||||
DROP PROCEDURE p1;
|
||||
# Now test what happens if the sp cache is invalidated.
|
||||
CREATE PROCEDURE p1(IN x INT) INSERT INTO t1 VALUES (x);
|
||||
CREATE VIEW t1 AS SELECT 10 AS f1;
|
||||
CREATE VIEW v2_unrelated AS SELECT 1 AS r1;
|
||||
# Load the procedure into the sp cache
|
||||
CALL p1(4);
|
||||
ERROR HY000: The target table t1 of the INSERT is not insertable-into
|
||||
CREATE TEMPORARY TABLE t1 (f1 int);
|
||||
ALTER VIEW v2_unrelated AS SELECT 2 AS r1;
|
||||
# Alter view causes the sp cache to be invalidated.
|
||||
# Now t1 refers to the temporary table, not the view.
|
||||
CALL p1(5);
|
||||
# Check which values were inserted into the temp table.
|
||||
SELECT * FROM t1;
|
||||
f1
|
||||
5
|
||||
DROP TEMPORARY TABLE t1;
|
||||
DROP VIEW t1, v2_unrelated;
|
||||
DROP PROCEDURE p1;
|
||||
CREATE PROCEDURE p1(IN x INT) INSERT INTO t1 VALUES (x);
|
||||
CREATE TEMPORARY TABLE t1 (f1 INT);
|
||||
# t1 refers to the temporary table
|
||||
CALL p1(6);
|
||||
CREATE VIEW t1 AS SELECT 10 AS f1;
|
||||
# Create view causes the sp cache to be invalidated.
|
||||
# t1 still refers to the temporary table since it shadows the view.
|
||||
CALL p1(7);
|
||||
DROP VIEW t1;
|
||||
# Check which values were inserted into the temp table.
|
||||
SELECT * FROM t1;
|
||||
f1
|
||||
6
|
||||
7
|
||||
DROP TEMPORARY TABLE t1;
|
||||
DROP PROCEDURE p1;
|
||||
|
@ -2162,3 +2162,23 @@ Warning 1265 Data truncated for column 'trg2' at row 1
|
||||
DROP TRIGGER trg1;
|
||||
DROP TRIGGER trg2;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug #46747 "Crash in MDL_ticket::upgrade_shared_lock_to_exclusive
|
||||
# on TRIGGER + TEMP table".
|
||||
#
|
||||
drop trigger if exists t1_bi;
|
||||
drop temporary table if exists t1;
|
||||
drop table if exists t1;
|
||||
create table t1 (i int);
|
||||
create trigger t1_bi before insert on t1 for each row set @a:=1;
|
||||
# Create temporary table which shadows base table with trigger.
|
||||
create temporary table t1 (j int);
|
||||
# Dropping of trigger should succeed.
|
||||
drop trigger t1_bi;
|
||||
select trigger_name from information_schema.triggers
|
||||
where event_object_schema = 'test' and event_object_table = 't1';
|
||||
trigger_name
|
||||
# Clean-up.
|
||||
drop temporary table t1;
|
||||
drop table t1;
|
||||
End of 6.0 tests.
|
||||
|
@ -1,4 +1,4 @@
|
||||
drop table if exists t1;
|
||||
drop table if exists t1, t2;
|
||||
create table t1 (a integer, b integer,c1 CHAR(10));
|
||||
insert into t1 (a) values (1),(2);
|
||||
truncate table t1;
|
||||
@ -60,3 +60,102 @@ truncate table v1;
|
||||
ERROR 42S02: Table 'test.v1' doesn't exist
|
||||
drop view v1;
|
||||
drop table t1;
|
||||
#
|
||||
# Bug#20667 - Truncate table fails for a write locked table
|
||||
#
|
||||
CREATE TABLE t1 (c1 INT);
|
||||
LOCK TABLE t1 WRITE;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
1
|
||||
TRUNCATE TABLE t1;
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
UNLOCK TABLES;
|
||||
LOCK TABLE t1 READ;
|
||||
TRUNCATE TABLE t1;
|
||||
ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
|
||||
UNLOCK TABLES;
|
||||
CREATE TABLE t2 (c1 INT);
|
||||
LOCK TABLE t2 WRITE;
|
||||
TRUNCATE TABLE t1;
|
||||
ERROR HY000: Table 't1' was not locked with LOCK TABLES
|
||||
UNLOCK TABLES;
|
||||
CREATE VIEW v1 AS SELECT t1.c1 FROM t1,t2 WHERE t1.c1 = t2.c1;
|
||||
INSERT INTO t1 VALUES (1), (2), (3);
|
||||
INSERT INTO t2 VALUES (1), (3), (4);
|
||||
SELECT * FROM v1;
|
||||
c1
|
||||
1
|
||||
3
|
||||
TRUNCATE v1;
|
||||
ERROR 42S02: Table 'test.v1' doesn't exist
|
||||
SELECT * FROM v1;
|
||||
c1
|
||||
1
|
||||
3
|
||||
LOCK TABLE t1 WRITE;
|
||||
SELECT * FROM v1;
|
||||
ERROR HY000: Table 'v1' was not locked with LOCK TABLES
|
||||
TRUNCATE v1;
|
||||
ERROR 42S02: Table 'test.v1' doesn't exist
|
||||
SELECT * FROM v1;
|
||||
ERROR HY000: Table 'v1' was not locked with LOCK TABLES
|
||||
UNLOCK TABLES;
|
||||
LOCK TABLE t1 WRITE, t2 WRITE;
|
||||
SELECT * FROM v1;
|
||||
ERROR HY000: Table 'v1' was not locked with LOCK TABLES
|
||||
TRUNCATE v1;
|
||||
ERROR 42S02: Table 'test.v1' doesn't exist
|
||||
SELECT * FROM v1;
|
||||
ERROR HY000: Table 'v1' was not locked with LOCK TABLES
|
||||
UNLOCK TABLES;
|
||||
LOCK TABLE v1 WRITE;
|
||||
SELECT * FROM v1;
|
||||
c1
|
||||
1
|
||||
3
|
||||
TRUNCATE v1;
|
||||
ERROR 42S02: Table 'test.v1' doesn't exist
|
||||
SELECT * FROM v1;
|
||||
c1
|
||||
1
|
||||
3
|
||||
UNLOCK TABLES;
|
||||
LOCK TABLE t1 WRITE, t2 WRITE, v1 WRITE;
|
||||
SELECT * FROM v1;
|
||||
c1
|
||||
1
|
||||
3
|
||||
TRUNCATE v1;
|
||||
ERROR 42S02: Table 'test.v1' doesn't exist
|
||||
SELECT * FROM v1;
|
||||
c1
|
||||
1
|
||||
3
|
||||
UNLOCK TABLES;
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1, t2;
|
||||
CREATE PROCEDURE p1() SET @a = 5;
|
||||
TRUNCATE p1;
|
||||
ERROR 42S02: Table 'test.p1' doesn't exist
|
||||
SHOW CREATE PROCEDURE p1;
|
||||
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
|
||||
p1 CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`()
|
||||
SET @a = 5 latin1 latin1_swedish_ci latin1_swedish_ci
|
||||
DROP PROCEDURE p1;
|
||||
#
|
||||
# Bug#46452 Crash in MDL, HANDLER OPEN + TRUNCATE TABLE
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 AS SELECT 1 AS f1;
|
||||
HANDLER t1 OPEN;
|
||||
# Here comes the crash.
|
||||
TRUNCATE t1;
|
||||
# Currently TRUNCATE, just like other DDL, implicitly closes
|
||||
# open HANDLER table.
|
||||
HANDLER t1 READ FIRST;
|
||||
ERROR 42S02: Unknown table 't1' in HANDLER
|
||||
DROP TABLE t1;
|
||||
# End of 6.0 tests
|
||||
|
73
mysql-test/r/truncate_coverage.result
Normal file
73
mysql-test/r/truncate_coverage.result
Normal file
@ -0,0 +1,73 @@
|
||||
SET DEBUG_SYNC='RESET';
|
||||
DROP TABLE IF EXISTS t1;
|
||||
#
|
||||
# Bug#20667 - Truncate table fails for a write locked table
|
||||
#
|
||||
CREATE TABLE t1 (c1 INT);
|
||||
INSERT INTO t1 VALUES (1);
|
||||
#
|
||||
# connection con1
|
||||
HANDLER t1 OPEN;
|
||||
#
|
||||
# connection default
|
||||
LOCK TABLE t1 WRITE;
|
||||
SET DEBUG_SYNC='mdl_upgrade_shared_lock_to_exclusive SIGNAL waiting';
|
||||
TRUNCATE TABLE t1;
|
||||
#
|
||||
# connection con2
|
||||
SET DEBUG_SYNC='now WAIT_FOR waiting';
|
||||
KILL QUERY @id;
|
||||
#
|
||||
# connection con1
|
||||
# Release shared metadata lock by closing HANDLER.
|
||||
HANDLER t1 CLOSE;
|
||||
#
|
||||
# connection default
|
||||
ERROR 70100: Query execution was interrupted
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE t1;
|
||||
SET DEBUG_SYNC='RESET';
|
||||
CREATE TABLE t1 (c1 INT);
|
||||
INSERT INTO t1 VALUES (1);
|
||||
#
|
||||
# connection con1
|
||||
HANDLER t1 OPEN;
|
||||
#
|
||||
# connection default
|
||||
LOCK TABLE t1 WRITE;
|
||||
SET DEBUG_SYNC='mdl_upgrade_shared_lock_to_exclusive SIGNAL waiting';
|
||||
TRUNCATE TABLE t1;
|
||||
#
|
||||
# connection con2
|
||||
SET DEBUG_SYNC='now WAIT_FOR waiting';
|
||||
#
|
||||
# connection con1
|
||||
HANDLER t1 CLOSE;
|
||||
#
|
||||
# connection default
|
||||
ERROR 42S02: Table 'test.t1' doesn't exist
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE t1;
|
||||
ERROR 42S02: Unknown table 't1'
|
||||
SET DEBUG_SYNC='RESET';
|
||||
CREATE TABLE t1 (c1 INT);
|
||||
INSERT INTO t1 VALUES (1);
|
||||
#
|
||||
# connection con1
|
||||
START TRANSACTION;
|
||||
INSERT INTO t1 VALUES (2);
|
||||
#
|
||||
# connection default
|
||||
SET DEBUG_SYNC='mdl_acquire_lock_wait SIGNAL waiting';
|
||||
TRUNCATE TABLE t1;
|
||||
#
|
||||
# connection con1
|
||||
SET DEBUG_SYNC='now WAIT_FOR waiting';
|
||||
KILL QUERY @id;
|
||||
COMMIT;
|
||||
#
|
||||
# connection default
|
||||
ERROR 70100: Query execution was interrupted
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE t1;
|
||||
SET DEBUG_SYNC='RESET';
|
@ -1063,11 +1063,9 @@ set global default_storage_engine =@my_storage_engine;
|
||||
set global thread_cache_size =@my_thread_cache_size;
|
||||
set global max_allowed_packet =@my_max_allowed_packet;
|
||||
set global join_buffer_size =@my_join_buffer_size;
|
||||
show global variables where Variable_name='table_definition_cache' or
|
||||
Variable_name='table_lock_wait_timeout';
|
||||
show global variables where Variable_name='table_definition_cache';
|
||||
Variable_name Value
|
||||
table_definition_cache #
|
||||
table_lock_wait_timeout #
|
||||
|
||||
# --
|
||||
# -- Bug#34820: log_output can be set to illegal value.
|
||||
|
@ -1102,10 +1102,8 @@ select * from v1;
|
||||
a
|
||||
select * from t2;
|
||||
ERROR HY000: Table 't2' was not locked with LOCK TABLES
|
||||
drop view v1;
|
||||
drop table t1, t2;
|
||||
ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
|
||||
unlock tables;
|
||||
drop view v1;
|
||||
drop table t1, t2;
|
||||
create table t1 (a int);
|
||||
create view v1 as select * from t1 where a < 2 with check option;
|
||||
@ -1957,15 +1955,15 @@ CHECK TABLE v1, v2, v3, v4, v5, v6;
|
||||
Table Op Msg_type Msg_text
|
||||
test.v1 check Error FUNCTION test.f1 does not exist
|
||||
test.v1 check Error View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
|
||||
test.v1 check error Corrupt
|
||||
test.v1 check status Operation failed
|
||||
test.v2 check status OK
|
||||
test.v3 check Error FUNCTION test.f1 does not exist
|
||||
test.v3 check Error View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
|
||||
test.v3 check error Corrupt
|
||||
test.v3 check status Operation failed
|
||||
test.v4 check status OK
|
||||
test.v5 check Error FUNCTION test.f1 does not exist
|
||||
test.v5 check Error View 'test.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
|
||||
test.v5 check error Corrupt
|
||||
test.v5 check status Operation failed
|
||||
test.v6 check status OK
|
||||
create function f1 () returns int return (select max(col1) from t1);
|
||||
DROP TABLE t1;
|
||||
@ -3974,3 +3972,35 @@ create view v_9801 as
|
||||
select sum(s1) from t_9801 group by s1 with rollup with check option;
|
||||
ERROR HY000: CHECK OPTION on non-updatable view 'test.v_9801'
|
||||
drop table t_9801;
|
||||
#
|
||||
# Bug #47335 assert in get_table_share
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP VIEW IF EXISTS v1;
|
||||
CREATE TEMPORARY TABLE t1 (id INT);
|
||||
ALTER VIEW t1 AS SELECT 1 AS f1;
|
||||
ERROR 42S02: Table 'test.t1' doesn't exist
|
||||
DROP TABLE t1;
|
||||
CREATE VIEW v1 AS SELECT 1 AS f1;
|
||||
CREATE TEMPORARY TABLE v1 (id INT);
|
||||
ALTER VIEW v1 AS SELECT 2 AS f1;
|
||||
DROP TABLE v1;
|
||||
SELECT * FROM v1;
|
||||
f1
|
||||
2
|
||||
DROP VIEW v1;
|
||||
#
|
||||
# Bug #47635 assert in start_waiting_global_read_lock
|
||||
# during CREATE VIEW
|
||||
#
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
DROP VIEW IF EXISTS t2;
|
||||
CREATE TABLE t1 (f1 integer);
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS t1 (f1 integer);
|
||||
CREATE TEMPORARY TABLE t2 (f1 integer);
|
||||
DROP TABLE t1;
|
||||
FLUSH TABLES WITH READ LOCK;
|
||||
CREATE VIEW t2 AS SELECT * FROM t1;
|
||||
ERROR HY000: Can't execute the query because you have a conflicting read lock
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE t1, t2;
|
||||
|
@ -779,9 +779,9 @@ GRANT CREATE VIEW ON db26813.v2 TO u26813@localhost;
|
||||
GRANT DROP, CREATE VIEW ON db26813.v3 TO u26813@localhost;
|
||||
GRANT SELECT ON db26813.t1 TO u26813@localhost;
|
||||
ALTER VIEW v1 AS SELECT f2 FROM t1;
|
||||
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
|
||||
ERROR 42000: CREATE VIEW command denied to user 'u26813'@'localhost' for table 'v1'
|
||||
ALTER VIEW v2 AS SELECT f2 FROM t1;
|
||||
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
|
||||
ERROR 42000: DROP command denied to user 'u26813'@'localhost' for table 'v2'
|
||||
ALTER VIEW v3 AS SELECT f2 FROM t1;
|
||||
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
|
||||
SHOW CREATE VIEW v3;
|
||||
|
16
mysql-test/suite/binlog/r/binlog_row_drop_tbl.result
Normal file
16
mysql-test/suite/binlog/r/binlog_row_drop_tbl.result
Normal file
@ -0,0 +1,16 @@
|
||||
DROP TABLE IF EXISTS t1;
|
||||
RESET MASTER;
|
||||
CREATE TABLE t1 (a INT);
|
||||
SET AUTOCOMMIT=OFF;
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(1);
|
||||
DROP TABLE t1;;
|
||||
COMMIT;
|
||||
show binlog events from <binlog_start>;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT)
|
||||
master-bin.000001 # Query # # BEGIN
|
||||
master-bin.000001 # Table_map # # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query # # COMMIT
|
||||
master-bin.000001 # Query # # use `test`; DROP TABLE t1
|
@ -241,6 +241,7 @@ select (@after:=unix_timestamp())*0;
|
||||
select (@after-@before) >= 2;
|
||||
(@after-@before) >= 2
|
||||
1
|
||||
commit;
|
||||
drop table t1,t2;
|
||||
commit;
|
||||
begin;
|
||||
|
15
mysql-test/suite/binlog/r/binlog_stm_drop_tbl.result
Normal file
15
mysql-test/suite/binlog/r/binlog_stm_drop_tbl.result
Normal file
@ -0,0 +1,15 @@
|
||||
DROP TABLE IF EXISTS t1;
|
||||
RESET MASTER;
|
||||
CREATE TABLE t1 (a INT);
|
||||
SET AUTOCOMMIT=OFF;
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(1);
|
||||
DROP TABLE t1;;
|
||||
COMMIT;
|
||||
show binlog events from <binlog_start>;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT)
|
||||
master-bin.000001 # Query # # BEGIN
|
||||
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES(1)
|
||||
master-bin.000001 # Query # # COMMIT
|
||||
master-bin.000001 # Query # # use `test`; DROP TABLE t1
|
@ -229,6 +229,7 @@ select (@after:=unix_timestamp())*0;
|
||||
select (@after-@before) >= 2;
|
||||
(@after-@before) >= 2
|
||||
1
|
||||
commit;
|
||||
drop table t1,t2;
|
||||
commit;
|
||||
begin;
|
||||
|
5
mysql-test/suite/binlog/t/binlog_row_drop_tbl.test
Normal file
5
mysql-test/suite/binlog/t/binlog_row_drop_tbl.test
Normal file
@ -0,0 +1,5 @@
|
||||
# This is a wrapper for drop_table.test so that the same test case can be used
|
||||
# For both statement and row based bin logs
|
||||
|
||||
-- source include/have_binlog_format_row.inc
|
||||
-- source extra/binlog_tests/drop_table.test
|
5
mysql-test/suite/binlog/t/binlog_stm_drop_tbl.test
Normal file
5
mysql-test/suite/binlog/t/binlog_stm_drop_tbl.test
Normal file
@ -0,0 +1,5 @@
|
||||
# This is a wrapper for drop_table.test so that the same test case can be used
|
||||
# For both statement and row based bin logs
|
||||
|
||||
-- source include/have_binlog_format_mixed_or_statement.inc
|
||||
-- source extra/binlog_tests/drop_table.test
|
@ -60,7 +60,7 @@ let $wait_condition=
|
||||
--echo # con1
|
||||
let $wait_condition=
|
||||
SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE
|
||||
state = "Locked" and info = "INSERT INTO t2 VALUES (3)";
|
||||
state = "Table lock" and info = "INSERT INTO t2 VALUES (3)";
|
||||
--source include/wait_condition.inc
|
||||
SELECT RELEASE_LOCK('Bug#34306');
|
||||
--connection con2
|
||||
|
@ -367,13 +367,13 @@ echo
|
||||
;
|
||||
connection default;
|
||||
echo
|
||||
# Poll till INFO is no more NULL and State = 'Locked'.
|
||||
# Poll till INFO is no more NULL and State = 'Waiting for table'.
|
||||
;
|
||||
let $wait_condition= SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST
|
||||
WHERE INFO IS NOT NULL AND STATE = 'Locked';
|
||||
WHERE INFO IS NOT NULL AND STATE = 'Waiting for table';
|
||||
--source include/wait_condition.inc
|
||||
#
|
||||
# Expect to see the state 'Locked' for the third connection because the SELECT
|
||||
# Expect to see the state 'Waiting for table' for the third connection because the SELECT
|
||||
# collides with the WRITE TABLE LOCK.
|
||||
--replace_column 1 <ID> 3 <HOST_NAME> 6 <TIME>
|
||||
SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST;
|
||||
@ -422,10 +422,10 @@ echo
|
||||
;
|
||||
connection default;
|
||||
echo
|
||||
# Poll till INFO is no more NULL and State = 'Locked'.
|
||||
# Poll till INFO is no more NULL and State = 'Waiting for table'.
|
||||
;
|
||||
let $wait_condition= SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST
|
||||
WHERE INFO IS NOT NULL AND STATE = 'Locked';
|
||||
WHERE INFO IS NOT NULL AND STATE = 'Waiting for table';
|
||||
--source include/wait_condition.inc
|
||||
echo
|
||||
# Expect result:
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user