summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2012-08-29 18:50:38 -0700
committerIgor Babaev <igor@askmonty.org>2012-08-29 18:50:38 -0700
commit98f239a8494104743b4a7f2df5b8d7f310975689 (patch)
tree4beee747e184ab6b7d873d936e244397e4f8b49d /sql
parentd0ad93fbc7eca575364e46f67c4613efb0807047 (diff)
parentb45c551ee32d0d5260f4958abf93efab1a4614a2 (diff)
downloadmariadb-git-98f239a8494104743b4a7f2df5b8d7f310975689.tar.gz
Merge 5.5->5.5-mwl248.
Diffstat (limited to 'sql')
-rw-r--r--sql/create_options.cc5
-rw-r--r--sql/filesort.cc12
-rw-r--r--sql/ha_ndbcluster_binlog.cc25
-rw-r--r--sql/ha_partition.cc2
-rw-r--r--sql/handler.cc10
-rw-r--r--sql/item.cc18
-rw-r--r--sql/item.h1
-rw-r--r--sql/item_cmpfunc.cc19
-rw-r--r--sql/item_func.cc4
-rw-r--r--sql/item_func.h2
-rw-r--r--sql/item_subselect.cc55
-rw-r--r--sql/log.cc11
-rw-r--r--sql/log.h2
-rw-r--r--sql/log_event.cc401
-rw-r--r--sql/log_event.h57
-rw-r--r--sql/log_event_old.cc2
-rw-r--r--sql/log_event_old.h2
-rw-r--r--sql/multi_range_read.cc2
-rw-r--r--sql/opt_range.cc3
-rw-r--r--sql/opt_subselect.cc12
-rw-r--r--sql/repl_failsafe.cc1
-rw-r--r--sql/rpl_record.cc2
-rw-r--r--sql/rpl_utility.cc7
-rw-r--r--sql/share/errmsg-utf8.txt3
-rw-r--r--sql/slave.cc3
-rw-r--r--sql/sp.cc1
-rw-r--r--sql/sp_head.cc1
-rw-r--r--sql/sql_admin.cc1
-rw-r--r--sql/sql_base.cc32
-rw-r--r--sql/sql_cache.cc3
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/sql_cursor.cc2
-rw-r--r--sql/sql_db.cc41
-rw-r--r--sql/sql_lex.cc1
-rw-r--r--sql/sql_load.cc90
-rw-r--r--sql/sql_parse.cc2
-rw-r--r--sql/sql_partition.cc6
-rw-r--r--sql/sql_repl.cc4
-rw-r--r--sql/sql_select.cc67
-rw-r--r--sql/sql_select.h13
-rw-r--r--sql/sql_show.cc25
-rw-r--r--sql/sql_show.h2
-rw-r--r--sql/sql_string.cc28
-rw-r--r--sql/sql_string.h1
-rw-r--r--sql/sql_table.cc60
-rw-r--r--sql/sql_truncate.cc41
-rw-r--r--sql/sql_union.cc2
-rw-r--r--sql/sql_yacc.yy2
-rw-r--r--sql/sys_vars.cc51
-rw-r--r--sql/sys_vars.h4
-rw-r--r--sql/table.cc2
51 files changed, 664 insertions, 481 deletions
diff --git a/sql/create_options.cc b/sql/create_options.cc
index 9a6f6b5cf7c..e4881388688 100644
--- a/sql/create_options.cc
+++ b/sql/create_options.cc
@@ -137,7 +137,10 @@ static bool set_one_value(ha_create_table_option *opt,
my_option optp=
{ opt->name, 1, 0, (uchar **)val, 0, 0, GET_ULL,
- REQUIRED_ARG, opt->def_value, opt->min_value, opt->max_value,
+ REQUIRED_ARG,
+ (longlong) opt->def_value,
+ (longlong) opt->min_value,
+ opt->max_value,
0, (long) opt->block_size, 0};
ulonglong orig_val= strtoull(value->str, NULL, 10);
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 03379f2738a..04b223b7db0 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -103,6 +103,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
int error;
ulong memory_available= thd->variables.sortbuff_size;
ulong min_sort_memory;
+ ulong sort_buff_sz;
uint maxbuffer;
BUFFPEK *buffpek;
ha_rows num_rows= HA_POS_ERROR;
@@ -193,19 +194,21 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
goto err;
min_sort_memory= max(MIN_SORT_MEMORY, param.sort_length * MERGEBUFF2);
+ set_if_bigger(min_sort_memory, sizeof(BUFFPEK*)*MERGEBUFF2);
if (!table_sort.sort_keys)
{
while (memory_available >= min_sort_memory)
{
ulong keys= memory_available / (param.rec_length + sizeof(char*));
table_sort.keys= (uint) min(num_rows, keys);
+ sort_buff_sz= table_sort.keys*(param.rec_length+sizeof(char*));
+ set_if_bigger(sort_buff_sz, param.rec_length * MERGEBUFF2);
DBUG_EXECUTE_IF("make_sort_keys_alloc_fail",
DBUG_SET("+d,simulate_out_of_memory"););
if ((table_sort.sort_keys=
- (uchar**) my_malloc(table_sort.keys*(param.rec_length+sizeof(char*)),
- MYF(0))))
+ (uchar**) my_malloc(sort_buff_sz, MYF(0))))
break;
ulong old_memory_available= memory_available;
memory_available= memory_available/4*3;
@@ -1259,9 +1262,8 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
to_start_filepos= my_b_tell(to_file);
strpos= sort_buffer;
org_max_rows=max_rows= param->max_rows;
-
- /* The following will fire if there is not enough space in sort_buffer */
- DBUG_ASSERT(maxcount!=0);
+
+ set_if_bigger(maxcount, 1);
if (unique_buff)
{
diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc
index f91e19df08e..59b9d6eab6b 100644
--- a/sql/ha_ndbcluster_binlog.cc
+++ b/sql/ha_ndbcluster_binlog.cc
@@ -1295,7 +1295,9 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
DBUG_RETURN(0);
}
- char tmp_buf2[FN_REFLEN];
+ char tmp_buf2_mem[FN_REFLEN];
+ String tmp_buf2(tmp_buf2_mem, sizeof(tmp_buf2_mem), system_charset_info);
+ tmp_buf2.length(0);
const char *type_str;
switch (type)
{
@@ -1304,17 +1306,24 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
if (thd->lex->sql_command == SQLCOM_DROP_DB)
DBUG_RETURN(0);
/* redo the drop table query as is may contain several tables */
- query= tmp_buf2;
- query_length= (uint) (strxmov(tmp_buf2, "drop table `",
- table_name, "`", NullS) - tmp_buf2);
+ tmp_buf2.append(STRING_WITH_LEN("drop table "));
+ append_identifier(thd, &tmp_buf2, table_name, strlen(table_name));
+ query= tmp_buf2.c_ptr_safe();
+ query_length= tmp_buf2.length();
type_str= "drop table";
break;
case SOT_RENAME_TABLE:
/* redo the rename table query as is may contain several tables */
- query= tmp_buf2;
- query_length= (uint) (strxmov(tmp_buf2, "rename table `",
- db, ".", table_name, "` to `",
- new_db, ".", new_table_name, "`", NullS) - tmp_buf2);
+ tmp_buf2.append(STRING_WITH_LEN("rename table "));
+ append_identifier(thd, &tmp_buf2, db, strlen(db));
+ tmp_buf2.append(STRING_WITH_LEN("."));
+ append_identifier(thd, &tmp_buf2, table_name, strlen(table_name));
+ tmp_buf2.append(STRING_WITH_LEN(" to "));
+ append_identifier(thd, &tmp_buf2, new_db, strlen(new_db));
+ tmp_buf2.append(STRING_WITH_LEN("."));
+ append_identifier(thd, &tmp_buf2, new_table_name, strlen(new_table_name));
+ query= tmp_buf2.c_ptr_safe();
+ query_length= tmp_buf2.length();
type_str= "rename table";
break;
case SOT_CREATE_TABLE:
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 0d2b4387327..b3f97d35033 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -3837,7 +3837,7 @@ int ha_partition::truncate_partition(Alter_info *alter_info, bool *binlog_stmt)
{
List_iterator<partition_element>
subpart_it(part_elem->subpartitions);
- partition_element *sub_elem;
+ partition_element *sub_elem __attribute__((unused));
uint j= 0, part;
do
{
diff --git a/sql/handler.cc b/sql/handler.cc
index b5c9716bbbf..58d37532796 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -3009,7 +3009,7 @@ void handler::print_error(int error, myf errflag)
textno=ER_TABLE_DEF_CHANGED;
break;
case HA_ERR_NO_SUCH_TABLE:
- my_error(ER_NO_SUCH_TABLE, errflag, table_share->db.str,
+ my_error(ER_NO_SUCH_TABLE_IN_ENGINE, errflag, table_share->db.str,
table_share->table_name.str);
DBUG_VOID_RETURN;
case HA_ERR_RBR_LOGGING_FAILED:
@@ -4800,10 +4800,14 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
db_type->show_status(db_type, thd, stat_print, stat) ? 1 : 0;
}
- if (!result)
+ /*
+ We also check thd->is_error() as Innodb may return 0 even if
+ there was an error.
+ */
+ if (!result && !thd->is_error())
my_eof(thd);
else if (!thd->is_error())
- my_error(ER_GET_ERRNO, MYF(0), 0);
+ my_error(ER_GET_ERRNO, MYF(0), errno);
return result;
}
diff --git a/sql/item.cc b/sql/item.cc
index eac33041797..ac54e1925b7 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -992,15 +992,31 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs)
if (!my_charset_same(cs, system_charset_info))
{
size_t res_length;
- name= sql_strmake_with_convert(str, name_length= length, cs,
+ name= sql_strmake_with_convert(str, length, cs,
MAX_ALIAS_NAME, system_charset_info,
&res_length);
+ name_length= res_length;
}
else
name= sql_strmake(str, (name_length= min(length,MAX_ALIAS_NAME)));
}
+void Item::set_name_no_truncate(const char *str, uint length, CHARSET_INFO *cs)
+{
+ if (!my_charset_same(cs, system_charset_info))
+ {
+ size_t res_length;
+ name= sql_strmake_with_convert(str, length, cs,
+ UINT_MAX, system_charset_info,
+ &res_length);
+ name_length= res_length;
+ }
+ else
+ name= sql_strmake(str, (name_length= length));
+}
+
+
void Item::set_name_for_rollback(THD *thd, const char *str, uint length,
CHARSET_INFO *cs)
{
diff --git a/sql/item.h b/sql/item.h
index f7f3edda384..8855996b76c 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -656,6 +656,7 @@ public:
#endif
} /*lint -e1509 */
void set_name(const char *str, uint length, CHARSET_INFO *cs);
+ void set_name_no_truncate(const char *str, uint length, CHARSET_INFO *cs);
void set_name_for_rollback(THD *thd, const char *str, uint length,
CHARSET_INFO *cs);
void rename(char *new_name);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 8cfbcb97144..d950c0c1443 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -3089,6 +3089,15 @@ void Item_func_case::fix_length_and_dec()
return;
}
}
+ /*
+ Set cmp_context of all WHEN arguments. This prevents
+ Item_field::equal_fields_propagator() from transforming a
+ zerofill argument into a string constant. Such a change would
+ require rebuilding cmp_items.
+ */
+ for (i= 0; i < ncases; i+= 2)
+ args[i]->cmp_context= item_cmp_type(left_result_type,
+ args[i]->result_type());
}
if (else_expr_num == -1 || args[else_expr_num]->maybe_null)
@@ -4069,6 +4078,16 @@ void Item_func_in::fix_length_and_dec()
}
}
}
+ /*
+ Set cmp_context of all arguments. This prevents
+ Item_field::equal_fields_propagator() from transforming a zerofill integer
+ argument into a string constant. Such a change would require rebuilding
+ cmp_itmes.
+ */
+ for (arg= args + 1, arg_end= args + arg_count; arg != arg_end ; arg++)
+ {
+ arg[0]->cmp_context= item_cmp_type(left_result_type, arg[0]->result_type());
+ }
max_length= 1;
}
diff --git a/sql/item_func.cc b/sql/item_func.cc
index d65f13931e2..7a7cdd4ba02 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -5443,10 +5443,10 @@ my_decimal* Item_user_var_as_out_param::val_decimal(my_decimal *decimal_buffer)
}
-void Item_user_var_as_out_param::print(String *str, enum_query_type query_type)
+void Item_user_var_as_out_param::print_for_load(THD *thd, String *str)
{
str->append('@');
- str->append(name.str,name.length);
+ append_identifier(thd, str, name.str, name.length);
}
diff --git a/sql/item_func.h b/sql/item_func.h
index cb9c1929d7d..111479c8e52 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1670,7 +1670,7 @@ public:
my_decimal *val_decimal(my_decimal *decimal_buffer);
/* fix_fields() binds variable name with its entry structure */
bool fix_fields(THD *thd, Item **ref);
- virtual void print(String *str, enum_query_type query_type);
+ void print_for_load(THD *thd, String *str);
void set_null_value(CHARSET_INFO* cs);
void set_value(const char *str, uint length, CHARSET_INFO* cs);
};
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 49d232d31be..8bb4e7af00f 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -819,7 +819,9 @@ table_map Item_subselect::used_tables() const
bool Item_subselect::const_item() const
{
- return thd->lex->context_analysis_only ? FALSE : const_item_cache;
+ return (thd->lex->context_analysis_only ?
+ FALSE :
+ forced_const || const_item_cache);
}
Item *Item_subselect::get_tmp_table_item(THD *thd_arg)
@@ -1272,7 +1274,7 @@ bool Item_singlerow_subselect::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
else
{
reset();
- return 0;
+ return 1;
}
}
@@ -1538,6 +1540,10 @@ double Item_in_subselect::val_real()
*/
DBUG_ASSERT(0);
DBUG_ASSERT(fixed == 1);
+ if (forced_const)
+ return value;
+ DBUG_ASSERT((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN) ||
+ ! engine->is_executed());
null_value= was_null= FALSE;
if (exec())
{
@@ -1558,6 +1564,10 @@ longlong Item_in_subselect::val_int()
*/
DBUG_ASSERT(0);
DBUG_ASSERT(fixed == 1);
+ if (forced_const)
+ return value;
+ DBUG_ASSERT((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN) ||
+ ! engine->is_executed());
null_value= was_null= FALSE;
if (exec())
{
@@ -1578,6 +1588,10 @@ String *Item_in_subselect::val_str(String *str)
*/
DBUG_ASSERT(0);
DBUG_ASSERT(fixed == 1);
+ if (forced_const)
+ goto value_is_ready;
+ DBUG_ASSERT((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN) ||
+ ! engine->is_executed());
null_value= was_null= FALSE;
if (exec())
{
@@ -1589,6 +1603,7 @@ String *Item_in_subselect::val_str(String *str)
null_value= TRUE;
return 0;
}
+value_is_ready:
str->set((ulonglong)value, &my_charset_bin);
return str;
}
@@ -1599,6 +1614,8 @@ bool Item_in_subselect::val_bool()
DBUG_ASSERT(fixed == 1);
if (forced_const)
return value;
+ DBUG_ASSERT((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN) ||
+ ! engine->is_executed());
null_value= was_null= FALSE;
if (exec())
{
@@ -1617,6 +1634,10 @@ my_decimal *Item_in_subselect::val_decimal(my_decimal *decimal_value)
method should not be used
*/
DBUG_ASSERT(0);
+ if (forced_const)
+ goto value_is_ready;
+ DBUG_ASSERT((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN) ||
+ ! engine->is_executed());
null_value= was_null= FALSE;
DBUG_ASSERT(fixed == 1);
if (exec())
@@ -1626,6 +1647,7 @@ my_decimal *Item_in_subselect::val_decimal(my_decimal *decimal_value)
}
if (was_null && !value)
null_value= TRUE;
+value_is_ready:
int2my_decimal(E_DEC_FATAL_ERROR, value, 0, decimal_value);
return decimal_value;
}
@@ -3176,6 +3198,8 @@ int subselect_single_select_engine::exec()
tab->read_record.read_record= tab->save_read_record;
}
executed= 1;
+ if (!(uncacheable() & ~UNCACHEABLE_EXPLAIN))
+ item->make_const();
thd->where= save_where;
thd->lex->current_select= save_select;
DBUG_RETURN(join->error || thd->is_fatal_error || thd->is_error());
@@ -5167,10 +5191,20 @@ Ordered_key::cmp_keys_by_row_data(ha_rows a, ha_rows b)
rowid_a= row_num_to_rowid + a * rowid_length;
rowid_b= row_num_to_rowid + b * rowid_length;
/* Fetch the rows for comparison. */
- error= tbl->file->ha_rnd_pos(tbl->record[0], rowid_a);
- DBUG_ASSERT(!error);
- error= tbl->file->ha_rnd_pos(tbl->record[1], rowid_b);
- DBUG_ASSERT(!error);
+ if ((error= tbl->file->ha_rnd_pos(tbl->record[0], rowid_a)))
+ {
+ /* purecov: begin inspected */
+ tbl->file->print_error(error, MYF(ME_FATALERROR)); // Sets fatal_error
+ return 0;
+ /* purecov: end */
+ }
+ if ((error= tbl->file->ha_rnd_pos(tbl->record[1], rowid_b)))
+ {
+ /* purecov: begin inspected */
+ tbl->file->print_error(error, MYF(ME_FATALERROR)); // Sets fatal_error
+ return 0;
+ /* purecov: end */
+ }
/*
Compare the two rows by the corresponding values of the indexed
columns.
@@ -5245,8 +5279,13 @@ int Ordered_key::cmp_key_with_search_key(rownum_t row_num)
uchar *cur_rowid= row_num_to_rowid + row_num * rowid_length;
int error, cmp_res;
- error= tbl->file->ha_rnd_pos(tbl->record[0], cur_rowid);
- DBUG_ASSERT(!error);
+ if ((error= tbl->file->ha_rnd_pos(tbl->record[0], cur_rowid)))
+ {
+ /* purecov: begin inspected */
+ tbl->file->print_error(error, MYF(ME_FATALERROR)); // Sets fatal_error
+ return 0;
+ /* purecov: end */
+ }
for (uint i= 0; i < key_column_count; i++)
{
diff --git a/sql/log.cc b/sql/log.cc
index 9cb85ab4b2b..56c07f81c9e 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -52,6 +52,7 @@
#include "sql_plugin.h"
#include "rpl_handler.h"
#include "debug_sync.h"
+#include "sql_show.h"
/* max size of the log message */
#define MAX_LOG_BUFFER_SIZE 1024
@@ -2073,9 +2074,8 @@ static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv)
String log_query;
if (log_query.append(STRING_WITH_LEN("SAVEPOINT ")) ||
- log_query.append("`") ||
- log_query.append(thd->lex->ident.str, thd->lex->ident.length) ||
- log_query.append("`"))
+ append_identifier(thd, &log_query,
+ thd->lex->ident.str, thd->lex->ident.length))
DBUG_RETURN(1);
int errcode= query_error_code(thd, thd->killed == NOT_KILLED);
Query_log_event qinfo(thd, log_query.ptr(), log_query.length(),
@@ -2097,9 +2097,8 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv)
{
String log_query;
if (log_query.append(STRING_WITH_LEN("ROLLBACK TO ")) ||
- log_query.append("`") ||
- log_query.append(thd->lex->ident.str, thd->lex->ident.length) ||
- log_query.append("`"))
+ append_identifier(thd, &log_query,
+ thd->lex->ident.str, thd->lex->ident.length))
DBUG_RETURN(1);
int errcode= query_error_code(thd, thd->killed == NOT_KILLED);
Query_log_event qinfo(thd, log_query.ptr(), log_query.length(),
diff --git a/sql/log.h b/sql/log.h
index 88352de5418..9b9bed1262a 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -863,7 +863,7 @@ int query_error_code(THD *thd, bool not_killed);
uint purge_log_get_error_code(int res);
int vprint_msg_to_log(enum loglevel level, const char *format, va_list args);
-void sql_print_error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
+void sql_print_error(const char *format, ...);
void sql_print_warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
void sql_print_information(const char *format, ...)
ATTRIBUTE_FORMAT(printf, 1, 2);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 6ef5a68e768..dca9091e03d 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -46,6 +46,7 @@
#include "rpl_record.h"
#include "transaction.h"
#include <my_dir.h>
+#include "sql_show.h"
#endif /* MYSQL_CLIENT */
@@ -471,29 +472,28 @@ inline bool unexpected_error_code(int unexpected_error)
pretty_print_str()
*/
-static char *pretty_print_str(char *packet, const char *str, int len)
+static void
+pretty_print_str(String *packet, const char *str, int len)
{
const char *end= str + len;
- char *pos= packet;
- *pos++= '\'';
+ packet->append(STRING_WITH_LEN("'"));
while (str < end)
{
char c;
switch ((c=*str++)) {
- case '\n': *pos++= '\\'; *pos++= 'n'; break;
- case '\r': *pos++= '\\'; *pos++= 'r'; break;
- case '\\': *pos++= '\\'; *pos++= '\\'; break;
- case '\b': *pos++= '\\'; *pos++= 'b'; break;
- case '\t': *pos++= '\\'; *pos++= 't'; break;
- case '\'': *pos++= '\\'; *pos++= '\''; break;
- case 0 : *pos++= '\\'; *pos++= '0'; break;
+ case '\n': packet->append(STRING_WITH_LEN("\\n")); break;
+ case '\r': packet->append(STRING_WITH_LEN("\\r")); break;
+ case '\\': packet->append(STRING_WITH_LEN("\\\\")); break;
+ case '\b': packet->append(STRING_WITH_LEN("\\b")); break;
+ case '\t': packet->append(STRING_WITH_LEN("\\t")); break;
+ case '\'': packet->append(STRING_WITH_LEN("\\'")); break;
+ case 0 : packet->append(STRING_WITH_LEN("\\0")); break;
default:
- *pos++= c;
+ packet->append(&c, 1);
break;
}
}
- *pos++= '\'';
- return pos;
+ packet->append(STRING_WITH_LEN("'"));
}
#endif /* !MYSQL_CLIENT */
@@ -926,7 +926,7 @@ Log_event::do_shall_skip(Relay_log_info *rli)
Log_event::pack_info()
*/
-void Log_event::pack_info(Protocol *protocol)
+void Log_event::pack_info(THD *thd, Protocol *protocol)
{
protocol->store("", &my_charset_bin);
}
@@ -935,7 +935,8 @@ void Log_event::pack_info(Protocol *protocol)
/**
Only called by SHOW BINLOG EVENTS
*/
-int Log_event::net_send(Protocol *protocol, const char* log_name, my_off_t pos)
+int Log_event::net_send(THD *thd, Protocol *protocol, const char* log_name,
+ my_off_t pos)
{
const char *p= strrchr(log_name, FN_LIBCHAR);
const char *event_type;
@@ -949,7 +950,7 @@ int Log_event::net_send(Protocol *protocol, const char* log_name, my_off_t pos)
protocol->store(event_type, strlen(event_type), &my_charset_bin);
protocol->store((uint32) server_id);
protocol->store((ulonglong) log_pos);
- pack_info(protocol);
+ pack_info(thd, protocol);
return protocol->write();
}
#endif /* HAVE_REPLICATION */
@@ -2448,27 +2449,22 @@ Log_event::continue_group(Relay_log_info *rli)
show the catalog ??
*/
-void Query_log_event::pack_info(Protocol *protocol)
+void Query_log_event::pack_info(THD *thd, Protocol *protocol)
{
// TODO: show the catalog ??
- char *buf, *pos;
- if (!(buf= (char*) my_malloc(9 + db_len + q_len, MYF(MY_WME))))
- return;
- pos= buf;
+ char buf_mem[1024];
+ String buf(buf_mem, sizeof(buf_mem), system_charset_info);
+ buf.real_alloc(9 + db_len + q_len);
if (!(flags & LOG_EVENT_SUPPRESS_USE_F)
&& db && db_len)
{
- pos= strmov(buf, "use `");
- memcpy(pos, db, db_len);
- pos= strmov(pos+db_len, "`; ");
+ buf.append(STRING_WITH_LEN("use "));
+ append_identifier(thd, &buf, db, db_len);
+ buf.append("; ");
}
if (query && q_len)
- {
- memcpy(pos, query, q_len);
- pos+= q_len;
- }
- protocol->store(buf, pos-buf, &my_charset_bin);
- my_free(buf);
+ buf.append(query, q_len);
+ protocol->store(&buf);
}
#endif
@@ -3334,11 +3330,17 @@ void Query_log_event::print_query_header(IO_CACHE* file,
}
else if (db)
{
+ /* Room for expand ` to `` + initial/final ` + \0 */
+ char buf[FN_REFLEN*2+3];
+
different_db= memcmp(print_event_info->db, db, db_len + 1);
if (different_db)
memcpy(print_event_info->db, db, db_len + 1);
if (db[0] && different_db)
- my_b_printf(file, "use %s%s\n", db, print_event_info->delimiter);
+ {
+ my_snprintf(buf, sizeof(buf), "%`s", db);
+ my_b_printf(file, "use %s%s\n", buf, print_event_info->delimiter);
+ }
}
end=int10_to_str((long) when, strmov(buff,"SET TIMESTAMP="),10);
@@ -3534,6 +3536,7 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli,
LEX_STRING new_db;
int expected_error,actual_error= 0;
HA_CREATE_INFO db_options;
+ DBUG_ENTER("Query_log_event::do_apply_event");
/*
Colleagues: please never free(thd->catalog) in MySQL. This would
@@ -3929,7 +3932,7 @@ end:
thd->first_successful_insert_id_in_prev_stmt= 0;
thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
- return thd->is_slave_error;
+ DBUG_RETURN(thd->is_slave_error);
}
int Query_log_event::do_update_pos(Relay_log_info *rli)
@@ -4002,7 +4005,7 @@ Start_log_event_v3::Start_log_event_v3()
*/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-void Start_log_event_v3::pack_info(Protocol *protocol)
+void Start_log_event_v3::pack_info(THD *thd, Protocol *protocol)
{
char buf[12 + ST_SERVER_VER_LEN + 14 + 22], *pos;
pos= strmov(buf, "Server ver: ");
@@ -4778,131 +4781,113 @@ uint8 get_checksum_alg(const char* buf, ulong len)
*/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-uint Load_log_event::get_query_buffer_length()
-{
- return
- 5 + db_len + 3 + // "use DB; "
- 18 + fname_len + 2 + // "LOAD DATA INFILE 'file''"
- 11 + // "CONCURRENT "
- 7 + // LOCAL
- 9 + // " REPLACE or IGNORE "
- 13 + table_name_len*2 + // "INTO TABLE `table`"
- 21 + sql_ex.field_term_len*4 + 2 + // " FIELDS TERMINATED BY 'str'"
- 23 + sql_ex.enclosed_len*4 + 2 + // " OPTIONALLY ENCLOSED BY 'str'"
- 12 + sql_ex.escaped_len*4 + 2 + // " ESCAPED BY 'str'"
- 21 + sql_ex.line_term_len*4 + 2 + // " LINES TERMINATED BY 'str'"
- 19 + sql_ex.line_start_len*4 + 2 + // " LINES STARTING BY 'str'"
- 15 + 22 + // " IGNORE xxx LINES"
- 3 + (num_fields-1)*2 + field_block_len; // " (field1, field2, ...)"
-}
-
-
-void Load_log_event::print_query(bool need_db, const char *cs, char *buf,
- char **end, char **fn_start, char **fn_end)
+void Load_log_event::print_query(THD *thd, bool need_db, const char *cs,
+ String *buf, my_off_t *fn_start,
+ my_off_t *fn_end, const char *qualify_db)
{
- char *pos= buf;
-
if (need_db && db && db_len)
{
- pos= strmov(pos, "use `");
- memcpy(pos, db, db_len);
- pos= strmov(pos+db_len, "`; ");
+ buf->append(STRING_WITH_LEN("use "));
+ append_identifier(thd, buf, db, db_len);
+ buf->append(STRING_WITH_LEN("; "));
}
- pos= strmov(pos, "LOAD DATA ");
+ buf->append(STRING_WITH_LEN("LOAD DATA "));
if (is_concurrent)
- pos= strmov(pos, "CONCURRENT ");
+ buf->append(STRING_WITH_LEN("CONCURRENT "));
if (fn_start)
- *fn_start= pos;
+ *fn_start= buf->length();
if (check_fname_outside_temp_buf())
- pos= strmov(pos, "LOCAL ");
- pos= strmov(pos, "INFILE '");
- memcpy(pos, fname, fname_len);
- pos= strmov(pos+fname_len, "' ");
+ buf->append(STRING_WITH_LEN("LOCAL "));
+ buf->append(STRING_WITH_LEN("INFILE '"));
+ buf->append_for_single_quote(fname, fname_len);
+ buf->append(STRING_WITH_LEN("' "));
if (sql_ex.opt_flags & REPLACE_FLAG)
- pos= strmov(pos, "REPLACE ");
+ buf->append(STRING_WITH_LEN("REPLACE "));
else if (sql_ex.opt_flags & IGNORE_FLAG)
- pos= strmov(pos, "IGNORE ");
+ buf->append(STRING_WITH_LEN("IGNORE "));
- pos= strmov(pos ,"INTO");
+ buf->append(STRING_WITH_LEN("INTO"));
if (fn_end)
- *fn_end= pos;
+ *fn_end= buf->length();
- pos= strmov(pos ," TABLE `");
- memcpy(pos, table_name, table_name_len);
- pos+= table_name_len;
+ buf->append(STRING_WITH_LEN(" TABLE "));
+ if (qualify_db)
+ {
+ append_identifier(thd, buf, qualify_db, strlen(qualify_db));
+ buf->append(STRING_WITH_LEN("."));
+ }
+ append_identifier(thd, buf, table_name, table_name_len);
if (cs != NULL)
{
- pos= strmov(pos ,"` CHARACTER SET ");
- pos= strmov(pos , cs);
+ buf->append(STRING_WITH_LEN(" CHARACTER SET "));
+ buf->append(cs, strlen(cs));
}
- else
- pos= strmov(pos, "`");
/* We have to create all optional fields as the default is not empty */
- pos= strmov(pos, " FIELDS TERMINATED BY ");
- pos= pretty_print_str(pos, sql_ex.field_term, sql_ex.field_term_len);
+ buf->append(STRING_WITH_LEN(" FIELDS TERMINATED BY "));
+ pretty_print_str(buf, sql_ex.field_term, sql_ex.field_term_len);
if (sql_ex.opt_flags & OPT_ENCLOSED_FLAG)
- pos= strmov(pos, " OPTIONALLY ");
- pos= strmov(pos, " ENCLOSED BY ");
- pos= pretty_print_str(pos, sql_ex.enclosed, sql_ex.enclosed_len);
+ buf->append(STRING_WITH_LEN(" OPTIONALLY "));
+ buf->append(STRING_WITH_LEN(" ENCLOSED BY "));
+ pretty_print_str(buf, sql_ex.enclosed, sql_ex.enclosed_len);
- pos= strmov(pos, " ESCAPED BY ");
- pos= pretty_print_str(pos, sql_ex.escaped, sql_ex.escaped_len);
+ buf->append(STRING_WITH_LEN(" ESCAPED BY "));
+ pretty_print_str(buf, sql_ex.escaped, sql_ex.escaped_len);
- pos= strmov(pos, " LINES TERMINATED BY ");
- pos= pretty_print_str(pos, sql_ex.line_term, sql_ex.line_term_len);
+ buf->append(STRING_WITH_LEN(" LINES TERMINATED BY "));
+ pretty_print_str(buf, sql_ex.line_term, sql_ex.line_term_len);
if (sql_ex.line_start_len)
{
- pos= strmov(pos, " STARTING BY ");
- pos= pretty_print_str(pos, sql_ex.line_start, sql_ex.line_start_len);
+ buf->append(STRING_WITH_LEN(" STARTING BY "));
+ pretty_print_str(buf, sql_ex.line_start, sql_ex.line_start_len);
}
if ((long) skip_lines > 0)
{
- pos= strmov(pos, " IGNORE ");
- pos= longlong10_to_str((longlong) skip_lines, pos, 10);
- pos= strmov(pos," LINES ");
+ buf->append(STRING_WITH_LEN(" IGNORE "));
+ buf->append_ulonglong(skip_lines);
+ buf->append(STRING_WITH_LEN(" LINES "));
}
if (num_fields)
{
uint i;
const char *field= fields;
- pos= strmov(pos, " (");
+ buf->append(STRING_WITH_LEN(" ("));
for (i = 0; i < num_fields; i++)
{
if (i)
{
- *pos++= ' ';
- *pos++= ',';
+ /*
+ Yes, the space and comma is reversed here. But this is mostly dead
+ code, at most used when reading really old binlogs from old servers,
+ so better just leave it as is...
+ */
+ buf->append(STRING_WITH_LEN(" ,"));
}
- memcpy(pos, field, field_lens[i]);
- pos+= field_lens[i];
+ append_identifier(thd, buf, field, field_lens[i]);
field+= field_lens[i] + 1;
}
- *pos++= ')';
+ buf->append(STRING_WITH_LEN(")"));
}
-
- *end= pos;
}
-void Load_log_event::pack_info(Protocol *protocol)
+void Load_log_event::pack_info(THD *thd, Protocol *protocol)
{
- char *buf, *end;
+ char query_buffer[1024];
+ String query_str(query_buffer, sizeof(query_buffer), system_charset_info);
- if (!(buf= (char*) my_malloc(get_query_buffer_length(), MYF(MY_WME))))
- return;
- print_query(TRUE, NULL, buf, &end, 0, 0);
- protocol->store(buf, end-buf, &my_charset_bin);
- my_free(buf);
+ query_str.length(0);
+ print_query(thd, TRUE, NULL, &query_str, 0, 0, NULL);
+ protocol->store(query_str.ptr(), query_str.length(), &my_charset_bin);
}
#endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
@@ -5284,6 +5269,8 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli,
bool use_rli_only_for_errors)
{
LEX_STRING new_db;
+ DBUG_ENTER("Load_log_event::do_apply_event");
+
new_db.length= db_len;
new_db.str= (char *) rpl_filter->get_rewrite_db(db, &new_db.length);
thd->set_db(new_db.str, new_db.length);
@@ -5358,16 +5345,20 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli,
else
{
char llbuff[22];
- char *end;
enum enum_duplicates handle_dup;
bool ignore= 0;
+ char query_buffer[1024];
+ String query_str(query_buffer, sizeof(query_buffer), system_charset_info);
char *load_data_query;
+ query_str.length(0);
/*
Forge LOAD DATA INFILE query which will be used in SHOW PROCESS LIST
and written to slave's binlog if binlogging is on.
*/
- if (!(load_data_query= (char *)thd->alloc(get_query_buffer_length() + 1)))
+ print_query(thd, FALSE, NULL, &query_str, NULL, NULL, NULL);
+ if (!(load_data_query= (char *)thd->strmake(query_str.ptr(),
+ query_str.length())))
{
/*
This will set thd->fatal_error in case of OOM. So we surely will notice
@@ -5376,9 +5367,7 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli,
goto error;
}
- print_query(FALSE, NULL, load_data_query, &end, NULL, NULL);
- *end= 0;
- thd->set_query(load_data_query, (uint) (end - load_data_query));
+ thd->set_query(load_data_query, (uint) (query_str.length()));
if (sql_ex.opt_flags & REPLACE_FLAG)
handle_dup= DUP_REPLACE;
@@ -5524,7 +5513,7 @@ error:
Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'",
err, (char*)table_name, print_slave_db_safe(remember_db));
free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
- return 1;
+ DBUG_RETURN(1);
}
free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
@@ -5539,10 +5528,10 @@ Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'",
rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
ER(ER_SLAVE_FATAL_ERROR), buf);
- return 1;
+ DBUG_RETURN(1);
}
- return ( use_rli_only_for_errors ? 0 : Log_event::do_apply_event(rli) );
+ DBUG_RETURN( use_rli_only_for_errors ? 0 : Log_event::do_apply_event(rli) );
}
#endif
@@ -5556,7 +5545,7 @@ Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'",
*/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-void Rotate_log_event::pack_info(Protocol *protocol)
+void Rotate_log_event::pack_info(THD *thd, Protocol *protocol)
{
char buf1[256], buf[22];
String tmp(buf1, sizeof(buf1), log_cs);
@@ -5774,7 +5763,7 @@ Rotate_log_event::do_shall_skip(Relay_log_info *rli)
*/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-void Intvar_log_event::pack_info(Protocol *protocol)
+void Intvar_log_event::pack_info(THD *thd, Protocol *protocol)
{
char buf[256], *pos;
pos= strmake(buf, get_var_type_name(), sizeof(buf)-23);
@@ -5928,7 +5917,7 @@ Intvar_log_event::do_shall_skip(Relay_log_info *rli)
**************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-void Rand_log_event::pack_info(Protocol *protocol)
+void Rand_log_event::pack_info(THD *thd, Protocol *protocol)
{
char buf1[256], *pos;
pos= strmov(buf1,"rand_seed1=");
@@ -6053,7 +6042,7 @@ bool slave_execute_deferred_events(THD *thd)
**************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-void Xid_log_event::pack_info(Protocol *protocol)
+void Xid_log_event::pack_info(THD *thd, Protocol *protocol)
{
char buf[128], *pos;
pos= strmov(buf, "COMMIT /* xid=");
@@ -6150,84 +6139,117 @@ Xid_log_event::do_shall_skip(Relay_log_info *rli)
**************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-void User_var_log_event::pack_info(Protocol* protocol)
+static bool
+user_var_append_name_part(THD *thd, String *buf,
+ const char *name, size_t name_len)
{
- char *buf= 0;
- uint val_offset= 4 + name_len;
- uint event_len= val_offset;
+ return buf->append("@") ||
+ append_identifier(thd, buf, name, name_len) ||
+ buf->append("=");
+}
+void User_var_log_event::pack_info(THD *thd, Protocol* protocol)
+{
if (is_null)
{
- if (!(buf= (char*) my_malloc(val_offset + 5, MYF(MY_WME))))
+ char buf_mem[FN_REFLEN+7];
+ String buf(buf_mem, sizeof(buf_mem), system_charset_info);
+ buf.length(0);
+ if (user_var_append_name_part(thd, &buf, name, name_len) ||
+ buf.append("NULL"))
return;
- strmov(buf + val_offset, "NULL");
- event_len= val_offset + 4;
+ protocol->store(buf.ptr(), buf.length(), &my_charset_bin);
}
else
{
switch (type) {
case REAL_RESULT:
+ {
double real_val;
+ char buf2[MY_GCVT_MAX_FIELD_WIDTH+1];
+ char buf_mem[FN_REFLEN + MY_GCVT_MAX_FIELD_WIDTH + 1];
+ String buf(buf_mem, sizeof(buf_mem), system_charset_info);
float8get(real_val, val);
- if (!(buf= (char*) my_malloc(val_offset + MY_GCVT_MAX_FIELD_WIDTH + 1,
- MYF(MY_WME))))
+ buf.length(0);
+ if (user_var_append_name_part(thd, &buf, name, name_len) ||
+ buf.append(buf2, my_gcvt(real_val, MY_GCVT_ARG_DOUBLE,
+ MY_GCVT_MAX_FIELD_WIDTH, buf2, NULL)))
return;
- event_len+= my_gcvt(real_val, MY_GCVT_ARG_DOUBLE, MY_GCVT_MAX_FIELD_WIDTH,
- buf + val_offset, NULL);
+ protocol->store(buf.ptr(), buf.length(), &my_charset_bin);
break;
+ }
case INT_RESULT:
- if (!(buf= (char*) my_malloc(val_offset + 22, MYF(MY_WME))))
+ {
+ char buf2[22];
+ char buf_mem[FN_REFLEN + 22];
+ String buf(buf_mem, sizeof(buf_mem), system_charset_info);
+ buf.length(0);
+ if (user_var_append_name_part(thd, &buf, name, name_len) ||
+ buf.append(buf2,
+ longlong10_to_str(uint8korr(val), buf2,
+ ((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10))-buf2))
return;
- event_len= longlong10_to_str(uint8korr(val), buf + val_offset,
- ((flags & User_var_log_event::UNSIGNED_F) ?
- 10 : -10))-buf;
+ protocol->store(buf.ptr(), buf.length(), &my_charset_bin);
break;
+ }
case DECIMAL_RESULT:
{
- if (!(buf= (char*) my_malloc(val_offset + DECIMAL_MAX_STR_LENGTH,
- MYF(MY_WME))))
- return;
- String str(buf+val_offset, DECIMAL_MAX_STR_LENGTH, &my_charset_bin);
+ char buf_mem[FN_REFLEN + DECIMAL_MAX_STR_LENGTH];
+ String buf(buf_mem, sizeof(buf_mem), system_charset_info);
+ char buf2[DECIMAL_MAX_STR_LENGTH+1];
+ String str(buf2, sizeof(buf2), &my_charset_bin);
my_decimal dec;
+ buf.length(0);
binary2my_decimal(E_DEC_FATAL_ERROR, (uchar*) (val+2), &dec, val[0],
val[1]);
my_decimal2string(E_DEC_FATAL_ERROR, &dec, 0, 0, 0, &str);
- event_len= str.length() + val_offset;
+ if (user_var_append_name_part(thd, &buf, name, name_len) ||
+ buf.append(buf2))
+ return;
+ protocol->store(buf.ptr(), buf.length(), &my_charset_bin);
break;
- }
+ }
case STRING_RESULT:
+ {
/* 15 is for 'COLLATE' and other chars */
- buf= (char*) my_malloc(event_len+val_len*2+1+2*MY_CS_NAME_SIZE+15,
- MYF(MY_WME));
+ char buf_mem[FN_REFLEN + 512 + 1 + 2*MY_CS_NAME_SIZE+15];
+ String buf(buf_mem, sizeof(buf_mem), system_charset_info);
CHARSET_INFO *cs;
- if (!buf)
- return;
+ buf.length(0);
if (!(cs= get_charset(charset_number, MYF(0))))
{
- strmov(buf+val_offset, "???");
- event_len+= 3;
+ if (buf.append("???"))
+ return;
}
else
{
- char *p= strxmov(buf + val_offset, "_", cs->csname, " ", NullS);
- p= str_to_hex(p, val, val_len);
- p= strxmov(p, " COLLATE ", cs->name, NullS);
- event_len= p-buf;
+ size_t old_len;
+ char *beg, *end;
+ if (user_var_append_name_part(thd, &buf, name, name_len) ||
+ buf.append("_") ||
+ buf.append(cs->csname) ||
+ buf.append(" "))
+ return;
+ old_len= buf.length();
+ if (buf.reserve(old_len + val_len*2 + 2 + sizeof(" COLLATE ") +
+ MY_CS_NAME_SIZE))
+ return;
+ beg= const_cast<char *>(buf.ptr()) + old_len;
+ end= str_to_hex(beg, val, val_len);
+ buf.length(old_len + (end - beg));
+ if (buf.append(" COLLATE ") ||
+ buf.append(cs->name))
+ return;
}
+ protocol->store(buf.ptr(), buf.length(), &my_charset_bin);
break;
+ }
case ROW_RESULT:
default:
DBUG_ASSERT(0);
return;
}
}
- buf[0]= '@';
- buf[1]= '`';
- memcpy(buf+2, name, name_len);
- buf[2+name_len]= '`';
- buf[3+name_len]= '=';
- protocol->store(buf, event_len, &my_charset_bin);
- my_free(buf);
}
#endif /* !MYSQL_CLIENT */
@@ -6385,9 +6407,8 @@ void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
my_b_printf(&cache, "\tUser_var\n");
}
- my_b_printf(&cache, "SET @`");
- my_b_write(&cache, (uchar*) name, (uint) (name_len));
- my_b_printf(&cache, "`");
+ my_b_printf(&cache, "SET @");
+ my_b_write_backtick_quote(&cache, name, name_len);
if (is_null)
{
@@ -6486,15 +6507,16 @@ int User_var_log_event::do_apply_event(Relay_log_info const *rli)
{
Item *it= 0;
CHARSET_INFO *charset;
+ DBUG_ENTER("User_var_log_event::do_apply_event");
if (rli->deferred_events_collecting)
{
set_deferred();
- return rli->deferred_events->add(this);
+ DBUG_RETURN(rli->deferred_events->add(this));
}
if (!(charset= get_charset(charset_number, MYF(MY_WME))))
- return 1;
+ DBUG_RETURN(1);
LEX_STRING user_var_name;
user_var_name.str= name;
user_var_name.length= name_len;
@@ -6540,7 +6562,7 @@ int User_var_log_event::do_apply_event(Relay_log_info const *rli)
case ROW_RESULT:
default:
DBUG_ASSERT(0);
- return 0;
+ DBUG_RETURN(0);
}
}
@@ -6554,7 +6576,7 @@ int User_var_log_event::do_apply_event(Relay_log_info const *rli)
error.
*/
if (e->fix_fields(thd, 0))
- return 1;
+ DBUG_RETURN(1);
/*
A variable can just be considered as a table with
@@ -6566,7 +6588,7 @@ int User_var_log_event::do_apply_event(Relay_log_info const *rli)
if (!is_deferred())
free_root(thd->mem_root, 0);
- return 0;
+ DBUG_RETURN(0);
}
int User_var_log_event::do_update_pos(Relay_log_info *rli)
@@ -6609,7 +6631,7 @@ void Unknown_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info
#endif
#ifndef MYSQL_CLIENT
-void Slave_log_event::pack_info(Protocol *protocol)
+void Slave_log_event::pack_info(THD *thd, Protocol *protocol)
{
char buf[256+HOSTNAME_LENGTH], *pos;
pos= strmov(buf, "host=");
@@ -6991,7 +7013,7 @@ void Create_file_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info
*/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-void Create_file_log_event::pack_info(Protocol *protocol)
+void Create_file_log_event::pack_info(THD *thd, Protocol *protocol)
{
char buf[SAFE_NAME_LEN*2 + 30 + 21*2], *pos;
pos= strmov(buf, "db=");
@@ -7177,7 +7199,7 @@ void Append_block_log_event::print(FILE* file,
*/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-void Append_block_log_event::pack_info(Protocol *protocol)
+void Append_block_log_event::pack_info(THD *thd, Protocol *protocol)
{
char buf[256];
uint length;
@@ -7334,7 +7356,7 @@ void Delete_file_log_event::print(FILE* file,
*/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-void Delete_file_log_event::pack_info(Protocol *protocol)
+void Delete_file_log_event::pack_info(THD *thd, Protocol *protocol)
{
char buf[64];
uint length;
@@ -7433,7 +7455,7 @@ void Execute_load_log_event::print(FILE* file,
*/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-void Execute_load_log_event::pack_info(Protocol *protocol)
+void Execute_load_log_event::pack_info(THD *thd, Protocol *protocol)
{
char buf[64];
uint length;
@@ -7695,27 +7717,24 @@ void Execute_load_query_log_event::print(FILE* file,
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-void Execute_load_query_log_event::pack_info(Protocol *protocol)
+void Execute_load_query_log_event::pack_info(THD *thd, Protocol *protocol)
{
- char *buf, *pos;
- if (!(buf= (char*) my_malloc(9 + db_len + q_len + 10 + 21, MYF(MY_WME))))
- return;
- pos= buf;
+ char buf_mem[1024];
+ String buf(buf_mem, sizeof(buf_mem), system_charset_info);
+ buf.real_alloc(9 + db_len + q_len + 10 + 21);
if (db && db_len)
{
- pos= strmov(buf, "use `");
- memcpy(pos, db, db_len);
- pos= strmov(pos+db_len, "`; ");
- }
- if (query && q_len)
- {
- memcpy(pos, query, q_len);
- pos+= q_len;
+ if (buf.append("use ") ||
+ append_identifier(thd, &buf, db, db_len) ||
+ buf.append("; "))
+ return;
}
- pos= strmov(pos, " ;file_id=");
- pos= int10_to_str((long) file_id, pos, 10);
- protocol->store(buf, pos-buf, &my_charset_bin);
- my_free(buf);
+ if (query && q_len && buf.append(query, q_len))
+ return;
+ if (buf.append(" ;file_id=") ||
+ buf.append_ulonglong(file_id))
+ return;
+ protocol->store(buf.ptr(), buf.length(), &my_charset_bin);
}
@@ -8678,7 +8697,7 @@ bool Rows_log_event::write_data_body(IO_CACHE*file)
#endif
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-void Rows_log_event::pack_info(Protocol *protocol)
+void Rows_log_event::pack_info(THD *thd, Protocol *protocol)
{
char buf[256];
char const *const flagstr=
@@ -8782,7 +8801,7 @@ bool Annotate_rows_log_event::write_data_body(IO_CACHE *file)
#endif
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
-void Annotate_rows_log_event::pack_info(Protocol* protocol)
+void Annotate_rows_log_event::pack_info(THD *thd, Protocol* protocol)
{
if (m_query_txt && m_query_len)
protocol->store(m_query_txt, m_query_len, &my_charset_bin);
@@ -9526,7 +9545,7 @@ bool Table_map_log_event::write_data_body(IO_CACHE *file)
*/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-void Table_map_log_event::pack_info(Protocol *protocol)
+void Table_map_log_event::pack_info(THD *thd, Protocol *protocol)
{
char buf[256];
size_t bytes= my_snprintf(buf, sizeof(buf),
@@ -9547,7 +9566,7 @@ void Table_map_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info)
{
print_header(&print_event_info->head_cache, print_event_info, TRUE);
my_b_printf(&print_event_info->head_cache,
- "\tTable_map: `%s`.`%s` mapped to number %lu\n",
+ "\tTable_map: %`s.%`s mapped to number %lu\n",
m_dbnam, m_tblnam, m_table_id);
print_base64(&print_event_info->body_cache, print_event_info, TRUE);
}
@@ -10880,7 +10899,7 @@ Incident_log_event::description() const
#ifndef MYSQL_CLIENT
-void Incident_log_event::pack_info(Protocol *protocol)
+void Incident_log_event::pack_info(THD *thd, Protocol *protocol)
{
char buf[256];
size_t bytes;
diff --git a/sql/log_event.h b/sql/log_event.h
index 19a77f03b84..bf45dd0cc93 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -1065,14 +1065,15 @@ public:
*/
static void init_show_field_list(List<Item>* field_list);
#ifdef HAVE_REPLICATION
- int net_send(Protocol *protocol, const char* log_name, my_off_t pos);
+ int net_send(THD *thd, Protocol *protocol, const char* log_name,
+ my_off_t pos);
/*
pack_info() is used by SHOW BINLOG EVENTS; as print() it prepares and sends
a string to display to the user, so it resembles print().
*/
- virtual void pack_info(Protocol *protocol);
+ virtual void pack_info(THD *thd, Protocol *protocol);
#endif /* HAVE_REPLICATION */
virtual const char* get_db()
@@ -1809,7 +1810,7 @@ public:
bool using_trans, bool direct, bool suppress_use, int error);
const char* get_db() { return db; }
#ifdef HAVE_REPLICATION
- void pack_info(Protocol* protocol);
+ void pack_info(THD *thd, Protocol* protocol);
#endif /* HAVE_REPLICATION */
#else
void print_query_header(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info);
@@ -1939,7 +1940,7 @@ public:
#ifdef MYSQL_SERVER
Slave_log_event(THD* thd_arg, Relay_log_info* rli);
- void pack_info(Protocol* protocol);
+ void pack_info(THD *thd, Protocol* protocol);
#else
void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
#endif
@@ -2172,9 +2173,9 @@ protected:
const Format_description_log_event* description_event);
public:
- uint get_query_buffer_length();
- void print_query(bool need_db, const char *cs, char *buf, char **end,
- char **fn_start, char **fn_end);
+ void print_query(THD *thd, bool need_db, const char *cs, String *buf,
+ my_off_t *fn_start, my_off_t *fn_end,
+ const char *qualify_db);
ulong thread_id;
ulong slave_proxy_id;
uint32 table_name_len;
@@ -2235,7 +2236,7 @@ public:
Name_resolution_context *context);
const char* get_db() { return db; }
#ifdef HAVE_REPLICATION
- void pack_info(Protocol* protocol);
+ void pack_info(THD *thd, Protocol* protocol);
#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
@@ -2332,7 +2333,7 @@ public:
#ifdef MYSQL_SERVER
Start_log_event_v3();
#ifdef HAVE_REPLICATION
- void pack_info(Protocol* protocol);
+ void pack_info(THD *thd, Protocol* protocol);
#endif /* HAVE_REPLICATION */
#else
Start_log_event_v3() {}
@@ -2496,7 +2497,7 @@ Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg,
cache_type= Log_event::EVENT_NO_CACHE;
}
#ifdef HAVE_REPLICATION
- void pack_info(Protocol* protocol);
+ void pack_info(THD *thd, Protocol* protocol);
#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
@@ -2576,7 +2577,7 @@ class Rand_log_event: public Log_event
cache_type= Log_event::EVENT_NO_CACHE;
}
#ifdef HAVE_REPLICATION
- void pack_info(Protocol* protocol);
+ void pack_info(THD *thd, Protocol* protocol);
#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
@@ -2625,7 +2626,7 @@ class Xid_log_event: public Log_event
cache_type= Log_event::EVENT_NO_CACHE;
}
#ifdef HAVE_REPLICATION
- void pack_info(Protocol* protocol);
+ void pack_info(THD *thd, Protocol* protocol);
#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
@@ -2687,7 +2688,7 @@ public:
if (direct)
cache_type= Log_event::EVENT_NO_CACHE;
}
- void pack_info(Protocol* protocol);
+ void pack_info(THD *thd, Protocol* protocol);
#else
void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
#endif
@@ -2825,7 +2826,7 @@ public:
uint ident_len_arg,
ulonglong pos_arg, uint flags);
#ifdef HAVE_REPLICATION
- void pack_info(Protocol* protocol);
+ void pack_info(THD *thd, Protocol* protocol);
#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
@@ -2886,7 +2887,7 @@ public:
uchar* block_arg, uint block_len_arg,
bool using_trans);
#ifdef HAVE_REPLICATION
- void pack_info(Protocol* protocol);
+ void pack_info(THD *thd, Protocol* protocol);
#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
@@ -2958,7 +2959,7 @@ public:
Append_block_log_event(THD* thd, const char* db_arg, uchar* block_arg,
uint block_len_arg, bool using_trans);
#ifdef HAVE_REPLICATION
- void pack_info(Protocol* protocol);
+ void pack_info(THD *thd, Protocol* protocol);
virtual int get_create_or_append() const;
#endif /* HAVE_REPLICATION */
#else
@@ -2999,7 +3000,7 @@ public:
#ifdef MYSQL_SERVER
Delete_file_log_event(THD* thd, const char* db_arg, bool using_trans);
#ifdef HAVE_REPLICATION
- void pack_info(Protocol* protocol);
+ void pack_info(THD *thd, Protocol* protocol);
#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
@@ -3040,7 +3041,7 @@ public:
#ifdef MYSQL_SERVER
Execute_load_log_event(THD* thd, const char* db_arg, bool using_trans);
#ifdef HAVE_REPLICATION
- void pack_info(Protocol* protocol);
+ void pack_info(THD *thd, Protocol* protocol);
#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
@@ -3136,7 +3137,7 @@ public:
bool using_trans, bool direct,
bool suppress_use, int errcode);
#ifdef HAVE_REPLICATION
- void pack_info(Protocol* protocol);
+ void pack_info(THD *thd, Protocol* protocol);
#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
@@ -3222,7 +3223,7 @@ public:
#endif
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
- virtual void pack_info(Protocol*);
+ virtual void pack_info(THD *thd, Protocol*);
#endif
#ifdef MYSQL_CLIENT
@@ -3636,7 +3637,7 @@ public:
#endif
#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
- virtual void pack_info(Protocol *protocol);
+ virtual void pack_info(THD *thd, Protocol *protocol);
#endif
#ifdef MYSQL_CLIENT
@@ -3748,7 +3749,7 @@ public:
flag_set get_flags(flag_set flags_arg) const { return m_flags & flags_arg; }
#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
- virtual void pack_info(Protocol *protocol);
+ virtual void pack_info(THD *thd, Protocol *protocol);
#endif
#ifdef MYSQL_CLIENT
@@ -4195,7 +4196,7 @@ public:
#endif
#ifdef MYSQL_SERVER
- void pack_info(Protocol*);
+ void pack_info(THD *thd, Protocol*);
#endif
Incident_log_event(const char *buf, uint event_len,
@@ -4294,6 +4295,16 @@ bool event_checksum_test(uchar *buf, ulong event_len, uint8 alg);
uint8 get_checksum_alg(const char* buf, ulong len);
extern TYPELIB binlog_checksum_typelib;
+#ifndef MYSQL_CLIENT
+/**
+ The function is called by slave applier in case there are
+ active table filtering rules to force gathering events associated
+ with Query-log-event into an array to execute
+ them once the fate of the Query is determined for execution.
+*/
+bool slave_execute_deferred_events(THD *thd);
+#endif
+
/**
@} (end of group Replication)
*/
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index 8f2c515e11c..d7c66af769a 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -1935,7 +1935,7 @@ bool Old_rows_log_event::write_data_body(IO_CACHE*file)
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-void Old_rows_log_event::pack_info(Protocol *protocol)
+void Old_rows_log_event::pack_info(THD *thd, Protocol *protocol)
{
char buf[256];
char const *const flagstr=
diff --git a/sql/log_event_old.h b/sql/log_event_old.h
index 8fe2e9e0a75..3e1efd8e2c0 100644
--- a/sql/log_event_old.h
+++ b/sql/log_event_old.h
@@ -108,7 +108,7 @@ public:
flag_set get_flags(flag_set flags_arg) const { return m_flags & flags_arg; }
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
- virtual void pack_info(Protocol *protocol);
+ virtual void pack_info(THD *thd, Protocol *protocol);
#endif
#ifdef MYSQL_CLIENT
diff --git a/sql/multi_range_read.cc b/sql/multi_range_read.cc
index 036775cdf3e..1361d5822c9 100644
--- a/sql/multi_range_read.cc
+++ b/sql/multi_range_read.cc
@@ -1404,7 +1404,7 @@ ha_rows DsMrr_impl::dsmrr_info(uint keyno, uint n_ranges, uint rows,
uint key_parts,
uint *bufsz, uint *flags, COST_VECT *cost)
{
- ha_rows res;
+ ha_rows res __attribute__((unused));
uint def_flags= *flags;
uint def_bufsz= *bufsz;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 11b397e3e0c..faac606a96b 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2001,7 +2001,7 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
{
handler *save_file= file, *org_file;
my_bool org_key_read;
- THD *thd;
+ THD *thd= head->in_use;
DBUG_ENTER("QUICK_RANGE_SELECT::init_ror_merged_scan");
in_ror_merged_scan= 1;
@@ -2023,7 +2023,6 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
DBUG_RETURN(0);
}
- thd= head->in_use;
if (!(file= head->file->clone(head->s->normalized_path.str, thd->mem_root)))
{
/*
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 8d1cbeba5f4..e70e5a784ba 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -160,18 +160,18 @@
3.2.1 Non-merged semi-joins and join optimization
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For join optimization purposes, non-merged semi-join nests are similar to
- base tables - they've got one JOIN_TAB, which can be accessed with one of
- two methods:
+ base tables. Each such nest is represented by one one JOIN_TAB, which has
+ two possible access strategies:
- full table scan (representing SJ-Materialization-Scan strategy)
- eq_ref-like table lookup (representing SJ-Materialization-Lookup)
Unlike regular base tables, non-merged semi-joins have:
- non-zero JOIN_TAB::startup_cost, and
- join_tab->table->is_filled_at_execution()==TRUE, which means one
- cannot do const table detection or range analysis or other table data-
- dependent inferences
- // instead, get_delayed_table_estimates() runs optimization on the nest so that
- // we get an idea about temptable size
+ cannot do const table detection, range analysis or other dataset-dependent
+ optimizations.
+ Instead, get_delayed_table_estimates() will run optimization for the
+ subquery and produce an E(materialized table size).
3.2.2 Merged semi-joins and join optimization
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index abc22a00695..89fb1bb27de 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -35,7 +35,6 @@
#include "rpl_mi.h"
#include "rpl_filter.h"
#include "log_event.h"
-#include "sql_db.h" // mysql_create_db
#include <mysql.h>
#define SLAVE_LIST_CHUNK 128
diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc
index a49f10db440..99bf8a82004 100644
--- a/sql/rpl_record.cc
+++ b/sql/rpl_record.cc
@@ -314,7 +314,7 @@ unpack_row(Relay_log_info const *rli,
if (!pack_ptr)
{
rli->report(ERROR_LEVEL, ER_SLAVE_CORRUPT_EVENT,
- "Could not read field `%s` of table `%s`.`%s`",
+ "Could not read field '%s' of table '%s.%s'",
f->field_name, table->s->db.str,
table->s->table_name.str);
DBUG_RETURN(ER_SLAVE_CORRUPT_EVENT);
diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc
index 388a6c9f9bb..069fac1c3ec 100644
--- a/sql/rpl_utility.cc
+++ b/sql/rpl_utility.cc
@@ -15,11 +15,10 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include "rpl_utility.h"
+#include "log_event.h"
-#ifndef MYSQL_CLIENT
-#include "unireg.h" // REQUIRED by later includes
+#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
#include "rpl_rli.h"
-#include "log_event.h"
#include "sql_select.h"
/**
@@ -954,7 +953,6 @@ TABLE *table_def::create_conversion_table(THD *thd, Relay_log_info *rli, TABLE *
target_table->s->table_name.str);
DBUG_RETURN(conv_table);
}
-
#endif /* MYSQL_CLIENT */
table_def::table_def(unsigned char *types, ulong size,
@@ -1115,7 +1113,6 @@ bool event_checksum_test(uchar *event_buf, ulong event_len, uint8 alg)
return DBUG_EVALUATE_IF("simulate_checksum_test_failure", TRUE, res);
}
-
#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
Deferred_log_events::Deferred_log_events(Relay_log_info *rli) : last_added(NULL)
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 923e8e73bc7..31a6f13e52f 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -6585,3 +6585,6 @@ ER_STORED_FUNCTION_PREVENTS_SWITCH_SKIP_REPLICATION
eng "Cannot modify @@session.skip_replication inside a stored function or trigger"
ER_QUERY_EXCEEDED_ROWS_EXAMINED_LIMIT
eng "Query execution was interrupted. The query examined at least %llu rows, which exceeds LIMIT ROWS EXAMINED (%llu). The query result may be incomplete."
+ER_NO_SUCH_TABLE_IN_ENGINE 42S02
+ eng "Table '%-.192s.%-.192s' doesn't exist in engine"
+ swe "Det finns ingen tabell som heter '%-.192s.%-.192s' i handlern"
diff --git a/sql/slave.cc b/sql/slave.cc
index 9149cd82d5e..7b7fd12e267 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -3005,6 +3005,8 @@ pthread_handler_t handle_slave_io(void *arg)
mysql= NULL ;
retry_count= 0;
+ thd= new THD; // note that contructor of THD uses DBUG_ !
+
mysql_mutex_lock(&mi->run_lock);
/* Inform waiting threads that slave has started */
mi->slave_run_id++;
@@ -3013,7 +3015,6 @@ pthread_handler_t handle_slave_io(void *arg)
mi->events_till_disconnect = disconnect_slave_event_count;
#endif
- thd= new THD; // note that contructor of THD uses DBUG_ !
THD_CHECK_SENTRY(thd);
mi->io_thd = thd;
diff --git a/sql/sp.cc b/sql/sp.cc
index 29195234a5a..93cd64b4104 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -1429,6 +1429,7 @@ public:
MYSQL_ERROR ** cond_hdl)
{
if (sql_errno == ER_NO_SUCH_TABLE ||
+ sql_errno == ER_NO_SUCH_TABLE_IN_ENGINE ||
sql_errno == ER_CANNOT_LOAD_FROM_TABLE ||
sql_errno == ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE ||
sql_errno == ER_COL_COUNT_DOESNT_MATCH_CORRUPTED)
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 9a356cb3321..f3ba0073c69 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -3032,6 +3032,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
if (!res || !thd->is_error() ||
(thd->stmt_da->sql_errno() != ER_CANT_REOPEN_TABLE &&
thd->stmt_da->sql_errno() != ER_NO_SUCH_TABLE &&
+ thd->stmt_da->sql_errno() != ER_NO_SUCH_TABLE_IN_ENGINE &&
thd->stmt_da->sql_errno() != ER_UPDATE_TABLE_USED))
thd->stmt_arena->state= Query_arena::STMT_EXECUTED;
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index e00b35a19db..1305e882ede 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -286,6 +286,7 @@ end:
static inline bool table_not_corrupt_error(uint sql_errno)
{
return (sql_errno == ER_NO_SUCH_TABLE ||
+ sql_errno == ER_NO_SUCH_TABLE_IN_ENGINE ||
sql_errno == ER_FILE_NOT_FOUND ||
sql_errno == ER_LOCK_WAIT_TIMEOUT ||
sql_errno == ER_LOCK_DEADLOCK ||
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 911f2560d85..0dfc98864b1 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -70,7 +70,7 @@ No_such_table_error_handler::handle_condition(THD *,
MYSQL_ERROR ** cond_hdl)
{
*cond_hdl= NULL;
- if (sql_errno == ER_NO_SUCH_TABLE)
+ if (sql_errno == ER_NO_SUCH_TABLE || sql_errno == ER_NO_SUCH_TABLE_IN_ENGINE)
{
m_handled_errors++;
return TRUE;
@@ -144,7 +144,9 @@ Repair_mrg_table_error_handler::handle_condition(THD *,
MYSQL_ERROR ** cond_hdl)
{
*cond_hdl= NULL;
- if (sql_errno == ER_NO_SUCH_TABLE || sql_errno == ER_WRONG_MRG_TABLE)
+ if (sql_errno == ER_NO_SUCH_TABLE ||
+ sql_errno == ER_NO_SUCH_TABLE_IN_ENGINE ||
+ sql_errno == ER_WRONG_MRG_TABLE)
{
m_handled_errors= true;
return TRUE;
@@ -717,7 +719,9 @@ get_table_share_with_discover(THD *thd, TABLE_LIST *table_list,
@todo Rework alternative ways to deal with ER_NO_SUCH TABLE.
*/
- if (share || (thd->is_error() && thd->stmt_da->sql_errno() != ER_NO_SUCH_TABLE))
+ if (share ||
+ (thd->is_error() && thd->stmt_da->sql_errno() != ER_NO_SUCH_TABLE &&
+ thd->stmt_da->sql_errno() != ER_NO_SUCH_TABLE_IN_ENGINE))
DBUG_RETURN(share);
*error= 0;
@@ -3897,22 +3901,22 @@ static bool open_table_entry_fini(THD *thd, TABLE_SHARE *share, TABLE *entry)
entry->file->implicit_emptied= 0;
if (mysql_bin_log.is_open())
{
- char *query, *end;
- uint query_buf_size= 20 + share->db.length + share->table_name.length +1;
- if ((query= (char*) my_malloc(query_buf_size,MYF(MY_WME))))
+ char query_buf[2*FN_REFLEN + 21];
+ String query(query_buf, sizeof(query_buf), system_charset_info);
+ query.length(0);
+ if (query.ptr())
{
/* this DELETE FROM is needed even with row-based binlogging */
- end = strxmov(strmov(query, "DELETE FROM `"),
- share->db.str,"`.`",share->table_name.str,"`", NullS);
+ query.append("DELETE FROM ");
+ append_identifier(thd, &query, share->db.str, share->db.length);
+ query.append(".");
+ append_identifier(thd, &query, share->table_name.str,
+ share->table_name.length);
int errcode= query_error_code(thd, TRUE);
if (thd->binlog_query(THD::STMT_QUERY_TYPE,
- query, (ulong)(end-query),
+ query.ptr(), query.length(),
FALSE, FALSE, FALSE, errcode))
- {
- my_free(query);
return TRUE;
- }
- my_free(query);
}
else
{
@@ -3922,7 +3926,7 @@ static bool open_table_entry_fini(THD *thd, TABLE_SHARE *share, TABLE *entry)
because of MYF(MY_WME) in my_malloc() above).
*/
sql_print_error("When opening HEAP table, could not allocate memory "
- "to write 'DELETE FROM `%s`.`%s`' to the binary log",
+ "to write 'DELETE FROM %`s.%`s' to the binary log",
share->db.str, share->table_name.str);
delete entry->triggers;
return TRUE;
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 7edd28446a2..191cc4e01c8 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1813,7 +1813,10 @@ Query_cache::send_result_to_client(THD *thd, char *org_sql, uint query_length)
goto err;
if (query_cache_size == 0)
+ {
+ thd->query_cache_is_applicable= 0; // Query can't be cached
goto err_unlock;
+ }
Query_cache_block *query_block;
if (thd->variables.query_cache_strip_comments)
diff --git a/sql/sql_class.h b/sql/sql_class.h
index b2fe8c21aae..b1e9b095be2 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1845,6 +1845,7 @@ public:
MEM_ROOT mem_root; // Transaction-life memory allocation pool
void cleanup()
{
+ DBUG_ENTER("thd::cleanup");
changed_tables= 0;
savepoints= 0;
/*
@@ -1856,6 +1857,7 @@ public:
if (!xid_state.rm_error)
xid_state.xid.null();
free_root(&mem_root,MYF(MY_KEEP_PREALLOC));
+ DBUG_VOID_RETURN;
}
my_bool is_active()
{
diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc
index c50cded7470..b8b979a282b 100644
--- a/sql/sql_cursor.cc
+++ b/sql/sql_cursor.cc
@@ -115,6 +115,8 @@ int mysql_open_cursor(THD *thd, select_result *result,
&thd->security_ctx->priv_user[0],
(char *) thd->security_ctx->host_or_ip,
2);
+ /* Mark that we can't use query cache with cursors */
+ thd->query_cache_is_applicable= 0;
rc= mysql_execute_command(thd);
MYSQL_QUERY_EXEC_DONE(rc);
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 28565b02c1f..086445948bd 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -544,7 +544,6 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
bool silent)
{
char path[FN_REFLEN+16];
- char tmp_query[FN_REFLEN+16];
long result= 1;
int error= 0;
MY_STAT stat_info;
@@ -622,17 +621,9 @@ not_silent:
char *query;
uint query_length;
- if (!thd->query()) // Only in replication
- {
- query= tmp_query;
- query_length= (uint) (strxmov(tmp_query,"create database `",
- db, "`", NullS) - tmp_query);
- }
- else
- {
- query= thd->query();
- query_length= thd->query_length();
- }
+ query= thd->query();
+ query_length= thd->query_length();
+ DBUG_ASSERT(query);
ha_binlog_log_query(thd, 0, LOGCOM_CREATE_DB,
query, query_length,
@@ -896,18 +887,11 @@ update_binlog:
{
const char *query;
ulong query_length;
- if (!thd->query())
- {
- /* The client used the old obsolete mysql_drop_db() call */
- query= path;
- query_length= (uint) (strxmov(path, "drop database `", db, "`",
- NullS) - path);
- }
- else
- {
- query= thd->query();
- query_length= thd->query_length();
- }
+
+ query= thd->query();
+ query_length= thd->query_length();
+ DBUG_ASSERT(query);
+
if (mysql_bin_log.is_open())
{
int errcode= query_error_code(thd, TRUE);
@@ -951,6 +935,7 @@ update_binlog:
{
uint tbl_name_len;
bool exists;
+ char quoted_name[FN_REFLEN+3];
// Only write drop table to the binlog for tables that no longer exist.
if (check_if_table_exists(thd, tbl, &exists))
@@ -961,8 +946,8 @@ update_binlog:
if (exists)
continue;
- /* 3 for the quotes and the comma*/
- tbl_name_len= strlen(tbl->table_name) + 3;
+ my_snprintf(quoted_name, sizeof(quoted_name), "%`s", tbl->table_name);
+ tbl_name_len= strlen(quoted_name) + 1; /* +1 for the comma */
if (query_pos + tbl_name_len + 1 >= query_end)
{
/*
@@ -977,9 +962,7 @@ update_binlog:
query_pos= query_data_start;
}
- *query_pos++ = '`';
- query_pos= strmov(query_pos,tbl->table_name);
- *query_pos++ = '`';
+ query_pos= strmov(query_pos, quoted_name);
*query_pos++ = ',';
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index d9d2f9fa649..f6e2ca09ec9 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -4161,7 +4161,6 @@ bool LEX::is_partition_management() const
alter_info.flags == ALTER_REORGANIZE_PARTITION));
}
-
#ifdef MYSQL_SERVER
uint binlog_unsafe_map[256];
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 33d1741b5ec..98031c96225 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -39,6 +39,7 @@
#include "sp_head.h"
#include "sql_trigger.h"
#include "sql_derived.h"
+#include "sql_show.h"
class XML_TAG {
public:
@@ -675,24 +676,28 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
bool transactional_table,
int errcode)
{
- char *load_data_query,
- *end,
- *fname_start,
- *fname_end,
- *p= NULL;
- size_t pl= 0;
+ char *load_data_query;
+ my_off_t fname_start,
+ fname_end;
List<Item> fv;
Item *item, *val;
int n;
- const char *tbl= table_name_arg;
const char *tdb= (thd->db != NULL ? thd->db : db_arg);
- char name_buffer[SAFE_NAME_LEN*2];
+ const char *qualify_db= NULL;
char command_buffer[1024];
- String string_buf(name_buffer, sizeof(name_buffer),
- system_charset_info);
- String pfields(command_buffer, sizeof(command_buffer),
+ String query_str(command_buffer, sizeof(command_buffer),
system_charset_info);
+ Load_log_event lle(thd, ex, tdb, table_name_arg, fv, is_concurrent,
+ duplicates, ignore, transactional_table);
+
+ /*
+ force in a LOCAL if there was one in the original.
+ */
+ if (thd->lex->local_file)
+ lle.set_fname_outside_temp_buf(ex->file_name, strlen(ex->file_name));
+
+ query_str.length(0);
if (!thd->db || strcmp(db_arg, thd->db))
{
/*
@@ -700,49 +705,35 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
prefix table name with database name so that it
becomes a FQ name.
*/
- string_buf.length(0);
- string_buf.append(db_arg);
- string_buf.append("`");
- string_buf.append(".");
- string_buf.append("`");
- string_buf.append(table_name_arg);
- tbl= string_buf.c_ptr_safe();
+ qualify_db= db_arg;
}
-
- Load_log_event lle(thd, ex, tdb, tbl, fv, is_concurrent,
- duplicates, ignore, transactional_table);
-
- /*
- force in a LOCAL if there was one in the original.
- */
- if (thd->lex->local_file)
- lle.set_fname_outside_temp_buf(ex->file_name, strlen(ex->file_name));
+ lle.print_query(thd, FALSE, (const char *) ex->cs?ex->cs->csname:NULL,
+ &query_str, &fname_start, &fname_end, qualify_db);
/*
prepare fields-list and SET if needed; print_query won't do that for us.
*/
- pfields.length(0);
if (!thd->lex->field_list.is_empty())
{
List_iterator<Item> li(thd->lex->field_list);
- pfields.append(" (");
+ query_str.append(" (");
n= 0;
while ((item= li++))
{
if (n++)
- pfields.append(", ");
+ query_str.append(", ");
if (item->type() == Item::FIELD_ITEM)
+ append_identifier(thd, &query_str, item->name, strlen(item->name));
+ else
{
- pfields.append("`");
- pfields.append(item->name);
- pfields.append("`");
+ /* Actually Item_user_var_as_out_param despite claiming STRING_ITEM. */
+ DBUG_ASSERT(item->type() == Item::STRING_ITEM);
+ ((Item_user_var_as_out_param *)item)->print_for_load(thd, &query_str);
}
- else
- item->print(&pfields, QT_ORDINARY);
}
- pfields.append(")");
+ query_str.append(")");
}
if (!thd->lex->update_list.is_empty())
@@ -750,38 +741,25 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
List_iterator<Item> lu(thd->lex->update_list);
List_iterator<Item> lv(thd->lex->value_list);
- pfields.append(" SET ");
+ query_str.append(" SET ");
n= 0;
while ((item= lu++))
{
val= lv++;
if (n++)
- pfields.append(", ");
- pfields.append("`");
- pfields.append(item->name);
- pfields.append("`");
- pfields.append(val->name);
+ query_str.append(", ");
+ append_identifier(thd, &query_str, item->name, strlen(item->name));
+ query_str.append(val->name);
}
}
- p= pfields.c_ptr_safe();
- pl= pfields.length();
-
- if (!(load_data_query= (char *)thd->alloc(lle.get_query_buffer_length() + 1 + pl)))
+ if (!(load_data_query= (char *)thd->strmake(query_str.ptr(), query_str.length())))
return TRUE;
- lle.print_query(FALSE, (const char *) ex->cs?ex->cs->csname:NULL,
- load_data_query, &end,
- (char **)&fname_start, (char **)&fname_end);
-
- strcpy(end, p);
- end += pl;
-
Execute_load_query_log_event
- e(thd, load_data_query, end-load_data_query,
- (uint) ((char*) fname_start - load_data_query - 1),
- (uint) ((char*) fname_end - load_data_query),
+ e(thd, load_data_query, query_str.length(),
+ (uint) (fname_start - 1), (uint) fname_end,
(duplicates == DUP_REPLACE) ? LOAD_DUP_REPLACE :
(ignore ? LOAD_DUP_IGNORE : LOAD_DUP_ERROR),
transactional_table, FALSE, FALSE, errcode);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 49014db9505..6f157c89ee2 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1325,7 +1325,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{
STATUS_VAR *current_global_status_var; // Big; Don't allocate on stack
ulong uptime;
- uint length;
+ uint length __attribute__((unused));
ulonglong queries_per_second1000;
char buff[250];
uint buff_len= sizeof(buff);
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index a9c79589faa..2bec12e4f66 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -5500,10 +5500,12 @@ static bool mysql_change_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
build_table_filename(path, sizeof(path) - 1, lpt->db, lpt->table_name, "", 0);
- if(mysql_trans_prepare_alter_copy_data(thd))
+ /* First lock the original tables */
+ if (file->ha_external_lock(thd, F_WRLCK))
DBUG_RETURN(TRUE);
- if (file->ha_external_lock(thd, F_WRLCK))
+ /* Disable transactions for all new tables */
+ if (mysql_trans_prepare_alter_copy_data(thd))
DBUG_RETURN(TRUE);
/* TODO: test if bulk_insert would increase the performance */
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 751c0d6ada5..53ac103dda1 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
- Copyright (c) 2008, 2011, Monty Program Ab
+ Copyright (c) 2008, 2012, Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -2000,7 +2000,7 @@ bool mysql_show_binlog_events(THD* thd)
description_event->checksum_alg= ev->checksum_alg;
if (event_count >= limit_start &&
- ev->net_send(protocol, linfo.log_file_name, pos))
+ ev->net_send(thd, protocol, linfo.log_file_name, pos))
{
errmsg = "Net error";
delete ev;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 51ba2d1c4e4..33991851218 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -272,8 +272,11 @@ Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
bool *inherited_fl);
JOIN_TAB *first_depth_first_tab(JOIN* join);
JOIN_TAB *next_depth_first_tab(JOIN* join, JOIN_TAB* tab);
-JOIN_TAB *first_breadth_first_tab(JOIN *join);
-JOIN_TAB *next_breadth_first_tab(JOIN *join, JOIN_TAB *tab);
+
+enum enum_exec_or_opt {WALK_OPTIMIZATION_TABS , WALK_EXECUTION_TABS};
+JOIN_TAB *first_breadth_first_tab(JOIN *join, enum enum_exec_or_opt tabs_kind);
+JOIN_TAB *next_breadth_first_tab(JOIN *join, enum enum_exec_or_opt tabs_kind,
+ JOIN_TAB *tab);
/**
This handles SELECT with and without UNION.
@@ -6410,7 +6413,8 @@ greedy_search(JOIN *join,
uint size_remain; // cardinality of remaining_tables
POSITION best_pos;
JOIN_TAB *best_table; // the next plan node to be added to the curr QEP
- uint n_tables; // ==join->tables or # tables in the sj-mat nest we're optimizing
+ // ==join->tables or # tables in the sj-mat nest we're optimizing
+ uint n_tables __attribute__((unused));
DBUG_ENTER("greedy_search");
@@ -6650,15 +6654,15 @@ double JOIN::get_examined_rows()
{
ha_rows examined_rows;
double prev_fanout= 1;
- JOIN_TAB *tab= first_breadth_first_tab(this);
+ JOIN_TAB *tab= first_breadth_first_tab(this, WALK_OPTIMIZATION_TABS);
JOIN_TAB *prev_tab= tab;
examined_rows= tab->get_examined_rows();
- while ((tab= next_breadth_first_tab(this, tab)))
+ while ((tab= next_breadth_first_tab(this, WALK_OPTIMIZATION_TABS, tab)))
{
prev_fanout *= prev_tab->records_read;
- examined_rows+= tab->get_examined_rows() * prev_fanout;
+ examined_rows+= (ha_rows) (tab->get_examined_rows() * prev_fanout);
prev_tab= tab;
}
return examined_rows;
@@ -7270,23 +7274,30 @@ prev_record_reads(POSITION *positions, uint idx, table_map found_ref)
Enumerate join tabs in breadth-first fashion, including const tables.
*/
-JOIN_TAB *first_breadth_first_tab(JOIN *join)
+JOIN_TAB *first_breadth_first_tab(JOIN *join, enum enum_exec_or_opt tabs_kind)
{
- return join->join_tab; /* There's always one (i.e. first) table */
+ /* There's always one (i.e. first) table */
+ return (tabs_kind == WALK_EXECUTION_TABS)? join->join_tab:
+ join->table_access_tabs;
}
-JOIN_TAB *next_breadth_first_tab(JOIN *join, JOIN_TAB *tab)
+JOIN_TAB *next_breadth_first_tab(JOIN *join, enum enum_exec_or_opt tabs_kind,
+ JOIN_TAB *tab)
{
+ JOIN_TAB* const first_top_tab= first_breadth_first_tab(join, tabs_kind);
+ const uint n_top_tabs_count= (tabs_kind == WALK_EXECUTION_TABS)?
+ join->top_join_tab_count:
+ join->top_table_access_tabs_count;
if (!tab->bush_root_tab)
{
/* We're at top level. Get the next top-level tab */
tab++;
- if (tab < join->join_tab + join->top_join_tab_count)
+ if (tab < first_top_tab + n_top_tabs_count)
return tab;
/* No more top-level tabs. Switch to enumerating SJM nest children */
- tab= join->join_tab;
+ tab= first_top_tab;
}
else
{
@@ -7310,7 +7321,7 @@ JOIN_TAB *next_breadth_first_tab(JOIN *join, JOIN_TAB *tab)
Ok, "tab" points to a top-level table, and we need to find the next SJM
nest and enter it.
*/
- for (; tab < join->join_tab + join->top_join_tab_count; tab++)
+ for (; tab < first_top_tab + n_top_tabs_count; tab++)
{
if (tab->bush_children)
return tab->bush_children->start;
@@ -7334,7 +7345,7 @@ JOIN_TAB *first_top_level_tab(JOIN *join, enum enum_with_const_tables with_const
JOIN_TAB *next_top_level_tab(JOIN *join, JOIN_TAB *tab)
{
- tab= next_breadth_first_tab(join, tab);
+ tab= next_breadth_first_tab(join, WALK_EXECUTION_TABS, tab);
if (tab && tab->bush_root_tab)
tab= NULL;
return tab;
@@ -7634,6 +7645,12 @@ get_best_combination(JOIN *join)
join->top_join_tab_count= join->join_tab_ranges.head()->end -
join->join_tab_ranges.head()->start;
+ /*
+ Save pointers to select join tabs for SHOW EXPLAIN
+ */
+ join->table_access_tabs= join->join_tab;
+ join->top_table_access_tabs_count= join->top_join_tab_count;
+
update_depend_map(join);
DBUG_RETURN(0);
}
@@ -10529,7 +10546,7 @@ void JOIN::join_free()
Optimization: if not EXPLAIN and we are done with the JOIN,
free all tables.
*/
- bool full= !(select_lex->uncacheable);
+ bool full= !(select_lex->uncacheable) && !(thd->lex->describe);
bool can_unlock= full;
DBUG_ENTER("JOIN::join_free");
@@ -11890,9 +11907,9 @@ static int compare_fields_by_table_order(Item *field1,
bool outer_ref= 0;
Item_field *f1= (Item_field *) (field1->real_item());
Item_field *f2= (Item_field *) (field2->real_item());
- if (f1->const_item())
+ if (field1->const_item() || f1->const_item())
return 1;
- if (f2->const_item())
+ if (field2->const_item() || f2->const_item())
return -1;
if (f2->used_tables() & OUTER_REF_TABLE_BIT)
{
@@ -16473,7 +16490,7 @@ int report_error(TABLE *table, int error)
&& !table->in_use->killed)
{
push_warning_printf(table->in_use, MYSQL_ERROR::WARN_LEVEL_WARN, error,
- "Got error %d when reading table `%s`.`%s`",
+ "Got error %d when reading table %`s.%`s",
error, table->s->db.str, table->s->table_name.str);
sql_print_error("Got error %d when reading table '%s'",
error, table->s->path.str);
@@ -21397,8 +21414,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
bool printing_materialize_nest= FALSE;
uint select_id= join->select_lex->select_number;
- for (JOIN_TAB *tab= first_breadth_first_tab(join); tab;
- tab= next_breadth_first_tab(join, tab))
+ for (JOIN_TAB *tab= first_breadth_first_tab(join, WALK_OPTIMIZATION_TABS); tab;
+ tab= next_breadth_first_tab(join, WALK_OPTIMIZATION_TABS, tab))
{
if (tab->bush_root_tab)
{
@@ -21481,16 +21498,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
else
{
TABLE_LIST *real_table= table->pos_in_table_list;
- /*
- Internal temporary tables have no corresponding table reference
- object. Such a table may appear in EXPLAIN when a subquery that needs
- a temporary table has been executed, and JOIN::exec replaced the
- original JOIN with a plan to access the data in the temp table
- (made by JOIN::make_simple_join).
- */
- const char *tab_name= real_table ? real_table->alias :
- "internal_tmp_table";
- item_list.push_back(new Item_string(tab_name, strlen(tab_name), cs));
+ item_list.push_back(new Item_string(real_table->alias,
+ strlen(real_table->alias), cs));
}
/* "partitions" column */
if (join->thd->lex->describe & DESCRIBE_PARTITIONS)
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 0ed976ac36a..be5f523a7e2 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -897,6 +897,19 @@ protected:
public:
JOIN_TAB *join_tab, **best_ref;
+
+ /*
+ For "Using temporary+Using filesort" queries, JOIN::join_tab can point to
+ either:
+ 1. array of join tabs describing how to run the select, or
+ 2. array of single join tab describing read from the temporary table.
+
+ SHOW EXPLAIN code needs to read/show #1. This is why two next members are
+ there for saving it.
+ */
+ JOIN_TAB *table_access_tabs;
+ uint top_table_access_tabs_count;
+
JOIN_TAB **map2table; ///< mapping between table indexes and JOIN_TABs
JOIN_TAB *join_tab_save; ///< saved join_tab for subquery reexecution
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 38ff07e0204..6d56bc8520b 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -660,6 +660,7 @@ public:
break;
case ER_NO_SUCH_TABLE:
+ case ER_NO_SUCH_TABLE_IN_ENGINE:
/* Established behavior: warn if underlying tables are missing. */
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_VIEW_INVALID,
@@ -992,9 +993,13 @@ static const char *require_quotes(const char *name, uint name_length)
packet target string
name the identifier to be appended
name_length length of the appending identifier
+
+ RETURN VALUES
+ true Error
+ false Ok
*/
-void
+bool
append_identifier(THD *thd, String *packet, const char *name, uint length)
{
const char *name_end;
@@ -1002,10 +1007,7 @@ append_identifier(THD *thd, String *packet, const char *name, uint length)
int q= get_quote_char_for_identifier(thd, name, length);
if (q == EOF)
- {
- packet->append(name, length, packet->charset());
- return;
- }
+ return packet->append(name, length, packet->charset());
/*
The identifier must be quoted as it includes a quote character or
@@ -1014,7 +1016,8 @@ append_identifier(THD *thd, String *packet, const char *name, uint length)
(void) packet->reserve(length*2 + 2);
quote_char= (char) q;
- packet->append(&quote_char, 1, system_charset_info);
+ if (packet->append(&quote_char, 1, system_charset_info))
+ return true;
for (name_end= name+length ; name < name_end ; name+= length)
{
@@ -1029,11 +1032,13 @@ append_identifier(THD *thd, String *packet, const char *name, uint length)
*/
if (!length)
length= 1;
- if (length == 1 && chr == (uchar) quote_char)
- packet->append(&quote_char, 1, system_charset_info);
- packet->append(name, length, system_charset_info);
+ if (length == 1 && chr == (uchar) quote_char &&
+ packet->append(&quote_char, 1, system_charset_info))
+ return true;
+ if (packet->append(name, length, system_charset_info))
+ return true;
}
- packet->append(&quote_char, 1, system_charset_info);
+ return packet->append(&quote_char, 1, system_charset_info);
}
diff --git a/sql/sql_show.h b/sql/sql_show.h
index 8ad9327c08c..611e3a64c73 100644
--- a/sql/sql_show.h
+++ b/sql/sql_show.h
@@ -90,7 +90,7 @@ int view_store_create_info(THD *thd, TABLE_LIST *table, String *buff);
int copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table);
-void append_identifier(THD *thd, String *packet, const char *name,
+bool append_identifier(THD *thd, String *packet, const char *name,
uint length);
void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild);
int mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd);
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index c4f5f315b08..75029a03790 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -1121,39 +1121,47 @@ outp:
-
-void String::print(String *str)
+/*
+ Append characters to a single-quoted string '...', escaping special
+ characters as necessary.
+ Does not add the enclosing quotes, this is left up to caller.
+*/
+void String::append_for_single_quote(const char *st, uint len)
{
- char *st= (char*)Ptr, *end= st+str_length;
+ const char *end= st+len;
for (; st < end; st++)
{
uchar c= *st;
switch (c)
{
case '\\':
- str->append(STRING_WITH_LEN("\\\\"));
+ append(STRING_WITH_LEN("\\\\"));
break;
case '\0':
- str->append(STRING_WITH_LEN("\\0"));
+ append(STRING_WITH_LEN("\\0"));
break;
case '\'':
- str->append(STRING_WITH_LEN("\\'"));
+ append(STRING_WITH_LEN("\\'"));
break;
case '\n':
- str->append(STRING_WITH_LEN("\\n"));
+ append(STRING_WITH_LEN("\\n"));
break;
case '\r':
- str->append(STRING_WITH_LEN("\\r"));
+ append(STRING_WITH_LEN("\\r"));
break;
case '\032': // Ctrl-Z
- str->append(STRING_WITH_LEN("\\Z"));
+ append(STRING_WITH_LEN("\\Z"));
break;
default:
- str->append(c);
+ append(c);
}
}
}
+void String::print(String *str)
+{
+ str->append_for_single_quote(Ptr, str_length);
+}
/*
Exchange state of this object and argument.
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 86af507918c..2f0cd9103dc 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -459,6 +459,7 @@ public:
return FALSE;
}
void print(String *print);
+ void append_for_single_quote(const char *st, uint len);
/* Swap two string objects. Efficient way to exchange data without memcpy. */
void swap(String &s);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 5cdfb62a047..9bbbf814422 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -163,6 +163,13 @@ static char* add_identifier(THD* thd, char *to_p, const char * end_p,
diagnostic, error etc. when it would be useful to know what a particular
file [and directory] means. Such as SHOW ENGINE STATUS, error messages etc.
+ Examples:
+
+ t1#P#p1 table t1 partition p1
+ t1#P#p1#SP#sp1 table t1 partition p1 subpartition sp1
+ t1#P#p1#SP#sp1#TMP# table t1 partition p1 subpartition sp1 temporary
+ t1#P#p1#SP#sp1#REN# table t1 partition p1 subpartition sp1 renamed
+
@param thd Thread handle
@param from Path name in my_charset_filename
Null terminated in my_charset_filename, normalized
@@ -201,7 +208,7 @@ uint explain_filename(THD* thd,
int part_name_len= 0;
const char *subpart_name= NULL;
int subpart_name_len= 0;
- enum enum_file_name_type {NORMAL, TEMP, RENAMED} name_type= NORMAL;
+ uint name_variant= NORMAL_PART_NAME;
const char *tmp_p;
DBUG_ENTER("explain_filename");
DBUG_PRINT("enter", ("from '%s'", from));
@@ -244,7 +251,6 @@ uint explain_filename(THD* thd,
(tmp_p[2] == 'L' || tmp_p[2] == 'l') &&
tmp_p[3] == '-')
{
- name_type= TEMP;
tmp_p+= 4; /* sql- prefix found */
}
else
@@ -255,7 +261,7 @@ uint explain_filename(THD* thd,
if ((tmp_p[1] == 'M' || tmp_p[1] == 'm') &&
(tmp_p[2] == 'P' || tmp_p[2] == 'p') &&
tmp_p[3] == '#' && !tmp_p[4])
- name_type= TEMP;
+ name_variant= TEMP_PART_NAME;
else
res= 3;
tmp_p+= 4;
@@ -265,7 +271,7 @@ uint explain_filename(THD* thd,
if ((tmp_p[1] == 'E' || tmp_p[1] == 'e') &&
(tmp_p[2] == 'N' || tmp_p[2] == 'n') &&
tmp_p[3] == '#' && !tmp_p[4])
- name_type= RENAMED;
+ name_variant= RENAMED_PART_NAME;
else
res= 4;
tmp_p+= 4;
@@ -290,7 +296,7 @@ uint explain_filename(THD* thd,
subpart_name_len= strlen(subpart_name);
else
part_name_len= strlen(part_name);
- if (name_type != NORMAL)
+ if (name_variant != NORMAL_PART_NAME)
{
if (subpart_name)
subpart_name_len-= 5;
@@ -332,9 +338,9 @@ uint explain_filename(THD* thd,
to_p= strnmov(to_p, " ", end_p - to_p);
else
to_p= strnmov(to_p, ", ", end_p - to_p);
- if (name_type != NORMAL)
+ if (name_variant != NORMAL_PART_NAME)
{
- if (name_type == TEMP)
+ if (name_variant == TEMP_PART_NAME)
to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_TEMPORARY_NAME),
end_p - to_p);
else
@@ -1972,27 +1978,28 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
static uint32 comment_length(THD *thd, uint32 comment_pos,
const char **comment_start)
{
- const char *query= thd->query();
- const char *query_end= query + thd->query_length();
+ /* We use uchar * here to make array indexing portable */
+ const uchar *query= (uchar*) thd->query();
+ const uchar *query_end= (uchar*) query + thd->query_length();
const uchar *const state_map= thd->charset()->state_map;
for (; query < query_end; query++)
{
- if (state_map[*query] == MY_LEX_SKIP)
+ if (state_map[static_cast<uchar>(*query)] == MY_LEX_SKIP)
continue;
if (comment_pos-- == 0)
break;
}
if (query > query_end - 3 /* comment can't be shorter than 4 */ ||
- state_map[*query] != MY_LEX_LONG_COMMENT || query[1] != '*')
+ state_map[static_cast<uchar>(*query)] != MY_LEX_LONG_COMMENT || query[1] != '*')
return 0;
- *comment_start= query;
+ *comment_start= (char*) query;
for (query+= 3; query < query_end; query++)
{
if (query[-1] == '*' && query[0] == '/')
- return query - *comment_start + 1;
+ return (char*) query - *comment_start + 1;
}
return 0;
}
@@ -2109,6 +2116,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
{
bool is_trans;
char *db=table->db;
+ size_t db_length= table->db_length;
handlerton *table_type;
enum legacy_db_type frm_db_type= DB_TYPE_UNKNOWN;
@@ -2170,14 +2178,14 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
Don't write the database name if it is the current one (or if
thd->db is NULL).
*/
- built_ptr_query->append("`");
if (thd->db == NULL || strcmp(db,thd->db) != 0)
{
- built_ptr_query->append(db);
- built_ptr_query->append("`.`");
+ append_identifier(thd, built_ptr_query, db, db_length);
+ built_ptr_query->append(".");
}
- built_ptr_query->append(table->table_name);
- built_ptr_query->append("`,");
+ append_identifier(thd, built_ptr_query, table->table_name,
+ table->table_name_length);
+ built_ptr_query->append(",");
}
/*
This means that a temporary table was droped and as such there
@@ -2192,7 +2200,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
if (thd->locked_tables_mode)
{
- if (wait_while_table_is_used(thd, table->table, HA_EXTRA_FORCE_REOPEN))
+ if (wait_while_table_is_used(thd, table->table, HA_EXTRA_NOT_USED))
{
error= -1;
goto err;
@@ -2233,15 +2241,15 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
Don't write the database name if it is the current one (or if
thd->db is NULL).
*/
- built_query.append("`");
if (thd->db == NULL || strcmp(db,thd->db) != 0)
{
- built_query.append(db);
- built_query.append("`.`");
+ append_identifier(thd, &built_query, db, db_length);
+ built_query.append(".");
}
- built_query.append(table->table_name);
- built_query.append("`,");
+ append_identifier(thd, &built_query, table->table_name,
+ table->table_name_length);
+ built_query.append(",");
}
}
DEBUG_SYNC(thd, "rm_table_no_locks_before_delete_table");
@@ -7302,7 +7310,7 @@ err_with_mdl:
bool mysql_trans_prepare_alter_copy_data(THD *thd)
{
- DBUG_ENTER("mysql_prepare_alter_copy_data");
+ DBUG_ENTER("mysql_trans_prepare_alter_copy_data");
/*
Turn off recovery logging since rollback of an alter table is to
delete the new table so there is no need to log the changes to it.
@@ -7322,7 +7330,7 @@ bool mysql_trans_prepare_alter_copy_data(THD *thd)
bool mysql_trans_commit_alter_copy_data(THD *thd)
{
bool error= FALSE;
- DBUG_ENTER("mysql_commit_alter_copy_data");
+ DBUG_ENTER("mysql_trans_commit_alter_copy_data");
if (ha_enable_transaction(thd, TRUE))
DBUG_RETURN(TRUE);
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index 3c1b231d3f2..9d4ca5e1373 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -24,6 +24,7 @@
#include "sql_acl.h" // DROP_ACL
#include "sql_parse.h" // check_one_table_access()
#include "sql_truncate.h"
+#include "sql_show.h"
/**
@@ -35,7 +36,8 @@
@return TRUE on failure, FALSE otherwise.
*/
-static bool fk_info_append_fields(String *str, List<LEX_STRING> *fields)
+static bool fk_info_append_fields(THD *thd, String *str,
+ List<LEX_STRING> *fields)
{
bool res= FALSE;
LEX_STRING *field;
@@ -43,9 +45,8 @@ static bool fk_info_append_fields(String *str, List<LEX_STRING> *fields)
while ((field= it++))
{
- res|= str->append("`");
- res|= str->append(field);
- res|= str->append("`, ");
+ res|= append_identifier(thd, str, field->str, field->length);
+ res|= str->append(", ");
}
str->chop();
@@ -76,20 +77,24 @@ static const char *fk_info_str(THD *thd, FOREIGN_KEY_INFO *fk_info)
`db`.`tbl`, CONSTRAINT `id` FOREIGN KEY (`fk`) REFERENCES `db`.`tbl` (`fk`)
*/
- res|= str.append('`');
- res|= str.append(fk_info->foreign_db);
- res|= str.append("`.`");
- res|= str.append(fk_info->foreign_table);
- res|= str.append("`, CONSTRAINT `");
- res|= str.append(fk_info->foreign_id);
- res|= str.append("` FOREIGN KEY (");
- res|= fk_info_append_fields(&str, &fk_info->foreign_fields);
- res|= str.append(") REFERENCES `");
- res|= str.append(fk_info->referenced_db);
- res|= str.append("`.`");
- res|= str.append(fk_info->referenced_table);
- res|= str.append("` (");
- res|= fk_info_append_fields(&str, &fk_info->referenced_fields);
+ res|= append_identifier(thd, &str, fk_info->foreign_db->str,
+ fk_info->foreign_db->length);
+ res|= str.append(".");
+ res|= append_identifier(thd, &str, fk_info->foreign_table->str,
+ fk_info->foreign_table->length);
+ res|= str.append(", CONSTRAINT ");
+ res|= append_identifier(thd, &str, fk_info->foreign_id->str,
+ fk_info->foreign_id->length);
+ res|= str.append(" FOREIGN KEY (");
+ res|= fk_info_append_fields(thd, &str, &fk_info->foreign_fields);
+ res|= str.append(") REFERENCES ");
+ res|= append_identifier(thd, &str, fk_info->referenced_db->str,
+ fk_info->referenced_db->length);
+ res|= str.append(".");
+ res|= append_identifier(thd, &str, fk_info->referenced_table->str,
+ fk_info->referenced_table->length);
+ res|= str.append(" (");
+ res|= fk_info_append_fields(thd, &str, &fk_info->referenced_fields);
res|= str.append(')');
return res ? NULL : thd->strmake(str.ptr(), str.length());
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 021267b53bd..8dcae907926 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -621,6 +621,8 @@ bool st_select_lex_unit::exec()
if (executed && !uncacheable && !describe)
DBUG_RETURN(FALSE);
executed= 1;
+ if (!(uncacheable & ~UNCACHEABLE_EXPLAIN) && item)
+ item->make_const();
saved_error= optimize();
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 13c6cd3aded..48d2406c559 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -12236,7 +12236,7 @@ load_data_set_elem:
if (lex->update_list.push_back($1) ||
lex->value_list.push_back($4))
MYSQL_YYABORT;
- $4->set_name($3, (uint) ($5 - $3), YYTHD->charset());
+ $4->set_name_no_truncate($3, (uint) ($5 - $3), YYTHD->charset());
}
;
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 47dc8b3addf..01505525d7e 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -47,6 +47,7 @@
#include "sql_base.h" // close_cached_tables
#include <myisam.h>
#include "log_slow.h"
+#include "debug_sync.h" // DEBUG_SYNC
#include "log_event.h"
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
@@ -3256,6 +3257,13 @@ bool Sys_var_rpl_filter::do_check(THD *thd, set_var *var)
{
bool status;
+ /*
+ We must not be holding LOCK_global_system_variables here, otherwise we can
+ deadlock with THD::init() which is invoked from within the slave threads
+ with opposite locking order.
+ */
+ mysql_mutex_assert_not_owner(&LOCK_global_system_variables);
+
mysql_mutex_lock(&LOCK_active_mi);
mysql_mutex_lock(&active_mi->rli.run_lock);
@@ -3272,22 +3280,43 @@ bool Sys_var_rpl_filter::do_check(THD *thd, set_var *var)
return status;
}
-bool Sys_var_rpl_filter::global_update(THD *thd, set_var *var)
+void Sys_var_rpl_filter::lock(void)
{
- bool slave_running, status= false;
+ /*
+ Starting a slave thread causes the new thread to attempt to
+ acquire LOCK_global_system_variables (in THD::init) while
+ LOCK_active_mi is being held by the thread that initiated
+ the process. In order to not violate the lock order, unlock
+ LOCK_global_system_variables before grabbing LOCK_active_mi.
+ */
+ mysql_mutex_unlock(&LOCK_global_system_variables);
mysql_mutex_lock(&LOCK_active_mi);
mysql_mutex_lock(&active_mi->rli.run_lock);
+}
- if (! (slave_running= active_mi->rli.slave_running))
- status= set_filter_value(var->save_result.string_value.str);
-
+void Sys_var_rpl_filter::unlock(void)
+{
mysql_mutex_unlock(&active_mi->rli.run_lock);
mysql_mutex_unlock(&LOCK_active_mi);
+ mysql_mutex_lock(&LOCK_global_system_variables);
+}
+
+bool Sys_var_rpl_filter::global_update(THD *thd, set_var *var)
+{
+ bool slave_running, status= false;
+
+ lock();
+
+ if (! (slave_running= active_mi->rli.slave_running))
+ status= set_filter_value(var->save_result.string_value.str);
+
if (slave_running)
my_error(ER_SLAVE_MUST_STOP, MYF(0));
+ unlock();
+
return slave_running || status;
}
@@ -3326,8 +3355,7 @@ uchar *Sys_var_rpl_filter::global_value_ptr(THD *thd, LEX_STRING *base)
tmp.length(0);
- mysql_mutex_lock(&LOCK_active_mi);
- mysql_mutex_lock(&active_mi->rli.run_lock);
+ lock();
switch (opt_id) {
case OPT_REPLICATE_DO_DB:
@@ -3350,8 +3378,7 @@ uchar *Sys_var_rpl_filter::global_value_ptr(THD *thd, LEX_STRING *base)
break;
}
- mysql_mutex_unlock(&active_mi->rli.run_lock);
- mysql_mutex_unlock(&LOCK_active_mi);
+ unlock();
return (uchar *) thd->strmake(tmp.ptr(), tmp.length());
}
@@ -3404,6 +3431,9 @@ static Sys_var_charptr Sys_slave_load_tmpdir(
static bool fix_slave_net_timeout(sys_var *self, THD *thd, enum_var_type type)
{
+ DEBUG_SYNC(thd, "fix_slave_net_timeout");
+
+ mysql_mutex_unlock(&LOCK_global_system_variables);
mysql_mutex_lock(&LOCK_active_mi);
DBUG_PRINT("info", ("slave_net_timeout=%u mi->heartbeat_period=%.3f",
slave_net_timeout,
@@ -3413,6 +3443,7 @@ static bool fix_slave_net_timeout(sys_var *self, THD *thd, enum_var_type type)
ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX,
ER(ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX));
mysql_mutex_unlock(&LOCK_active_mi);
+ mysql_mutex_lock(&LOCK_global_system_variables);
return false;
}
static Sys_var_uint Sys_slave_net_timeout(
@@ -3439,6 +3470,7 @@ static bool check_slave_skip_counter(sys_var *self, THD *thd, set_var *var)
}
static bool fix_slave_skip_counter(sys_var *self, THD *thd, enum_var_type type)
{
+ mysql_mutex_unlock(&LOCK_global_system_variables);
mysql_mutex_lock(&LOCK_active_mi);
mysql_mutex_lock(&active_mi->rli.run_lock);
/*
@@ -3454,6 +3486,7 @@ static bool fix_slave_skip_counter(sys_var *self, THD *thd, enum_var_type type)
}
mysql_mutex_unlock(&active_mi->rli.run_lock);
mysql_mutex_unlock(&LOCK_active_mi);
+ mysql_mutex_lock(&LOCK_global_system_variables);
return 0;
}
static Sys_var_uint Sys_slave_skip_counter(
diff --git a/sql/sys_vars.h b/sql/sys_vars.h
index 4ea6b1f036e..21bebcd762c 100644
--- a/sql/sys_vars.h
+++ b/sql/sys_vars.h
@@ -588,6 +588,8 @@ public:
protected:
uchar *global_value_ptr(THD *thd, LEX_STRING *base);
bool set_filter_value(const char *value);
+ void lock(void);
+ void unlock(void);
};
/**
@@ -957,7 +959,7 @@ public:
Sys_var_max_user_conn(const char *name_arg,
const char *comment, int flag_args, ptrdiff_t off, size_t size,
CMD_LINE getopt,
- uint min_val, uint max_val, uint def_val,
+ int min_val, int max_val, int def_val,
uint block_size, PolyLock *lock=0,
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
diff --git a/sql/table.cc b/sql/table.cc
index daccb0d1ca6..1fa5069a07e 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -4400,7 +4400,7 @@ bool TABLE_LIST::prep_check_option(THD *thd, uint8 check_opt_type)
There are currently two mechanisms at work that handle errors for views,
this one and a more general mechanism based on an Internal_error_handler,
see Show_create_error_handler. The latter handles errors encountered during
- execution of SHOW CREATE VIEW, while the machanism using this method is
+ execution of SHOW CREATE VIEW, while the mechanism using this method is
handles SELECT from views. The two methods should not clash.
@param[in,out] thd thread handler