summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/client_priv.h4
-rw-r--r--client/mysql.cc93
-rw-r--r--client/mysqladmin.cc39
-rw-r--r--client/mysqlcheck.c2
-rw-r--r--client/mysqldump.c185
-rw-r--r--client/mysqltest.cc128
-rw-r--r--client/sql_string.cc1
-rw-r--r--client/sql_string.h4
-rw-r--r--config/ac-macros/misc.m46
-rw-r--r--include/m_string.h69
-rw-r--r--include/mysql_com.h1
-rw-r--r--include/violite.h16
-rw-r--r--libmysql/libmysql.c3
-rw-r--r--libmysqld/lib_sql.cc1
-rw-r--r--mysql-test/r/alias.result139
-rw-r--r--mysql-test/r/delete.result143
-rw-r--r--mysql-test/r/derived.result2
-rw-r--r--mysql-test/r/dirty_close.result10
-rw-r--r--mysql-test/r/func_sapdb.result30
-rw-r--r--mysql-test/r/func_time.result6
-rw-r--r--mysql-test/r/mysql.result196
-rw-r--r--mysql-test/r/partition_sync.result25
-rw-r--r--mysql-test/r/rpl_mysqldump_slave.result17
-rw-r--r--mysql-test/r/sp-error.result12
-rw-r--r--mysql-test/r/sp.result95
-rw-r--r--mysql-test/r/trigger.result47
-rw-r--r--mysql-test/r/type_time.result25
-rw-r--r--mysql-test/suite/rpl/r/rpl_multi_delete2.result2
-rw-r--r--mysql-test/suite/rpl/t/rpl_multi_delete2.test2
-rw-r--r--mysql-test/suite/sys_vars/r/group_concat_max_len_func.result11
-rw-r--r--mysql-test/t/alias.test129
-rw-r--r--mysql-test/t/delete.test155
-rw-r--r--mysql-test/t/derived.test2
-rw-r--r--mysql-test/t/dirty_close.test33
-rw-r--r--mysql-test/t/func_sapdb.test22
-rw-r--r--mysql-test/t/func_time.test10
-rw-r--r--mysql-test/t/lock_multi.test2
-rw-r--r--mysql-test/t/mysql.test8
-rw-r--r--mysql-test/t/partition_sync.test41
-rw-r--r--mysql-test/t/rpl_mysqldump_slave.test25
-rw-r--r--mysql-test/t/shm.test10
-rw-r--r--mysql-test/t/sp-error.test21
-rw-r--r--mysql-test/t/sp.test113
-rw-r--r--mysql-test/t/trigger.test64
-rw-r--r--mysql-test/t/type_time.test21
-rw-r--r--mysys/my_alloc.c4
-rw-r--r--mysys/my_getopt.c8
-rw-r--r--sql/event_data_objects.cc2
-rw-r--r--sql/field.cc350
-rw-r--r--sql/field.h42
-rw-r--r--sql/ha_partition.cc3
-rw-r--r--sql/item_cmpfunc.cc3
-rw-r--r--sql/item_func.cc81
-rw-r--r--sql/item_subselect.cc7
-rw-r--r--sql/item_timefunc.cc18
-rw-r--r--sql/mysql_priv.h4
-rw-r--r--sql/opt_sum.cc6
-rw-r--r--sql/share/errmsg.txt1
-rw-r--r--sql/sp.cc3
-rw-r--r--sql/sp_head.cc4
-rw-r--r--sql/sql_cache.cc10
-rw-r--r--sql/sql_class.h14
-rw-r--r--sql/sql_insert.cc14
-rw-r--r--sql/sql_list.h2
-rw-r--r--sql/sql_parse.cc126
-rw-r--r--sql/sql_partition.cc8
-rw-r--r--sql/sql_select.cc8
-rw-r--r--sql/sql_servers.cc4
-rw-r--r--sql/sql_show.cc60
-rw-r--r--sql/sql_string.cc17
-rw-r--r--sql/sql_string.h4
-rw-r--r--sql/sql_trigger.cc4
-rw-r--r--sql/sql_update.cc18
-rw-r--r--sql/sql_yacc.yy36
-rw-r--r--sql/table.h6
-rw-r--r--sql/tztime.cc2
-rw-r--r--storage/ndb/include/kernel/signaldata/DictTabInfo.hpp4
-rw-r--r--strings/ctype-bin.c5
-rw-r--r--strings/ctype-latin1.c5
-rw-r--r--strings/ctype-mb.c5
-rw-r--r--strings/ctype-simple.c10
-rw-r--r--vio/vio.c32
-rw-r--r--vio/vio_priv.h14
-rw-r--r--vio/viosocket.c166
84 files changed, 2377 insertions, 703 deletions
diff --git a/client/client_priv.h b/client/client_priv.h
index e99d34ffa97..53027465771 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -62,6 +62,9 @@ enum options_client
OPT_MYSQL_NUMBER_OF_QUERY,
OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE,
OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_CREATE_SLAP_SCHEMA,
+ OPT_MYSQLDUMP_SLAVE_APPLY,
+ OPT_MYSQLDUMP_SLAVE_DATA,
+ OPT_MYSQLDUMP_INCLUDE_MASTER_HOST_PORT,
OPT_SLAP_CSV, OPT_SLAP_CREATE_STRING,
OPT_SLAP_AUTO_GENERATE_SQL_LOAD_TYPE, OPT_SLAP_AUTO_GENERATE_WRITE_NUM,
OPT_SLAP_AUTO_GENERATE_ADD_AUTO,
@@ -78,6 +81,7 @@ enum options_client
OPT_SLAP_DETACH,
OPT_MYSQL_REPLACE_INTO, OPT_BASE64_OUTPUT_MODE, OPT_SERVER_ID,
OPT_FIX_TABLE_NAMES, OPT_FIX_DB_NAMES, OPT_SSL_VERIFY_SERVER_CERT,
+ OPT_AUTO_VERTICAL_OUTPUT,
OPT_DEBUG_INFO, OPT_DEBUG_CHECK, OPT_COLUMN_TYPES, OPT_ERROR_LOG_FILE,
OPT_WRITE_BINLOG, OPT_DUMP_DATE,
OPT_INIT_COMMAND,
diff --git a/client/mysql.cc b/client/mysql.cc
index 3fa416330e8..ca0584df0cd 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -143,6 +143,7 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0,
tty_password= 0, opt_nobeep=0, opt_reconnect=1,
opt_secure_auth= 0,
default_pager_set= 0, opt_sigint_ignore= 0,
+ auto_vertical_output= 0,
show_warnings= 0, executing_query= 0, interrupted_query= 0,
ignore_spaces= 0;
static my_bool debug_info_flag, debug_check_flag;
@@ -185,6 +186,7 @@ static MEM_ROOT hash_mem_root;
static uint prompt_counter;
static char delimiter[16]= DEFAULT_DELIMITER;
static uint delimiter_length= 1;
+unsigned short terminal_width= 80;
#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
@@ -238,6 +240,8 @@ static const char* construct_prompt();
static char *get_arg(char *line, my_bool get_next_arg);
static void init_username();
static void add_int_to_prompt(int toadd);
+static int get_result_width(MYSQL_RES *res);
+static int get_field_disp_length(MYSQL_FIELD * field);
/* A structure which contains information on the commands this program
can understand. */
@@ -1065,6 +1069,10 @@ static void mysql_end_timer(ulong start_time,char *buff);
static void nice_time(double sec,char *buff,bool part_second);
extern "C" sig_handler mysql_end(int sig);
extern "C" sig_handler handle_sigint(int sig);
+#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
+static sig_handler window_resize(int sig);
+#endif
+
int main(int argc,char *argv[])
{
@@ -1144,8 +1152,8 @@ int main(int argc,char *argv[])
if (sql_connect(current_host,current_db,current_user,opt_password,
opt_silent))
{
- quick=1; // Avoid history
- status.exit_status=1;
+ quick= 1; // Avoid history
+ status.exit_status= 1;
mysql_end(-1);
}
if (!status.batch)
@@ -1157,6 +1165,13 @@ int main(int argc,char *argv[])
signal(SIGINT, handle_sigint); // Catch SIGINT to clean up
signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up
+#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
+ /* Readline will call this if it installs a handler */
+ signal(SIGWINCH, window_resize);
+ /* call the SIGWINCH handler to get the default term width */
+ window_resize(0);
+#endif
+
put_info("Welcome to the MySQL monitor. Commands end with ; or \\g.",
INFO_INFO);
sprintf((char*) glob_buffer.ptr(),
@@ -1329,6 +1344,16 @@ err:
}
+#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
+sig_handler window_resize(int sig)
+{
+ struct winsize window_size;
+
+ if (ioctl(fileno(stdin), TIOCGWINSZ, &window_size) == 0)
+ terminal_width= window_size.ws_col;
+}
+#endif
+
static struct my_option my_long_options[] =
{
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
@@ -1346,6 +1371,9 @@ static struct my_option my_long_options[] =
{"no-auto-rehash", 'A',
"No automatic rehashing. One has to use 'rehash' to get table and field completion. This gives a quicker start of mysql and disables rehashing on reconnect. WARNING: options deprecated; use --disable-auto-rehash instead.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"auto-vertical-output", OPT_AUTO_VERTICAL_OUTPUT,
+ "Automatically switch to vertical output mode if the result is wider than the terminal width.",
+ (uchar**) &auto_vertical_output, (uchar**) &auto_vertical_output, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"batch", 'B',
"Don't use history file. Disable interactive behavior. (Enables --silent)", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"character-sets-dir", OPT_CHARSETS_DIR,
@@ -3052,7 +3080,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
print_table_data_html(result);
else if (opt_xml)
print_table_data_xml(result);
- else if (vertical)
+ else if (vertical || (auto_vertical_output && (terminal_width < get_result_width(result))))
print_table_data_vertically(result);
else if (opt_silent && verbose <= 2 && !output_tables)
print_tab_data(result);
@@ -3383,6 +3411,65 @@ print_table_data(MYSQL_RES *result)
my_afree((uchar*) num_flag);
}
+/**
+ Return the length of a field after it would be rendered into text.
+
+ This doesn't know or care about multibyte characters. Assume we're
+ using such a charset. We can't know that all of the upcoming rows
+ for this column will have bytes that each render into some fraction
+ of a character. It's at least possible that a row has bytes that
+ all render into one character each, and so the maximum length is
+ still the number of bytes. (Assumption 1: This can't be better
+ because we can never know the number of characters that the DB is
+ going to send -- only the number of bytes. 2: Chars <= Bytes.)
+
+ @param field Pointer to a field to be inspected
+
+ @returns number of character positions to be used, at most
+*/
+static int get_field_disp_length(MYSQL_FIELD *field)
+{
+ uint length= column_names ? field->name_length : 0;
+
+ if (quick)
+ length= max(length, field->length);
+ else
+ length= max(length, field->max_length);
+
+ if (length < 4 && !IS_NOT_NULL(field->flags))
+ length= 4; /* Room for "NULL" */
+
+ return length;
+}
+
+/**
+ For a new result, return the max number of characters that any
+ upcoming row may return.
+
+ @param result Pointer to the result to judge
+
+ @returns The max number of characters in any row of this result
+*/
+static int get_result_width(MYSQL_RES *result)
+{
+ unsigned int len= 0;
+ MYSQL_FIELD *field;
+ MYSQL_FIELD_OFFSET offset;
+
+#ifndef DBUG_OFF
+ offset= mysql_field_tell(result);
+ DBUG_ASSERT(offset == 0);
+#else
+ offset= 0;
+#endif
+
+ while ((field= mysql_fetch_field(result)) != NULL)
+ len+= get_field_disp_length(field) + 3; /* plus bar, space, & final space */
+
+ (void) mysql_field_seek(result, offset);
+
+ return len + 1; /* plus final bar. */
+}
static void
tee_print_sized_data(const char *data, unsigned int data_length, unsigned int total_bytes_to_send, bool right_justified)
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index a3eee14e0d1..500a890a9ab 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -900,23 +900,38 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
char buff[128],crypted_pw[64];
time_t start_time;
+ char *typed_password= NULL, *verified= NULL;
/* Do initialization the same way as we do in mysqld */
start_time=time((time_t*) 0);
randominit(&rand_st,(ulong) start_time,(ulong) start_time/2);
- if (argc < 2)
+ if (argc < 1)
{
my_printf_error(0, "Too few arguments to change password", error_flags);
return 1;
}
- if (argv[1][0])
+ else if (argc == 1)
+ {
+ /* prompt for password */
+ typed_password= get_tty_password("New password: ");
+ verified= get_tty_password("Confirm new password: ");
+ if (strcmp(typed_password, verified) != 0)
+ {
+ my_printf_error(0,"Passwords don't match",MYF(ME_BELL));
+ return -1;
+ }
+ }
+ else
+ typed_password= argv[1];
+
+ if (typed_password[0])
{
- char *pw= argv[1];
bool old= (find_type(argv[0], &command_typelib, 2) ==
ADMIN_OLD_PASSWORD);
#ifdef __WIN__
- uint pw_len= (uint) strlen(pw);
- if (pw_len > 1 && pw[0] == '\'' && pw[pw_len-1] == '\'')
+ size_t pw_len= strlen(typed_password);
+ if (pw_len > 1 && typed_password[0] == '\'' &&
+ typed_password[pw_len-1] == '\'')
printf("Warning: single quotes were not trimmed from the password by"
" your command\nline client, as you might have expected.\n");
#endif
@@ -954,9 +969,9 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
}
if (old)
- make_scrambled_password_323(crypted_pw, pw);
+ make_scrambled_password_323(crypted_pw, typed_password);
else
- make_scrambled_password(crypted_pw, pw);
+ make_scrambled_password(crypted_pw, typed_password);
}
else
crypted_pw[0]=0; /* No password */
@@ -991,6 +1006,12 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
return -1;
}
}
+ /* free up memory from prompted password */
+ if (typed_password != argv[1])
+ {
+ my_free(typed_password,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(verified,MYF(MY_ALLOW_ZERO_PTR));
+ }
argc--; argv++;
break;
}
@@ -1082,8 +1103,8 @@ static void usage(void)
kill id,id,... Kill mysql threads");
#if MYSQL_VERSION_ID >= 32200
puts("\
- password new-password Change old password to new-password, MySQL 4.1 hashing.\n\
- old-password new-password Change old password to new-password in old format.\n");
+ password [new-password] Change old password to new-password in current format\n\
+ old-password [new-password] Change old password to new-password in old format");
#endif
puts("\
ping Check if mysqld is alive\n\
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index 1affea1d189..5c801eb6e26 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -128,7 +128,7 @@ static struct my_option my_long_options[] =
"Faster than extended-check, but only finds 99.99 percent of all errors. Should be good enough for most cases.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"write-binlog", OPT_WRITE_BINLOG,
- "Log ANALYZE, OPTIMIZE and REPAIR TABLE commands. Enabled by default; use --skip-write-binlog when commands should not be sent to replication slaves.",
+ "Log ANALYZE, OPTIMIZE and REPAIR TABLE commands. Use --skip-write-binlog when commands should not be sent to replication slaves.",
(uchar**) &opt_write_binlog, (uchar**) &opt_write_binlog, 0, GET_BOOL, NO_ARG,
1, 0, 0, 0, 0, 0},
{"optimize", 'o', "Optimize table.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0,
diff --git a/client/mysqldump.c b/client/mysqldump.c
index aa81a0e98bf..95206802fd7 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -98,6 +98,8 @@ static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0,
opt_complete_insert= 0, opt_drop_database= 0,
opt_replace_into= 0,
opt_dump_triggers= 0, opt_routines=0, opt_tz_utc=1,
+ opt_slave_apply= 0,
+ opt_include_master_host_port= 0,
opt_events= 0,
opt_alltspcs=0, opt_notspcs= 0;
static my_bool insert_pat_inited= 0, debug_info_flag= 0, debug_check_flag= 0;
@@ -118,7 +120,10 @@ static my_bool server_supports_switching_charsets= TRUE;
static ulong opt_compatible_mode= 0;
#define MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL 1
#define MYSQL_OPT_MASTER_DATA_COMMENTED_SQL 2
+#define MYSQL_OPT_SLAVE_DATA_EFFECTIVE_SQL 1
+#define MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL 2
static uint opt_mysql_port= 0, opt_master_data;
+static uint opt_slave_data;
static uint my_end_arg;
static char * opt_mysql_unix_port=0;
static int first_error=0;
@@ -206,6 +211,10 @@ static struct my_option my_long_options[] =
{"allow-keywords", OPT_KEYWORDS,
"Allow creation of column names that are keywords.", (uchar**) &opt_keywords,
(uchar**) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"apply-slave-statements", OPT_MYSQLDUMP_SLAVE_APPLY,
+ "Adds 'STOP SLAVE' prior to 'CHANGE MASTER' and 'START SLAVE' to bottom of dump.",
+ (uchar**) &opt_slave_apply, (uchar**) &opt_slave_apply, 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
#ifdef __NETWARE__
{"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -264,6 +273,19 @@ static struct my_option my_long_options[] =
{"disable-keys", 'K',
"'/*!40000 ALTER TABLE tb_name DISABLE KEYS */; and '/*!40000 ALTER TABLE tb_name ENABLE KEYS */; will be put in the output.", (uchar**) &opt_disable_keys,
(uchar**) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+ {"dump-slave", OPT_MYSQLDUMP_SLAVE_DATA,
+ "This causes the binary log position and filename of the master to be "
+ "appended to the dumped data output. Setting the value to 1, will print"
+ "it as a CHANGE MASTER command in the dumped data output; if equal"
+ " to 2, that command will be prefixed with a comment symbol. "
+ "This option will turn --lock-all-tables on, unless "
+ "--single-transaction is specified too (in which case a "
+ "global read lock is only taken a short time at the beginning of the dump "
+ "- don't forget to read about --single-transaction below). In all cases "
+ "any action on logs will happen at the exact moment of the dump."
+ "Option automatically turns --lock-tables off.",
+ (uchar**) &opt_slave_data, (uchar**) &opt_slave_data, 0,
+ GET_UINT, OPT_ARG, 0, 0, MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL, 0, 0, 0},
{"events", 'E', "Dump events.",
(uchar**) &opt_events, (uchar**) &opt_events, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -317,6 +339,12 @@ static struct my_option my_long_options[] =
"use the directive multiple times, once for each table. Each table must "
"be specified with both database and table names, e.g. --ignore-table=database.table",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"include-master-host-port", OPT_MYSQLDUMP_INCLUDE_MASTER_HOST_PORT,
+ "Adds 'MASTER_HOST=<host>, MASTER_PORT=<port>' to 'CHANGE MASTER TO..' in dump produced with --dump-slave.",
+ (uchar**) &opt_include_master_host_port,
+ (uchar**) &opt_include_master_host_port,
+ 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
{"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
(uchar**) &opt_ignore, (uchar**) &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
@@ -402,7 +430,7 @@ static struct my_option my_long_options[] =
(uchar**) &opt_routines, (uchar**) &opt_routines, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
{"set-charset", OPT_SET_CHARSET,
- "Add 'SET NAMES default_character_set' to the output. Enabled by default; suppress with --skip-set-charset.",
+ "Add 'SET NAMES default_character_set' to the output.",
(uchar**) &opt_set_charset, (uchar**) &opt_set_charset, 0, GET_BOOL, NO_ARG, 1,
0, 0, 0, 0, 0},
{"set-variable", 'O',
@@ -764,6 +792,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
if (!argument) /* work like in old versions */
opt_master_data= MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL;
break;
+ case (int) OPT_MYSQLDUMP_SLAVE_DATA:
+ if (!argument) /* work like in old versions */
+ opt_slave_data= MYSQL_OPT_SLAVE_DATA_EFFECTIVE_SQL;
+ break;
case (int) OPT_OPTIMIZE:
extended_insert= opt_drop= opt_lock= quick= create_options=
opt_disable_keys= lock_tables= opt_set_charset= 1;
@@ -896,6 +928,14 @@ static int get_options(int *argc, char ***argv)
return(EX_USAGE);
}
+ /* We don't delete master logs if slave data option */
+ if (opt_slave_data)
+ {
+ opt_lock_all_tables= !opt_single_transaction;
+ opt_master_data= 0;
+ opt_delete_master_logs= 0;
+ }
+
/* Ensure consistency of the set of binlog & locking options */
if (opt_delete_master_logs && !opt_master_data)
opt_master_data= MYSQL_OPT_MASTER_DATA_COMMENTED_SQL;
@@ -906,7 +946,10 @@ static int get_options(int *argc, char ***argv)
return(EX_USAGE);
}
if (opt_master_data)
+ {
opt_lock_all_tables= !opt_single_transaction;
+ opt_slave_data= 0;
+ }
if (opt_single_transaction || opt_lock_all_tables)
lock_tables= 0;
if (enclosed && opt_enclosed)
@@ -4333,6 +4376,130 @@ static int do_show_master_status(MYSQL *mysql_con)
return 0;
}
+static int do_stop_slave_sql(MYSQL *mysql_con)
+{
+ MYSQL_RES *slave;
+ /* We need to check if the slave sql is running in the first place */
+ if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS"))
+ return(1);
+ else
+ {
+ MYSQL_ROW row= mysql_fetch_row(slave);
+ if (row && row[11])
+ {
+ /* if SLAVE SQL is not running, we don't stop it */
+ if (!strcmp(row[11],"No"))
+ {
+ mysql_free_result(slave);
+ /* Silently assume that they don't have the slave running */
+ return(0);
+ }
+ }
+ }
+ mysql_free_result(slave);
+
+ /* now, stop slave if running */
+ if (mysql_query_with_error_report(mysql_con, 0, "STOP SLAVE SQL_THREAD"))
+ return(1);
+
+ return(0);
+}
+
+static int add_stop_slave(void)
+{
+ if (opt_comments)
+ fprintf(md_result_file,
+ "\n--\n-- stop slave statement to make a recovery dump)\n--\n\n");
+ fprintf(md_result_file, "STOP SLAVE;\n");
+ return(0);
+}
+
+static int add_slave_statements(void)
+{
+ if (opt_comments)
+ fprintf(md_result_file,
+ "\n--\n-- start slave statement to make a recovery dump)\n--\n\n");
+ fprintf(md_result_file, "START SLAVE;\n");
+ return(0);
+}
+
+static int do_show_slave_status(MYSQL *mysql_con)
+{
+ MYSQL_RES *slave;
+ const char *comment_prefix=
+ (opt_slave_data == MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL) ? "-- " : "";
+ if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS"))
+ {
+ if (!ignore_errors)
+ {
+ /* SHOW SLAVE STATUS reports nothing and --force is not enabled */
+ my_printf_error(0, "Error: Slave not set up", MYF(0));
+ }
+ mysql_free_result(slave);
+ return 1;
+ }
+ else
+ {
+ MYSQL_ROW row= mysql_fetch_row(slave);
+ if (row && row[9] && row[21])
+ {
+ /* SHOW MASTER STATUS reports file and position */
+ if (opt_comments)
+ fprintf(md_result_file,
+ "\n--\n-- Position to start replication or point-in-time "
+ "recovery from (the master of this slave)\n--\n\n");
+
+ fprintf(md_result_file, "%sCHANGE MASTER TO ", comment_prefix);
+
+ if (opt_include_master_host_port)
+ {
+ if (row[1])
+ fprintf(md_result_file, "MASTER_HOST='%s', ", row[1]);
+ if (row[3])
+ fprintf(md_result_file, "MASTER_PORT='%s', ", row[3]);
+ }
+ fprintf(md_result_file,
+ "MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", row[9], row[21]);
+
+ check_io(md_result_file);
+ }
+ mysql_free_result(slave);
+ }
+ return 0;
+}
+
+static int do_start_slave_sql(MYSQL *mysql_con)
+{
+ MYSQL_RES *slave;
+ /* We need to check if the slave sql is stopped in the first place */
+ if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS"))
+ return(1);
+ else
+ {
+ MYSQL_ROW row= mysql_fetch_row(slave);
+ if (row && row[11])
+ {
+ /* if SLAVE SQL is not running, we don't start it */
+ if (!strcmp(row[11],"Yes"))
+ {
+ mysql_free_result(slave);
+ /* Silently assume that they don't have the slave running */
+ return(0);
+ }
+ }
+ }
+ mysql_free_result(slave);
+
+ /* now, start slave if stopped */
+ if (mysql_query_with_error_report(mysql_con, 0, "START SLAVE"))
+ {
+ my_printf_error(0, "Error: Unable to start slave", MYF(0));
+ return 1;
+ }
+ return(0);
+}
+
+
static int do_flush_tables_read_lock(MYSQL *mysql_con)
{
@@ -4995,6 +5162,9 @@ int main(int argc, char **argv)
if (!path)
write_header(md_result_file, *argv);
+ if (opt_slave_data && do_stop_slave_sql(mysql))
+ goto err;
+
if ((opt_lock_all_tables || opt_master_data) &&
do_flush_tables_read_lock(mysql))
goto err;
@@ -5013,8 +5183,13 @@ int main(int argc, char **argv)
goto err;
flush_logs= 0; /* not anymore; that would not be sensible */
}
+ /* Add 'STOP SLAVE to beginning of dump */
+ if (opt_slave_apply && add_stop_slave())
+ goto err;
if (opt_master_data && do_show_master_status(mysql))
goto err;
+ if (opt_slave_data && do_show_slave_status(mysql))
+ goto err;
if (opt_single_transaction && do_unlock_tables(mysql)) /* unlock but no commit! */
goto err;
@@ -5042,6 +5217,14 @@ int main(int argc, char **argv)
dump_databases(argv);
}
+ /* if --dump-slave , start the slave sql thread */
+ if (opt_slave_data && do_start_slave_sql(mysql))
+ goto err;
+
+ /* add 'START SLAVE' to end of dump */
+ if (opt_slave_apply && add_slave_statements())
+ goto err;
+
/* ensure dumped data flushed */
if (md_result_file && fflush(md_result_file))
{
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 04a3526139e..a4c526be70c 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -75,7 +75,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_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES,
+ OPT_RESULT_FORMAT_VERSION
};
static int record= 0, opt_sleep= -1;
@@ -88,6 +89,7 @@ const char *opt_logdir= "";
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 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;
@@ -284,11 +286,12 @@ enum enum_commands {
Q_SEND_QUIT, Q_CHANGE_USER, Q_MKDIR, Q_RMDIR,
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_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
- Q_COMMENT_WITH_COMMAND
+ Q_COMMENT_WITH_COMMAND,
+ Q_EMPTY_LINE
};
@@ -378,6 +381,7 @@ const char *command_names[]=
"list_files_append_file",
"send_shutdown",
"shutdown_server",
+ "result_format",
"move_file",
"send_eval",
@@ -2193,6 +2197,59 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
}
+static void
+set_result_format_version(ulong new_version)
+{
+ switch (new_version){
+ case 1:
+ /* The first format */
+ break;
+ case 2:
+ /* New format that also writes comments and empty lines
+ from test file to result */
+ break;
+ default:
+ die("Version format %lu has not yet been implemented", new_version);
+ break;
+ }
+ opt_result_format_version= new_version;
+}
+
+
+/*
+ Set the result format version to use when generating
+ the .result file
+*/
+
+static void
+do_result_format_version(struct st_command *command)
+{
+ long version;
+ static DYNAMIC_STRING ds_version;
+ const struct command_arg result_format_args[] = {
+ "version", ARG_STRING, TRUE, &ds_version, "Version to use",
+ };
+
+ DBUG_ENTER("do_result_format_version");
+
+ check_command_args(command, command->first_argument,
+ result_format_args,
+ sizeof(result_format_args)/sizeof(struct command_arg),
+ ',');
+
+ /* Convert version number to int */
+ if (!str2int(ds_version.str, 10, (long) 0, (long) INT_MAX, &version))
+ die("Invalid version number: '%s'", ds_version.str);
+
+ set_result_format_version(version);
+
+ dynstr_append(&ds_res, "result_format: ");
+ dynstr_append_mem(&ds_res, ds_version.str, ds_version.length);
+ dynstr_append(&ds_res, "\n");
+ dynstr_free(&ds_version);
+}
+
+
/*
Set variable from the result of a field in a query
@@ -5273,7 +5330,7 @@ my_bool end_of_query(int c)
int read_line(char *buf, int size)
{
- char c, UNINIT_VAR(last_quote);
+ char c, UNINIT_VAR(last_quote), last_char= 0;
char *p= buf, *buf_end= buf + size - 1;
int skip_char= 0;
enum {R_NORMAL, R_Q, R_SLASH_IN_Q,
@@ -5371,14 +5428,24 @@ int read_line(char *buf, int size)
}
else if (my_isspace(charset_info, c))
{
- /* Skip all space at begining of line */
if (c == '\n')
{
+ if (last_char == '\n')
+ {
+ /* Two new lines in a row, return empty line */
+ DBUG_PRINT("info", ("Found two new lines in a row"));
+ *p++= c;
+ *p= 0;
+ DBUG_RETURN(0);
+ }
+
/* Query hasn't started yet */
start_lineno= cur_file->lineno;
DBUG_PRINT("info", ("Query hasn't started yet, start_lineno: %d",
start_lineno));
}
+
+ /* Skip all space at begining of line */
skip_char= 1;
}
else if (end_of_query(c))
@@ -5419,6 +5486,8 @@ int read_line(char *buf, int size)
}
+ last_char= c;
+
if (!skip_char)
{
/* Could be a multibyte character */
@@ -5628,9 +5697,10 @@ int read_command(struct st_command** command_ptr)
DBUG_RETURN(1);
}
- convert_to_format_v1(read_command_buf);
+ if (opt_result_format_version == 1)
+ convert_to_format_v1(read_command_buf);
- DBUG_PRINT("info", ("query: %s", read_command_buf));
+ DBUG_PRINT("info", ("query: '%s'", read_command_buf));
if (*p == '#')
{
command->type= Q_COMMENT;
@@ -5640,6 +5710,10 @@ int read_command(struct st_command** command_ptr)
command->type= Q_COMMENT_WITH_COMMAND;
p+= 2; /* Skip past -- */
}
+ else if (*p == '\n')
+ {
+ command->type= Q_EMPTY_LINE;
+ }
/* Skip leading spaces */
while (*p && my_isspace(charset_info, *p))
@@ -5734,6 +5808,11 @@ static struct my_option my_long_options[] =
{"result-file", 'R', "Read/Store result from/in this file.",
(uchar**) &result_file_name, (uchar**) &result_file_name, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"result-format-version", OPT_RESULT_FORMAT_VERSION,
+ "Version of the result file format to use",
+ (uchar**) &opt_result_format_version,
+ (uchar**) &opt_result_format_version, 0,
+ GET_INT, REQUIRED_ARG, 1, 1, 2, 0, 0, 0},
{"server-arg", 'A', "Send option value to embedded server as a parameter.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"server-file", 'F', "Read embedded server arguments from file.",
@@ -5943,6 +6022,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
sf_malloc_quick=1;
#endif
break;
+ case OPT_RESULT_FORMAT_VERSION:
+ set_result_format_version(opt_result_format_version);
+ break;
case 'V':
print_version();
exit(0);
@@ -7816,6 +7898,7 @@ int main(int argc, char **argv)
case Q_MOVE_FILE: do_move_file(command); break;
case Q_CHMOD_FILE: do_chmod_file(command); break;
case Q_PERL: do_perl(command); break;
+ case Q_RESULT_FORMAT_VERSION: do_result_format_version(command); break;
case Q_DELIMITER:
do_delimiter(command);
break;
@@ -7933,9 +8016,38 @@ int main(int argc, char **argv)
do_sync_with_master2(command, 0);
break;
}
- case Q_COMMENT: /* Ignore row */
+ case Q_COMMENT:
+ {
command->last_argument= command->end;
+
+ /* Don't output comments in v1 */
+ if (opt_result_format_version == 1)
+ break;
+
+ /* Don't output comments if query logging is off */
+ if (disable_query_log)
+ break;
+
+ /* Write comment's with two starting #'s to result file */
+ const char* p= command->query;
+ if (p && *p == '#' && *(p+1) == '#')
+ {
+ dynstr_append_mem(&ds_res, command->query, command->query_len);
+ dynstr_append(&ds_res, "\n");
+ }
break;
+ }
+ case Q_EMPTY_LINE:
+ /* Don't output newline in v1 */
+ if (opt_result_format_version == 1)
+ break;
+
+ /* Don't output newline if query logging is off */
+ if (disable_query_log)
+ break;
+
+ dynstr_append(&ds_res, "\n");
+ break;
case Q_PING:
handle_command_error(command, mysql_ping(&cur_con->mysql));
break;
diff --git a/client/sql_string.cc b/client/sql_string.cc
index dc6147b563f..46fd1cb0012 100644
--- a/client/sql_string.cc
+++ b/client/sql_string.cc
@@ -23,6 +23,7 @@
#include <my_sys.h>
#include <m_string.h>
#include <m_ctype.h>
+#include <mysql_com.h>
#ifdef HAVE_FCONVERT
#include <floatingpoint.h>
#endif
diff --git a/client/sql_string.h b/client/sql_string.h
index 0e6d6da4476..1a3ac5d33c5 100644
--- a/client/sql_string.h
+++ b/client/sql_string.h
@@ -22,10 +22,6 @@
#pragma interface /* gcc class implementation */
#endif
-#ifndef NOT_FIXED_DEC
-#define NOT_FIXED_DEC 31
-#endif
-
class String;
int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
diff --git a/config/ac-macros/misc.m4 b/config/ac-macros/misc.m4
index 1eec0e9e18c..996ac62e025 100644
--- a/config/ac-macros/misc.m4
+++ b/config/ac-macros/misc.m4
@@ -601,15 +601,15 @@ dnl ---------------------------------------------------------------------------
dnl MYSQL_NEEDS_MYSYS_NEW
AC_DEFUN([MYSQL_NEEDS_MYSYS_NEW],
-[AC_CACHE_CHECK([needs mysys_new helpers], mysql_use_mysys_new,
+[AC_CACHE_CHECK([needs mysys_new helpers], mysql_cv_use_mysys_new,
[
AC_LANG_PUSH(C++)
AC_TRY_LINK([], [
class A { public: int b; }; A *a=new A; a->b=10; delete a;
-], mysql_use_mysys_new=no, mysql_use_mysys_new=yes)
+], mysql_cv_use_mysys_new=no, mysql_cv_use_mysys_new=yes)
AC_LANG_POP(C++)
])
-if test "$mysql_use_mysys_new" = "yes"
+if test "$mysql_cv_use_mysys_new" = "yes"
then
AC_DEFINE([USE_MYSYS_NEW], [1], [Needs to use mysys_new helpers])
fi
diff --git a/include/m_string.h b/include/m_string.h
index 3c4c6ea088a..a6a36f32ca4 100644
--- a/include/m_string.h
+++ b/include/m_string.h
@@ -260,4 +260,73 @@ typedef struct st_mysql_lex_string LEX_STRING;
#define USTRING_WITH_LEN(X) ((uchar*) X), ((size_t) (sizeof(X) - 1))
#define C_STRING_WITH_LEN(X) ((char *) (X)), ((size_t) (sizeof(X) - 1))
+/* SPACE_INT is a word that contains only spaces */
+#if SIZEOF_INT == 4
+#define SPACE_INT 0x20202020
+#elif SIZEOF_INT == 8
+#define SPACE_INT 0x2020202020202020
+#else
+#error define the appropriate constant for a word full of spaces
+#endif
+
+/**
+ Skip trailing space.
+
+ On most systems reading memory in larger chunks (ideally equal to the size of
+ the chinks that the machine physically reads from memory) causes fewer memory
+ access loops and hence increased performance.
+ This is why the 'int' type is used : it's closest to that (according to how
+ it's defined in C).
+ So when we determine the amount of whitespace at the end of a string we do
+ the following :
+ 1. We divide the string into 3 zones :
+ a) from the start of the string (__start) to the first multiple
+ of sizeof(int) (__start_words)
+ b) from the end of the string (__end) to the last multiple of sizeof(int)
+ (__end_words)
+ c) a zone that is aligned to sizeof(int) and can be safely accessed
+ through an int *
+ 2. We start comparing backwards from (c) char-by-char. If all we find is
+ space then we continue
+ 3. If there are elements in zone (b) we compare them as unsigned ints to a
+ int mask (SPACE_INT) consisting of all spaces
+ 4. Finally we compare the remaining part (a) of the string char by char.
+ This covers for the last non-space unsigned int from 3. (if any)
+
+ This algorithm works well for relatively larger strings, but it will slow
+ the things down for smaller strings (because of the additional calculations
+ and checks compared to the naive method). Thus the barrier of length 20
+ is added.
+
+ @param ptr pointer to the input string
+ @param len the length of the string
+ @return the last non-space character
+*/
+
+static inline const uchar *skip_trailing_space(const uchar *ptr,size_t len)
+{
+ const uchar *end= ptr + len;
+
+ if (len > 20)
+ {
+ const uchar *end_words= (const uchar *)(intptr)
+ (((ulonglong)(intptr)end) / SIZEOF_INT * SIZEOF_INT);
+ const uchar *start_words= (const uchar *)(intptr)
+ ((((ulonglong)(intptr)ptr) + SIZEOF_INT - 1) / SIZEOF_INT * SIZEOF_INT);
+
+ DBUG_ASSERT(((ulonglong)(intptr)ptr) >= SIZEOF_INT);
+ if (end_words > ptr)
+ {
+ while (end > end_words && end[-1] == 0x20)
+ end--;
+ if (end[-1] == 0x20 && start_words < end_words)
+ while (end > start_words && ((unsigned *)end)[-1] == SPACE_INT)
+ end -= SIZEOF_INT;
+ }
+ }
+ while (end > ptr && end[-1] == 0x20)
+ end--;
+ return (end);
+}
+
#endif
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 345ecd5dd93..93b9ccebda2 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -524,4 +524,5 @@ uchar *net_store_length(uchar *pkg, ulonglong length);
#define MYSQL_STMT_HEADER 4
#define MYSQL_LONG_DATA_HEADER 6
+#define NOT_FIXED_DEC 31
#endif
diff --git a/include/violite.h b/include/violite.h
index 3f68ccde10f..0af7a566307 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -51,9 +51,6 @@ Vio* vio_new_win32shared_memory(HANDLE handle_file_map,
HANDLE event_client_wrote,
HANDLE event_client_read,
HANDLE event_conn_closed);
-size_t vio_read_pipe(Vio *vio, uchar * buf, size_t size);
-size_t vio_write_pipe(Vio *vio, const uchar * buf, size_t size);
-int vio_close_pipe(Vio * vio);
#else
#define HANDLE void *
#endif /* __WIN__ */
@@ -87,7 +84,8 @@ my_socket vio_fd(Vio*vio);
my_bool vio_peer_addr(Vio* vio, char *buf, uint16 *port);
/* Remotes in_addr */
void vio_in_addr(Vio *vio, struct in_addr *in);
-my_bool vio_poll_read(Vio *vio,uint timeout);
+my_bool vio_poll_read(Vio *vio, uint timeout);
+my_bool vio_is_connected(Vio *vio);
#ifdef HAVE_OPENSSL
#include <openssl/opensslv.h>
@@ -136,12 +134,6 @@ struct st_VioSSLFd
void free_vio_ssl_acceptor_fd(struct st_VioSSLFd *fd);
#endif /* HAVE_OPENSSL */
-#ifdef HAVE_SMEM
-size_t vio_read_shared_memory(Vio *vio, uchar * buf, size_t size);
-size_t vio_write_shared_memory(Vio *vio, const uchar * buf, size_t size);
-int vio_close_shared_memory(Vio * vio);
-#endif
-
void vio_end(void);
#ifdef __cplusplus
@@ -164,6 +156,8 @@ void vio_end(void);
#define vio_peer_addr(vio, buf, prt) (vio)->peer_addr(vio, buf, prt)
#define vio_in_addr(vio, in) (vio)->in_addr(vio, in)
#define vio_timeout(vio, which, seconds) (vio)->timeout(vio, which, seconds)
+#define vio_poll_read(vio, timeout) (vio)->poll_read(vio, timeout)
+#define vio_is_connected(vio) (vio)->is_connected(vio)
#endif /* !defined(DONT_MAP_VIO) */
/* This enumerator is used in parser - should be always visible */
@@ -208,6 +202,8 @@ struct st_vio
my_bool (*was_interrupted)(Vio*);
int (*vioclose)(Vio*);
void (*timeout)(Vio*, unsigned int which, unsigned int timeout);
+ my_bool (*poll_read)(Vio *vio, uint timeout);
+ my_bool (*is_connected)(Vio*);
#ifdef HAVE_OPENSSL
void *ssl_arg;
#endif
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 477830a6ebd..820c64cf84b 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -3478,10 +3478,7 @@ static void fetch_float_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
*/
char buff[MAX_DOUBLE_STRING_REP_LENGTH];
char *end;
- /* TODO: move this to a header shared between client and server. */
-#define NOT_FIXED_DEC 31
if (field->decimals >= NOT_FIXED_DEC)
-#undef NOT_FIXED_DEC
{
/*
DBL_DIG below is to ensure that the server and client has the same
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 1a078d0d0c6..9717c2fcfb6 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -138,6 +138,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
result= dispatch_command(command, thd, (char *) arg, arg_length);
thd->cur_data= 0;
+ thd->mysys_var= NULL;
if (!skip_check)
result= thd->is_error() ? -1 : 0;
diff --git a/mysql-test/r/alias.result b/mysql-test/r/alias.result
index 6f0315da234..3190e8994e5 100644
--- a/mysql-test/r/alias.result
+++ b/mysql-test/r/alias.result
@@ -73,3 +73,142 @@ UPDATE t1 SET t1.xstatus_vor = Greatest(t1.xstatus_vor,1) WHERE t1.aufnr =
"40004712" AND t1.plnfl = "000001" AND t1.vornr > "0010" ORDER BY t1.vornr
ASC LIMIT 1;
drop table t1;
+drop table if exists t1,t2,t3;
+create table t1 (a int, b int, c int);
+create table t2 (d int);
+create table t3 (a1 int, b1 int, c1 int);
+insert into t1 values(1,2,3);
+insert into t1 values(11,22,33);
+insert into t2 values(99);
+select t1.* as 'with_alias' from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias' from t1' at line 1
+select t2.* as 'with_alias' from t2;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias' from t2' at line 1
+select t1.*, t1.* as 'with_alias' from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias' from t1' at line 1
+select t1.* as 'with_alias', t1.* from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias', t1.* from t1' at line 1
+select t1.* as 'with_alias', t1.* as 'alias2' from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias', t1.* as 'alias2' from t1' at line 1
+select t1.* as 'with_alias', a, t1.* as 'alias2' from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias', a, t1.* as 'alias2' from t1' at line 1
+select a, t1.* as 'with_alias' from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias' from t1' at line 1
+select t1.* as 'with_alias', a from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias', a from t1' at line 1
+select a, t1.* as 'with_alias', b from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias', b from t1' at line 1
+select (select d from t2 where d > a), t1.* as 'with_alias' from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias' from t1' at line 1
+select t1.* as 'with_alias', (select a from t2 where d > a) from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias', (select a from t2 where d > a) from t1' at line 1
+select a as 'x', t1.* as 'with_alias' from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias' from t1' at line 1
+select t1.* as 'with_alias', a as 'x' from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias', a as 'x' from t1' at line 1
+select a as 'x', t1.* as 'with_alias', b as 'x' from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias', b as 'x' from t1' at line 1
+select (select d from t2 where d > a) as 'x', t1.* as 'with_alias' from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias' from t1' at line 1
+select t1.* as 'with_alias', (select a from t2 where d > a) as 'x' from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias', (select a from t2 where d > a) as 'x' from t1' at line 1
+select (select t2.* as 'x' from t2) from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'x' from t2) from t1' at line 1
+select a, (select t2.* as 'x' from t2) from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'x' from t2) from t1' at line 1
+select t1.*, (select t2.* as 'x' from t2) from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'x' from t2) from t1' at line 1
+insert into t3 select t1.* as 'with_alias' from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias' from t1' at line 1
+insert into t3 select t2.* as 'with_alias', 1, 2 from t2;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias', 1, 2 from t2' at line 1
+insert into t3 select t2.* as 'with_alias', d as 'x', d as 'z' from t2;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias', d as 'x', d as 'z' from t2' at line 1
+insert into t3 select t2.*, t2.* as 'with_alias', 3 from t2;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias', 3 from t2' at line 1
+create table t3 select t1.* as 'with_alias' from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias' from t1' at line 1
+create table t3 select t2.* as 'with_alias', 1, 2 from t2;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias', 1, 2 from t2' at line 1
+create table t3 select t2.* as 'with_alias', d as 'x', d as 'z' from t2;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias', d as 'x', d as 'z' from t2' at line 1
+create table t3 select t2.*, t2.* as 'with_alias', 3 from t2;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as 'with_alias', 3 from t2' at line 1
+select t1.* from t1;
+a b c
+1 2 3
+11 22 33
+select t2.* from t2;
+d
+99
+select t1.*, t1.* from t1;
+a b c a b c
+1 2 3 1 2 3
+11 22 33 11 22 33
+select t1.*, a, t1.* from t1;
+a b c a a b c
+1 2 3 1 1 2 3
+11 22 33 11 11 22 33
+select a, t1.* from t1;
+a a b c
+1 1 2 3
+11 11 22 33
+select t1.*, a from t1;
+a b c a
+1 2 3 1
+11 22 33 11
+select a, t1.*, b from t1;
+a a b c b
+1 1 2 3 2
+11 11 22 33 22
+select (select d from t2 where d > a), t1.* from t1;
+(select d from t2 where d > a) a b c
+99 1 2 3
+99 11 22 33
+select t1.*, (select a from t2 where d > a) from t1;
+a b c (select a from t2 where d > a)
+1 2 3 1
+11 22 33 11
+select a as 'x', t1.* from t1;
+x a b c
+1 1 2 3
+11 11 22 33
+select t1.*, a as 'x' from t1;
+a b c x
+1 2 3 1
+11 22 33 11
+select a as 'x', t1.*, b as 'x' from t1;
+x a b c x
+1 1 2 3 2
+11 11 22 33 22
+select (select d from t2 where d > a) as 'x', t1.* from t1;
+x a b c
+99 1 2 3
+99 11 22 33
+select t1.*, (select a from t2 where d > a) as 'x' from t1;
+a b c x
+1 2 3 1
+11 22 33 11
+select (select t2.* from t2) from t1;
+(select t2.* from t2)
+99
+99
+select a, (select t2.* from t2) from t1;
+a (select t2.* from t2)
+1 99
+11 99
+select t1.*, (select t2.* from t2) from t1;
+a b c (select t2.* from t2)
+1 2 3 99
+11 22 33 99
+insert into t3 select t1.* from t1;
+insert into t3 select t2.*, 1, 2 from t2;
+insert into t3 select t2.*, d as 'x', d as 'z' from t2;
+insert into t3 select t2.*, t2.*, 3 from t2;
+create table t4 select t1.* from t1;
+drop table t4;
+create table t4 select t2.*, 1, 2 from t2;
+drop table t4;
+create table t4 select t2.*, d as 'x', d as 'z' from t2;
+drop table t4;
+drop table t1,t2,t3;
diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result
index 0124a7da35a..03a3165aad0 100644
--- a/mysql-test/r/delete.result
+++ b/mysql-test/r/delete.result
@@ -259,8 +259,8 @@ ERROR 42S02: Unknown table 't2' in MULTI DELETE
DELETE FROM db1.t1 alias USING db1.t1, db2.t1 alias WHERE db1.t1.a = alias.a;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'alias USING db1.t1, db2.t1 alias WHERE db1.t1.a = alias.a' at line 1
DELETE FROM alias USING db1.t1, db2.t1 alias WHERE db1.t1.a = alias.a;
-ERROR 42S02: Unknown table 'alias' in MULTI DELETE
DELETE FROM db2.alias USING db1.t1, db2.t1 alias WHERE db1.t1.a = alias.a;
+ERROR 42S02: Unknown table 'alias' in MULTI DELETE
DELETE FROM t1 USING t1 WHERE a = 1;
SELECT * FROM t1;
a
@@ -279,6 +279,147 @@ ERROR 42000: Incorrect number of arguments for FUNCTION test.f1; expected 0, got
DROP TABLE t1;
DROP FUNCTION f1;
End of 5.0 tests
+DROP DATABASE IF EXISTS db1;
+DROP DATABASE IF EXISTS db2;
+DROP DATABASE IF EXISTS db3;
+DROP DATABASE IF EXISTS db4;
+DROP TABLE IF EXISTS t1, t2;
+DROP PROCEDURE IF EXISTS count;
+USE test;
+CREATE DATABASE db1;
+CREATE DATABASE db2;
+CREATE TABLE db1.t1 (a INT, b INT);
+INSERT INTO db1.t1 VALUES (1,1),(2,2),(3,3);
+CREATE TABLE db1.t2 AS SELECT * FROM db1.t1;
+CREATE TABLE db2.t1 AS SELECT * FROM db1.t2;
+CREATE TABLE db2.t2 AS SELECT * FROM db2.t1;
+CREATE TABLE t1 AS SELECT * FROM db2.t2;
+CREATE TABLE t2 AS SELECT * FROM t1;
+CREATE PROCEDURE count_rows()
+BEGIN
+SELECT COUNT(*) AS "COUNT(db1.t1)" FROM db1.t1;
+SELECT COUNT(*) AS "COUNT(db1.t2)" FROM db1.t2;
+SELECT COUNT(*) AS "COUNT(db2.t1)" FROM db2.t1;
+SELECT COUNT(*) AS "COUNT(db2.t2)" FROM db2.t2;
+SELECT COUNT(*) AS "COUNT(test.t1)" FROM test.t1;
+SELECT COUNT(*) AS "COUNT(test.t2)" FROM test.t2;
+END|
+CREATE DATABASE db3;
+USE db3;
+DROP DATABASE db3;
+SELECT * FROM t1;
+ERROR 3D000: No database selected
+DELETE a1,a2 FROM db1.t1, db2.t2;
+ERROR 3D000: No database selected
+DELETE a1,a2 FROM db1.t1, db2.t2;
+ERROR 3D000: No database selected
+DELETE a1,a2 FROM db1.t1 AS a1, db2.t2;
+ERROR 3D000: No database selected
+DELETE a1,a2 FROM db1.t1, db2.t2 AS a2;
+ERROR 3D000: No database selected
+DELETE a1,a2 FROM db3.t1 AS a1, db4.t2 AS a2;
+ERROR 3D000: No database selected
+DELETE a1,a2 FROM db3.t1 AS a1, db4.t2 AS a2;
+ERROR 3D000: No database selected
+DELETE FROM a1,a2 USING db1.t1, db2.t2;
+ERROR 3D000: No database selected
+DELETE FROM a1,a2 USING db1.t1, db2.t2;
+ERROR 3D000: No database selected
+DELETE FROM a1,a2 USING db1.t1 AS a1, db2.t2;
+ERROR 3D000: No database selected
+DELETE FROM a1,a2 USING db1.t1, db2.t2 AS a2;
+ERROR 3D000: No database selected
+DELETE FROM a1,a2 USING db3.t1 AS a1, db4.t2 AS a2;
+ERROR 3D000: No database selected
+DELETE FROM a1,a2 USING db3.t1 AS a1, db4.t2 AS a2;
+ERROR 3D000: No database selected
+DELETE a1 FROM db1.t1 AS a1, db2.t2 AS a1;
+ERROR 3D000: No database selected
+DELETE a1 FROM db1.a1, db2.t2 AS a1;
+ERROR 3D000: No database selected
+DELETE a1 FROM a1, db1.t1 AS a1;
+ERROR 3D000: No database selected
+DELETE t1 FROM db1.t1, db2.t1 AS a1;
+ERROR 3D000: No database selected
+DELETE t1 FROM db1.t1 AS a1, db2.t1 AS a2;
+ERROR 3D000: No database selected
+DELETE t1 FROM db1.t1, db2.t1;
+ERROR 3D000: No database selected
+USE test;
+DELETE a1,a2 FROM db1.t1, db2.t2;
+ERROR 42S02: Unknown table 'a1' in MULTI DELETE
+DELETE a1,a2 FROM db1.t1, db2.t2;
+ERROR 42S02: Unknown table 'a1' in MULTI DELETE
+DELETE a1,a2 FROM db1.t1 AS a1, db2.t2;
+ERROR 42S02: Unknown table 'a2' in MULTI DELETE
+DELETE a1,a2 FROM db1.t1, db2.t2 AS a2;
+ERROR 42S02: Unknown table 'a1' in MULTI DELETE
+DELETE a1,a2 FROM db3.t1 AS a1, db4.t2 AS a2;
+ERROR 42S02: Table 'db3.t1' doesn't exist
+DELETE a1,a2 FROM db3.t1 AS a1, db4.t2 AS a2;
+ERROR 42S02: Table 'db3.t1' doesn't exist
+DELETE FROM a1,a2 USING db1.t1, db2.t2;
+ERROR 42S02: Unknown table 'a1' in MULTI DELETE
+DELETE FROM a1,a2 USING db1.t1, db2.t2;
+ERROR 42S02: Unknown table 'a1' in MULTI DELETE
+DELETE FROM a1,a2 USING db1.t1 AS a1, db2.t2;
+ERROR 42S02: Unknown table 'a2' in MULTI DELETE
+DELETE FROM a1,a2 USING db1.t1, db2.t2 AS a2;
+ERROR 42S02: Unknown table 'a1' in MULTI DELETE
+DELETE FROM a1,a2 USING db3.t1 AS a1, db4.t2 AS a2;
+ERROR 42S02: Table 'db3.t1' doesn't exist
+DELETE FROM a1,a2 USING db3.t1 AS a1, db4.t2 AS a2;
+ERROR 42S02: Table 'db3.t1' doesn't exist
+DELETE a1 FROM db1.t1 AS a1, db2.t2 AS a1;
+ERROR 42000: Not unique table/alias: 'a1'
+DELETE a1 FROM db1.a1, db2.t2 AS a1;
+ERROR 42S02: Table 'db1.a1' doesn't exist
+DELETE a1 FROM a1, db1.t1 AS a1;
+ERROR 42000: Not unique table/alias: 'a1'
+DELETE t1 FROM db1.t1, db2.t1 AS a1;
+ERROR 42S02: Unknown table 't1' in MULTI DELETE
+DELETE t1 FROM db1.t1 AS a1, db2.t1 AS a2;
+ERROR 42S02: Unknown table 't1' in MULTI DELETE
+DELETE t1 FROM db1.t1, db2.t1;
+ERROR 42S02: Unknown table 't1' in MULTI DELETE
+DELETE t1 FROM db1.t2 AS t1, db2.t2 AS t2 WHERE t2.a = 1 AND t1.a = t2.a;
+SELECT ROW_COUNT();
+ROW_COUNT()
+1
+CALL count_rows();
+COUNT(db1.t1)
+3
+COUNT(db1.t2)
+2
+COUNT(db2.t1)
+3
+COUNT(db2.t2)
+3
+COUNT(test.t1)
+3
+COUNT(test.t2)
+3
+DELETE a1, a2 FROM db2.t1 AS a1, t2 AS a2 WHERE a1.a = 2 AND a2.a = 2;
+SELECT ROW_COUNT();
+ROW_COUNT()
+2
+CALL count_rows();
+COUNT(db1.t1)
+3
+COUNT(db1.t2)
+2
+COUNT(db2.t1)
+2
+COUNT(db2.t2)
+3
+COUNT(test.t1)
+3
+COUNT(test.t2)
+2
+DROP DATABASE db1;
+DROP DATABASE db2;
+DROP PROCEDURE count_rows;
+DROP TABLE t1, t2;
#
# Bug#46958: Assertion in Diagnostics_area::set_ok_status, trigger,
# merge table
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index 80f04ffd455..53cd89c13c1 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -277,7 +277,7 @@ select * from t1;
N M
3 0
delete P1.*,p2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS p2 ON P1.N = p2.N;
-ERROR 42S02: Unknown table 'p2' in MULTI DELETE
+ERROR HY000: The target table p2 of the DELETE is not updatable
delete P1.* from `t1` AS P1 INNER JOIN (SELECT aaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
ERROR 42S22: Unknown column 'aaa' in 'field list'
drop table t1;
diff --git a/mysql-test/r/dirty_close.result b/mysql-test/r/dirty_close.result
index b49b72f1b95..f7012ff9c01 100644
--- a/mysql-test/r/dirty_close.result
+++ b/mysql-test/r/dirty_close.result
@@ -7,3 +7,13 @@ n
2
3
DROP TABLE t1;
+SELECT GET_LOCK("dangling", 0);
+GET_LOCK("dangling", 0)
+1
+SELECT GET_LOCK('dangling', 3600);;
+SELECT GET_LOCK('dangling', 3600);;
+SELECT RELEASE_LOCK('dangling');
+RELEASE_LOCK('dangling')
+1
+GET_LOCK('dangling', 3600)
+1
diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result
index 87b88692a34..2d6154cd1f7 100644
--- a/mysql-test/r/func_sapdb.result
+++ b/mysql-test/r/func_sapdb.result
@@ -282,3 +282,33 @@ TIMEDIFF(TIME('17:59:00'),TIME('17:00:00')),
TIMEDIFF(TIME('17:00:00'),TIME('17:59:00'));
1Eq 1NEq1 1NEq2 2Eq 2NEq1 2NEq2 3Eq 3NEq1 3NEq2 Time0 Time00 Literal0000 TIMEDIFF(TIME('17:59:00'),TIME('17:00:00')) TIMEDIFF(TIME('17:00:00'),TIME('17:59:00'))
1 0 0 1 0 0 1 0 0 00:00:00 00:00:00 00:00:00 00:59:00 -00:59:00
+SELECT sec_to_time(3020399)=TIME('838:59:59');
+sec_to_time(3020399)=TIME('838:59:59')
+1
+SELECT sec_to_time(-3020399)=TIME('-838:59:59');
+sec_to_time(-3020399)=TIME('-838:59:59')
+1
+SELECT sec_to_time(-3020399)='-838:59:59';
+sec_to_time(-3020399)='-838:59:59'
+1
+SELECT time(sec_to_time(-3020399))=TIME('-838:59:59');
+time(sec_to_time(-3020399))=TIME('-838:59:59')
+1
+SELECT time(sec_to_time(-3020399))=TIME('-838:59:58');
+time(sec_to_time(-3020399))=TIME('-838:59:58')
+0
+SELECT maketime(-1,0,1)='-01:00:01';
+maketime(-1,0,1)='-01:00:01'
+1
+SELECT TIME(maketime(-1,0,1))=CAST('-01:00:01' AS TIME);
+TIME(maketime(-1,0,1))=CAST('-01:00:01' AS TIME)
+1
+SELECT maketime(-1,0,1)=CAST('-01:00:01' AS TIME);
+maketime(-1,0,1)=CAST('-01:00:01' AS TIME)
+1
+SELECT maketime(1,0,1)=CAST('01:00:01' AS TIME);
+maketime(1,0,1)=CAST('01:00:01' AS TIME)
+1
+SELECT maketime(1,0,1)=CAST('01:00:02' AS TIME);
+maketime(1,0,1)=CAST('01:00:02' AS TIME)
+0
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index 5e72b69c41d..59527e0b418 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -1301,6 +1301,12 @@ SELECT '2008-02-18' + INTERVAL 1 FRAC_SECOND;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FRAC_SECOND' at line 1
SELECT '2008-02-18' - INTERVAL 1 FRAC_SECOND;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FRAC_SECOND' at line 1
+select date_add('1000-01-01 00:00:00', interval '1.03:02:01.05' day_microsecond);
+date_add('1000-01-01 00:00:00', interval '1.03:02:01.05' day_microsecond)
+1000-01-02 03:02:01.050000
+select date_add('1000-01-01 00:00:00', interval '1.02' day_microsecond);
+date_add('1000-01-01 00:00:00', interval '1.02' day_microsecond)
+1000-01-01 00:00:01.020000
End of 5.0 tests
select date_sub("0050-01-01 00:00:01",INTERVAL 2 SECOND);
date_sub("0050-01-01 00:00:01",INTERVAL 2 SECOND)
diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result
index 70e93c3e01f..ee64f60c759 100644
--- a/mysql-test/r/mysql.result
+++ b/mysql-test/r/mysql.result
@@ -201,6 +201,202 @@ COUNT (*)
ERROR 2005 (HY000) at line 1: Unknown MySQL server host 'invalid_hostname' (errno)
End of 5.0 tests
WARNING: --server-arg option not supported in this configuration.
+*************************** 1. row ***************************
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
+1: 1
+2: 2
+3: 3
+4: 4
+5: 5
+6: 6
+7: 7
+8: 8
+9: 9
+0: 0
++---+
+| 1 |
++---+
+| 1 |
++---+
Warning (Code 1286): Unknown table engine 'nonexistent'
Warning (Code 1266): Using storage engine MyISAM for table 't2'
Warning (Code 1286): Unknown table engine 'nonexistent2'
diff --git a/mysql-test/r/partition_sync.result b/mysql-test/r/partition_sync.result
new file mode 100644
index 00000000000..31cf0569464
--- /dev/null
+++ b/mysql-test/r/partition_sync.result
@@ -0,0 +1,25 @@
+#
+# Bug #43867 ALTER TABLE on a partitioned table
+# causes unnecessary deadlocks
+#
+CREATE TABLE t1 (a int) PARTITION BY RANGE (a)
+(PARTITION p0 VALUES LESS THAN (1),
+PARTITION p1 VALUES LESS THAN (2));
+INSERT INTO t1 VALUES (0),(1);
+# Connection 2
+BEGIN;
+SELECT * FROM t1;
+a
+0
+1
+# Connection 1
+ALTER TABLE t1 DROP PARTITION p3;
+ERROR HY000: Error in list of partitions to DROP
+# Connection 2
+# This failed with deadlock and should not do so.
+SELECT * FROM t1;
+a
+0
+1
+# Connection 1
+DROP TABLE t1;
diff --git a/mysql-test/r/rpl_mysqldump_slave.result b/mysql-test/r/rpl_mysqldump_slave.result
new file mode 100644
index 00000000000..158a43a658c
--- /dev/null
+++ b/mysql-test/r/rpl_mysqldump_slave.result
@@ -0,0 +1,17 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+#
+# New --dump-slave, --apply-slave-statements functionality
+#
+use test;
+CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=107;
+STOP SLAVE;
+CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=107;
+START SLAVE;
+STOP SLAVE;
+CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT='MASTER_MYPORT', MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=107;
+START SLAVE;
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
index b3968ea7eb6..499506957fa 100644
--- a/mysql-test/r/sp-error.result
+++ b/mysql-test/r/sp-error.result
@@ -1659,6 +1659,18 @@ begin
declare continue handler for sqlstate '00000' set @x=0;
end$$
ERROR 42000: Bad SQLSTATE: '00000'
+drop procedure if exists p1;
+set @old_recursion_depth = @@max_sp_recursion_depth;
+set @@max_sp_recursion_depth = 255;
+create procedure p1(a int)
+begin
+declare continue handler for 1436 -- ER_STACK_OVERRUN_NEED_MORE
+select 'exception';
+call p1(a+1);
+end|
+call p1(1);
+set @@max_sp_recursion_depth = @old_recursion_depth;
+drop procedure p1;
LOAD DATA INFILE '../../tmp/proc.txt' INTO TABLE mysql.proc;
CREATE TABLE t1 (a INT, b INT);
INSERT INTO t1 VALUES (1,1), (2,2);
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 45dac2f5523..26ba2af8f68 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -6941,6 +6941,101 @@ SELECT * FROM t1 WHERE a = f1();
ERROR 42S02: Table 'test.t_non_existing' doesn't exist
DROP FUNCTION f1;
DROP TABLE t1;
+DROP PROCEDURE IF EXISTS p1;
+CREATE PROCEDURE p1(a INT, b CHAR)
+BEGIN
+IF a > 0 THEN
+CALL p1(a-1, 'ab');
+ELSE
+SELECT 1;
+END IF;
+END|
+SET @save_max_sp_recursion= @@max_sp_recursion_depth;
+SET @@max_sp_recursion_depth= 5;
+CALL p1(4, 'a');
+1
+1
+Warnings:
+Warning 1265 Data truncated for column 'b' at row 1
+Warning 1265 Data truncated for column 'b' at row 1
+Warning 1265 Data truncated for column 'b' at row 1
+Warning 1265 Data truncated for column 'b' at row 1
+SET @@max_sp_recursion_depth= @save_max_sp_recursion;
+DROP PROCEDURE p1;
+DROP PROCEDURE IF EXISTS p1;
+CREATE PROCEDURE p1(a CHAR)
+BEGIN
+SELECT 1;
+SELECT CAST('10 ' as UNSIGNED INTEGER);
+SELECT 1;
+END|
+CALL p1('data truncated parameter');
+1
+1
+CAST('10 ' as UNSIGNED INTEGER)
+10
+1
+1
+Warnings:
+Warning 1265 Data truncated for column 'a' at row 1
+Warning 1292 Truncated incorrect INTEGER value: '10 '
+DROP PROCEDURE p1;
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+DROP PROCEDURE IF EXISTS p3;
+DROP PROCEDURE IF EXISTS p4;
+CREATE PROCEDURE p1()
+CALL p2()|
+CREATE PROCEDURE p2()
+CALL p3()|
+CREATE PROCEDURE p3()
+CALL p4()|
+CREATE PROCEDURE p4()
+BEGIN
+SELECT 1;
+SELECT CAST('10 ' as UNSIGNED INTEGER);
+SELECT 2;
+END|
+CALL p1();
+1
+1
+CAST('10 ' as UNSIGNED INTEGER)
+10
+2
+2
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: '10 '
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+DROP PROCEDURE p3;
+DROP PROCEDURE p4;
+DROP FUNCTION IF EXISTS f1;
+DROP FUNCTION IF EXISTS f2;
+DROP FUNCTION IF EXISTS f3;
+DROP FUNCTION IF EXISTS f4;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a CHAR(2));
+INSERT INTO t1 VALUES ('aa');
+CREATE FUNCTION f1() RETURNS CHAR
+RETURN (SELECT f2())|
+CREATE FUNCTION f2() RETURNS CHAR
+RETURN (SELECT f3())|
+CREATE FUNCTION f3() RETURNS CHAR
+RETURN (SELECT f4())|
+CREATE FUNCTION f4() RETURNS CHAR
+BEGIN
+RETURN (SELECT a FROM t1);
+END|
+SELECT f1();
+f1()
+a
+Warnings:
+Warning 1265 Data truncated for column 'f4()' at row 1
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+DROP FUNCTION f3;
+DROP FUNCTION f4;
+DROP TABLE t1;
#
# Bug#34197: CREATE PROCEDURE fails when COMMENT truncated in non
# strict SQL mode
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index 1a6494e03ad..47b50b233b3 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -2115,3 +2115,50 @@ s1
DELETE FROM t1;
DROP TABLE t1;
DROP TEMPORARY TABLE t2;
+DROP TRIGGER IF EXISTS trg1;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a INT);
+CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+DECLARE a CHAR;
+SELECT 'ab' INTO a;
+SELECT 'ab' INTO a;
+SELECT 'a' INTO a;
+END|
+INSERT INTO t1 VALUES (1);
+Warnings:
+Warning 1265 Data truncated for column 'a' at row 1
+DROP TRIGGER trg1;
+DROP TABLE t1;
+DROP TRIGGER IF EXISTS trg1;
+DROP TRIGGER IF EXISTS trg2;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a INT);
+CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+DECLARE trg1 CHAR;
+SELECT 'ab' INTO trg1;
+END|
+CREATE TRIGGER trg2 AFTER INSERT ON t1 FOR EACH ROW
+BEGIN
+DECLARE trg2 CHAR;
+SELECT 'ab' INTO trg2;
+END|
+INSERT INTO t1 VALUES (0);
+Warnings:
+Warning 1265 Data truncated for column 'trg1' at row 1
+Warning 1265 Data truncated for column 'trg2' at row 1
+SELECT * FROM t1;
+a
+0
+SHOW WARNINGS;
+Level Code Message
+INSERT INTO t1 VALUES (1),(2);
+Warnings:
+Warning 1265 Data truncated for column 'trg1' at row 1
+Warning 1265 Data truncated for column 'trg2' at row 1
+Warning 1265 Data truncated for column 'trg1' at row 1
+Warning 1265 Data truncated for column 'trg2' at row 1
+DROP TRIGGER trg1;
+DROP TRIGGER trg2;
+DROP TABLE t1;
diff --git a/mysql-test/r/type_time.result b/mysql-test/r/type_time.result
index e4b90196c2d..a5880f2b452 100644
--- a/mysql-test/r/type_time.result
+++ b/mysql-test/r/type_time.result
@@ -85,6 +85,7 @@ sec_to_time(time_to_sec(t))
13:00:00
09:00:00
drop table t1;
+End of 4.1 tests
select cast('100:55:50' as time) < cast('24:00:00' as time);
cast('100:55:50' as time) < cast('24:00:00' as time)
0
@@ -138,3 +139,27 @@ CAST(c AS TIME)
00:00:00
DROP TABLE t1;
End of 5.0 tests
+CREATE TABLE t1 (f1 TIME);
+INSERT INTO t1 VALUES ('24:00:00');
+SELECT '24:00:00' = (SELECT f1 FROM t1);
+'24:00:00' = (SELECT f1 FROM t1)
+1
+SELECT CAST('24:00:00' AS TIME) = (SELECT f1 FROM t1);
+CAST('24:00:00' AS TIME) = (SELECT f1 FROM t1)
+1
+SELECT CAST('-24:00:00' AS TIME) = (SELECT f1 FROM t1);
+CAST('-24:00:00' AS TIME) = (SELECT f1 FROM t1)
+0
+TRUNCATE t1;
+INSERT INTO t1 VALUES ('-24:00:00');
+SELECT CAST('24:00:00' AS TIME) = (SELECT f1 FROM t1);
+CAST('24:00:00' AS TIME) = (SELECT f1 FROM t1)
+0
+SELECT CAST('-24:00:00' AS TIME) = (SELECT f1 FROM t1);
+CAST('-24:00:00' AS TIME) = (SELECT f1 FROM t1)
+1
+SELECT '-24:00:00' = (SELECT f1 FROM t1);
+'-24:00:00' = (SELECT f1 FROM t1)
+1
+DROP TABLE t1;
+End of 6.0 tests
diff --git a/mysql-test/suite/rpl/r/rpl_multi_delete2.result b/mysql-test/suite/rpl/r/rpl_multi_delete2.result
index 87abe60b268..8e6a6a3d4d0 100644
--- a/mysql-test/suite/rpl/r/rpl_multi_delete2.result
+++ b/mysql-test/suite/rpl/r/rpl_multi_delete2.result
@@ -16,7 +16,7 @@ DELETE alias FROM a alias WHERE alias.i=1;
SELECT * FROM a;
i
insert into a values(2),(3);
-delete a alias FROM a alias where alias.i=2;
+delete alias FROM a alias where alias.i=2;
select * from a;
i
3
diff --git a/mysql-test/suite/rpl/t/rpl_multi_delete2.test b/mysql-test/suite/rpl/t/rpl_multi_delete2.test
index 81379d4056b..e91fad1872a 100644
--- a/mysql-test/suite/rpl/t/rpl_multi_delete2.test
+++ b/mysql-test/suite/rpl/t/rpl_multi_delete2.test
@@ -25,7 +25,7 @@ INSERT INTO a VALUES(1);
DELETE alias FROM a alias WHERE alias.i=1;
SELECT * FROM a;
insert into a values(2),(3);
-delete a alias FROM a alias where alias.i=2;
+delete alias FROM a alias where alias.i=2;
select * from a;
save_master_pos;
connection slave;
diff --git a/mysql-test/suite/sys_vars/r/group_concat_max_len_func.result b/mysql-test/suite/sys_vars/r/group_concat_max_len_func.result
index 52d67b8d274..f04dfee583d 100644
--- a/mysql-test/suite/sys_vars/r/group_concat_max_len_func.result
+++ b/mysql-test/suite/sys_vars/r/group_concat_max_len_func.result
@@ -41,7 +41,10 @@ id rollno GROUP_CONCAT(name)
4 3 Reco
7 4 Reco
Warnings:
-Warning 1260 4 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 1 was cut by GROUP_CONCAT()
+Warning 1260 Row 2 was cut by GROUP_CONCAT()
+Warning 1260 Row 3 was cut by GROUP_CONCAT()
+Warning 1260 Row 4 was cut by GROUP_CONCAT()
## Changing session value of variable and verifying its behavior, ##
## warning should come here ##
SET @@session.group_concat_max_len = 10;
@@ -52,7 +55,9 @@ id rollno GROUP_CONCAT(name)
4 3 Record_4,R
7 4 Record_7,R
Warnings:
-Warning 1260 3 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 2 was cut by GROUP_CONCAT()
+Warning 1260 Row 5 was cut by GROUP_CONCAT()
+Warning 1260 Row 7 was cut by GROUP_CONCAT()
'#--------------------FN_DYNVARS_034_03-------------------------#'
## Connecting with new connection test_con2 ##
## Verifying initial value of variable. It should be 4 ##
@@ -71,7 +76,7 @@ id rollno GROUP_CONCAT(name)
4 3 Record_4,Record_6
7 4 Record_7,Record_8
Warnings:
-Warning 1260 1 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 3 was cut by GROUP_CONCAT()
'#--------------------FN_DYNVARS_034_04-------------------------#'
## Setting session value of variable to 26. No warning should appear here ##
## because the value after concatination is less than 30 ##
diff --git a/mysql-test/t/alias.test b/mysql-test/t/alias.test
index 6546581eef2..0e2d57598e2 100644
--- a/mysql-test/t/alias.test
+++ b/mysql-test/t/alias.test
@@ -86,3 +86,132 @@ ASC LIMIT 1;
drop table t1;
# End of 4.1 tests
+
+#
+# Bug#27249 table_wild with alias: select t1.* as something
+#
+
+--disable_warnings
+drop table if exists t1,t2,t3;
+--enable_warnings
+
+create table t1 (a int, b int, c int);
+create table t2 (d int);
+create table t3 (a1 int, b1 int, c1 int);
+insert into t1 values(1,2,3);
+insert into t1 values(11,22,33);
+insert into t2 values(99);
+
+# Invalid queries with alias on wild
+--error ER_PARSE_ERROR
+select t1.* as 'with_alias' from t1;
+--error ER_PARSE_ERROR
+select t2.* as 'with_alias' from t2;
+--error ER_PARSE_ERROR
+select t1.*, t1.* as 'with_alias' from t1;
+--error ER_PARSE_ERROR
+select t1.* as 'with_alias', t1.* from t1;
+--error ER_PARSE_ERROR
+select t1.* as 'with_alias', t1.* as 'alias2' from t1;
+--error ER_PARSE_ERROR
+select t1.* as 'with_alias', a, t1.* as 'alias2' from t1;
+
+# other fields without alias
+--error ER_PARSE_ERROR
+select a, t1.* as 'with_alias' from t1;
+--error ER_PARSE_ERROR
+select t1.* as 'with_alias', a from t1;
+--error ER_PARSE_ERROR
+select a, t1.* as 'with_alias', b from t1;
+--error ER_PARSE_ERROR
+select (select d from t2 where d > a), t1.* as 'with_alias' from t1;
+--error ER_PARSE_ERROR
+select t1.* as 'with_alias', (select a from t2 where d > a) from t1;
+
+# other fields with alias
+--error ER_PARSE_ERROR
+select a as 'x', t1.* as 'with_alias' from t1;
+--error ER_PARSE_ERROR
+select t1.* as 'with_alias', a as 'x' from t1;
+--error ER_PARSE_ERROR
+select a as 'x', t1.* as 'with_alias', b as 'x' from t1;
+--error ER_PARSE_ERROR
+select (select d from t2 where d > a) as 'x', t1.* as 'with_alias' from t1;
+--error ER_PARSE_ERROR
+select t1.* as 'with_alias', (select a from t2 where d > a) as 'x' from t1;
+
+# some more subquery
+--error ER_PARSE_ERROR
+select (select t2.* as 'x' from t2) from t1;
+--error ER_PARSE_ERROR
+select a, (select t2.* as 'x' from t2) from t1;
+--error ER_PARSE_ERROR
+select t1.*, (select t2.* as 'x' from t2) from t1;
+
+# insert
+--error ER_PARSE_ERROR
+insert into t3 select t1.* as 'with_alias' from t1;
+--error ER_PARSE_ERROR
+insert into t3 select t2.* as 'with_alias', 1, 2 from t2;
+--error ER_PARSE_ERROR
+insert into t3 select t2.* as 'with_alias', d as 'x', d as 'z' from t2;
+--error ER_PARSE_ERROR
+insert into t3 select t2.*, t2.* as 'with_alias', 3 from t2;
+
+# create
+--error ER_PARSE_ERROR
+create table t3 select t1.* as 'with_alias' from t1;
+--error ER_PARSE_ERROR
+create table t3 select t2.* as 'with_alias', 1, 2 from t2;
+--error ER_PARSE_ERROR
+create table t3 select t2.* as 'with_alias', d as 'x', d as 'z' from t2;
+--error ER_PARSE_ERROR
+create table t3 select t2.*, t2.* as 'with_alias', 3 from t2;
+
+#
+# Valid queries without alias on wild
+# (proof the above fail due to invalid aliasing)
+#
+
+select t1.* from t1;
+select t2.* from t2;
+select t1.*, t1.* from t1;
+select t1.*, a, t1.* from t1;
+
+# other fields without alias
+select a, t1.* from t1;
+select t1.*, a from t1;
+select a, t1.*, b from t1;
+select (select d from t2 where d > a), t1.* from t1;
+select t1.*, (select a from t2 where d > a) from t1;
+
+# other fields with alias
+select a as 'x', t1.* from t1;
+select t1.*, a as 'x' from t1;
+select a as 'x', t1.*, b as 'x' from t1;
+select (select d from t2 where d > a) as 'x', t1.* from t1;
+select t1.*, (select a from t2 where d > a) as 'x' from t1;
+
+# some more subquery
+select (select t2.* from t2) from t1;
+select a, (select t2.* from t2) from t1;
+select t1.*, (select t2.* from t2) from t1;
+
+# insert
+insert into t3 select t1.* from t1;
+insert into t3 select t2.*, 1, 2 from t2;
+insert into t3 select t2.*, d as 'x', d as 'z' from t2;
+insert into t3 select t2.*, t2.*, 3 from t2;
+
+# create
+create table t4 select t1.* from t1;
+drop table t4;
+create table t4 select t2.*, 1, 2 from t2;
+drop table t4;
+create table t4 select t2.*, d as 'x', d as 'z' from t2;
+drop table t4;
+
+# end
+drop table t1,t2,t3;
+
+# End of 5.2 tests
diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test
index d77f5eb128b..81cadb432af 100644
--- a/mysql-test/t/delete.test
+++ b/mysql-test/t/delete.test
@@ -265,8 +265,8 @@ DELETE FROM t1, alias USING t1, t2 alias WHERE t1.a = alias.a;
DELETE FROM t1, t2 USING t1, t2 alias WHERE t1.a = alias.a;
--error ER_PARSE_ERROR
DELETE FROM db1.t1 alias USING db1.t1, db2.t1 alias WHERE db1.t1.a = alias.a;
---error ER_UNKNOWN_TABLE
DELETE FROM alias USING db1.t1, db2.t1 alias WHERE db1.t1.a = alias.a;
+--error ER_UNKNOWN_TABLE
DELETE FROM db2.alias USING db1.t1, db2.t1 alias WHERE db1.t1.a = alias.a;
DELETE FROM t1 USING t1 WHERE a = 1;
SELECT * FROM t1;
@@ -293,6 +293,159 @@ DROP FUNCTION f1;
--echo End of 5.0 tests
+#
+# Bug#27525: table not found when using multi-table-deletes with aliases over
+# several databas
+# Bug#21148: MULTI-DELETE fails to resolve a table by alias if it's from a
+# different database
+#
+
+--disable_warnings
+DROP DATABASE IF EXISTS db1;
+DROP DATABASE IF EXISTS db2;
+DROP DATABASE IF EXISTS db3;
+DROP DATABASE IF EXISTS db4;
+DROP TABLE IF EXISTS t1, t2;
+DROP PROCEDURE IF EXISTS count;
+--enable_warnings
+USE test;
+CREATE DATABASE db1;
+CREATE DATABASE db2;
+
+CREATE TABLE db1.t1 (a INT, b INT);
+INSERT INTO db1.t1 VALUES (1,1),(2,2),(3,3);
+CREATE TABLE db1.t2 AS SELECT * FROM db1.t1;
+CREATE TABLE db2.t1 AS SELECT * FROM db1.t2;
+CREATE TABLE db2.t2 AS SELECT * FROM db2.t1;
+CREATE TABLE t1 AS SELECT * FROM db2.t2;
+CREATE TABLE t2 AS SELECT * FROM t1;
+
+delimiter |;
+CREATE PROCEDURE count_rows()
+BEGIN
+ SELECT COUNT(*) AS "COUNT(db1.t1)" FROM db1.t1;
+ SELECT COUNT(*) AS "COUNT(db1.t2)" FROM db1.t2;
+ SELECT COUNT(*) AS "COUNT(db2.t1)" FROM db2.t1;
+ SELECT COUNT(*) AS "COUNT(db2.t2)" FROM db2.t2;
+ SELECT COUNT(*) AS "COUNT(test.t1)" FROM test.t1;
+ SELECT COUNT(*) AS "COUNT(test.t2)" FROM test.t2;
+END|
+delimiter ;|
+
+#
+# Testing without a selected database
+#
+
+CREATE DATABASE db3;
+USE db3;
+DROP DATABASE db3;
+--error ER_NO_DB_ERROR
+SELECT * FROM t1;
+
+# Detect missing table references
+
+--error ER_NO_DB_ERROR
+DELETE a1,a2 FROM db1.t1, db2.t2;
+--error ER_NO_DB_ERROR
+DELETE a1,a2 FROM db1.t1, db2.t2;
+--error ER_NO_DB_ERROR
+DELETE a1,a2 FROM db1.t1 AS a1, db2.t2;
+--error ER_NO_DB_ERROR
+DELETE a1,a2 FROM db1.t1, db2.t2 AS a2;
+--error ER_NO_DB_ERROR
+DELETE a1,a2 FROM db3.t1 AS a1, db4.t2 AS a2;
+--error ER_NO_DB_ERROR
+DELETE a1,a2 FROM db3.t1 AS a1, db4.t2 AS a2;
+
+--error ER_NO_DB_ERROR
+DELETE FROM a1,a2 USING db1.t1, db2.t2;
+--error ER_NO_DB_ERROR
+DELETE FROM a1,a2 USING db1.t1, db2.t2;
+--error ER_NO_DB_ERROR
+DELETE FROM a1,a2 USING db1.t1 AS a1, db2.t2;
+--error ER_NO_DB_ERROR
+DELETE FROM a1,a2 USING db1.t1, db2.t2 AS a2;
+--error ER_NO_DB_ERROR
+DELETE FROM a1,a2 USING db3.t1 AS a1, db4.t2 AS a2;
+--error ER_NO_DB_ERROR
+DELETE FROM a1,a2 USING db3.t1 AS a1, db4.t2 AS a2;
+
+# Ambiguous table references
+
+--error ER_NO_DB_ERROR
+DELETE a1 FROM db1.t1 AS a1, db2.t2 AS a1;
+--error ER_NO_DB_ERROR
+DELETE a1 FROM db1.a1, db2.t2 AS a1;
+--error ER_NO_DB_ERROR
+DELETE a1 FROM a1, db1.t1 AS a1;
+--error ER_NO_DB_ERROR
+DELETE t1 FROM db1.t1, db2.t1 AS a1;
+--error ER_NO_DB_ERROR
+DELETE t1 FROM db1.t1 AS a1, db2.t1 AS a2;
+--error ER_NO_DB_ERROR
+DELETE t1 FROM db1.t1, db2.t1;
+
+# Test all again, now with a selected database
+
+USE test;
+
+# Detect missing table references
+
+--error ER_UNKNOWN_TABLE
+DELETE a1,a2 FROM db1.t1, db2.t2;
+--error ER_UNKNOWN_TABLE
+DELETE a1,a2 FROM db1.t1, db2.t2;
+--error ER_UNKNOWN_TABLE
+DELETE a1,a2 FROM db1.t1 AS a1, db2.t2;
+--error ER_UNKNOWN_TABLE
+DELETE a1,a2 FROM db1.t1, db2.t2 AS a2;
+--error ER_NO_SUCH_TABLE
+DELETE a1,a2 FROM db3.t1 AS a1, db4.t2 AS a2;
+--error ER_NO_SUCH_TABLE
+DELETE a1,a2 FROM db3.t1 AS a1, db4.t2 AS a2;
+
+--error ER_UNKNOWN_TABLE
+DELETE FROM a1,a2 USING db1.t1, db2.t2;
+--error ER_UNKNOWN_TABLE
+DELETE FROM a1,a2 USING db1.t1, db2.t2;
+--error ER_UNKNOWN_TABLE
+DELETE FROM a1,a2 USING db1.t1 AS a1, db2.t2;
+--error ER_UNKNOWN_TABLE
+DELETE FROM a1,a2 USING db1.t1, db2.t2 AS a2;
+--error ER_NO_SUCH_TABLE
+DELETE FROM a1,a2 USING db3.t1 AS a1, db4.t2 AS a2;
+--error ER_NO_SUCH_TABLE
+DELETE FROM a1,a2 USING db3.t1 AS a1, db4.t2 AS a2;
+
+# Ambiguous table references
+
+--error ER_NONUNIQ_TABLE
+DELETE a1 FROM db1.t1 AS a1, db2.t2 AS a1;
+--error ER_NO_SUCH_TABLE
+DELETE a1 FROM db1.a1, db2.t2 AS a1;
+--error ER_NONUNIQ_TABLE
+DELETE a1 FROM a1, db1.t1 AS a1;
+--error ER_UNKNOWN_TABLE
+DELETE t1 FROM db1.t1, db2.t1 AS a1;
+--error ER_UNKNOWN_TABLE
+DELETE t1 FROM db1.t1 AS a1, db2.t1 AS a2;
+--error ER_UNKNOWN_TABLE
+DELETE t1 FROM db1.t1, db2.t1;
+
+# Test multiple-table cross database deletes
+
+DELETE t1 FROM db1.t2 AS t1, db2.t2 AS t2 WHERE t2.a = 1 AND t1.a = t2.a;
+SELECT ROW_COUNT();
+CALL count_rows();
+DELETE a1, a2 FROM db2.t1 AS a1, t2 AS a2 WHERE a1.a = 2 AND a2.a = 2;
+SELECT ROW_COUNT();
+CALL count_rows();
+
+DROP DATABASE db1;
+DROP DATABASE db2;
+DROP PROCEDURE count_rows;
+DROP TABLE t1, t2;
+
--echo #
--echo # Bug#46958: Assertion in Diagnostics_area::set_ok_status, trigger,
--echo # merge table
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index d28c19bbd18..27e85ee237b 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -158,7 +158,7 @@ UPDATE `t1` AS P1 INNER JOIN (SELECT aaaa FROM `t1` GROUP BY N HAVING Count(M) >
delete P1.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
select * from t1;
--replace_result P2 p2
---error ER_UNKNOWN_TABLE
+--error ER_NON_UPDATABLE_TABLE
delete P1.*,P2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
-- error 1054
delete P1.* from `t1` AS P1 INNER JOIN (SELECT aaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
diff --git a/mysql-test/t/dirty_close.test b/mysql-test/t/dirty_close.test
index 1bbd53e8c06..e49618170ab 100644
--- a/mysql-test/t/dirty_close.test
+++ b/mysql-test/t/dirty_close.test
@@ -1,3 +1,4 @@
+--source include/not_embedded.inc
# Save the initial number of concurrent sessions
--source include/count_sessions.inc
@@ -22,6 +23,38 @@ disconnect con2;
# End of 4.1 tests
+#
+# Bug#10374 GET_LOCK does not let connection to close on the server side if it's aborted
+#
+
+connection default;
+SELECT GET_LOCK("dangling", 0);
+connect(con1, localhost, root,,);
+connection con1;
+--send SELECT GET_LOCK('dangling', 3600);
+connection default;
+let $wait_condition=
+ SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = "User lock"
+ AND INFO = "SELECT GET_LOCK('dangling', 3600)";
+--source include/wait_condition.inc
+dirty_close con1;
+let $wait_condition=
+ SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = "User lock"
+ AND INFO = "SELECT GET_LOCK('dangling', 3600)";
+--source include/wait_condition.inc
+connect(con1, localhost, root,,);
+--send SELECT GET_LOCK('dangling', 3600);
+connection default;
+let $wait_condition=
+ SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = "User lock"
+ AND INFO = "SELECT GET_LOCK('dangling', 3600)";
+--source include/wait_condition.inc
+SELECT RELEASE_LOCK('dangling');
+connection con1;
+--reap
+connection default;
+disconnect con1;
+
# Wait till all disconnects are completed
--source include/wait_until_count_sessions.inc
diff --git a/mysql-test/t/func_sapdb.test b/mysql-test/t/func_sapdb.test
index 1292c475732..89eae5955aa 100644
--- a/mysql-test/t/func_sapdb.test
+++ b/mysql-test/t/func_sapdb.test
@@ -169,4 +169,26 @@ SELECT TIMEDIFF(TIME('17:00:00'),TIME('17:00:00'))=TIME('00:00:00') AS 1Eq,
TIMEDIFF(TIME('17:59:00'),TIME('17:00:00')),
TIMEDIFF(TIME('17:00:00'),TIME('17:59:00'));
+#
+# Bug#42661 - sec_to_time() and signedness
+#
+
+SELECT sec_to_time(3020399)=TIME('838:59:59');
+SELECT sec_to_time(-3020399)=TIME('-838:59:59');
+SELECT sec_to_time(-3020399)='-838:59:59';
+SELECT time(sec_to_time(-3020399))=TIME('-838:59:59');
+SELECT time(sec_to_time(-3020399))=TIME('-838:59:58');
+
+#
+# Bug#42662 - maketime() and signedness
+#
+
+# TIME(...) and CAST(... AS TIME) go through the same code-path here,
+# but we'll explicitly show show that both work in case the ever changes.
+SELECT maketime(-1,0,1)='-01:00:01';
+SELECT TIME(maketime(-1,0,1))=CAST('-01:00:01' AS TIME);
+SELECT maketime(-1,0,1)=CAST('-01:00:01' AS TIME);
+SELECT maketime(1,0,1)=CAST('01:00:01' AS TIME);
+SELECT maketime(1,0,1)=CAST('01:00:02' AS TIME);
+
# End of 5.0 tests
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index b9da946a55f..95b8a8ec38d 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -819,6 +819,16 @@ SELECT '2008-02-18' + INTERVAL 1 FRAC_SECOND;
--error ER_PARSE_ERROR
SELECT '2008-02-18' - INTERVAL 1 FRAC_SECOND;
+#
+# Bug #36466:
+# Adding days to day_microsecond changes interpretation of microseconds
+#
+
+# show that we treat fractions of seconds correctly (zerofill from right to
+# six places) even if we left out fields on the left.
+select date_add('1000-01-01 00:00:00', interval '1.03:02:01.05' day_microsecond);
+select date_add('1000-01-01 00:00:00', interval '1.02' day_microsecond);
+
--echo End of 5.0 tests
#
diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test
index 47b5aa0292b..dbaa96b0374 100644
--- a/mysql-test/t/lock_multi.test
+++ b/mysql-test/t/lock_multi.test
@@ -1,5 +1,3 @@
--- source include/not_embedded.inc
-
# Save the initial number of concurrent sessions
--source include/count_sessions.inc
diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test
index 6e74e065720..8cc12c6a41f 100644
--- a/mysql-test/t/mysql.test
+++ b/mysql-test/t/mysql.test
@@ -367,6 +367,14 @@ remove_file $MYSQLTEST_VARDIR/tmp/bug31060.sql;
--enable_query_log
#
+# Bug#26780: patch to add auto vertical output option to the cli.
+#
+# Make this wide enough that it will wrap almost everywhere.
+--exec $MYSQL test --auto-vertical-output --table -e "SELECT 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0;"
+# Too short to wrap.
+--exec $MYSQL test --auto-vertical-output --table -e "SELECT 1;"
+
+#
# Bug #25146: Some warnings/errors not shown when using --show-warnings
#
diff --git a/mysql-test/t/partition_sync.test b/mysql-test/t/partition_sync.test
new file mode 100644
index 00000000000..a732b35b8b9
--- /dev/null
+++ b/mysql-test/t/partition_sync.test
@@ -0,0 +1,41 @@
+--source include/have_partition.inc
+# Save the initial number of concurrent sessions.
+--source include/count_sessions.inc
+
+--echo #
+--echo # Bug #43867 ALTER TABLE on a partitioned table
+--echo # causes unnecessary deadlocks
+--echo #
+
+CREATE TABLE t1 (a int) PARTITION BY RANGE (a)
+(PARTITION p0 VALUES LESS THAN (1),
+ PARTITION p1 VALUES LESS THAN (2));
+
+INSERT INTO t1 VALUES (0),(1);
+
+connect(con1,localhost,root);
+
+--echo # Connection 2
+connection con1;
+BEGIN;
+SELECT * FROM t1;
+
+--echo # Connection 1
+connection default;
+--error ER_DROP_PARTITION_NON_EXISTENT
+ALTER TABLE t1 DROP PARTITION p3;
+
+--echo # Connection 2
+connection con1;
+--echo # This failed with deadlock and should not do so.
+SELECT * FROM t1;
+
+--echo # Connection 1
+connection default;
+disconnect con1;
+DROP TABLE t1;
+
+
+# Check that all connections opened by test cases in this file are really
+# gone so execution of other tests won't be affected by their presence.
+--source include/wait_until_count_sessions.inc
diff --git a/mysql-test/t/rpl_mysqldump_slave.test b/mysql-test/t/rpl_mysqldump_slave.test
new file mode 100644
index 00000000000..5723f1282aa
--- /dev/null
+++ b/mysql-test/t/rpl_mysqldump_slave.test
@@ -0,0 +1,25 @@
+source include/master-slave.inc;
+
+--echo #
+--echo # New --dump-slave, --apply-slave-statements functionality
+--echo #
+
+# There is a gap between when START SLAVE returns and when MASTER_LOG_FILE and
+# MASTER_LOG_POS are set. Ensure that we don't call SHOW SLAVE STATUS during
+# that gap.
+--sync_slave_with_master
+
+connection master;
+use test;
+
+connection slave;
+
+# Execute mysqldump with --dump-slave
+--exec $MYSQL_DUMP_SLAVE --compact --dump-slave test
+
+# Execute mysqldump with --dump-slave and --apply-slave-statements
+--exec $MYSQL_DUMP_SLAVE --compact --dump-slave --apply-slave-statements test
+
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+# Execute mysqldump with --dump-slave ,--apply-slave-statements and --include-master-host-port
+--exec $MYSQL_DUMP_SLAVE --compact --dump-slave --apply-slave-statements --include-master-host-port test
diff --git a/mysql-test/t/shm.test b/mysql-test/t/shm.test
index 88e96ae7b45..567caa4989a 100644
--- a/mysql-test/t/shm.test
+++ b/mysql-test/t/shm.test
@@ -7,10 +7,17 @@ let $shm= query_get_value("SHOW VARIABLES LIKE 'shared_memory'", Value, 1);
if (`SELECT '$shm' != 'ON'`){
skip No shm support;
}
+let $shm_name= query_get_value("SHOW GLOBAL VARIABLES LIKE 'shared_memory_base_name'", Value, 1);
+
+# Connect using SHM for testing
+connect(shm_con,localhost,root,,,,$shm_name,SHM);
# Source select test case
-- source include/common-tests.inc
+connection default;
+disconnect shm_con;
+
#
# Bug #24924: shared-memory-base-name that is too long causes buffer overflow
#
@@ -20,7 +27,6 @@ if (`SELECT '$shm' != 'ON'`){
# Bug #33899: Deadlock in mysql_real_query with shared memory connections
#
-let $name= query_get_value("SHOW GLOBAL VARIABLES LIKE 'shared_memory_base_name'", Value, 1);
let $stmt= `SELECT REPEAT('a', 2048)`;
SET @max_allowed_packet= @@global.max_allowed_packet;
@@ -30,7 +36,7 @@ SET GLOBAL max_allowed_packet= 1024;
SET GLOBAL net_buffer_length= 1024;
--error 1
---exec echo SELECT '$stmt'| $MYSQL --protocol=memory --shared-memory-base-name=$name 2>&1
+--exec echo SELECT '$stmt'| $MYSQL --protocol=memory --shared-memory-base-name=$shm_name 2>&1
SET GLOBAL max_allowed_packet= @max_allowed_packet;
SET GLOBAL net_buffer_length= @net_buffer_length;
diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
index 18a4a117939..b022ca4b0e1 100644
--- a/mysql-test/t/sp-error.test
+++ b/mysql-test/t/sp-error.test
@@ -2419,6 +2419,27 @@ end$$
delimiter ;$$
+#
+# Bug#15192: "fatal errors" are caught by handlers in stored procedures
+#
+
+--disable_warnings
+drop procedure if exists p1;
+--enable_warnings
+set @old_recursion_depth = @@max_sp_recursion_depth;
+set @@max_sp_recursion_depth = 255;
+delimiter |;
+create procedure p1(a int)
+begin
+ declare continue handler for 1436 -- ER_STACK_OVERRUN_NEED_MORE
+ select 'exception';
+ call p1(a+1);
+end|
+delimiter ;|
+--error 0,ER_STACK_OVERRUN_NEED_MORE,ER_SP_RECURSION_LIMIT
+call p1(1);
+set @@max_sp_recursion_depth = @old_recursion_depth;
+drop procedure p1;
#
# BUG#NNNN: New bug synopsis
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index eef843ded59..a9825d13f66 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -8295,6 +8295,119 @@ SELECT * FROM t1 WHERE a = f1();
DROP FUNCTION f1;
DROP TABLE t1;
+#
+# Bug#36649: Condition area is not properly cleaned up after stored routine invocation
+#
+
+--disable_warnings
+DROP PROCEDURE IF EXISTS p1;
+--enable_warnings
+
+delimiter |;
+CREATE PROCEDURE p1(a INT, b CHAR)
+BEGIN
+ IF a > 0 THEN
+ CALL p1(a-1, 'ab');
+ ELSE
+ SELECT 1;
+ END IF;
+END|
+delimiter ;|
+
+SET @save_max_sp_recursion= @@max_sp_recursion_depth;
+SET @@max_sp_recursion_depth= 5;
+CALL p1(4, 'a');
+SET @@max_sp_recursion_depth= @save_max_sp_recursion;
+
+DROP PROCEDURE p1;
+
+#
+# Ensure that rules for message list clean up are being respected.
+#
+
+--disable_warnings
+DROP PROCEDURE IF EXISTS p1;
+--enable_warnings
+
+delimiter |;
+CREATE PROCEDURE p1(a CHAR)
+BEGIN
+ SELECT 1;
+ SELECT CAST('10 ' as UNSIGNED INTEGER);
+ SELECT 1;
+END|
+delimiter ;|
+
+CALL p1('data truncated parameter');
+
+DROP PROCEDURE p1;
+
+#
+# Cascading stored procedure/function calls.
+#
+
+--disable_warnings
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+DROP PROCEDURE IF EXISTS p3;
+DROP PROCEDURE IF EXISTS p4;
+--enable_warnings
+
+delimiter |;
+CREATE PROCEDURE p1()
+ CALL p2()|
+CREATE PROCEDURE p2()
+ CALL p3()|
+CREATE PROCEDURE p3()
+ CALL p4()|
+CREATE PROCEDURE p4()
+BEGIN
+ SELECT 1;
+ SELECT CAST('10 ' as UNSIGNED INTEGER);
+ SELECT 2;
+END|
+delimiter ;|
+
+CALL p1();
+
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+DROP PROCEDURE p3;
+DROP PROCEDURE p4;
+
+--disable_warnings
+DROP FUNCTION IF EXISTS f1;
+DROP FUNCTION IF EXISTS f2;
+DROP FUNCTION IF EXISTS f3;
+DROP FUNCTION IF EXISTS f4;
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (a CHAR(2));
+
+INSERT INTO t1 VALUES ('aa');
+
+delimiter |;
+CREATE FUNCTION f1() RETURNS CHAR
+ RETURN (SELECT f2())|
+CREATE FUNCTION f2() RETURNS CHAR
+ RETURN (SELECT f3())|
+CREATE FUNCTION f3() RETURNS CHAR
+ RETURN (SELECT f4())|
+CREATE FUNCTION f4() RETURNS CHAR
+BEGIN
+ RETURN (SELECT a FROM t1);
+END|
+delimiter ;|
+
+SELECT f1();
+
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+DROP FUNCTION f3;
+DROP FUNCTION f4;
+DROP TABLE t1;
+
--echo #
--echo # Bug#34197: CREATE PROCEDURE fails when COMMENT truncated in non
--echo # strict SQL mode
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
index 3ab724a835a..f3b9d6bb91e 100644
--- a/mysql-test/t/trigger.test
+++ b/mysql-test/t/trigger.test
@@ -2425,3 +2425,67 @@ DELETE FROM t1;
DROP TABLE t1;
DROP TEMPORARY TABLE t2;
+
+#
+# Bug#36649: Condition area is not properly cleaned up after stored routine invocation
+#
+
+--disable_warnings
+DROP TRIGGER IF EXISTS trg1;
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (a INT);
+
+delimiter |;
+CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+ DECLARE a CHAR;
+ SELECT 'ab' INTO a;
+ SELECT 'ab' INTO a;
+ SELECT 'a' INTO a;
+END|
+delimiter ;|
+
+INSERT INTO t1 VALUES (1);
+
+DROP TRIGGER trg1;
+DROP TABLE t1;
+
+#
+# Successive trigger actuations
+#
+
+--disable_warnings
+DROP TRIGGER IF EXISTS trg1;
+DROP TRIGGER IF EXISTS trg2;
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (a INT);
+
+delimiter |;
+
+CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+ DECLARE trg1 CHAR;
+ SELECT 'ab' INTO trg1;
+END|
+
+CREATE TRIGGER trg2 AFTER INSERT ON t1 FOR EACH ROW
+BEGIN
+ DECLARE trg2 CHAR;
+ SELECT 'ab' INTO trg2;
+END|
+
+delimiter ;|
+
+INSERT INTO t1 VALUES (0);
+SELECT * FROM t1;
+SHOW WARNINGS;
+INSERT INTO t1 VALUES (1),(2);
+
+DROP TRIGGER trg1;
+DROP TRIGGER trg2;
+DROP TABLE t1;
+
diff --git a/mysql-test/t/type_time.test b/mysql-test/t/type_time.test
index 5bb521601e5..3cec27d7782 100644
--- a/mysql-test/t/type_time.test
+++ b/mysql-test/t/type_time.test
@@ -39,7 +39,7 @@ drop table t1;
# SELECT CAST(0.2359591234567e+30 AS TIME);
# ##########################################################
-# End of 4.1 tests
+--echo End of 4.1 tests
#
# Bug#29555: Comparing time values as strings may lead to a wrong result.
@@ -90,3 +90,22 @@ DROP TABLE t1;
--echo End of 5.0 tests
+
+
+#
+# Bug#42664 - Sign ignored for TIME types when not comparing as longlong
+#
+
+CREATE TABLE t1 (f1 TIME);
+INSERT INTO t1 VALUES ('24:00:00');
+SELECT '24:00:00' = (SELECT f1 FROM t1);
+SELECT CAST('24:00:00' AS TIME) = (SELECT f1 FROM t1);
+SELECT CAST('-24:00:00' AS TIME) = (SELECT f1 FROM t1);
+TRUNCATE t1;
+INSERT INTO t1 VALUES ('-24:00:00');
+SELECT CAST('24:00:00' AS TIME) = (SELECT f1 FROM t1);
+SELECT CAST('-24:00:00' AS TIME) = (SELECT f1 FROM t1);
+SELECT '-24:00:00' = (SELECT f1 FROM t1);
+DROP TABLE t1;
+
+--echo End of 6.0 tests
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index 2607ea57d08..9c45cdc2277 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -155,7 +155,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
DBUG_ASSERT(alloc_root_inited(mem_root));
length+=ALIGN_SIZE(sizeof(USED_MEM));
- if (!(next = (USED_MEM*) my_malloc(length,MYF(MY_WME))))
+ if (!(next = (USED_MEM*) my_malloc(length,MYF(MY_WME | ME_FATALERROR))))
{
if (mem_root->error_handler)
(*mem_root->error_handler)();
@@ -198,7 +198,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
get_size= length+ALIGN_SIZE(sizeof(USED_MEM));
get_size= max(get_size, block_size);
- if (!(next = (USED_MEM*) my_malloc(get_size,MYF(MY_WME))))
+ if (!(next = (USED_MEM*) my_malloc(get_size,MYF(MY_WME | ME_FATALERROR))))
{
if (mem_root->error_handler)
(*mem_root->error_handler)();
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index f444e0f0c94..2e8f09f14fd 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -1222,6 +1222,14 @@ void my_print_help(const struct my_option *options)
printf("%s", comment);
}
putchar('\n');
+ if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG ||
+ (optp->var_type & GET_TYPE_MASK) == GET_BOOL)
+ {
+ if (optp->def_value != 0)
+ {
+ printf("%*s(Defaults to on; use --skip-%s to disable.)\n", name_space, "", optp->name);
+ }
+ }
}
}
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc
index 23eec749a30..b2bbd340e14 100644
--- a/sql/event_data_objects.cc
+++ b/sql/event_data_objects.cc
@@ -196,7 +196,7 @@ Event_basic::Event_basic()
{
DBUG_ENTER("Event_basic::Event_basic");
/* init memory root */
- init_alloc_root(&mem_root, 256, 512);
+ init_sql_alloc(&mem_root, 256, 512);
dbname.str= name.str= NULL;
dbname.length= name.length= 0;
time_zone= NULL;
diff --git a/sql/field.cc b/sql/field.cc
index dc32624db10..615d081918b 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -6819,86 +6819,6 @@ int Field_string::do_save_field_metadata(uchar *metadata_ptr)
}
-/*
- Compare two packed keys
-
- SYNOPSIS
- pack_cmp()
- a New key
- b Original key
- length Key length
- insert_or_update 1 if this is an insert or update
-
- RETURN
- < 0 a < b
- 0 a = b
- > 0 a > b
-*/
-
-int Field_string::pack_cmp(const uchar *a, const uchar *b, uint length,
- my_bool insert_or_update)
-{
- uint a_length, b_length;
- if (length > 255)
- {
- a_length= uint2korr(a);
- b_length= uint2korr(b);
- a+= 2;
- b+= 2;
- }
- else
- {
- a_length= (uint) *a++;
- b_length= (uint) *b++;
- }
- return field_charset->coll->strnncollsp(field_charset,
- a, a_length,
- b, b_length,
- insert_or_update);
-}
-
-
-/**
- Compare a packed key against row.
-
- @param key Original key
- @param length Key length. (May be less than field length)
- @param insert_or_update 1 if this is an insert or update
-
- @return
- < 0 row < key
- @return
- 0 row = key
- @return
- > 0 row > key
-*/
-
-int Field_string::pack_cmp(const uchar *key, uint length,
- my_bool insert_or_update)
-{
- uint row_length, local_key_length;
- uchar *end;
- if (length > 255)
- {
- local_key_length= uint2korr(key);
- key+= 2;
- }
- else
- local_key_length= (uint) *key++;
-
- /* Only use 'length' of key, not field_length */
- end= ptr + length;
- while (end > ptr && end[-1] == ' ')
- end--;
- row_length= (uint) (end - ptr);
-
- return field_charset->coll->strnncollsp(field_charset,
- ptr, row_length,
- key, local_key_length,
- insert_or_update);
-}
-
-
uint Field_string::packed_col_length(const uchar *data_ptr, uint length)
{
if (length > 255)
@@ -7258,90 +7178,6 @@ uchar *Field_varstring::pack(uchar *to, const uchar *from,
}
-uchar *
-Field_varstring::pack_key(uchar *to, const uchar *key, uint max_length,
- bool low_byte_first __attribute__((unused)))
-{
- uint length= length_bytes == 1 ? (uint) *key : uint2korr(key);
- uint local_char_length= ((field_charset->mbmaxlen > 1) ?
- max_length/field_charset->mbmaxlen : max_length);
- key+= length_bytes;
- if (length > local_char_length)
- {
- local_char_length= my_charpos(field_charset, key, key+length,
- local_char_length);
- set_if_smaller(length, local_char_length);
- }
- *to++= (char) (length & 255);
- if (max_length > 255)
- *to++= (char) (length >> 8);
- if (length)
- memcpy(to, key, length);
- return to+length;
-}
-
-
-/**
- Unpack a key into a record buffer.
-
- A VARCHAR key has a maximum size of 64K-1.
- In its packed form, the length field is one or two bytes long,
- depending on 'max_length'.
-
- @param to Pointer into the record buffer.
- @param key Pointer to the packed key.
- @param max_length Key length limit from key description.
-
- @return
- Pointer to end of 'key' (To the next key part if multi-segment key)
-*/
-
-const uchar *
-Field_varstring::unpack_key(uchar *to, const uchar *key, uint max_length,
- bool low_byte_first __attribute__((unused)))
-{
- /* get length of the blob key */
- uint32 length= *key++;
- if (max_length > 255)
- length+= (*key++) << 8;
-
- /* put the length into the record buffer */
- if (length_bytes == 1)
- *ptr= (uchar) length;
- else
- int2store(ptr, length);
- memcpy(ptr + length_bytes, key, length);
- return key + length;
-}
-
-/**
- Create a packed key that will be used for storage in the index tree.
-
- @param to Store packed key segment here
- @param from Key segment (as given to index_read())
- @param max_length Max length of key
-
- @return
- end of key storage
-*/
-
-uchar *
-Field_varstring::pack_key_from_key_image(uchar *to, const uchar *from, uint max_length,
- bool low_byte_first __attribute__((unused)))
-{
- /* Key length is always stored as 2 bytes */
- uint length= uint2korr(from);
- if (length > max_length)
- length= max_length;
- *to++= (char) (length & 255);
- if (max_length > 255)
- *to++= (char) (length >> 8);
- if (length)
- memcpy(to, from+HA_KEY_BLOB_LENGTH, length);
- return to+length;
-}
-
-
/**
Unpack a varstring field from row data.
@@ -7384,59 +7220,6 @@ Field_varstring::unpack(uchar *to, const uchar *from,
}
-int Field_varstring::pack_cmp(const uchar *a, const uchar *b,
- uint key_length_arg,
- my_bool insert_or_update)
-{
- uint a_length, b_length;
- if (key_length_arg > 255)
- {
- a_length=uint2korr(a); a+= 2;
- b_length=uint2korr(b); b+= 2;
- }
- else
- {
- a_length= (uint) *a++;
- b_length= (uint) *b++;
- }
- return field_charset->coll->strnncollsp(field_charset,
- a, a_length,
- b, b_length,
- insert_or_update);
-}
-
-
-int Field_varstring::pack_cmp(const uchar *b, uint key_length_arg,
- my_bool insert_or_update)
-{
- uchar *a= ptr+ length_bytes;
- uint a_length= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr);
- uint b_length;
- uint local_char_length= ((field_charset->mbmaxlen > 1) ?
- key_length_arg / field_charset->mbmaxlen :
- key_length_arg);
-
- if (key_length_arg > 255)
- {
- b_length=uint2korr(b); b+= HA_KEY_BLOB_LENGTH;
- }
- else
- b_length= (uint) *b++;
-
- if (a_length > local_char_length)
- {
- local_char_length= my_charpos(field_charset, a, a+a_length,
- local_char_length);
- set_if_smaller(a_length, local_char_length);
- }
-
- return field_charset->coll->strnncollsp(field_charset,
- a, a_length,
- b, b_length,
- insert_or_update);
-}
-
-
uint Field_varstring::packed_col_length(const uchar *data_ptr, uint length)
{
if (length > 255)
@@ -8135,139 +7918,6 @@ const uchar *Field_blob::unpack(uchar *to,
DBUG_RETURN(from + master_packlength + length);
}
-/* Keys for blobs are like keys on varchars */
-
-int Field_blob::pack_cmp(const uchar *a, const uchar *b, uint key_length_arg,
- my_bool insert_or_update)
-{
- uint a_length, b_length;
- if (key_length_arg > 255)
- {
- a_length=uint2korr(a); a+=2;
- b_length=uint2korr(b); b+=2;
- }
- else
- {
- a_length= (uint) *a++;
- b_length= (uint) *b++;
- }
- return field_charset->coll->strnncollsp(field_charset,
- a, a_length,
- b, b_length,
- insert_or_update);
-}
-
-
-int Field_blob::pack_cmp(const uchar *b, uint key_length_arg,
- my_bool insert_or_update)
-{
- uchar *a;
- uint a_length, b_length;
- memcpy_fixed(&a,ptr+packlength,sizeof(char*));
- if (!a)
- return key_length_arg > 0 ? -1 : 0;
-
- a_length= get_length(ptr);
- if (key_length_arg > 255)
- {
- b_length= uint2korr(b); b+=2;
- }
- else
- b_length= (uint) *b++;
- return field_charset->coll->strnncollsp(field_charset,
- a, a_length,
- b, b_length,
- insert_or_update);
-}
-
-/** Create a packed key that will be used for storage from a MySQL row. */
-
-uchar *
-Field_blob::pack_key(uchar *to, const uchar *from, uint max_length,
- bool low_byte_first __attribute__((unused)))
-{
- uchar *save= ptr;
- ptr= (uchar*) from;
- uint32 length=get_length(); // Length of from string
- uint local_char_length= ((field_charset->mbmaxlen > 1) ?
- max_length/field_charset->mbmaxlen : max_length);
- if (length)
- get_ptr((uchar**) &from);
- if (length > local_char_length)
- local_char_length= my_charpos(field_charset, from, from+length,
- local_char_length);
- set_if_smaller(length, local_char_length);
- *to++= (uchar) length;
- if (max_length > 255) // 2 byte length
- *to++= (uchar) (length >> 8);
- memcpy(to, from, length);
- ptr=save; // Restore org row pointer
- return to+length;
-}
-
-
-/**
- Unpack a blob key into a record buffer.
-
- A blob key has a maximum size of 64K-1.
- In its packed form, the length field is one or two bytes long,
- depending on 'max_length'.
- Depending on the maximum length of a blob, its length field is
- put into 1 to 4 bytes. This is a property of the blob object,
- described by 'packlength'.
- Blobs are internally stored apart from the record buffer, which
- contains a pointer to the blob buffer.
-
-
- @param to Pointer into the record buffer.
- @param from Pointer to the packed key.
- @param max_length Key length limit from key description.
-
- @return
- Pointer into 'from' past the last byte copied from packed key.
-*/
-
-const uchar *
-Field_blob::unpack_key(uchar *to, const uchar *from, uint max_length,
- bool low_byte_first __attribute__((unused)))
-{
- /* get length of the blob key */
- uint32 length= *from++;
- if (max_length > 255)
- length+= *from++ << 8;
-
- /* put the length into the record buffer */
- put_length(to, length);
-
- /* put the address of the blob buffer or NULL */
- if (length)
- memcpy_fixed(to + packlength, &from, sizeof(from));
- else
- bzero(to + packlength, sizeof(from));
-
- /* point to first byte of next field in 'from' */
- return from + length;
-}
-
-
-/** Create a packed key that will be used for storage from a MySQL key. */
-
-uchar *
-Field_blob::pack_key_from_key_image(uchar *to, const uchar *from, uint max_length,
- bool low_byte_first __attribute__((unused)))
-{
- uint length=uint2korr(from);
- if (length > max_length)
- length=max_length;
- *to++= (char) (length & 255);
- if (max_length > 255)
- *to++= (char) (length >> 8);
- if (length)
- memcpy(to, from+HA_KEY_BLOB_LENGTH, length);
- return to+length;
-}
-
-
uint Field_blob::packed_col_length(const uchar *data_ptr, uint length)
{
if (length > 255)
diff --git a/sql/field.h b/sql/field.h
index 7235115a888..fb6ca34e88e 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -25,7 +25,6 @@
#pragma interface /* gcc class implementation */
#endif
-#define NOT_FIXED_DEC 31
#define DATETIME_DEC 6
const uint32 max_field_size= (uint32) 4294967295U;
@@ -410,32 +409,11 @@ public:
DBUG_RETURN(result);
}
- virtual uchar *pack_key(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first)
- {
- return pack(to, from, max_length, low_byte_first);
- }
- virtual uchar *pack_key_from_key_image(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first)
- {
- return pack(to, from, max_length, low_byte_first);
- }
- virtual const uchar *unpack_key(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first)
- {
- return unpack(to, from, max_length, low_byte_first);
- }
virtual uint packed_col_length(const uchar *to, uint length)
{ return length;}
virtual uint max_packed_col_length(uint max_length)
{ return max_length;}
- virtual int pack_cmp(const uchar *a,const uchar *b, uint key_length_arg,
- my_bool insert_or_update)
- { return cmp(a,b); }
- virtual int pack_cmp(const uchar *b, uint key_length_arg,
- my_bool insert_or_update)
- { return cmp(ptr,b); }
uint offset(uchar *record)
{
return (uint) (ptr - record);
@@ -1503,9 +1481,6 @@ public:
int compatible_field_size(uint field_metadata,
const Relay_log_info *rli);
uint row_pack_length() { return (field_length + 1); }
- int pack_cmp(const uchar *a,const uchar *b,uint key_length,
- my_bool insert_or_update);
- int pack_cmp(const uchar *b,uint key_length,my_bool insert_or_update);
uint packed_col_length(const uchar *to, uint length);
uint max_packed_col_length(uint max_length);
uint size_of() const { return sizeof(*this); }
@@ -1579,16 +1554,8 @@ public:
void sql_type(String &str) const;
virtual uchar *pack(uchar *to, const uchar *from,
uint max_length, bool low_byte_first);
- uchar *pack_key(uchar *to, const uchar *from, uint max_length, bool low_byte_first);
- uchar *pack_key_from_key_image(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first);
virtual const uchar *unpack(uchar* to, const uchar *from,
uint param_data, bool low_byte_first);
- const uchar *unpack_key(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first);
- int pack_cmp(const uchar *a, const uchar *b, uint key_length,
- my_bool insert_or_update);
- int pack_cmp(const uchar *b, uint key_length,my_bool insert_or_update);
int cmp_binary(const uchar *a,const uchar *b, uint32 max_length=~0L);
int key_cmp(const uchar *,const uchar*);
int key_cmp(const uchar *str, uint length);
@@ -1764,17 +1731,8 @@ public:
}
virtual uchar *pack(uchar *to, const uchar *from,
uint max_length, bool low_byte_first);
- uchar *pack_key(uchar *to, const uchar *from,
- uint max_length, bool low_byte_first);
- uchar *pack_key_from_key_image(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first);
virtual const uchar *unpack(uchar *to, const uchar *from,
uint param_data, bool low_byte_first);
- const uchar *unpack_key(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first);
- int pack_cmp(const uchar *a, const uchar *b, uint key_length,
- my_bool insert_or_update);
- int pack_cmp(const uchar *b, uint key_length,my_bool insert_or_update);
uint packed_col_length(const uchar *col_ptr, uint length);
uint max_packed_col_length(uint max_length);
void free() { value.free(); }
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 7e5eccb2374..0d5fc454a0c 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -1980,8 +1980,7 @@ partition_element *ha_partition::find_partition_element(uint part_id)
return part_elem;
}
DBUG_ASSERT(0);
- my_error(ER_OUT_OF_RESOURCES, MYF(0));
- current_thd->fatal_error(); // Abort
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
return NULL;
}
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index c6b88cd8188..981b4bf0b92 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -855,7 +855,8 @@ get_time_value(THD *thd, Item ***item_arg, Item **cache_arg,
else
{
*is_null= item->get_time(&ltime);
- value= !*is_null ? (longlong) TIME_to_ulonglong_datetime(&ltime) : 0;
+ value= !*is_null ? (longlong) TIME_to_ulonglong_datetime(&ltime) *
+ (ltime.neg ? -1 : 1) : 0;
}
/*
Do not cache GET_USER_VAR() function as its const_item() may return TRUE
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 23af528c256..ccb55feff81 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -3474,6 +3474,48 @@ void debug_sync_point(const char* lock_name, uint lock_timeout)
#endif
+
+/**
+ Wait for a given condition to be signaled within the specified timeout.
+
+ @param cond the condition variable to wait on
+ @param lock the associated mutex
+ @param abstime the amount of time in seconds to wait
+
+ @retval return value from pthread_cond_timedwait
+*/
+
+#define INTERRUPT_INTERVAL (5 * ULL(1000000000))
+
+static int interruptible_wait(THD *thd, pthread_cond_t *cond,
+ pthread_mutex_t *lock, double time)
+{
+ int error;
+ struct timespec abstime;
+ ulonglong slice, timeout= (ulonglong) (time * 1000000000.0);
+
+ do
+ {
+ /* Wait for a fixed interval. */
+ if (timeout > INTERRUPT_INTERVAL)
+ slice= INTERRUPT_INTERVAL;
+ else
+ slice= timeout;
+
+ timeout-= slice;
+ set_timespec_nsec(abstime, slice);
+ error= pthread_cond_timedwait(cond, lock, &abstime);
+ if (error == ETIMEDOUT || error == ETIME)
+ {
+ /* Return error if timed out or connection is broken. */
+ if (!timeout || !thd->is_connected())
+ break;
+ }
+ } while (error && timeout);
+
+ return error;
+}
+
/**
Get a user level lock. If the thread has an old lock this is first released.
@@ -3489,8 +3531,7 @@ longlong Item_func_get_lock::val_int()
{
DBUG_ASSERT(fixed == 1);
String *res=args[0]->val_str(&value);
- longlong timeout=args[1]->val_int();
- struct timespec abstime;
+ double timeout= args[1]->val_real();
THD *thd=current_thd;
User_level_lock *ull;
int error;
@@ -3554,12 +3595,11 @@ longlong Item_func_get_lock::val_int()
thd->mysys_var->current_mutex= &LOCK_user_locks;
thd->mysys_var->current_cond= &ull->cond;
- set_timespec(abstime,timeout);
error= 0;
while (ull->locked && !thd->killed)
{
DBUG_PRINT("info", ("waiting on lock"));
- error= pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime);
+ error= interruptible_wait(thd, &ull->cond, &LOCK_user_locks, timeout);
if (error == ETIMEDOUT || error == ETIME)
{
DBUG_PRINT("info", ("lock wait timeout"));
@@ -3754,13 +3794,13 @@ void Item_func_benchmark::print(String *str, enum_query_type query_type)
longlong Item_func_sleep::val_int()
{
THD *thd= current_thd;
- struct timespec abstime;
pthread_cond_t cond;
+ double timeout;
int error;
DBUG_ASSERT(fixed == 1);
- double time= args[0]->val_real();
+ timeout= args[0]->val_real();
/*
On 64-bit OSX pthread_cond_timedwait() waits forever
if passed abstime time has already been exceeded by
@@ -3770,10 +3810,8 @@ longlong Item_func_sleep::val_int()
We assume that the lines between this test and the call
to pthread_cond_timedwait() will be executed in less than 0.00001 sec.
*/
- if (time < 0.00001)
+ if (timeout < 0.00001)
return 0;
-
- set_timespec_nsec(abstime, (ulonglong)(time * ULL(1000000000)));
pthread_cond_init(&cond, NULL);
pthread_mutex_lock(&LOCK_user_locks);
@@ -3785,7 +3823,7 @@ longlong Item_func_sleep::val_int()
error= 0;
while (!thd->killed)
{
- error= pthread_cond_timedwait(&cond, &LOCK_user_locks, &abstime);
+ error= interruptible_wait(thd, &cond, &LOCK_user_locks, timeout);
if (error == ETIMEDOUT || error == ETIME)
break;
error= 0;
@@ -3817,7 +3855,7 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
uint size=ALIGN_SIZE(sizeof(user_var_entry))+name.length+1+extra_size;
if (!my_hash_inited(hash))
return 0;
- if (!(entry = (user_var_entry*) my_malloc(size,MYF(MY_WME))))
+ if (!(entry = (user_var_entry*) my_malloc(size,MYF(MY_WME | ME_FATALERROR))))
return 0;
entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+
extra_size;
@@ -3955,6 +3993,8 @@ bool Item_func_set_user_var::register_field_in_read_map(uchar *arg)
@param dv derivation for new value
@param unsigned_arg indiates if a value of type INT_RESULT is unsigned
+ @note Sets error and fatal error if allocation fails.
+
@retval
false success
@retval
@@ -3998,7 +4038,8 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length,
if (entry->value == pos)
entry->value=0;
entry->value= (char*) my_realloc(entry->value, length,
- MYF(MY_ALLOW_ZERO_PTR | MY_WME));
+ MYF(MY_ALLOW_ZERO_PTR | MY_WME |
+ ME_FATALERROR));
if (!entry->value)
return 1;
}
@@ -4035,7 +4076,6 @@ Item_func_set_user_var::update_hash(void *ptr, uint length,
if (::update_hash(entry, (null_value= args[0]->null_value),
ptr, length, res_type, cs, dv, unsigned_arg))
{
- current_thd->fatal_error(); // Probably end of memory
null_value= 1;
return 1;
}
@@ -4768,11 +4808,6 @@ void Item_func_get_user_var::fix_length_and_dec()
m_cached_result_type= STRING_RESULT;
max_length= MAX_BLOB_WIDTH;
}
-
- if (error)
- thd->fatal_error();
-
- return;
}
@@ -4843,18 +4878,16 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs)
{
- if (::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs,
- DERIVATION_IMPLICIT, 0 /* unsigned_arg */))
- current_thd->fatal_error(); // Probably end of memory
+ ::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs,
+ DERIVATION_IMPLICIT, 0 /* unsigned_arg */);
}
void Item_user_var_as_out_param::set_value(const char *str, uint length,
CHARSET_INFO* cs)
{
- if (::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
- DERIVATION_IMPLICIT, 0 /* unsigned_arg */))
- current_thd->fatal_error(); // Probably end of memory
+ ::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
+ DERIVATION_IMPLICIT, 0 /* unsigned_arg */);
}
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 0ce9c555fea..a619827b2d3 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1740,8 +1740,6 @@ subselect_union_engine::subselect_union_engine(st_select_lex_unit *u,
:subselect_engine(item_arg, result_arg)
{
unit= u;
- if (!result_arg) //out of memory
- current_thd->fatal_error();
unit->item= item_arg;
}
@@ -1753,10 +1751,7 @@ int subselect_single_select_engine::prepare()
join= new JOIN(thd, select_lex->item_list,
select_lex->options | SELECT_NO_UNLOCK, result);
if (!join || !result)
- {
- thd->fatal_error(); //out of memory
- return 1;
- }
+ return 1; /* Fatal error is set already. */
prepared= 1;
SELECT_LEX *save_select= thd->lex->current_select;
thd->lex->current_select= select_lex;
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 84ddc88487d..3009c48cac7 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -865,6 +865,8 @@ static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs,
{
const char *end=str+length;
uint i;
+ long msec_length= 0;
+
while (str != end && !my_isdigit(cs,*str))
str++;
@@ -874,12 +876,7 @@ static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs,
const char *start= str;
for (value=0; str != end && my_isdigit(cs,*str) ; str++)
value= value*LL(10) + (longlong) (*str - '0');
- if (transform_msec && i == count - 1) // microseconds always last
- {
- long msec_length= 6 - (uint) (str - start);
- if (msec_length > 0)
- value*= (long) log_10_int[msec_length];
- }
+ msec_length= 6 - (str - start);
values[i]= value;
while (str != end && !my_isdigit(cs,*str))
str++;
@@ -893,6 +890,10 @@ static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs,
break;
}
}
+
+ if (transform_msec && msec_length > 0)
+ values[count - 1] *= (long) log_10_int[msec_length];
+
return (str != end);
}
@@ -1854,7 +1855,7 @@ longlong Item_func_sec_to_time::val_int()
sec_to_time(arg_val, args[0]->unsigned_flag, &ltime);
return (ltime.neg ? -1 : 1) *
- ((ltime.hour)*10000 + ltime.minute*100 + ltime.second);
+ (longlong) ((ltime.hour)*10000 + ltime.minute*100 + ltime.second);
}
@@ -2666,7 +2667,8 @@ longlong Item_time_typecast::val_int()
null_value= 1;
return 0;
}
- return ltime.hour * 10000L + ltime.minute * 100 + ltime.second;
+ return (ltime.neg ? -1 : 1) *
+ (longlong) ((ltime.hour)*10000 + ltime.minute*100 + ltime.second);
}
String *Item_time_typecast::val_str(String *str)
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index b539e004481..6d97bfe3f16 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1074,9 +1074,9 @@ inline bool check_access(THD *thd, ulong access, const char *db,
return false;
}
inline bool check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
- bool no_errors,
bool any_combination_of_privileges_will_do,
- uint number)
+ uint number,
+ bool no_errors)
{ return false; }
#endif /*NO_EMBEDDED_ACCESS_CHECKS*/
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 13b10ac2e8f..d85e976e9c8 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -175,8 +175,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
error= tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
if(error)
{
- tl->table->file->print_error(error, MYF(0));
- tl->table->in_use->fatal_error();
+ tl->table->file->print_error(error, MYF(ME_FATALERROR));
return error;
}
count*= tl->table->file->stats.records;
@@ -427,8 +426,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
return HA_ERR_KEY_NOT_FOUND; // No rows matching WHERE
/* HA_ERR_LOCK_DEADLOCK or some other error */
- table->file->print_error(error, MYF(0));
- table->in_use->fatal_error();
+ table->file->print_error(error, MYF(ME_FATALERROR));
return(error);
}
removed_tables|= table->map;
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 034f987e0e7..b0ea4774a29 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -4880,6 +4880,7 @@ ER_ZLIB_Z_DATA_ERROR
spa "ZLIB: Dato de entrada fué corrompido para zlib"
ER_CUT_VALUE_GROUP_CONCAT
eng "Row %u was cut by GROUP_CONCAT()"
+ por "Linha %u foi cortada por GROUP_CONCAT()"
ER_WARN_TOO_FEW_RECORDS 01000
eng "Row %ld doesn't contain data for all columns"
ger "Zeile %ld enthält nicht für alle Felder Daten"
diff --git a/sql/sp.cc b/sql/sp.cc
index aec953988b9..f6bfba71726 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -1711,6 +1711,9 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
ret= SP_OK;
break;
default:
+ /* Query might have been killed, don't set error. */
+ if (thd->killed)
+ break;
/*
Any error when loading an existing routine is either some problem
with the mysql.proc table, or a parse error because the contents
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 7cabae255cc..1fb8fd257df 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1086,7 +1086,6 @@ sp_head::execute(THD *thd)
Item_change_list old_change_list;
String old_packet;
Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer;
-
Object_creation_ctx *saved_creation_ctx;
Warning_info *saved_warning_info, warning_info(thd->warning_info->warn_id());
@@ -4017,10 +4016,7 @@ sp_add_to_query_tables(THD *thd, LEX *lex,
TABLE_LIST *table;
if (!(table= (TABLE_LIST *)thd->calloc(sizeof(TABLE_LIST))))
- {
- thd->fatal_error();
return NULL;
- }
table->db_length= strlen(db);
table->db= thd->strmake(db, table->db_length);
table->table_name_length= strlen(name);
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 35d2c886119..ed6f593cc2e 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1331,12 +1331,12 @@ end:
@param thd Pointer to the thread handler
@param sql A pointer to the sql statement *
@param query_length Length of the statement in characters
-
+
@return status code
- @retval 1 Query was not cached.
- @retval 0 The query was cached and user was sent the result.
- @retval -1 The query was cached but we didn't have rights to use it.
-
+ @retval 0 Query was not cached.
+ @retval 1 The query was cached and user was sent the result.
+ @retval -1 The query was cached but we didn't have rights to use it.
+
In case of -1, no error is sent to the client.
*) The buffer must be allocated memory of size:
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 01ac3c12641..2dd45997ee1 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1982,9 +1982,15 @@ public:
DBUG_VOID_RETURN;
}
inline bool vio_ok() const { return net.vio != 0; }
+ /** Return FALSE if connection to client is broken. */
+ bool is_connected()
+ {
+ return vio_ok() ? vio_is_connected(net.vio) : FALSE;
+ }
#else
void clear_error();
- inline bool vio_ok() const { return true; }
+ inline bool vio_ok() const { return TRUE; }
+ inline bool is_connected() { return TRUE; }
#endif
/**
Mark the current error as fatal. Warning: this does not
@@ -1993,6 +1999,7 @@ public:
*/
inline void fatal_error()
{
+ DBUG_ASSERT(main_da.is_error());
is_fatal_error= 1;
DBUG_PRINT("error",("Fatal error set"));
}
@@ -2158,7 +2165,10 @@ public:
else
{
x_free(db);
- db= new_db ? my_strndup(new_db, new_db_len, MYF(MY_WME)) : NULL;
+ if (new_db)
+ db= my_strndup(new_db, new_db_len, MYF(MY_WME | ME_FATALERROR));
+ else
+ db= NULL;
}
db_length= db ? new_db_len : 0;
return new_db && !db;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 173e7f1ca2f..b1c7c7f647e 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1922,20 +1922,17 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
if (! (di= find_handler(thd, table_list)))
{
if (!(di= new Delayed_insert()))
- {
- thd->fatal_error();
goto end_create;
- }
pthread_mutex_lock(&LOCK_thread_count);
thread_count++;
pthread_mutex_unlock(&LOCK_thread_count);
di->thd.set_db(table_list->db, (uint) strlen(table_list->db));
- di->thd.set_query(my_strdup(table_list->table_name, MYF(MY_WME)), 0);
+ di->thd.set_query(my_strdup(table_list->table_name,
+ MYF(MY_WME | ME_FATALERROR)), 0);
if (di->thd.db == NULL || di->thd.query() == NULL)
{
/* The error is reported */
delete di;
- thd->fatal_error();
goto end_create;
}
di->table_list= *table_list; // Needed to open table
@@ -1953,8 +1950,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
pthread_mutex_unlock(&di->mutex);
di->unlock();
delete di;
- my_error(ER_CANT_CREATE_THREAD, MYF(0), error);
- thd->fatal_error();
+ my_error(ER_CANT_CREATE_THREAD, MYF(ME_FATALERROR), error);
goto end_create;
}
@@ -2331,8 +2327,8 @@ static void handle_delayed_insert_impl(THD *thd, Delayed_insert *di)
}
if (!(di->table->file->ha_table_flags() & HA_CAN_INSERT_DELAYED))
{
- thd->fatal_error();
- my_error(ER_DELAYED_NOT_SUPPORTED, MYF(0), di->table_list.table_name);
+ my_error(ER_DELAYED_NOT_SUPPORTED, MYF(ME_FATALERROR),
+ di->table_list.table_name);
goto err;
}
if (di->table->triggers)
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 74f4cc0ec0d..e1bf05fff23 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -458,7 +458,7 @@ struct ilink
struct ilink **prev,*next;
static void *operator new(size_t size) throw ()
{
- return (void*)my_malloc((uint)size, MYF(MY_WME | MY_FAE));
+ return (void*)my_malloc((uint)size, MYF(MY_WME | MY_FAE | ME_FATALERROR));
}
static void operator delete(void* ptr_arg, size_t size)
{
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index d4440b547f2..99fb08abcca 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1369,54 +1369,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->stmt_da->disable_status(); // Don't send anything back
error=TRUE; // End server
break;
-
-#ifdef REMOVED
- case COM_CREATE_DB: // QQ: To be removed
- {
- LEX_STRING db, alias;
- HA_CREATE_INFO create_info;
-
- status_var_increment(thd->status_var.com_stat[SQLCOM_CREATE_DB]);
- if (thd->make_lex_string(&db, packet, packet_length, FALSE) ||
- thd->make_lex_string(&alias, db.str, db.length, FALSE) ||
- check_db_name(&db))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), db.str ? db.str : "NULL");
- break;
- }
- if (check_access(thd, CREATE_ACL, db.str , 0, 1, 0,
- is_schema_db(db.str)))
- break;
- general_log_print(thd, command, "%.*s", db.length, db.str);
- bzero(&create_info, sizeof(create_info));
- mysql_create_db(thd, (lower_case_table_names == 2 ? alias.str : db.str),
- &create_info, 0);
- break;
- }
- case COM_DROP_DB: // QQ: To be removed
- {
- status_var_increment(thd->status_var.com_stat[SQLCOM_DROP_DB]);
- LEX_STRING db;
-
- if (thd->make_lex_string(&db, packet, packet_length, FALSE) ||
- check_db_name(&db))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), db.str ? db.str : "NULL");
- break;
- }
- if (check_access(thd, DROP_ACL, db.str, 0, 1, 0, is_schema_db(db.str)))
- break;
- if (thd->locked_tables || thd->active_transaction())
- {
- my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
- ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
- break;
- }
- general_log_write(thd, command, "%.*s", db.length, db.str);
- mysql_rm_db(thd, db.str, 0, 0);
- break;
- }
-#endif
#ifndef EMBEDDED_LIBRARY
case COM_BINLOG_DUMP:
{
@@ -2073,7 +2025,6 @@ mysql_execute_command(THD *thd)
A better approach would be to reset this for any commands
that is not a SHOW command or a select that only access local
variables, but for now this is probably good enough.
- Don't reset warnings when executing a stored routine.
*/
if ((sql_command_flags[lex->sql_command] & CF_DIAGNOSTIC_STMT) != 0)
thd->warning_info->set_read_only(TRUE);
@@ -2276,7 +2227,7 @@ mysql_execute_command(THD *thd)
privileges_requested,
all_tables, FALSE, UINT_MAX, FALSE);
else
- res= check_access(thd, privileges_requested, any_db, 0, 0, 0, UINT_MAX);
+ res= check_access(thd, privileges_requested, any_db, 0, 0, 0, 0);
if (res)
break;
@@ -5830,7 +5781,6 @@ bool check_stack_overrun(THD *thd, long margin,
my_snprintf(ebuff, sizeof(ebuff), ER(ER_STACK_OVERRUN_NEED_MORE),
stack_used, my_thread_stack_size, margin);
my_message(ER_STACK_OVERRUN_NEED_MORE, ebuff, MYF(ME_FATALERROR));
- thd->fatal_error();
return 1;
}
#ifndef DBUG_OFF
@@ -6494,13 +6444,17 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
DBUG_RETURN(0); /* purecov: inspected */
if (table->db.str)
{
+ ptr->is_fqtn= TRUE;
ptr->db= table->db.str;
ptr->db_length= table->db.length;
}
else if (lex->copy_db_to(&ptr->db, &ptr->db_length))
DBUG_RETURN(0);
+ else
+ ptr->is_fqtn= FALSE;
ptr->alias= alias_str;
+ ptr->is_alias= alias ? TRUE : FALSE;
if (lower_case_table_names && table->table.length)
table->table.length= my_casedn_str(files_charset_info, table->table.str);
ptr->table_name=table->table.str;
@@ -7547,6 +7501,63 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
}
+/*
+ Given a table in the source list, find a correspondent table in the
+ table references list.
+
+ @param lex Pointer to LEX representing multi-delete.
+ @param src Source table to match.
+ @param ref Table references list.
+
+ @remark The source table list (tables listed before the FROM clause
+ or tables listed in the FROM clause before the USING clause) may
+ contain table names or aliases that must match unambiguously one,
+ and only one, table in the target table list (table references list,
+ after FROM/USING clause).
+
+ @return Matching table, NULL otherwise.
+*/
+
+static TABLE_LIST *multi_delete_table_match(LEX *lex, TABLE_LIST *tbl,
+ TABLE_LIST *tables)
+{
+ TABLE_LIST *match= NULL;
+ DBUG_ENTER("multi_delete_table_match");
+
+ for (TABLE_LIST *elem= tables; elem; elem= elem->next_local)
+ {
+ int cmp;
+
+ if (tbl->is_fqtn && elem->is_alias)
+ continue; /* no match */
+ if (tbl->is_fqtn && elem->is_fqtn)
+ cmp= my_strcasecmp(table_alias_charset, tbl->table_name, elem->table_name) ||
+ strcmp(tbl->db, elem->db);
+ else if (elem->is_alias)
+ cmp= my_strcasecmp(table_alias_charset, tbl->alias, elem->alias);
+ else
+ cmp= my_strcasecmp(table_alias_charset, tbl->table_name, elem->table_name) ||
+ strcmp(tbl->db, elem->db);
+
+ if (cmp)
+ continue;
+
+ if (match)
+ {
+ my_error(ER_NONUNIQ_TABLE, MYF(0), elem->alias);
+ DBUG_RETURN(NULL);
+ }
+
+ match= elem;
+ }
+
+ if (!match)
+ my_error(ER_UNKNOWN_TABLE, MYF(0), tbl->table_name, "MULTI DELETE");
+
+ DBUG_RETURN(match);
+}
+
+
/**
Link tables in auxilary table list of multi-delete with corresponding
elements in main table list, and set proper locks for them.
@@ -7572,20 +7583,9 @@ bool multi_delete_set_locks_and_link_aux_tables(LEX *lex)
{
lex->table_count++;
/* All tables in aux_tables must be found in FROM PART */
- TABLE_LIST *walk;
- for (walk= tables; walk; walk= walk->next_local)
- {
- if (!my_strcasecmp(table_alias_charset,
- target_tbl->alias, walk->alias) &&
- !strcmp(walk->db, target_tbl->db))
- break;
- }
+ TABLE_LIST *walk= multi_delete_table_match(lex, target_tbl, tables);
if (!walk)
- {
- my_error(ER_UNKNOWN_TABLE, MYF(0),
- target_tbl->table_name, "MULTI DELETE");
DBUG_RETURN(TRUE);
- }
if (!walk->derived)
{
target_tbl->table_name= walk->table_name;
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 417b23c076e..868dfc3e968 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -2407,8 +2407,7 @@ char *generate_partition_syntax(partition_info *part_info,
default:
DBUG_ASSERT(0);
/* We really shouldn't get here, no use in continuing from here */
- my_error(ER_OUT_OF_RESOURCES, MYF(0));
- current_thd->fatal_error();
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
DBUG_RETURN(NULL);
}
if (part_info->part_expr)
@@ -5483,10 +5482,7 @@ static bool mysql_change_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
&lpt->deleted, lpt->pack_frm_data,
lpt->pack_frm_len)))
{
- if (error != ER_OUTOFMEMORY)
- file->print_error(error, MYF(0));
- else
- lpt->thd->fatal_error();
+ file->print_error(error, MYF(error != ER_OUTOFMEMORY ? 0 : ME_FATALERROR));
DBUG_RETURN(TRUE);
}
DBUG_RETURN(FALSE);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 95270487ec8..5fdab6b6f2f 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -9708,7 +9708,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item_sum *item_sum=(Item_sum*) item;
result= item_sum->create_tmp_field(group, table, convert_blob_length);
if (!result)
- thd->fatal_error();
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
return result;
}
case Item::FIELD_ITEM:
@@ -10852,8 +10852,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
We don't want this error to be converted to a warning, e.g. in case of
INSERT IGNORE ... SELECT.
*/
- thd->fatal_error();
- table->file->print_error(error,MYF(0));
+ table->file->print_error(error, MYF(ME_FATALERROR));
DBUG_RETURN(1);
}
@@ -15059,8 +15058,7 @@ calc_group_buffer(JOIN *join,ORDER *group)
default:
/* This case should never be choosen */
DBUG_ASSERT(0);
- my_error(ER_OUT_OF_RESOURCES, MYF(0));
- join->thd->fatal_error();
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
}
}
parts++;
diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc
index e8fa3d984a7..be86d1150b7 100644
--- a/sql/sql_servers.cc
+++ b/sql/sql_servers.cc
@@ -128,7 +128,7 @@ bool servers_init(bool dont_read_servers_table)
}
/* Initialize the mem root for data */
- init_alloc_root(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
+ init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
if (dont_read_servers_table)
goto end;
@@ -180,7 +180,7 @@ static bool servers_load(THD *thd, TABLE_LIST *tables)
my_hash_reset(&servers_cache);
free_root(&mem, MYF(0));
- init_alloc_root(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
+ init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
init_read_record(&read_record_info,thd,table=tables[0].table,NULL,1,0,
FALSE);
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index b9f5015f8f0..3af0df73079 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1705,6 +1705,32 @@ public:
template class I_List<thread_info>;
#endif
+static const char *thread_state_info(THD *tmp)
+{
+ if (tmp->locked)
+ return "Locked";
+#ifndef EMBEDDED_LIBRARY
+ if (tmp->net.reading_or_writing)
+ {
+ if (tmp->net.reading_or_writing == 2)
+ return "Writing to net";
+ else if (tmp->command == COM_SLEEP)
+ return "";
+ else
+ return "Reading from net";
+ }
+ else
+#endif
+ {
+ if (tmp->proc_info)
+ return tmp->proc_info;
+ else if (tmp->mysys_var && tmp->mysys_var->current_cond)
+ return "Waiting on cond";
+ else
+ return NULL;
+ }
+}
+
void mysqld_list_processes(THD *thd,const char *user, bool verbose)
{
Item *field;
@@ -1766,20 +1792,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
if ((mysys_var= tmp->mysys_var))
pthread_mutex_lock(&mysys_var->mutex);
thd_info->proc_info= (char*) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0);
-#ifndef EMBEDDED_LIBRARY
- thd_info->state_info= (char*) (tmp->locked ? "Locked" :
- tmp->net.reading_or_writing ?
- (tmp->net.reading_or_writing == 2 ?
- "Writing to net" :
- thd_info->command == COM_SLEEP ? "" :
- "Reading from net") :
- tmp->proc_info ? tmp->proc_info :
- tmp->mysys_var &&
- tmp->mysys_var->current_cond ?
- "Waiting on cond" : NullS);
-#else
- thd_info->state_info= (char*)"Writing to net";
-#endif
+ thd_info->state_info= thread_state_info(tmp);
if (mysys_var)
pthread_mutex_unlock(&mysys_var->mutex);
@@ -1891,21 +1904,7 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond)
table->field[5]->store((longlong)(tmp->start_time ?
now - tmp->start_time : 0), FALSE);
/* STATE */
-#ifndef EMBEDDED_LIBRARY
- val= (char*) (tmp->locked ? "Locked" :
- tmp->net.reading_or_writing ?
- (tmp->net.reading_or_writing == 2 ?
- "Writing to net" :
- tmp->command == COM_SLEEP ? "" :
- "Reading from net") :
- tmp->proc_info ? tmp->proc_info :
- tmp->mysys_var &&
- tmp->mysys_var->current_cond ?
- "Waiting on cond" : NullS);
-#else
- val= (char *) (tmp->proc_info ? tmp->proc_info : NullS);
-#endif
- if (val)
+ if ((val= thread_state_info(tmp)))
{
table->field[6]->store(val, strlen(val), cs);
table->field[6]->set_notnull();
@@ -5071,8 +5070,7 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
break;
default:
DBUG_ASSERT(0);
- my_error(ER_OUT_OF_RESOURCES, MYF(0));
- current_thd->fatal_error();
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
DBUG_RETURN(1);
}
table->field[7]->set_notnull();
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 593450cacd5..a0ea75a0b0a 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -23,6 +23,7 @@
#include <my_sys.h>
#include <m_string.h>
#include <m_ctype.h>
+#include <mysql_com.h>
#ifdef HAVE_FCONVERT
#include <floatingpoint.h>
#endif
@@ -499,22 +500,6 @@ bool String::append(const char *s,uint32 arg_length, CHARSET_INFO *cs)
return FALSE;
}
-
-#ifdef TO_BE_REMOVED
-bool String::append(FILE* file, uint32 arg_length, myf my_flags)
-{
- if (realloc(str_length+arg_length))
- return TRUE;
- if (my_fread(file, (uchar*) Ptr + str_length, arg_length, my_flags))
- {
- shrink(str_length);
- return TRUE;
- }
- str_length+=arg_length;
- return FALSE;
-}
-#endif
-
bool String::append(IO_CACHE* file, uint32 arg_length)
{
if (realloc(str_length+arg_length))
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 75dc1163eec..38f843e7e8f 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -22,10 +22,6 @@
#pragma interface /* gcc class implementation */
#endif
-#ifndef NOT_FIXED_DEC
-#define NOT_FIXED_DEC 31
-#endif
-
class String;
int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 61da4617610..d5c03d902e0 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -1660,7 +1660,7 @@ bool Table_triggers_list::drop_all_triggers(THD *thd, char *db, char *name)
DBUG_ENTER("drop_all_triggers");
bzero(&table, sizeof(table));
- init_alloc_root(&table.mem_root, 8192, 0);
+ init_sql_alloc(&table.mem_root, 8192, 0);
if (Table_triggers_list::check_n_load(thd, db, name, &table, 1))
{
@@ -1871,7 +1871,7 @@ bool Table_triggers_list::change_table_name(THD *thd, const char *db,
DBUG_ENTER("change_table_name");
bzero(&table, sizeof(table));
- init_alloc_root(&table.mem_root, 8192, 0);
+ init_sql_alloc(&table.mem_root, 8192, 0);
/*
This method interfaces the mysql server code protected by
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index e7b4eb22e78..4ab46107f2c 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -662,11 +662,13 @@ int mysql_update(THD *thd,
If (ignore && error is ignorable) we don't have to
do anything; otherwise...
*/
+ myf flags= 0;
+
if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
- thd->fatal_error(); /* Other handler errors are fatal */
+ flags|= ME_FATALERROR; /* Other handler errors are fatal */
prepare_record_for_error_message(error, table);
- table->file->print_error(error,MYF(0));
+ table->file->print_error(error,MYF(flags));
error= 1;
break;
}
@@ -763,9 +765,8 @@ int mysql_update(THD *thd,
*/
{
/* purecov: begin inspected */
- thd->fatal_error();
prepare_record_for_error_message(loc_error, table);
- table->file->print_error(loc_error,MYF(0));
+ table->file->print_error(loc_error,MYF(ME_FATALERROR));
error= 1;
/* purecov: end */
}
@@ -1742,11 +1743,13 @@ bool multi_update::send_data(List<Item> &not_used_values)
If (ignore && error == is ignorable) we don't have to
do anything; otherwise...
*/
+ myf flags= 0;
+
if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
- thd->fatal_error(); /* Other handler errors are fatal */
+ flags|= ME_FATALERROR; /* Other handler errors are fatal */
prepare_record_for_error_message(error, table);
- table->file->print_error(error,MYF(0));
+ table->file->print_error(error,MYF(flags));
DBUG_RETURN(1);
}
}
@@ -2029,9 +2032,8 @@ int multi_update::do_updates()
err:
{
- thd->fatal_error();
prepare_record_for_error_message(local_error, table);
- table->file->print_error(local_error,MYF(0));
+ table->file->print_error(local_error,MYF(ME_FATALERROR));
}
err2:
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index a0026183245..b1e750f09d5 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1190,7 +1190,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <item>
literal text_literal insert_ident order_ident
- simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
+ simple_ident expr opt_expr opt_else sum_expr in_sum_expr
variable variable_aux bool_pri
predicate bit_expr
table_wild simple_expr udf_expr
@@ -1350,7 +1350,7 @@ END_OF_INPUT
%type <NONE>
'-' '+' '*' '/' '%' '(' ')'
',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_SYM BETWEEN_SYM CASE_SYM
- THEN_SYM WHEN_SYM DIV_SYM MOD_SYM OR2_SYM AND_AND_SYM
+ THEN_SYM WHEN_SYM DIV_SYM MOD_SYM OR2_SYM AND_AND_SYM DELETE_SYM
%%
/*
@@ -6946,7 +6946,14 @@ select_item_list:
;
select_item:
- remember_name select_item2 remember_end select_alias
+ remember_name table_wild remember_end
+ {
+ THD *thd= YYTHD;
+
+ if (add_item_to_list(thd, $2))
+ MYSQL_YYABORT;
+ }
+ | remember_name expr remember_end select_alias
{
THD *thd= YYTHD;
DBUG_ASSERT($1 < $3);
@@ -6983,11 +6990,6 @@ remember_end:
}
;
-select_item2:
- table_wild { $$=$1; /* table.* */ }
- | expr { $$=$1; }
- ;
-
select_alias:
/* empty */ { $$=null_lex_str;}
| AS ident { $$=$2; }
@@ -10048,7 +10050,7 @@ delete:
lex->ignore= 0;
lex->select_lex.init_order();
}
- opt_delete_options single_multi {}
+ opt_delete_options single_multi
;
single_multi:
@@ -10063,45 +10065,45 @@ single_multi:
| table_wild_list
{ mysql_init_multi_delete(Lex); }
FROM join_table_list where_clause
- {
+ {
if (multi_delete_set_locks_and_link_aux_tables(Lex))
MYSQL_YYABORT;
}
| FROM table_alias_ref_list
{ mysql_init_multi_delete(Lex); }
USING join_table_list where_clause
- {
+ {
if (multi_delete_set_locks_and_link_aux_tables(Lex))
MYSQL_YYABORT;
}
;
table_wild_list:
- table_wild_one {}
- | table_wild_list ',' table_wild_one {}
+ table_wild_one
+ | table_wild_list ',' table_wild_one
;
table_wild_one:
- ident opt_wild opt_table_alias
+ ident opt_wild
{
Table_ident *ti= new Table_ident($1);
if (ti == NULL)
MYSQL_YYABORT;
if (!Select->add_table_to_list(YYTHD,
ti,
- $3,
+ NULL,
TL_OPTION_UPDATING | TL_OPTION_ALIAS,
Lex->lock_option))
MYSQL_YYABORT;
}
- | ident '.' ident opt_wild opt_table_alias
+ | ident '.' ident opt_wild
{
Table_ident *ti= new Table_ident(YYTHD, $1, $3, 0);
if (ti == NULL)
MYSQL_YYABORT;
if (!Select->add_table_to_list(YYTHD,
ti,
- $5,
+ NULL,
TL_OPTION_UPDATING | TL_OPTION_ALIAS,
Lex->lock_option))
MYSQL_YYABORT;
diff --git a/sql/table.h b/sql/table.h
index 49a97958807..76bebd3fdaa 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1332,6 +1332,12 @@ struct TABLE_LIST
*/
bool create;
bool internal_tmp_table;
+ /** TRUE if an alias for this table was specified in the SQL. */
+ bool is_alias;
+ /** TRUE if the table is referred to in the statement using a fully
+ qualified name (<db_name>.<table_name>).
+ */
+ bool is_fqtn;
/* View creation context. */
diff --git a/sql/tztime.cc b/sql/tztime.cc
index 650678c721b..93ff614b10b 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -1594,7 +1594,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
my_hash_free(&tz_names);
goto end;
}
- init_alloc_root(&tz_storage, 32 * 1024, 0);
+ init_sql_alloc(&tz_storage, 32 * 1024, 0);
VOID(pthread_mutex_init(&tz_LOCK, MY_MUTEX_INIT_FAST));
tz_inited= 1;
diff --git a/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp b/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp
index 3923d8e6fbf..43de91b7c22 100644
--- a/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp
+++ b/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp
@@ -30,10 +30,6 @@
#define DECIMAL_MAX_LENGTH ((8 * 9) - 8)
-#ifndef NOT_FIXED_DEC
-#define NOT_FIXED_DEC 31
-#endif
-
C_MODE_START
extern int decimal_bin_size(int, int);
C_MODE_END
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index 95d97af2bfb..3b6a977e47c 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -278,14 +278,11 @@ void my_hash_sort_8bit_bin(CHARSET_INFO *cs __attribute__((unused)),
{
const uchar *pos = key;
- key+= len;
-
/*
Remove trailing spaces. We have to do this to be able to compare
'A ' and 'A' as identical
*/
- while (key > pos && key[-1] == ' ')
- key--;
+ key= skip_trailing_space(key, len);
for (; pos < (uchar*) key ; pos++)
{
diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c
index e5333c4101b..dbd91c09637 100644
--- a/strings/ctype-latin1.c
+++ b/strings/ctype-latin1.c
@@ -678,13 +678,12 @@ void my_hash_sort_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
const uchar *key, size_t len,
ulong *nr1, ulong *nr2)
{
- const uchar *end= key+len;
+ const uchar *end;
/*
Remove end space. We have to do this to be able to compare
'AE' and 'Ä' as identical
*/
- while (end > key && end[-1] == ' ')
- end--;
+ end= skip_trailing_space(key, len);
for (; key < end ; key++)
{
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index 903811e2ab9..b0f7c297260 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -469,14 +469,11 @@ static void my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)),
{
const uchar *pos = key;
- key+= len;
-
/*
Remove trailing spaces. We have to do this to be able to compare
'A ' and 'A' as identical
*/
- while (key > pos && key[-1] == ' ')
- key--;
+ key= skip_trailing_space(key, len);
for (; pos < (uchar*) key ; pos++)
{
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index 4f3aaa6f668..6ff8c83dcf7 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -304,14 +304,13 @@ void my_hash_sort_simple(CHARSET_INFO *cs,
ulong *nr1, ulong *nr2)
{
register uchar *sort_order=cs->sort_order;
- const uchar *end= key + len;
+ const uchar *end;
/*
Remove end space. We have to do this to be able to compare
'A ' and 'A' as identical
*/
- while (end > key && end[-1] == ' ')
- end--;
+ end= skip_trailing_space(key, len);
for (; key < (uchar*) end ; key++)
{
@@ -1165,9 +1164,8 @@ size_t my_well_formed_len_8bit(CHARSET_INFO *cs __attribute__((unused)),
size_t my_lengthsp_8bit(CHARSET_INFO *cs __attribute__((unused)),
const char *ptr, size_t length)
{
- const char *end= ptr+length;
- while (end > ptr && end[-1] == ' ')
- end--;
+ const char *end;
+ end= (const char *) skip_trailing_space((const uchar *)ptr, length);
return (size_t) (end-ptr);
}
diff --git a/vio/vio.c b/vio/vio.c
index fd8e2e5a402..34e02adae3d 100644
--- a/vio/vio.c
+++ b/vio/vio.c
@@ -22,6 +22,28 @@
#include "vio_priv.h"
+#if defined(__WIN__) || defined(HAVE_SMEM)
+
+/**
+ Stub poll_read method that defaults to indicate that there
+ is data to read.
+
+ Used for named pipe and shared memory VIO types.
+
+ @param vio Unused.
+ @param timeout Unused.
+
+ @retval FALSE There is data to read.
+*/
+
+static my_bool no_poll_read(Vio *vio __attribute__((unused)),
+ uint timeout __attribute__((unused)))
+{
+ return FALSE;
+}
+
+#endif
+
/*
* Helper to fill most of the Vio* with defaults.
*/
@@ -60,6 +82,9 @@ static void vio_init(Vio* vio, enum enum_vio_type type,
vio->vioblocking =vio_blocking;
vio->is_blocking =vio_is_blocking;
+ vio->poll_read =no_poll_read;
+ vio->is_connected =vio_is_connected_pipe;
+
vio->timeout=vio_win32_timeout;
/* Set default timeout */
vio->read_timeout_millis = INFINITE;
@@ -87,6 +112,9 @@ static void vio_init(Vio* vio, enum enum_vio_type type,
vio->vioblocking =vio_blocking;
vio->is_blocking =vio_is_blocking;
+ vio->poll_read =no_poll_read;
+ vio->is_connected =vio_is_connected_shared_memory;
+
/* Currently, shared memory is on Windows only, hence the below is ok*/
vio->timeout= vio_win32_timeout;
/* Set default timeout */
@@ -112,6 +140,8 @@ static void vio_init(Vio* vio, enum enum_vio_type type,
vio->vioblocking =vio_ssl_blocking;
vio->is_blocking =vio_is_blocking;
vio->timeout =vio_timeout;
+ vio->poll_read =vio_poll_read;
+ vio->is_connected =vio_is_connected;
DBUG_VOID_RETURN;
}
#endif /* HAVE_OPENSSL */
@@ -130,6 +160,8 @@ static void vio_init(Vio* vio, enum enum_vio_type type,
vio->vioblocking =vio_blocking;
vio->is_blocking =vio_is_blocking;
vio->timeout =vio_timeout;
+ vio->poll_read =vio_poll_read;
+ vio->is_connected =vio_is_connected;
}
DBUG_VOID_RETURN;
}
diff --git a/vio/vio_priv.h b/vio/vio_priv.h
index 21fa80143cd..c1ac2ab8365 100644
--- a/vio/vio_priv.h
+++ b/vio/vio_priv.h
@@ -29,6 +29,20 @@
void vio_win32_timeout(Vio *vio, uint which, uint timeout);
#endif
+#ifdef __WIN__
+size_t vio_read_pipe(Vio *vio, uchar * buf, size_t size);
+size_t vio_write_pipe(Vio *vio, const uchar * buf, size_t size);
+my_bool vio_is_connected_pipe(Vio *vio);
+int vio_close_pipe(Vio * vio);
+#endif
+
+#ifdef HAVE_SMEM
+size_t vio_read_shared_memory(Vio *vio, uchar * buf, size_t size);
+size_t vio_write_shared_memory(Vio *vio, const uchar * buf, size_t size);
+my_bool vio_is_connected_shared_memory(Vio *vio);
+int vio_close_shared_memory(Vio * vio);
+#endif
+
void vio_timeout(Vio *vio,uint which, uint timeout);
#ifdef HAVE_OPENSSL
diff --git a/vio/viosocket.c b/vio/viosocket.c
index c929cac2a05..30187cbed56 100644
--- a/vio/viosocket.c
+++ b/vio/viosocket.c
@@ -350,28 +350,163 @@ void vio_in_addr(Vio *vio, struct in_addr *in)
}
-/* Return 0 if there is data to be read */
+/**
+ Indicate whether there is data to read on a given socket.
+
+ @note An exceptional condition event and/or errors are
+ interpreted as if there is data to read.
+
+ @param sd A connected socket.
+ @param timeout Maximum time in seconds to poll.
+
+ @retval FALSE There is data to read.
+ @retval TRUE There is no data to read.
+*/
-my_bool vio_poll_read(Vio *vio,uint timeout)
+static my_bool socket_poll_read(my_socket sd, uint timeout)
{
-#ifndef HAVE_POLL
- return 0;
-#else
+#ifdef __WIN__
+ int res;
+ my_socket fd= sd;
+ fd_set readfds, errorfds;
+ struct timeval tm;
+ DBUG_ENTER("socket_poll_read");
+ tm.tv_sec= timeout;
+ tm.tv_usec= 0;
+ FD_ZERO(&readfds);
+ FD_ZERO(&errorfds);
+ FD_SET(fd, &readfds);
+ FD_SET(fd, &errorfds);
+ if ((res= select(fd, &readfds, NULL, &errorfds, &tm) <= 0))
+ {
+ DBUG_RETURN(res < 0 ? 0 : 1);
+ }
+ res= FD_ISSET(fd, &readfds) || FD_ISSET(fd, &errorfds);
+ DBUG_RETURN(!res);
+#elif defined(HAVE_POLL)
struct pollfd fds;
int res;
- DBUG_ENTER("vio_poll");
- fds.fd=vio->sd;
+ DBUG_ENTER("socket_poll_read");
+ fds.fd=sd;
fds.events=POLLIN;
fds.revents=0;
if ((res=poll(&fds,1,(int) timeout*1000)) <= 0)
{
DBUG_RETURN(res < 0 ? 0 : 1); /* Don't return 1 on errors */
}
- DBUG_RETURN(fds.revents & POLLIN ? 0 : 1);
+ DBUG_RETURN(fds.revents & (POLLIN | POLLERR | POLLHUP) ? 0 : 1);
+#else
+ return 0;
#endif
}
+/**
+ Retrieve the amount of data that can be read from a socket.
+
+ @param vio A VIO object.
+ @param bytes[out] The amount of bytes available.
+
+ @retval FALSE Success.
+ @retval TRUE Failure.
+*/
+
+static my_bool socket_peek_read(Vio *vio, uint *bytes)
+{
+#ifdef __WIN__
+ int len;
+ if (ioctlsocket(vio->sd, FIONREAD, &len))
+ return TRUE;
+ *bytes= len;
+ return FALSE;
+#elif FIONREAD_IN_SYS_IOCTL
+ int len;
+ if (ioctl(vio->sd, FIONREAD, &len) < 0)
+ return TRUE;
+ *bytes= len;
+ return FALSE;
+#else
+ char buf[1024];
+ ssize_t res= recv(vio->sd, &buf, sizeof(buf), MSG_PEEK);
+ if (res < 0)
+ return TRUE;
+ *bytes= res;
+ return FALSE;
+#endif
+}
+
+
+/**
+ Indicate whether there is data to read on a given socket.
+
+ @remark Errors are interpreted as if there is data to read.
+
+ @param sd A connected socket.
+ @param timeout Maximum time in seconds to wait.
+
+ @retval FALSE There is data (or EOF) to read. Also FALSE if error.
+ @retval TRUE There is _NO_ data to read or timed out.
+*/
+
+my_bool vio_poll_read(Vio *vio, uint timeout)
+{
+ my_socket sd= vio->sd;
+ DBUG_ENTER("vio_poll_read");
+#ifdef HAVE_OPENSSL
+ if (vio->type == VIO_TYPE_SSL)
+ sd= SSL_get_fd((SSL*) vio->ssl_arg);
+#endif
+ DBUG_RETURN(socket_poll_read(sd, timeout));
+}
+
+
+/**
+ Determine if the endpoint of a connection is still available.
+
+ @remark The socket is assumed to be disconnected if an EOF
+ condition is encountered.
+
+ @param vio The VIO object.
+
+ @retval TRUE EOF condition not found.
+ @retval FALSE EOF condition is signaled.
+*/
+
+my_bool vio_is_connected(Vio *vio)
+{
+ uint bytes= 0;
+ DBUG_ENTER("vio_is_connected");
+
+ /* In the presence of errors the socket is assumed to be connected. */
+
+ /*
+ The first step of detecting a EOF condition is veryfing
+ whether there is data to read. Data in this case would
+ be the EOF.
+ */
+ if (vio_poll_read(vio, 0))
+ DBUG_RETURN(TRUE);
+
+ /*
+ The second step is read() or recv() from the socket returning
+ 0 (EOF). Unfortunelly, it's not possible to call read directly
+ as we could inadvertently read meaningful connection data.
+ Simulate a read by retrieving the number of bytes available to
+ read -- 0 meaning EOF.
+ */
+ if (socket_peek_read(vio, &bytes))
+ DBUG_RETURN(TRUE);
+
+#ifdef HAVE_OPENSSL
+ /* There might be buffered data at the SSL layer. */
+ if (!bytes && vio->type == VIO_TYPE_SSL)
+ bytes= SSL_pending((SSL*) vio->ssl_arg);
+#endif
+
+ DBUG_RETURN(bytes ? TRUE : FALSE);
+}
+
+
void vio_timeout(Vio *vio, uint which, uint timeout)
{
#if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO)
@@ -494,6 +629,15 @@ size_t vio_write_pipe(Vio * vio, const uchar* buf, size_t size)
}
+my_bool vio_is_connected_pipe(Vio *vio)
+{
+ if (PeekNamedPipe(vio->hPipe, NULL, 0, NULL, NULL, NULL))
+ return TRUE;
+ else
+ return (GetLastError() != ERROR_BROKEN_PIPE);
+}
+
+
int vio_close_pipe(Vio * vio)
{
int r;
@@ -644,6 +788,12 @@ size_t vio_write_shared_memory(Vio * vio, const uchar* buf, size_t size)
}
+my_bool vio_is_connected_shared_memory(Vio *vio)
+{
+ return (WaitForSingleObject(vio->event_conn_closed, 0) != WAIT_OBJECT_0);
+}
+
+
/**
Close shared memory and DBUG_PRINT any errors that happen on closing.
@return Zero if all closing functions succeed, and nonzero otherwise.