summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2010-09-11 20:43:48 +0200
committerSergei Golubchik <sergii@pisem.net>2010-09-11 20:43:48 +0200
commita3d80d952d7b99680ca4a3a89e128ecc0d490c10 (patch)
tree0d72ee69e037cdd09618ddb53652dd1b220890dc /sql
parentec06ba24553d2d83b3a6a6bc4d8150910b01ee7c (diff)
parent966661c8cc75dd7d540a5fe40b4d893c40e91d26 (diff)
downloadmariadb-git-a3d80d952d7b99680ca4a3a89e128ecc0d490c10.tar.gz
merge with 5.1
Diffstat (limited to 'sql')
-rw-r--r--sql/Makefile.am3
-rw-r--r--sql/field.cc8
-rw-r--r--sql/ha_partition.cc54
-rw-r--r--sql/ha_partition.h15
-rw-r--r--sql/handler.h18
-rw-r--r--sql/item.cc8
-rw-r--r--sql/item.h1
-rw-r--r--sql/item_buff.cc6
-rw-r--r--sql/item_create.cc26
-rw-r--r--sql/item_func.cc7
-rw-r--r--sql/item_sum.cc20
-rw-r--r--sql/item_timefunc.cc7
-rw-r--r--sql/log.cc106
-rw-r--r--sql/log.h2
-rw-r--r--sql/log_event.cc108
-rw-r--r--sql/log_event.h9
-rw-r--r--sql/log_event_old.cc6
-rw-r--r--sql/mysql_priv.h6
-rw-r--r--sql/mysqld.cc70
-rw-r--r--sql/opt_range.cc2
-rw-r--r--sql/partition_info.cc6
-rw-r--r--sql/protocol.cc15
-rw-r--r--sql/rpl_filter.cc4
-rw-r--r--sql/rpl_rli.cc3
-rw-r--r--sql/set_var.cc31
-rw-r--r--sql/set_var.h2
-rw-r--r--sql/slave.cc6
-rw-r--r--sql/sp.cc4
-rw-r--r--sql/sp_head.cc4
-rw-r--r--sql/spatial.cc44
-rw-r--r--sql/spatial.h26
-rw-r--r--sql/sql_acl.cc35
-rw-r--r--sql/sql_base.cc22
-rw-r--r--sql/sql_cache.cc3
-rw-r--r--sql/sql_class.cc46
-rw-r--r--sql/sql_class.h64
-rw-r--r--sql/sql_cursor.cc7
-rw-r--r--sql/sql_insert.cc11
-rw-r--r--sql/sql_lex.cc16
-rw-r--r--sql/sql_lex.h20
-rw-r--r--sql/sql_list.h2
-rw-r--r--sql/sql_load.cc64
-rw-r--r--sql/sql_parse.cc55
-rw-r--r--sql/sql_partition.cc2
-rw-r--r--sql/sql_partition.h2
-rw-r--r--sql/sql_prepare.cc15
-rw-r--r--sql/sql_repl.cc8
-rw-r--r--sql/sql_select.cc44
-rw-r--r--sql/sql_show.cc93
-rw-r--r--sql/sql_table.cc101
-rw-r--r--sql/sql_trigger.cc4
-rw-r--r--sql/sql_udf.cc4
-rw-r--r--sql/sql_update.cc13
-rw-r--r--sql/sql_view.cc2
-rw-r--r--sql/table.cc18
-rw-r--r--sql/table.h3
-rw-r--r--sql/udf_example.c2
-rw-r--r--sql/unireg.h4
58 files changed, 865 insertions, 422 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am
index b738565f818..ba91f94d72d 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -194,6 +194,3 @@ install-exec-hook:
test ! -x mysqld-debug$(EXEEXT) || $(INSTALL_PROGRAM) mysqld-debug$(EXEEXT) $(DESTDIR)$(libexecdir)
test ! -f mysqld-debug.sym.gz || $(INSTALL_DATA) mysqld-debug.sym.gz $(DESTDIR)$(pkglibdir)
test ! -f mysqld.sym.gz || $(INSTALL_DATA) mysqld.sym.gz $(DESTDIR)$(pkglibdir)
-
-# Don't update the files from bitkeeper
-%::SCCS/s.%
diff --git a/sql/field.cc b/sql/field.cc
index 597ec4f68d0..633c0d96f2c 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -8696,7 +8696,13 @@ int Field_set::store(longlong nr, bool unsigned_val)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
- ulonglong max_nr= set_bits(ulonglong, typelib->count);
+ ulonglong max_nr;
+
+ if (sizeof(ulonglong)*8 <= typelib->count)
+ max_nr= ULONGLONG_MAX;
+ else
+ max_nr= (ULL(1) << typelib->count) - 1;
+
if ((ulonglong) nr > max_nr)
{
nr&= max_nr;
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 2bd2eabb58b..a46df40a5ed 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -997,7 +997,7 @@ static bool print_admin_msg(THD* thd, const char* msg_type,
Protocol *protocol= thd->protocol;
uint length, msg_length;
char msgbuf[HA_MAX_MSG_BUF];
- char name[NAME_LEN*2+2];
+ char name[SAFE_NAME_LEN*2+2];
va_start(args, fmt);
msg_length= my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
@@ -4195,6 +4195,58 @@ int ha_partition::common_first_last(uchar *buf)
/*
+ Optimization of the default implementation to take advantage of dynamic
+ partition pruning.
+*/
+int ha_partition::index_read_idx_map(uchar *buf, uint index,
+ const uchar *key,
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag)
+{
+ int error= HA_ERR_KEY_NOT_FOUND;
+ DBUG_ENTER("ha_partition::index_read_idx_map");
+
+ if (find_flag == HA_READ_KEY_EXACT)
+ {
+ uint part;
+ m_start_key.key= key;
+ m_start_key.keypart_map= keypart_map;
+ m_start_key.flag= find_flag;
+ m_start_key.length= calculate_key_len(table, index, m_start_key.key,
+ m_start_key.keypart_map);
+
+ get_partition_set(table, buf, index, &m_start_key, &m_part_spec);
+
+ /* How can it be more than one partition with the current use? */
+ DBUG_ASSERT(m_part_spec.start_part == m_part_spec.end_part);
+
+ for (part= m_part_spec.start_part; part <= m_part_spec.end_part; part++)
+ {
+ if (bitmap_is_set(&(m_part_info->used_partitions), part))
+ {
+ error= m_file[part]->index_read_idx_map(buf, index, key,
+ keypart_map, find_flag);
+ if (error != HA_ERR_KEY_NOT_FOUND &&
+ error != HA_ERR_END_OF_FILE)
+ break;
+ }
+ }
+ }
+ else
+ {
+ /*
+ If not only used with READ_EXACT, we should investigate if possible
+ to optimize for other find_flag's as well.
+ */
+ DBUG_ASSERT(0);
+ /* fall back on the default implementation */
+ error= handler::index_read_idx_map(buf, index, key, keypart_map, find_flag);
+ }
+ DBUG_RETURN(error);
+}
+
+
+/*
Read next record in a forward index scan
SYNOPSIS
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index c8c45d72b26..1a9ec5bbf70 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -53,8 +53,7 @@ typedef struct st_ha_data_partition
HA_CAN_FULLTEXT | \
HA_DUPLICATE_POS | \
HA_CAN_SQL_HANDLER | \
- HA_CAN_INSERT_DELAYED | \
- HA_PRIMARY_KEY_REQUIRED_FOR_POSITION)
+ HA_CAN_INSERT_DELAYED)
class ha_partition :public handler
{
private:
@@ -448,6 +447,15 @@ public:
virtual int index_init(uint idx, bool sorted);
virtual int index_end();
+ /**
+ @breif
+ Positions an index cursor to the index specified in the hanlde. Fetches the
+ row if available. If the key value is null, begin at first key of the
+ index.
+ */
+ virtual int index_read_idx_map(uchar *buf, uint index, const uchar *key,
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag);
/*
These methods are used to jump to next or previous entry in the index
scan. There are also methods to jump to first and last entry.
@@ -764,9 +772,6 @@ public:
HA_PRIMARY_KEY_REQUIRED_FOR_POSITION:
Does the storage engine need a PK for position?
- Used with hidden primary key in InnoDB.
- Hidden primary keys cannot be supported by partitioning, since the
- partitioning expressions columns must be a part of the primary key.
(InnoDB)
HA_FILE_BASED is always set for partition handler since we use a
diff --git a/sql/handler.h b/sql/handler.h
index 0306f8aec61..7767a48bae9 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -100,7 +100,10 @@
#define HA_PRIMARY_KEY_IN_READ_INDEX (1 << 15)
/*
If HA_PRIMARY_KEY_REQUIRED_FOR_POSITION is set, it means that to position()
- uses a primary key. Without primary key, we can't call position().
+ uses a primary key given by the record argument.
+ Without primary key, we can't call position().
+ If not set, the position is returned as the current rows position
+ regardless of what argument is given.
*/
#define HA_PRIMARY_KEY_REQUIRED_FOR_POSITION (1 << 16)
#define HA_CAN_RTREEKEYS (1 << 17)
@@ -1612,10 +1615,9 @@ private:
virtual int rnd_next(uchar *buf)=0;
virtual int rnd_pos(uchar * buf, uchar *pos)=0;
/**
- One has to use this method when to find
- random position by record as the plain
- position() call doesn't work for some
- handlers for random position.
+ This function only works for handlers having
+ HA_PRIMARY_KEY_REQUIRED_FOR_POSITION set.
+ It will return the row with the PK given in the record argument.
*/
virtual int rnd_pos_by_record(uchar *record)
{
@@ -1646,6 +1648,12 @@ public:
virtual ha_rows records_in_range(uint inx, key_range *min_key,
key_range *max_key)
{ return (ha_rows) 10; }
+ /*
+ If HA_PRIMARY_KEY_REQUIRED_FOR_POSITION is set, then it sets ref
+ (reference to the row, aka position, with the primary key given in
+ the record).
+ Otherwise it set ref to the current row.
+ */
virtual void position(const uchar *record)=0;
virtual int info(uint)=0; // see my_base.h for full description
virtual void get_dynamic_partition_info(PARTITION_INFO *stat_info,
diff --git a/sql/item.cc b/sql/item.cc
index 2edeb4c0ee0..2dc65c5fb17 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -255,8 +255,9 @@ my_decimal *Item::val_decimal_from_int(my_decimal *decimal_value)
my_decimal *Item::val_decimal_from_string(my_decimal *decimal_value)
{
String *res;
+
if (!(res= val_str(&str_value)))
- return 0; // NULL or EOM
+ return 0;
if (str2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_BAD_NUM,
res->ptr(), res->length(), res->charset(),
@@ -3742,7 +3743,7 @@ static Item** find_field_in_group_list(Item *find_item, ORDER *group_list)
int found_match_degree= 0;
Item_ident *cur_field;
int cur_match_degree= 0;
- char name_buff[NAME_LEN+1];
+ char name_buff[SAFE_NAME_LEN+1];
if (find_item->type() == Item::FIELD_ITEM ||
find_item->type() == Item::REF_ITEM)
@@ -4154,8 +4155,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
context->first_name_resolution_table,
context->last_name_resolution_table,
reference, REPORT_ALL_ERRORS,
- !any_privileges &&
- TRUE, TRUE);
+ !any_privileges, TRUE);
}
return -1;
}
diff --git a/sql/item.h b/sql/item.h
index 94a25d7eaea..3d0f35f5984 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2892,6 +2892,7 @@ public:
class Cached_item_str :public Cached_item
{
Item *item;
+ uint32 value_max_length;
String value,tmp_value;
public:
Cached_item_str(THD *thd, Item *arg);
diff --git a/sql/item_buff.cc b/sql/item_buff.cc
index 2f45d0a17c2..0ac4edb3656 100644
--- a/sql/item_buff.cc
+++ b/sql/item_buff.cc
@@ -58,7 +58,9 @@ Cached_item::~Cached_item() {}
*/
Cached_item_str::Cached_item_str(THD *thd, Item *arg)
- :item(arg), value(min(arg->max_length, thd->variables.max_sort_length))
+ :item(arg),
+ value_max_length(min(arg->max_length, thd->variables.max_sort_length)),
+ value(value_max_length)
{}
bool Cached_item_str::cmp(void)
@@ -67,7 +69,7 @@ bool Cached_item_str::cmp(void)
bool tmp;
if ((res=item->val_str(&tmp_value)))
- res->length(min(res->length(), value.alloced_length()));
+ res->length(min(res->length(), value_max_length));
if (null_value != item->null_value)
{
if ((null_value= item->null_value))
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 2e72ab24fb0..eade395a229 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -5054,8 +5054,6 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type,
CHARSET_INFO *cs)
{
Item *UNINIT_VAR(res);
- ulong len;
- uint dec;
switch (cast_type) {
case ITEM_CAST_BINARY:
@@ -5078,11 +5076,10 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type,
break;
case ITEM_CAST_DECIMAL:
{
- if (c_len == NULL)
- {
- len= 0;
- }
- else
+ ulong len= 0;
+ uint dec= 0;
+
+ if (c_len)
{
ulong decoded_size;
errno= 0;
@@ -5096,11 +5093,7 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type,
len= decoded_size;
}
- if (c_dec == NULL)
- {
- dec= 0;
- }
- else
+ if (c_dec)
{
ulong decoded_size;
errno= 0;
@@ -5136,12 +5129,9 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type,
}
case ITEM_CAST_CHAR:
{
+ int len= -1;
CHARSET_INFO *real_cs= (cs ? cs : thd->variables.collation_connection);
- if (c_len == NULL)
- {
- len= (ulong) -1L;
- }
- else
+ if (c_len)
{
ulong decoded_size;
errno= 0;
@@ -5151,7 +5141,7 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type,
my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), "cast as char", MAX_FIELD_BLOBLENGTH);
return NULL;
}
- len= decoded_size;
+ len= (int) decoded_size;
}
res= new (thd->mem_root) Item_char_typecast(a, len, real_cs);
break;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 3cb9d4724b9..a139968ae37 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2244,6 +2244,8 @@ void Item_func_min_max::fix_length_and_dec()
max_length= my_decimal_precision_to_length_no_truncation(max_int_part +
decimals, decimals,
unsigned_flag);
+ else if (cmp_type == REAL_RESULT)
+ max_length= float_length(decimals);
cached_field_type= agg_field_type(args, arg_count);
}
@@ -4740,6 +4742,7 @@ bool Item_func_get_user_var::set_value(THD *thd,
bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
+ DBUG_ASSERT(thd->lex->exchange);
if (Item::fix_fields(thd, ref) ||
!(entry= get_variable(&thd->user_vars, name, 1)))
return TRUE;
@@ -4749,7 +4752,9 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
of fields in LOAD DATA INFILE.
(Since Item_user_var_as_out_param is used only there).
*/
- entry->collation.set(thd->variables.collation_database);
+ entry->collation.set(thd->lex->exchange->cs ?
+ thd->lex->exchange->cs :
+ thd->variables.collation_database);
entry->update_query_id= thd->query_id;
return FALSE;
}
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index b3b07119066..45c3ee3cd20 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -3043,7 +3043,6 @@ Item_func_group_concat::Item_func_group_concat(THD *thd,
tree(item->tree),
unique_filter(item->unique_filter),
table(item->table),
- order(item->order),
context(item->context),
arg_count_order(item->arg_count_order),
arg_count_field(item->arg_count_field),
@@ -3056,8 +3055,25 @@ Item_func_group_concat::Item_func_group_concat(THD *thd,
{
quick_group= item->quick_group;
result.set_charset(collation.collation);
-}
+ /*
+ Since the ORDER structures pointed to by the elements of the 'order' array
+ may be modified in find_order_in_list() called from
+ Item_func_group_concat::setup(), create a copy of those structures so that
+ such modifications done in this object would not have any effect on the
+ object being copied.
+ */
+ ORDER *tmp;
+ if (!(tmp= (ORDER *) thd->alloc(sizeof(ORDER *) * arg_count_order +
+ sizeof(ORDER) * arg_count_order)))
+ return;
+ order= (ORDER **)(tmp + arg_count_order);
+ for (uint i= 0; i < arg_count_order; i++, tmp++)
+ {
+ memcpy(tmp, item->order[i], sizeof(ORDER));
+ order[i]= tmp;
+ }
+}
void Item_func_group_concat::cleanup()
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index d91ccee1575..57656f30294 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -288,11 +288,6 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
CHARSET_INFO *cs= &my_charset_bin;
DBUG_ENTER("extract_date_time");
- LINT_INIT(strict_week_number);
- /* Remove valgrind varnings when using gcc 3.3 and -O1 */
- VALGRIND_OR_LINT_INIT(strict_week_number_year_type);
- VALGRIND_OR_LINT_INIT(sunday_first_n_first_week_non_iso);
-
if (!sub_pattern_end)
bzero((char*) l_time, sizeof(*l_time));
@@ -2996,7 +2991,7 @@ String *Item_func_maketime::val_str(String *str)
buf, len, MYSQL_TIMESTAMP_TIME,
NullS);
}
-
+
if (make_time_with_warn((DATE_TIME_FORMAT *) 0, &ltime, str))
{
null_value= 1;
diff --git a/sql/log.cc b/sql/log.cc
index 9cbf33d9890..8173b44c21f 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1663,6 +1663,19 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
DBUG_RETURN(error);
}
+/**
+ Cleanup the cache.
+
+ @param thd The client thread that wants to clean up the cache.
+*/
+void MYSQL_BIN_LOG::reset_gathered_updates(THD *thd)
+{
+ binlog_trx_data *const trx_data=
+ (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
+
+ trx_data->reset();
+}
+
void MYSQL_BIN_LOG::set_write_error(THD *thd)
{
DBUG_ENTER("MYSQL_BIN_LOG::set_write_error");
@@ -1771,17 +1784,17 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv)
int check_binlog_magic(IO_CACHE* log, const char** errmsg)
{
- char magic[4];
+ uchar magic[4];
DBUG_ASSERT(my_b_tell(log) == 0);
- if (my_b_read(log, (uchar*) magic, sizeof(magic)))
+ if (my_b_read(log, magic, sizeof(magic)))
{
*errmsg = "I/O error reading the header from the binary log";
sql_print_error("%s, errno=%d, io cache code=%d", *errmsg, my_errno,
log->error);
return 1;
}
- if (memcmp(magic, BINLOG_MAGIC, sizeof(magic)))
+ if (bcmp(magic, BINLOG_MAGIC, sizeof(magic)))
{
*errmsg = "Binlog has bad magic number; It's not a binary log file that can be used by this version of MySQL";
return 1;
@@ -1898,7 +1911,7 @@ static int find_uniq_filename(char *name)
file_info= dir_info->dir_entry;
for (i=dir_info->number_off_files ; i-- ; file_info++)
{
- if (bcmp((uchar*) file_info->name, (uchar*) start, length) == 0 &&
+ if (memcmp(file_info->name, start, length) == 0 &&
test_if_number(file_info->name+length, &number,0))
{
set_if_bigger(max_found,(ulong) number);
@@ -2676,7 +2689,7 @@ bool MYSQL_BIN_LOG::open(const char *log_name,
an extension for the binary log files.
In this case we write a standard header to it.
*/
- if (my_b_safe_write(&log_file, (uchar*) BINLOG_MAGIC,
+ if (my_b_safe_write(&log_file, BINLOG_MAGIC,
BIN_LOG_HEADER_SIZE))
goto err;
bytes_written+= BIN_LOG_HEADER_SIZE;
@@ -5126,6 +5139,22 @@ void sql_perror(const char *message)
}
+/*
+ Unfortunately, there seems to be no good way
+ to restore the original streams upon failure.
+*/
+static bool redirect_std_streams(const char *file)
+{
+ if (freopen(file, "a+", stdout) && freopen(file, "a+", stderr))
+ {
+ setbuf(stderr, NULL);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
bool flush_error_log()
{
bool result=0;
@@ -5154,11 +5183,7 @@ bool flush_error_log()
setbuf(stderr, NULL);
(void) my_delete(err_renamed, MYF(0));
my_rename(log_error_file,err_renamed,MYF(0));
- if (freopen(log_error_file,"a+",stdout))
- {
- freopen(log_error_file,"a+",stderr);
- setbuf(stderr, NULL);
- }
+ redirect_std_streams(log_error_file);
if ((fd = my_open(err_temp, O_RDONLY, MYF(0))) >= 0)
{
@@ -5173,13 +5198,7 @@ bool flush_error_log()
result= 1;
#else
my_rename(log_error_file,err_renamed,MYF(0));
- if (freopen(log_error_file,"a+",stdout))
- {
- FILE *reopen;
- reopen= freopen(log_error_file,"a+",stderr);
- setbuf(stderr, NULL);
- }
- else
+ if (redirect_std_streams(log_error_file))
result= 1;
#endif
VOID(pthread_mutex_unlock(&LOCK_error_log));
@@ -5230,25 +5249,9 @@ static void print_buffer_to_nt_eventlog(enum loglevel level, char *buff,
#endif /* __NT__ */
-/**
- Prints a printf style message to the error log and, under NT, to the
- Windows event log.
-
- This function prints the message into a buffer and then sends that buffer
- to other functions to write that message to other logging sources.
-
- @param event_type Type of event to write (Error, Warning, or Info)
- @param format Printf style format of message
- @param args va_list list of arguments for the message
-
- @returns
- The function always returns 0. The return value is present in the
- signature to be compatible with other logging routines, which could
- return an error (e.g. logging to the log tables)
-*/
-
#ifndef EMBEDDED_LIBRARY
-static void print_buffer_to_file(enum loglevel level, const char *buffer)
+static void print_buffer_to_file(enum loglevel level, const char *buffer,
+ size_t length)
{
time_t skr;
struct tm tm_tmp;
@@ -5262,7 +5265,7 @@ static void print_buffer_to_file(enum loglevel level, const char *buffer)
localtime_r(&skr, &tm_tmp);
start=&tm_tmp;
- fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %s\n",
+ fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %.*s\n",
start->tm_year % 100,
start->tm_mon+1,
start->tm_mday,
@@ -5271,7 +5274,7 @@ static void print_buffer_to_file(enum loglevel level, const char *buffer)
start->tm_sec,
(level == ERROR_LEVEL ? "ERROR" : level == WARNING_LEVEL ?
"Warning" : "Note"),
- buffer);
+ (int) length, buffer);
fflush(stderr);
@@ -5279,17 +5282,30 @@ static void print_buffer_to_file(enum loglevel level, const char *buffer)
DBUG_VOID_RETURN;
}
+/**
+ Prints a printf style message to the error log and, under NT, to the
+ Windows event log.
+
+ This function prints the message into a buffer and then sends that buffer
+ to other functions to write that message to other logging sources.
+
+ @param level The level of the msg significance
+ @param format Printf style format of message
+ @param args va_list list of arguments for the message
+ @returns
+ The function always returns 0. The return value is present in the
+ signature to be compatible with other logging routines, which could
+ return an error (e.g. logging to the log tables)
+*/
int vprint_msg_to_log(enum loglevel level, const char *format, va_list args)
{
char buff[1024];
+ size_t length;
DBUG_ENTER("vprint_msg_to_log");
-#ifdef __NT__
- size_t length=
-#endif
- my_vsnprintf(buff, sizeof(buff), format, args);
- print_buffer_to_file(level, buff);
+ length= my_vsnprintf(buff, sizeof(buff), format, args);
+ print_buffer_to_file(level, buff, length);
#ifdef __NT__
print_buffer_to_nt_eventlog(level, buff, length, sizeof(buff));
@@ -5297,7 +5313,7 @@ int vprint_msg_to_log(enum loglevel level, const char *format, va_list args)
DBUG_RETURN(0);
}
-#endif /*EMBEDDED_LIBRARY*/
+#endif /* EMBEDDED_LIBRARY */
void sql_print_error(const char *format, ...)
@@ -5383,7 +5399,7 @@ ulong tc_log_page_waits= 0;
#define TC_LOG_HEADER_SIZE (sizeof(tc_log_magic)+1)
-static const char tc_log_magic[]={(char) 254, 0x23, 0x05, 0x74};
+static const uchar tc_log_magic[]={(uchar) 254, 0x23, 0x05, 0x74};
ulong opt_tc_log_size= TC_LOG_MIN_SIZE;
ulong tc_log_max_pages_used=0, tc_log_page_size=0, tc_log_cur_pages_used=0;
@@ -5783,7 +5799,7 @@ int TC_LOG_MMAP::recover()
HASH xids;
PAGE *p=pages, *end_p=pages+npages;
- if (memcmp(data, tc_log_magic, sizeof(tc_log_magic)))
+ if (bcmp(data, tc_log_magic, sizeof(tc_log_magic)))
{
sql_print_error("Bad magic header in tc log");
goto err1;
diff --git a/sql/log.h b/sql/log.h
index 1cfd7ce9ae5..8ee94ab5807 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -356,10 +356,10 @@ public:
/* Use this to start writing a new log file */
void new_file();
+ void reset_gathered_updates(THD *thd);
bool write(Log_event* event_info); // binary log write
bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event, bool incident);
bool write_incident(THD *thd, bool lock);
-
int write_cache(THD *thd, IO_CACHE *cache, bool lock_log,
bool flush_and_sync);
void set_write_error(THD *thd);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index a1ecb79ff56..fa7bb01077d 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1673,7 +1673,7 @@ beg:
precision, decimals);
return bin_size;
}
-
+
case MYSQL_TYPE_FLOAT:
{
float fl;
@@ -2306,6 +2306,53 @@ bool Query_log_event::write(IO_CACHE* file)
start+= 4;
}
+ if (thd && thd->is_current_user_used())
+ {
+ LEX_STRING user;
+ LEX_STRING host;
+ memset(&user, 0, sizeof(user));
+ memset(&host, 0, sizeof(host));
+
+ if (thd->slave_thread && thd->has_invoker())
+ {
+ /* user will be null, if master is older than this patch */
+ user= thd->get_invoker_user();
+ host= thd->get_invoker_host();
+ }
+ else if (thd->security_ctx->priv_user)
+ {
+ Security_context *ctx= thd->security_ctx;
+
+ user.length= strlen(ctx->priv_user);
+ user.str= ctx->priv_user;
+ if (ctx->priv_host[0] != '\0')
+ {
+ host.str= ctx->priv_host;
+ host.length= strlen(ctx->priv_host);
+ }
+ }
+
+ if (user.length > 0)
+ {
+ *start++= Q_INVOKER;
+
+ /*
+ Store user length and user. The max length of use is 16, so 1 byte is
+ enough to store the user's length.
+ */
+ *start++= (uchar)user.length;
+ memcpy(start, user.str, user.length);
+ start+= user.length;
+
+ /*
+ Store host length and host. The max length of host is 60, so 1 byte is
+ enough to store the host's length.
+ */
+ *start++= (uchar)host.length;
+ memcpy(start, host.str, host.length);
+ start+= host.length;
+ }
+ }
/*
NOTE: When adding new status vars, please don't forget to update
the MAX_SIZE_LOG_EVENT_STATUS in log_event.h and update the function
@@ -2348,6 +2395,8 @@ bool Query_log_event::write(IO_CACHE* file)
Query_log_event::Query_log_event()
:Log_event(), data_buf(0)
{
+ memset(&user, 0, sizeof(user));
+ memset(&host, 0, sizeof(host));
}
@@ -2390,6 +2439,9 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
{
time_t end_time;
+ memset(&user, 0, sizeof(user));
+ memset(&host, 0, sizeof(host));
+
error_code= errcode;
time(&end_time);
@@ -2574,6 +2626,8 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
bool catalog_nz= 1;
DBUG_ENTER("Query_log_event::Query_log_event(char*,...)");
+ memset(&user, 0, sizeof(user));
+ memset(&host, 0, sizeof(host));
common_header_len= description_event->common_header_len;
post_header_len= description_event->post_header_len[event_type-1];
DBUG_PRINT("info",("event_len: %u common_header_len: %d post_header_len: %d",
@@ -2728,6 +2782,20 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
data_written= master_data_written= uint4korr(pos);
pos+= 4;
break;
+ case Q_INVOKER:
+ {
+ CHECK_SPACE(pos, end, 1);
+ user.length= *pos++;
+ CHECK_SPACE(pos, end, user.length);
+ user.str= (char *)pos;
+ pos+= user.length;
+
+ CHECK_SPACE(pos, end, 1);
+ host.length= *pos++;
+ CHECK_SPACE(pos, end, host.length);
+ host.str= (char *)pos;
+ pos+= host.length;
+ }
default:
/* That's why you must write status vars in growing order of code */
DBUG_PRINT("info",("Query_log_event has unknown status vars (first has\
@@ -2741,12 +2809,16 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
time_zone_len + 1 +
data_len + 1 +
QUERY_CACHE_FLAGS_SIZE +
+ user.length + 1 +
+ host.length + 1 +
db_len + 1,
MYF(MY_WME))))
#else
if (!(start= data_buf = (Log_event::Byte*) my_malloc(catalog_len + 1 +
time_zone_len + 1 +
- data_len + 1,
+ data_len + 1 +
+ user.length + 1 +
+ host.length + 1,
MYF(MY_WME))))
#endif
DBUG_VOID_RETURN;
@@ -2769,6 +2841,11 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
if (time_zone_len)
copy_str_and_move(&time_zone_str, &start, time_zone_len);
+ if (user.length > 0)
+ copy_str_and_move((const char **)&(user.str), &start, user.length);
+ if (host.length > 0)
+ copy_str_and_move((const char **)&(host.str), &start, host.length);
+
/**
if time_zone_len or catalog_len are 0, then time_zone and catalog
are uninitialized at this point. shouldn't they point to the
@@ -2904,7 +2981,7 @@ void Query_log_event::print_query_header(IO_CACHE* file,
if (likely(charset_inited) &&
(unlikely(!print_event_info->charset_inited ||
- bcmp((uchar*) print_event_info->charset, (uchar*) charset, 6))))
+ memcmp(print_event_info->charset, charset, 6))))
{
CHARSET_INFO *cs_info= get_charset(uint2korr(charset), MYF(MY_WME));
if (cs_info)
@@ -2927,8 +3004,8 @@ void Query_log_event::print_query_header(IO_CACHE* file,
}
if (time_zone_len)
{
- if (bcmp((uchar*) print_event_info->time_zone_str,
- (uchar*) time_zone_str, time_zone_len+1))
+ if (memcmp(print_event_info->time_zone_str,
+ time_zone_str, time_zone_len+1))
{
my_b_printf(file,"SET @@session.time_zone='%s'%s\n",
time_zone_str, print_event_info->delimiter);
@@ -3177,7 +3254,7 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli,
thd->variables.collation_database= thd->db_charset;
thd->table_map_for_update= (table_map)table_map_for_update;
-
+ thd->set_invoker(&user, &host);
/* Execute the query (note that we bypass dispatch_command()) */
const char* found_semicolon= NULL;
mysql_parse(thd, thd->query(), thd->query_length(), &found_semicolon);
@@ -5588,7 +5665,7 @@ void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
double real_val;
char real_buf[FMT_G_BUFSIZE(14)];
float8get(real_val, val);
- my_sprintf(real_buf, (real_buf, "%.14g", real_val));
+ sprintf(real_buf, "%.14g", real_val);
my_b_printf(&cache, ":=%s%s\n", real_buf, print_event_info->delimiter);
break;
case INT_RESULT:
@@ -6157,7 +6234,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)
{
- char buf[NAME_LEN*2 + 30 + 21*2], *pos;
+ char buf[SAFE_NAME_LEN*2 + 30 + 21*2], *pos;
pos= strmov(buf, "db=");
memcpy(pos, db, db_len);
pos= strmov(pos + db_len, ";table=");
@@ -7505,8 +7582,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
{
int actual_error= convert_handler_error(error, thd, table);
bool idempotent_error= (idempotent_error_code(error) &&
- ((bit_is_set(slave_exec_mode,
- SLAVE_EXEC_MODE_IDEMPOTENT)) == 1));
+ (slave_exec_mode & SLAVE_EXEC_MODE_IDEMPOTENT));
bool ignored_error= (idempotent_error == 0 ?
ignored_error_code(actual_error) : 0);
@@ -8439,7 +8515,7 @@ Write_rows_log_event::do_before_row_operations(const Slave_reporting_capability
todo: to introduce a property for the event (handler?) which forces
applying the event in the replace (idempotent) fashion.
*/
- if (bit_is_set(slave_exec_mode, SLAVE_EXEC_MODE_IDEMPOTENT) == 1 ||
+ if ((slave_exec_mode & SLAVE_EXEC_MODE_IDEMPOTENT) ||
m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER)
{
/*
@@ -8518,7 +8594,7 @@ Write_rows_log_event::do_after_row_operations(const Slave_reporting_capability *
int local_error= 0;
m_table->next_number_field=0;
m_table->auto_increment_field_not_null= FALSE;
- if (bit_is_set(slave_exec_mode, SLAVE_EXEC_MODE_IDEMPOTENT) == 1 ||
+ if ((slave_exec_mode & SLAVE_EXEC_MODE_IDEMPOTENT) ||
m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER)
{
m_table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
@@ -8621,7 +8697,7 @@ Rows_log_event::write_row(const Relay_log_info *const rli,
TABLE *table= m_table; // pointer to event's table
int error;
- int keynum;
+ int UNINIT_VAR(keynum);
auto_afree_ptr<char> key(NULL);
/* fill table->record[0] with default values */
@@ -8819,10 +8895,8 @@ int
Write_rows_log_event::do_exec_row(const Relay_log_info *const rli)
{
DBUG_ASSERT(m_table != NULL);
- int error=
- write_row(rli, /* if 1 then overwrite */
- bit_is_set(slave_exec_mode, SLAVE_EXEC_MODE_IDEMPOTENT) == 1);
-
+ int error= write_row(rli, (slave_exec_mode & SLAVE_EXEC_MODE_IDEMPOTENT));
+
if (error && !thd->is_error())
{
DBUG_ASSERT(0);
diff --git a/sql/log_event.h b/sql/log_event.h
index d82fc385d86..3c7ba766545 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -264,7 +264,8 @@ struct sql_ex_info
1 + 2 /* type, lc_time_names_number */ + \
1 + 2 /* type, charset_database_number */ + \
1 + 8 /* type, table_map_for_update */ + \
- 1 + 4 /* type, master_data_written */)
+ 1 + 4 /* type, master_data_written */ + \
+ 1 + 16 + 1 + 60/* type, user_len, user, host_len, host */)
#define MAX_LOG_EVENT_HEADER ( /* in order of Query_log_event::write */ \
LOG_EVENT_HEADER_LEN + /* write_header */ \
QUERY_HEADER_LEN + /* write_data */ \
@@ -333,6 +334,8 @@ struct sql_ex_info
#define Q_MASTER_DATA_WRITTEN_CODE 10
+#define Q_INVOKER 11
+
/* Intvar event post-header */
/* Intvar event data */
@@ -395,7 +398,7 @@ struct sql_ex_info
#define ELQ_DUP_HANDLING_OFFSET ELQ_FILE_ID_OFFSET + 12
/* 4 bytes which all binlogs should begin with */
-#define BINLOG_MAGIC "\xfe\x62\x69\x6e"
+#define BINLOG_MAGIC (const uchar*) "\xfe\x62\x69\x6e"
/*
The 2 flags below were useless :
@@ -1558,6 +1561,8 @@ protected:
*/
class Query_log_event: public Log_event
{
+ LEX_STRING user;
+ LEX_STRING host;
protected:
Log_event::Byte* data_buf;
public:
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index b96d1684d77..5d3ab1f17d5 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -441,7 +441,7 @@ copy_extra_record_fields(TABLE *table,
DBUG_ASSERT(master_reclength <= table->s->reclength);
if (master_reclength < table->s->reclength)
- bmove_align(table->record[0] + master_reclength,
+ memcpy(table->record[0] + master_reclength,
table->record[1] + master_reclength,
table->s->reclength - master_reclength);
@@ -720,7 +720,7 @@ static int find_and_fetch_row(TABLE *table, uchar *key)
rnd_pos() returns the record in table->record[0], so we have to
move it to table->record[1].
*/
- bmove_align(table->record[1], table->record[0], table->s->reclength);
+ memcpy(table->record[1], table->record[0], table->s->reclength);
DBUG_RETURN(error);
}
@@ -1218,7 +1218,7 @@ int Update_rows_log_event_old::do_exec_row(TABLE *table)
overwriting the default values that where put there by the
unpack_row() function.
*/
- bmove_align(table->record[0], m_after_image, table->s->reclength);
+ memcpy(table->record[0], m_after_image, table->s->reclength);
copy_extra_record_fields(table, m_master_reclength, m_width);
/*
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 299597632dd..8815f60d9e2 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1056,7 +1056,7 @@ bool mysql_opt_change_db(THD *thd,
bool force_switch,
bool *cur_db_changed);
-void mysql_parse(THD *thd, const char *inBuf, uint length,
+void mysql_parse(THD *thd, char *rawbuf, uint length,
const char ** semicolon);
bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length);
@@ -2302,6 +2302,7 @@ char *fn_rext(char *name);
/* Conversion functions */
#endif /* MYSQL_SERVER */
+
#if defined MYSQL_SERVER || defined INNODB_COMPATIBILITY_HOOKS
uint strconvert(CHARSET_INFO *from_cs, const char *from,
CHARSET_INFO *to_cs, char *to, uint to_length, uint *errors);
@@ -2326,9 +2327,6 @@ uint build_table_filename(char *buff, size_t bufflen, const char *db,
const char *get_canonical_filename(handler *file, const char *path,
char *tmp_path);
-#define MYSQL50_TABLE_NAME_PREFIX "#mysql50#"
-#define MYSQL50_TABLE_NAME_PREFIX_LENGTH 9
-
uint build_table_shadow_filename(char *buff, size_t bufflen,
ALTER_PARTITION_PARAM_TYPE *lpt);
/* Flags for conversion functions. */
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index ccbc7fd3ba1..e89c6b0ab85 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -188,7 +188,7 @@ typedef fp_except fp_except_t;
# define fpu_control_t unsigned int
# define _FPU_EXTENDED 0x300
# define _FPU_DOUBLE 0x200
-# if defined(__GNUC__) || defined(__SUNPRO_CC)
+# if defined(__GNUC__) || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590)
# define _FPU_GETCW(cw) asm volatile ("fnstcw %0" : "=m" (*&cw))
# define _FPU_SETCW(cw) asm volatile ("fldcw %0" : : "m" (*&cw))
# else
@@ -586,7 +586,7 @@ ulong query_buff_size, slow_launch_time, slave_open_temp_tables;
ulong open_files_limit, max_binlog_size, max_relay_log_size;
ulong slave_net_timeout, slave_trans_retries;
ulong slave_exec_mode_options;
-const char *slave_exec_mode_str= "STRICT";
+static const char *slave_exec_mode_str= "STRICT";
ulong thread_cache_size=0, thread_pool_size= 0;
ulong binlog_cache_size=0;
ulonglong max_binlog_cache_size=0;
@@ -2579,7 +2579,9 @@ extern "C" sig_handler handle_segfault(int sig)
{
time_t curr_time;
struct tm tm;
+#ifdef HAVE_STACKTRACE
THD *thd=current_thd;
+#endif
/*
Strictly speaking, one needs a mutex here
@@ -2646,13 +2648,14 @@ the thread stack. Please read http://dev.mysql.com/doc/mysql/en/linux.html\n\n",
#endif /* HAVE_LINUXTHREADS */
#ifdef HAVE_STACKTRACE
+
if (!(test_flags & TEST_NO_STACKTRACE))
{
- fprintf(stderr,"thd: 0x%lx\n",(long) thd);
- fprintf(stderr,"\
-Attempting backtrace. You can use the following information to find out\n\
-where mysqld died. If you see no messages after this, something went\n\
-terribly wrong...\n");
+ fprintf(stderr, "thd: 0x%lx\n",(long) thd);
+ fprintf(stderr, "Attempting backtrace. You can use the following "
+ "information to find out\nwhere mysqld died. If "
+ "you see no messages after this, something went\n"
+ "terribly wrong...\n");
my_print_stacktrace(thd ? (uchar*) thd->thread_stack : NULL,
my_thread_stack_size);
}
@@ -3097,7 +3100,20 @@ int my_message_sql(uint error, const char *str, myf MyFlags)
}
else
{
- if (! thd->main_da.is_error()) // Return only first message
+ if (thd->main_da.is_ok() && !thd->main_da.can_overwrite_status)
+ {
+ /*
+ Client has already got ok packet and we are not in net_flush(), so
+ we write a message to error log.
+ This could happen if we get an error in implicit commit.
+ This should never happen in normal operation, so lets
+ assert here in debug builds.
+ */
+ DBUG_ASSERT(0);
+ func= sql_print_error;
+ MyFlags|= ME_NOREFRESH;
+ }
+ else if (! thd->main_da.is_error()) // Return only first message
{
thd->main_da.set_error_status(thd, error, str);
}
@@ -4226,7 +4242,6 @@ a file name for --log-bin-index option", opt_binlog_index_name);
unireg_abort(1);
}
-#ifdef WITH_CSV_STORAGE_ENGINE
if (opt_bootstrap)
log_output_options= LOG_FILE;
else
@@ -4260,10 +4275,6 @@ a file name for --log-bin-index option", opt_binlog_index_name);
logger.set_handlers(LOG_FILE, opt_slow_log ? log_output_options:LOG_NONE,
opt_log ? log_output_options:LOG_NONE);
}
-#else
- logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
- opt_log ? LOG_FILE:LOG_NONE);
-#endif
/*
Check that the default storage engine is actually available.
@@ -6004,6 +6015,7 @@ enum options_mysqld
#if defined(ENABLED_DEBUG_SYNC)
OPT_DEBUG_SYNC_TIMEOUT,
#endif /* defined(ENABLED_DEBUG_SYNC) */
+ OPT_DEPRECATED_OPTION,
OPT_SLAVE_EXEC_MODE,
OPT_DEADLOCK_SEARCH_DEPTH_SHORT,
OPT_DEADLOCK_SEARCH_DEPTH_LONG,
@@ -6344,13 +6356,11 @@ each time the SQL thread starts.",
"Log some extra information to update log. Please note that this option "
"is deprecated; see --log-short-format option.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
-#ifdef WITH_CSV_STORAGE_ENGINE
{"log-output", OPT_LOG_OUTPUT,
"Syntax: log-output[=value[,value...]], where \"value\" could be TABLE, "
"FILE or NONE.",
&log_output_str, &log_output_str, 0,
GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
-#endif
{"log-queries-not-using-indexes", OPT_LOG_QUERIES_NOT_USING_INDEXES,
"Log queries that are executed without benefit of any index to the slow log if it is open.",
&opt_log_queries_not_using_indexes, &opt_log_queries_not_using_indexes,
@@ -6782,6 +6792,9 @@ thread is in the relay logs.",
"Show user and password in SHOW SLAVE HOSTS on this master.",
&opt_show_slave_auth_info, &opt_show_slave_auth_info, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"skip-bdb", OPT_DEPRECATED_OPTION,
+ "Deprecated option; Exist only for compatiblity with old my.cnf files",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#ifndef DISABLE_GRANT_OPTIONS
{"skip-grant-tables", OPT_SKIP_GRANT,
"Start without grant tables. This gives all users FULL ACCESS to all tables.",
@@ -8222,10 +8235,11 @@ static int mysql_init_variables(void)
/* Things with default values that are not zero */
delay_key_write_options= (uint) DELAY_KEY_WRITE_ON;
- slave_exec_mode_options= 0;
- slave_exec_mode_options= (uint)
- find_bit_type_or_exit(slave_exec_mode_str, &slave_exec_mode_typelib, NULL,
- &error);
+ slave_exec_mode_options= find_bit_type_or_exit(slave_exec_mode_str,
+ &slave_exec_mode_typelib,
+ NULL, &error);
+ /* Default mode string must not yield a error. */
+ DBUG_ASSERT(!error);
if (error)
return 1;
opt_specialflag= SPECIAL_ENGLISH;
@@ -8473,6 +8487,10 @@ mysqld_get_one_option(int optid,
case '0':
WARN_DEPRECATED(NULL, VER_CELOSIA, "--log-long-format", "--log-short-format");
break;
+ case OPT_DEPRECATED_OPTION:
+ sql_print_warning("'%s' is deprecated and exists only for compatiblity with old my.cnf files; Please remove this option from all your my.cnf files!",
+ opt->name);
+ break;
case 'a':
global_system_variables.sql_mode= fix_sql_mode(MODE_ANSI);
global_system_variables.tx_isolation= ISO_SERIALIZABLE;
@@ -8516,8 +8534,9 @@ mysqld_get_one_option(int optid,
init_slave_skip_errors(argument);
break;
case OPT_SLAVE_EXEC_MODE:
- slave_exec_mode_options= (uint)
- find_bit_type_or_exit(argument, &slave_exec_mode_typelib, "", &error);
+ slave_exec_mode_options= find_bit_type_or_exit(argument,
+ &slave_exec_mode_typelib,
+ "", &error);
if (error)
return 1;
break;
@@ -8622,7 +8641,7 @@ mysqld_get_one_option(int optid,
*val= 0;
val+= 2;
while (*val && my_isspace(mysqld_charset, *val))
- *val++;
+ val++;
if (!*val)
{
sql_print_error("Bad syntax in replicate-rewrite-db - empty TO db!\n");
@@ -8695,7 +8714,6 @@ mysqld_get_one_option(int optid,
WARN_DEPRECATED(NULL, "7.0", "--log_slow_queries", "'--slow_query_log'/'--log-slow-file'");
opt_slow_log= 1;
break;
-#ifdef WITH_CSV_STORAGE_ENGINE
case OPT_LOG_OUTPUT:
{
if (!argument || !argument[0])
@@ -8713,7 +8731,6 @@ mysqld_get_one_option(int optid,
}
break;
}
-#endif
case OPT_EVENT_SCHEDULER:
#ifndef HAVE_EVENT_SCHEDULER
sql_perror("Event scheduler is not supported in embedded build.");
@@ -8838,8 +8855,7 @@ mysqld_get_one_option(int optid,
if (!slave_warning_issued) //only show the warning once
{
slave_warning_issued = true;
- WARN_DEPRECATED(NULL, "6.0", "for replication startup options",
- "'CHANGE MASTER'");
+ WARN_DEPRECATED(NULL, "6.0", opt->name, "'CHANGE MASTER'");
}
break;
case OPT_CONSOLE:
@@ -9215,7 +9231,7 @@ static int get_options(int *argc,char **argv)
/* Set global MyISAM variables from delay_key_write_options */
fix_delay_key_write((THD*) 0, OPT_GLOBAL);
/* Set global slave_exec_mode from its option */
- fix_slave_exec_mode(OPT_GLOBAL);
+ fix_slave_exec_mode();
global_system_variables.log_slow_filter=
fix_log_slow_filter(global_system_variables.log_slow_filter);
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 044f1ce1391..5fdd2de49d3 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -7589,7 +7589,7 @@ check_quick_keys(PARAM *param, uint idx, SEL_ARG *key_tree,
if (unlikely(param->thd->killed != 0))
return HA_POS_ERROR;
-
+
keynr=param->real_keynr[idx];
param->range_count++;
if (!tmp_min_flag && ! tmp_max_flag &&
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index 1bf137011ab..9e07d735598 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -103,8 +103,8 @@ char *partition_info::create_default_partition_names(uint part_no,
{
do
{
- my_sprintf(move_ptr, (move_ptr,"p%u", (start_no + i)));
- move_ptr+=MAX_PART_NAME_SIZE;
+ sprintf(move_ptr, "p%u", (start_no + i));
+ move_ptr+= MAX_PART_NAME_SIZE;
} while (++i < no_parts_arg);
}
else
@@ -135,7 +135,7 @@ char *partition_info::create_subpartition_name(uint subpart_no,
if (likely(ptr != NULL))
{
- my_sprintf(ptr, (ptr, "%ssp%u", part_name, subpart_no));
+ my_snprintf(ptr, size_alloc, "%ssp%u", part_name, subpart_no);
}
else
{
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 7721d43f936..786d6ef8544 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -578,7 +578,11 @@ void Protocol::end_partial_result_set(THD *thd_arg)
bool Protocol::flush()
{
#ifndef EMBEDDED_LIBRARY
- return net_flush(&thd->net);
+ bool error;
+ thd->main_da.can_overwrite_status= TRUE;
+ error= net_flush(&thd->net);
+ thd->main_da.can_overwrite_status= FALSE;
+ return error;
#else
return 0;
#endif
@@ -618,7 +622,8 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
if (flags & SEND_NUM_ROWS)
{ // Packet with number of elements
uchar *pos= net_store_length(buff, list->elements);
- (void) my_net_write(&thd->net, buff, (size_t) (pos-buff));
+ if (my_net_write(&thd->net, buff, (size_t) (pos-buff)))
+ DBUG_RETURN(1);
}
#ifndef DBUG_OFF
@@ -742,7 +747,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
if (flags & SEND_DEFAULTS)
item->send(&prot, &tmp); // Send default value
if (prot.write())
- break; /* purecov: inspected */
+ DBUG_RETURN(1);
#ifndef DBUG_OFF
field_types[count++]= field.type;
#endif
@@ -755,7 +760,9 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
to show that there is no cursor.
Send no warning information, as it will be sent at statement end.
*/
- write_eof_packet(thd, &thd->net, thd->server_status, thd->total_warn_count);
+ if (write_eof_packet(thd, &thd->net, thd->server_status,
+ thd->total_warn_count))
+ DBUG_RETURN(1);
}
DBUG_RETURN(prepare_for_send(list));
diff --git a/sql/rpl_filter.cc b/sql/rpl_filter.cc
index ffae94f733a..8c0523f6766 100644
--- a/sql/rpl_filter.cc
+++ b/sql/rpl_filter.cc
@@ -92,7 +92,7 @@ Rpl_filter::tables_ok(const char* db, TABLE_LIST* tables)
for (; tables; tables= tables->next_global)
{
- char hash_key[2*NAME_LEN+2];
+ char hash_key[SAFE_NAME_LEN*2+2];
char *end;
uint len;
@@ -227,7 +227,7 @@ Rpl_filter::db_ok_with_wild_table(const char *db)
{
DBUG_ENTER("Rpl_filter::db_ok_with_wild_table");
- char hash_key[NAME_LEN+2];
+ char hash_key[SAFE_NAME_LEN+2];
char *end;
int len;
end= strmov(hash_key, db);
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index 46ae057f97e..c37c4735e37 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -1115,8 +1115,7 @@ bool Relay_log_info::cached_charset_compare(char *charset) const
{
DBUG_ENTER("Relay_log_info::cached_charset_compare");
- if (bcmp((uchar*) cached_charset, (uchar*) charset,
- sizeof(cached_charset)))
+ if (memcmp(cached_charset, charset, sizeof(cached_charset)))
{
memcpy(const_cast<char*>(cached_charset), charset, sizeof(cached_charset));
DBUG_RETURN(1);
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 3e2d27a012d..f521ab6d6aa 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -95,14 +95,13 @@ TYPELIB delay_key_write_typelib=
delay_key_write_type_names, NULL
};
-const char *slave_exec_mode_names[]=
-{ "STRICT", "IDEMPOTENT", NullS };
-static const unsigned int slave_exec_mode_names_len[]=
-{ sizeof("STRICT") - 1, sizeof("IDEMPOTENT") - 1, 0 };
+static const char *slave_exec_mode_names[]= { "STRICT", "IDEMPOTENT", NullS };
+static unsigned int slave_exec_mode_names_len[]= { sizeof("STRICT") - 1,
+ sizeof("IDEMPOTENT") - 1, 0 };
TYPELIB slave_exec_mode_typelib=
{
array_elements(slave_exec_mode_names)-1, "",
- slave_exec_mode_names, (unsigned int *) slave_exec_mode_names_len
+ slave_exec_mode_names, slave_exec_mode_names_len
};
static int sys_check_ftb_syntax(THD *thd, set_var *var);
@@ -1275,7 +1274,7 @@ uchar *sys_var_set::value_ptr(THD *thd, enum_var_type type,
void sys_var_set_slave_mode::set_default(THD *thd, enum_var_type type)
{
- slave_exec_mode_options= (ULL(1) << SLAVE_EXEC_MODE_STRICT);
+ slave_exec_mode_options= SLAVE_EXEC_MODE_STRICT;
}
bool sys_var_set_slave_mode::check(THD *thd, set_var *var)
@@ -1283,8 +1282,7 @@ bool sys_var_set_slave_mode::check(THD *thd, set_var *var)
bool rc= sys_var_set::check(thd, var);
if (!rc &&
test_all_bits(var->save_result.ulong_value,
- ((ULL(1) << SLAVE_EXEC_MODE_STRICT) |
- (ULL(1) << SLAVE_EXEC_MODE_IDEMPOTENT))))
+ SLAVE_EXEC_MODE_STRICT | SLAVE_EXEC_MODE_IDEMPOTENT))
{
rc= true;
my_error(ER_SLAVE_AMBIGOUS_EXEC_MODE, MYF(0), "");
@@ -1301,21 +1299,18 @@ bool sys_var_set_slave_mode::update(THD *thd, set_var *var)
return rc;
}
-void fix_slave_exec_mode(enum_var_type type)
+void fix_slave_exec_mode(void)
{
DBUG_ENTER("fix_slave_exec_mode");
- compile_time_assert(sizeof(slave_exec_mode_options) * CHAR_BIT
- > SLAVE_EXEC_MODE_LAST_BIT - 1);
+
if (test_all_bits(slave_exec_mode_options,
- ((ULL(1) << SLAVE_EXEC_MODE_STRICT) |
- (ULL(1) << SLAVE_EXEC_MODE_IDEMPOTENT))))
+ SLAVE_EXEC_MODE_STRICT | SLAVE_EXEC_MODE_IDEMPOTENT))
{
- sql_print_error("Ambiguous slave modes combination."
- " STRICT will be used");
- slave_exec_mode_options&= ~(ULL(1) << SLAVE_EXEC_MODE_IDEMPOTENT);
+ sql_print_error("Ambiguous slave modes combination. STRICT will be used");
+ slave_exec_mode_options&= ~SLAVE_EXEC_MODE_IDEMPOTENT;
}
- if (!(slave_exec_mode_options & (ULL(1) << SLAVE_EXEC_MODE_IDEMPOTENT)))
- slave_exec_mode_options|= (ULL(1)<< SLAVE_EXEC_MODE_STRICT);
+ if (!(slave_exec_mode_options & SLAVE_EXEC_MODE_IDEMPOTENT))
+ slave_exec_mode_options|= SLAVE_EXEC_MODE_STRICT;
DBUG_VOID_RETURN;
}
diff --git a/sql/set_var.h b/sql/set_var.h
index 54e4ac7e2f1..653f9b5155d 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -1452,7 +1452,7 @@ sys_var *find_sys_var(THD *thd, const char *str, uint length=0);
int sql_set_variables(THD *thd, List<set_var_base> *var_list);
bool not_all_support_one_shot(List<set_var_base> *var_list);
void fix_delay_key_write(THD *thd, enum_var_type type);
-void fix_slave_exec_mode(enum_var_type type);
+void fix_slave_exec_mode(void);
ulong fix_sql_mode(ulong sql_mode);
extern sys_var_const_str sys_charset_system;
extern sys_var_str sys_init_connect;
diff --git a/sql/slave.cc b/sql/slave.cc
index 1421f300804..55bfcceeb47 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -2073,7 +2073,7 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli)
DBUG_PRINT("info", ("thd->options: %s%s; rli->last_event_start_time: %lu",
FLAGSTR(thd->options, OPTION_NOT_AUTOCOMMIT),
FLAGSTR(thd->options, OPTION_BEGIN),
- rli->last_event_start_time));
+ (ulong) rli->last_event_start_time));
/*
Execute the event to change the database and update the binary
@@ -2846,8 +2846,8 @@ pthread_handler_t handle_slave_sql(void *arg)
char llbuff[22],llbuff1[22];
char saved_log_name[FN_REFLEN];
char saved_master_log_name[FN_REFLEN];
- my_off_t saved_log_pos;
- my_off_t saved_master_log_pos;
+ my_off_t UNINIT_VAR(saved_log_pos);
+ my_off_t UNINIT_VAR(saved_master_log_pos);
my_off_t saved_skip= 0;
Relay_log_info* rli = &((Master_info*)arg)->rli;
const char *errmsg;
diff --git a/sql/sp.cc b/sql/sp.cc
index e2e7583b901..ebf2b3c360d 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -719,7 +719,7 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
{
LEX *old_lex= thd->lex, newlex;
String defstr;
- char saved_cur_db_name_buf[NAME_LEN+1];
+ char saved_cur_db_name_buf[SAFE_NAME_LEN+1];
LEX_STRING saved_cur_db_name=
{ saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
bool cur_db_changed;
@@ -1932,7 +1932,7 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
Hence, the overrun happens only if the name is in length > 32 and
uses multibyte (cyrillic, greek, etc.)
*/
- char n[NAME_LEN*2+2];
+ char n[SAFE_NAME_LEN*2+2];
/* m_qname.str is not always \0 terminated */
memcpy(n, name.m_qname.str, name.m_qname.length);
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 9f9219566d7..2f1aa042c61 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1087,7 +1087,7 @@ bool
sp_head::execute(THD *thd)
{
DBUG_ENTER("sp_head::execute");
- char saved_cur_db_name_buf[NAME_LEN+1];
+ char saved_cur_db_name_buf[SAFE_NAME_LEN+1];
LEX_STRING saved_cur_db_name=
{ saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
bool cur_db_changed= FALSE;
@@ -3856,7 +3856,7 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check)
for (; table ; table= table->next_global)
if (!table->derived && !table->schema_table)
{
- char tname[(NAME_LEN + 1) * 3]; // db\0table\0alias\0
+ char tname[(SAFE_NAME_LEN + 1) * 3]; // db\0table\0alias\0
uint tlen, alen;
tlen= table->db_length;
diff --git a/sql/spatial.cc b/sql/spatial.cc
index a23e8ec0d90..2305a8eb97d 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -53,7 +53,7 @@ static Geometry::Class_info **ci_collection_end=
Geometry::ci_collection+Geometry::wkb_last + 1;
Geometry::Class_info::Class_info(const char *name, int type_id,
- void(*create_func)(void *)):
+ create_geom_t create_func):
m_type_id(type_id), m_create_func(create_func)
{
m_name.str= (char *) name;
@@ -62,39 +62,39 @@ Geometry::Class_info::Class_info(const char *name, int type_id,
ci_collection[type_id]= this;
}
-static void create_point(void *buffer)
+static Geometry *create_point(char *buffer)
{
- new(buffer) Gis_point;
+ return new (buffer) Gis_point;
}
-static void create_linestring(void *buffer)
+static Geometry *create_linestring(char *buffer)
{
- new(buffer) Gis_line_string;
+ return new (buffer) Gis_line_string;
}
-static void create_polygon(void *buffer)
+static Geometry *create_polygon(char *buffer)
{
- new(buffer) Gis_polygon;
+ return new (buffer) Gis_polygon;
}
-static void create_multipoint(void *buffer)
+static Geometry *create_multipoint(char *buffer)
{
- new(buffer) Gis_multi_point;
+ return new (buffer) Gis_multi_point;
}
-static void create_multipolygon(void *buffer)
+static Geometry *create_multipolygon(char *buffer)
{
- new(buffer) Gis_multi_polygon;
+ return new (buffer) Gis_multi_polygon;
}
-static void create_multilinestring(void *buffer)
+static Geometry *create_multilinestring(char *buffer)
{
- new(buffer) Gis_multi_line_string;
+ return new (buffer) Gis_multi_line_string;
}
-static void create_geometrycollection(void *buffer)
+static Geometry *create_geometrycollection(char *buffer)
{
- new(buffer) Gis_geometry_collection;
+ return new (buffer) Gis_geometry_collection;
}
@@ -145,6 +145,15 @@ Geometry::Class_info *Geometry::find_class(const char *name, uint32 len)
}
+Geometry *Geometry::create_by_typeid(Geometry_buffer *buffer, int type_id)
+{
+ Class_info *ci;
+ if (!(ci= find_class(type_id)))
+ return NULL;
+ return (*ci->m_create_func)(buffer->data);
+}
+
+
Geometry *Geometry::construct(Geometry_buffer *buffer,
const char *data, uint32 data_len)
{
@@ -153,6 +162,7 @@ Geometry *Geometry::construct(Geometry_buffer *buffer,
if (data_len < SRID_SIZE + WKB_HEADER_SIZE) // < 4 + (1 + 4)
return NULL;
+ /* + 1 to skip the byte order (stored in position SRID_SIZE). */
geom_type= uint4korr(data + SRID_SIZE + 1);
if (!(result= create_by_typeid(buffer, (int) geom_type)))
return NULL;
@@ -177,9 +187,7 @@ Geometry *Geometry::create_from_wkt(Geometry_buffer *buffer,
if (!(ci= find_class(name.str, name.length)) ||
wkt->reserve(1 + 4, 512))
return NULL;
- (*ci->m_create_func)((void *)buffer);
- Geometry *result= (Geometry *)buffer;
-
+ Geometry *result= (*ci->m_create_func)(buffer->data);
wkt->q_append((char) wkb_ndr);
wkt->q_append((uint32) result->get_class_info()->m_type_id);
if (trs->check_next_symbol('(') ||
diff --git a/sql/spatial.h b/sql/spatial.h
index 86c2ed8c197..f778acd6c34 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -225,15 +225,18 @@ public:
{
wkb_xdr= 0, /* Big Endian */
wkb_ndr= 1 /* Little Endian */
- };
+ };
+
+ /** Callback which creates Geometry objects on top of a given placement. */
+ typedef Geometry *(*create_geom_t)(char *);
class Class_info
{
public:
LEX_STRING m_name;
int m_type_id;
- void (*m_create_func)(void *);
- Class_info(const char *name, int type_id, void(*create_func)(void *));
+ create_geom_t m_create_func;
+ Class_info(const char *name, int type_id, create_geom_t create_func);
};
virtual const Class_info *get_class_info() const=0;
@@ -263,15 +266,7 @@ public:
virtual int geometry_n(uint32 num, String *result) const { return -1; }
public:
- static Geometry *create_by_typeid(Geometry_buffer *buffer, int type_id)
- {
- Class_info *ci;
- if (!(ci= find_class((int) type_id)))
- return NULL;
- (*ci->m_create_func)((void *)buffer);
- return my_reinterpret_cast(Geometry *)(buffer);
- }
-
+ static Geometry *create_by_typeid(Geometry_buffer *buffer, int type_id);
static Geometry *construct(Geometry_buffer *buffer,
const char *data, uint32 data_len);
static Geometry *create_from_wkt(Geometry_buffer *buffer,
@@ -528,11 +523,8 @@ public:
const Class_info *get_class_info() const;
};
-const int geometry_buffer_size= sizeof(Gis_point);
-struct Geometry_buffer
-{
- void *arr[(geometry_buffer_size - 1)/sizeof(void *) + 1];
-};
+struct Geometry_buffer : public
+ my_aligned_storage<sizeof(Gis_point), MY_ALIGNOF(Gis_point)> {};
#endif /*HAVE_SPATAIAL*/
#endif
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index be093b8738e..496e8c310dd 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -294,6 +294,7 @@ static bool compare_hostname(const acl_host_and_ip *host,const char *hostname,
const char *ip);
static my_bool acl_load(THD *thd, TABLE_LIST *tables);
static my_bool grant_load(THD *thd, TABLE_LIST *tables);
+static inline void get_grantor(THD *thd, char* grantor);
/*
Convert scrambled password to binary form, according to scramble type,
@@ -467,7 +468,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
READ_RECORD read_record_info;
my_bool return_val= TRUE;
bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE;
- char tmp_name[NAME_LEN+1];
+ char tmp_name[SAFE_NAME_LEN+1];
int password_length;
ulong old_sql_mode= thd->variables.sql_mode;
DBUG_ENTER("acl_load");
@@ -2481,7 +2482,7 @@ static GRANT_NAME *name_hash_search(HASH *name_hash,
const char *user, const char *tname,
bool exact, bool name_tolower)
{
- char helping [NAME_LEN*2+USERNAME_LENGTH+3], *name_ptr;
+ char helping [SAFE_NAME_LEN*2+USERNAME_LENGTH+3], *name_ptr;
uint len;
GRANT_NAME *grant_name,*found=0;
HASH_SEARCH_STATE state;
@@ -2734,6 +2735,20 @@ end:
DBUG_RETURN(result);
}
+static inline void get_grantor(THD *thd, char *grantor)
+{
+ const char *user= thd->security_ctx->user;
+ const char *host= thd->security_ctx->host_or_ip;
+
+#if defined(HAVE_REPLICATION)
+ if (thd->slave_thread && thd->has_invoker())
+ {
+ user= thd->get_invoker_user().str;
+ host= thd->get_invoker_host().str;
+ }
+#endif
+ strxmov(grantor, user, "@", host, NullS);
+}
static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
TABLE *table, const LEX_USER &combo,
@@ -2748,9 +2763,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
uchar user_key[MAX_KEY_LENGTH];
DBUG_ENTER("replace_table_table");
- strxmov(grantor, thd->security_ctx->user, "@",
- thd->security_ctx->host_or_ip, NullS);
-
+ get_grantor(thd, grantor);
/*
The following should always succeed as new users are created before
this function is called!
@@ -2880,9 +2893,7 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name,
DBUG_RETURN(-1);
}
- strxmov(grantor, thd->security_ctx->user, "@",
- thd->security_ctx->host_or_ip, NullS);
-
+ get_grantor(thd, grantor);
/*
New users are created before this function is called.
@@ -3449,7 +3460,7 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
{
List_iterator <LEX_USER> str_list (list);
LEX_USER *Str, *tmp_Str;
- char tmp_db[NAME_LEN+1];
+ char tmp_db[SAFE_NAME_LEN+1];
bool create_new_users=0;
TABLE_LIST tables[2];
bool save_binlog_row_based;
@@ -4336,7 +4347,7 @@ static bool check_grant_db_routine(THD *thd, const char *db, HASH *hash)
bool check_grant_db(THD *thd,const char *db)
{
Security_context *sctx= thd->security_ctx;
- char helping [NAME_LEN+USERNAME_LENGTH+2];
+ char helping [SAFE_NAME_LEN + USERNAME_LENGTH+2];
uint len;
bool error= TRUE;
@@ -7281,7 +7292,7 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length)
char *passwd= strend(user)+1;
uint user_len= passwd - user - 1;
char *db= passwd;
- char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
+ char db_buff[SAFE_NAME_LEN + 1]; // buffer to store db in utf8
char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
uint dummy_errors;
@@ -7480,7 +7491,7 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
char *passwd= strend(user)+1;
uint user_len= passwd - user - 1, db_len;
char *db= passwd;
- char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
+ char db_buff[SAFE_NAME_LEN + 1]; // buffer to store db in utf8
char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
uint dummy_errors;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 66a4f7694f9..0dd1ef73463 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -613,7 +613,7 @@ void release_table_share(TABLE_SHARE *share, enum release_type type)
TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name)
{
- char key[NAME_LEN*2+2];
+ char key[SAFE_NAME_LEN*2+2];
TABLE_LIST table_list;
uint key_length;
safe_mutex_assert_owner(&LOCK_open);
@@ -5709,7 +5709,7 @@ static void update_field_dependencies(THD *thd, Field *field, TABLE *table)
DBUG_ENTER("update_field_dependencies");
if (thd->mark_used_columns != MARK_COLUMNS_NONE)
{
- MY_BITMAP *current_bitmap;
+ MY_BITMAP *bitmap;
/*
We always want to register the used keys, as the column bitmap may have
@@ -5723,9 +5723,9 @@ static void update_field_dependencies(THD *thd, Field *field, TABLE *table)
table->mark_virtual_col(field);
if (thd->mark_used_columns == MARK_COLUMNS_READ)
- current_bitmap= table->read_set;
+ bitmap= table->read_set;
else
- current_bitmap= table->write_set;
+ bitmap= table->write_set;
/*
The test-and-set mechanism in the bitmap is not reliable during
@@ -5734,7 +5734,7 @@ static void update_field_dependencies(THD *thd, Field *field, TABLE *table)
only those columns that are used in the SET clause. I.e they are being
set here. See multi_update::prepare()
*/
- if (bitmap_fast_test_and_set(current_bitmap, field->field_index))
+ if (bitmap_fast_test_and_set(bitmap, field->field_index))
{
if (thd->mark_used_columns == MARK_COLUMNS_WRITE)
{
@@ -6327,7 +6327,7 @@ find_field_in_tables(THD *thd, Item_ident *item,
const char *table_name= item->table_name;
const char *name= item->field_name;
uint length=(uint) strlen(name);
- char name_buff[NAME_LEN+1];
+ char name_buff[SAFE_NAME_LEN+1];
TABLE_LIST *cur_table= first_table;
TABLE_LIST *actual_table;
bool allow_rowid;
@@ -6484,7 +6484,7 @@ find_field_in_tables(THD *thd, Item_ident *item,
(report_error == REPORT_ALL_ERRORS ||
report_error == REPORT_EXCEPT_NON_UNIQUE))
{
- char buff[NAME_LEN*2 + 2];
+ char buff[SAFE_NAME_LEN*2 + 2];
if (db && db[0])
{
strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS);
@@ -7870,7 +7870,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
{
Field_iterator_table_ref field_iterator;
bool found;
- char name_buff[NAME_LEN+1];
+ char name_buff[SAFE_NAME_LEN+1];
DBUG_ENTER("insert_fields");
DBUG_PRINT("arena", ("stmt arena: 0x%lx", (ulong)thd->stmt_arena));
@@ -8569,15 +8569,15 @@ my_bool mysql_rm_tmp_tables(void)
(file->name[1] == '.' && !file->name[2])))
continue;
- if (!bcmp((uchar*) file->name, (uchar*) tmp_file_prefix,
- tmp_file_prefix_length))
+ if (!memcmp(file->name, tmp_file_prefix,
+ tmp_file_prefix_length))
{
char *ext= fn_ext(file->name);
uint ext_len= strlen(ext);
uint filePath_len= my_snprintf(filePath, sizeof(filePath),
"%s%c%s", tmpdir, FN_LIBCHAR,
file->name);
- if (!bcmp((uchar*) reg_ext, (uchar*) ext, ext_len))
+ if (!strcmp(reg_ext, ext))
{
handler *handler_file= 0;
/* We should cut file extention before deleting of table */
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 302d5e95a28..cde040a88a4 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1679,7 +1679,8 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
thd->limit_found_rows = query->found_rows();
thd->status_var.last_query_cost= 0.0;
thd->query_plan_flags= (thd->query_plan_flags & ~QPLAN_QC_NO) | QPLAN_QC;
- thd->main_da.disable_status();
+ if (!thd->main_da.is_set())
+ thd->main_da.disable_status();
BLOCK_UNLOCK_RD(query_block);
DBUG_RETURN(1); // Result sent to client
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index b4e34fc1890..cac9b624bae 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -802,8 +802,10 @@ THD::THD()
thr_lock_owner_init(&main_lock_id, &lock_info);
m_internal_handler= NULL;
-
arena_for_cached_items= 0;
+ current_user_used= FALSE;
+ memset(&invoker_user, 0, sizeof(invoker_user));
+ memset(&invoker_host, 0, sizeof(invoker_host));
}
@@ -1216,13 +1218,13 @@ void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
while (to != end)
*(to++)+= *(from++) - *(dec++);
- to_var->bytes_received= (from_var->bytes_received -
- dec_var->bytes_received);
- to_var->bytes_sent+= from_var->bytes_sent - dec_var->bytes_sent;
- to_var->binlog_bytes_written= (from_var->binlog_bytes_written -
- dec_var->binlog_bytes_written);
- to_var->cpu_time+= from_var->cpu_time - dec_var->cpu_time;
- to_var->busy_time+= from_var->busy_time - dec_var->busy_time;
+ to_var->bytes_received+= from_var->bytes_received -
+ dec_var->bytes_received;
+ to_var->bytes_sent+= from_var->bytes_sent - dec_var->bytes_sent;
+ to_var->binlog_bytes_written+= from_var->binlog_bytes_written -
+ dec_var->binlog_bytes_written;
+ to_var->cpu_time+= from_var->cpu_time - dec_var->cpu_time;
+ to_var->busy_time+= from_var->busy_time - dec_var->busy_time;
}
#define SECONDS_TO_WAIT_FOR_KILL 2
@@ -1429,6 +1431,7 @@ void THD::cleanup_after_query()
where= THD::DEFAULT_WHERE;
/* reset table map for multi-table update */
table_map_for_update= 0;
+ clean_current_user_used();
}
@@ -3455,6 +3458,23 @@ void THD::set_query(char *query_arg, uint32 query_length_arg)
pthread_mutex_unlock(&LOCK_thd_data);
}
+void THD::get_definer(LEX_USER *definer)
+{
+ set_current_user_used();
+#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
+ if (slave_thread && has_invoker())
+ {
+ definer->user = invoker_user;
+ definer->host= invoker_host;
+ definer->password= null_lex_str;
+ definer->plugin= empty_lex_str;
+ definer->auth= empty_lex_str;
+ }
+ else
+#endif
+ get_default_definer(this, definer);
+}
+
/**
Mark transaction to rollback and mark error as fatal to a sub-statement.
@@ -3553,9 +3573,13 @@ bool xid_cache_insert(XID *xid, enum xa_states xa_state)
bool xid_cache_insert(XID_STATE *xid_state)
{
pthread_mutex_lock(&LOCK_xid_cache);
- DBUG_ASSERT(hash_search(&xid_cache, xid_state->xid.key(),
- xid_state->xid.key_length())==0);
- my_bool res=my_hash_insert(&xid_cache, (uchar*)xid_state);
+ if (hash_search(&xid_cache, xid_state->xid.key(), xid_state->xid.key_length()))
+ {
+ pthread_mutex_unlock(&LOCK_xid_cache);
+ my_error(ER_XAER_DUPID, MYF(0));
+ return TRUE;
+ }
+ my_bool res= my_hash_insert(&xid_cache, (uchar*)xid_state);
pthread_mutex_unlock(&LOCK_xid_cache);
return res;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 2240236a0e5..20f34bacca7 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -86,9 +86,10 @@ enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME };
enum enum_duplicates { DUP_ERROR, DUP_REPLACE, DUP_UPDATE };
enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON,
DELAY_KEY_WRITE_ALL };
-enum enum_slave_exec_mode { SLAVE_EXEC_MODE_STRICT,
- SLAVE_EXEC_MODE_IDEMPOTENT,
- SLAVE_EXEC_MODE_LAST_BIT};
+
+#define SLAVE_EXEC_MODE_STRICT (1U << 0)
+#define SLAVE_EXEC_MODE_IDEMPOTENT (1U << 1)
+
enum enum_mark_columns
{ MARK_COLUMNS_NONE, MARK_COLUMNS_READ, MARK_COLUMNS_WRITE};
@@ -418,7 +419,11 @@ struct system_variables
};
-/* per thread status variables */
+/**
+ Per thread status variables.
+ Must be long/ulong up to last_system_status_var so that
+ add_to_status/add_diff_to_status can work.
+*/
typedef struct system_status_var
{
@@ -479,17 +484,15 @@ typedef struct system_status_var
Number of statements sent from the client
*/
ulong questions;
- ulong empty_queries;
- ulong access_denied_errors; /* Can only be 0 or 1 */
- ulong lost_connections;
/*
IMPORTANT!
SEE last_system_status_var DEFINITION BELOW.
- Below 'last_system_status_var' are all variables which doesn't make any
- sense to add to the /global/ status variable counter.
- Status variables which it does not make sense to add to
- global status variable counter
+ Below 'last_system_status_var' are all variables that cannot be handled
+ automatically by add_to_status()/add_diff_to_status().
*/
+ ulong empty_queries;
+ ulong access_denied_errors; /* Can only be 0 or 1 */
+ ulong lost_connections;
ulonglong bytes_received;
ulonglong bytes_sent;
ulonglong binlog_bytes_written;
@@ -2391,6 +2394,18 @@ public:
Protected with LOCK_thd_data mutex.
*/
void set_query(char *query_arg, uint32 query_length_arg);
+ void set_current_user_used() { current_user_used= TRUE; }
+ bool is_current_user_used() { return current_user_used; }
+ void clean_current_user_used() { current_user_used= FALSE; }
+ void get_definer(LEX_USER *definer);
+ void set_invoker(const LEX_STRING *user, const LEX_STRING *host)
+ {
+ invoker_user= *user;
+ invoker_host= *host;
+ }
+ LEX_STRING get_invoker_user() { return invoker_user; }
+ LEX_STRING get_invoker_host() { return invoker_host; }
+ bool has_invoker() { return invoker_user.length > 0; }
private:
/*
@@ -2431,6 +2446,25 @@ private:
tree itself is reused between executions and thus is stored elsewhere.
*/
MEM_ROOT main_mem_root;
+
+ /**
+ It will be set TURE if CURRENT_USER() is called in account management
+ statements or default definer is set in CREATE/ALTER SP, SF, Event,
+ TRIGGER or VIEW statements.
+
+ Current user will be binlogged into Query_log_event if current_user_used
+ is TRUE; It will be stored into invoker_host and invoker_user by SQL thread.
+ */
+ bool current_user_used;
+
+ /**
+ It points to the invoker in the Query_log_event.
+ SQL thread use it as the default definer in CREATE/ALTER SP, SF, Event,
+ TRIGGER or VIEW statements or current user in account management
+ statements if it is not NULL.
+ */
+ LEX_STRING invoker_user;
+ LEX_STRING invoker_host;
};
/** A short cut for thd->main_da.set_ok_status(). */
@@ -2489,7 +2523,7 @@ class select_result :public Sql_alloc {
protected:
THD *thd;
SELECT_LEX_UNIT *unit;
- uint nest_level;
+ int nest_level;
public:
select_result();
virtual ~select_result() {};
@@ -2630,7 +2664,7 @@ public:
Creates a select_export to represent INTO OUTFILE <filename> with a
defined level of subquery nesting.
*/
- select_export(sql_exchange *ex, uint nest_level_arg) :select_to_file(ex)
+ select_export(sql_exchange *ex, int nest_level_arg) :select_to_file(ex)
{
nest_level= nest_level_arg;
}
@@ -2647,7 +2681,7 @@ public:
Creates a select_export to represent INTO DUMPFILE <filename> with a
defined level of subquery nesting.
*/
- select_dump(sql_exchange *ex, uint nest_level_arg) :
+ select_dump(sql_exchange *ex, int nest_level_arg) :
select_to_file(ex)
{
nest_level= nest_level_arg;
@@ -3124,7 +3158,7 @@ public:
Creates a select_dumpvar to represent INTO <variable> with a defined
level of subquery nesting.
*/
- select_dumpvar(uint nest_level_arg)
+ select_dumpvar(int nest_level_arg)
{
var_list.empty();
row_count= 0;
diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc
index e9ef5ef0cf3..77be6eaff34 100644
--- a/sql/sql_cursor.cc
+++ b/sql/sql_cursor.cc
@@ -658,7 +658,12 @@ void Materialized_cursor::fetch(ulong num_rows)
if ((res= table->file->ha_rnd_next(table->record[0])))
break;
/* Send data only if the read was successful. */
- result->send_data(item_list);
+ /*
+ If network write failed (i.e. due to a closed socked),
+ the error has already been set. Just return.
+ */
+ if (result->send_data(item_list))
+ return;
}
switch (res) {
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index ea138807122..f6549858a9d 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -3924,6 +3924,17 @@ void select_create::abort()
if (table)
{
+ if (thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
+ thd->current_stmt_binlog_row_based &&
+ !(thd->lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
+ mysql_bin_log.is_open())
+ {
+ /*
+ This should be removed after BUG#47899.
+ */
+ mysql_bin_log.reset_gathered_updates(thd);
+ }
+
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
if (!create_info->table_existed)
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 33121e5301d..524206d0af1 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -111,7 +111,7 @@ st_parsing_options::reset()
}
-bool Lex_input_stream::init(THD *thd, const char *buff, unsigned int length)
+bool Lex_input_stream::init(THD *thd, char *buff, unsigned int length)
{
DBUG_EXECUTE_IF("bug42064_simulate_oom",
DBUG_SET("+d,simulate_out_of_memory"););
@@ -1303,11 +1303,10 @@ int MYSQLlex(void *arg, void *yythd)
ulong version;
version=strtol(version_str, NULL, 10);
- /* Accept 'M' 'm' 'm' 'd' 'd' */
- lip->yySkipn(5);
-
if (version <= MYSQL_VERSION_ID)
{
+ /* Accept 'M' 'm' 'm' 'd' 'd' */
+ lip->yySkipn(5);
/* Expand the content of the special comment as real code */
lip->set_echo(TRUE);
state=MY_LEX_START;
@@ -1315,7 +1314,16 @@ int MYSQLlex(void *arg, void *yythd)
}
else
{
+ /*
+ Patch and skip the conditional comment to avoid it
+ being propagated infinitely (eg. to a slave).
+ */
+ char *pcom= lip->yyUnput(' ');
comment_closed= ! consume_comment(lip, 1);
+ if (! comment_closed)
+ {
+ *pcom= '!';
+ }
/* version allowed to have one level of comment inside. */
}
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 2f14f3eb575..020e2b4e76e 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -1190,7 +1190,7 @@ public:
@retval FALSE OK
@retval TRUE Error
*/
- bool init(THD *thd, const char *buff, unsigned int length);
+ bool init(THD *thd, char *buff, unsigned int length);
/**
Set the echo mode.
@@ -1305,6 +1305,20 @@ public:
}
/**
+ Puts a character back into the stream, canceling
+ the effect of the last yyGet() or yySkip().
+ Note that the echo mode should not change between calls
+ to unput, get, or skip from the stream.
+ */
+ char *yyUnput(char ch)
+ {
+ *--m_ptr= ch;
+ if (m_echo)
+ m_cpp_ptr--;
+ return m_ptr;
+ }
+
+ /**
End of file indicator for the query text to parse.
@return true if there are no more characters to parse
*/
@@ -1450,7 +1464,7 @@ public:
private:
/** Pointer to the current position in the raw input stream. */
- const char *m_ptr;
+ char *m_ptr;
/** Starting position of the last token parsed, in the raw buffer. */
const char *m_tok_start;
@@ -1996,7 +2010,7 @@ public:
@retval FALSE OK
@retval TRUE Error
*/
- bool init(THD *thd, const char *buff, unsigned int length)
+ bool init(THD *thd, char *buff, unsigned int length)
{
return m_lip.init(thd, buff, length);
}
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 15eb85ab52c..dc840cefc66 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -74,7 +74,7 @@ public:
SQL_I_List() { empty(); }
- SQL_I_List(const SQL_I_List &tmp) :Sql_alloc()
+ SQL_I_List(const SQL_I_List &tmp) : Sql_alloc()
{
elements= tmp.elements;
first= tmp.first;
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index d0506d75925..1b7f690259a 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -128,6 +128,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
bool is_fifo=0;
#ifndef EMBEDDED_LIBRARY
LOAD_FILE_INFO lf_info;
+ THD::killed_state killed_status;
#endif
char *db = table_list->db; // This is never null
/*
@@ -138,7 +139,6 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
char *tdb= thd->db ? thd->db : db; // Result is never null
ulong skip_lines= ex->skip_lines;
bool transactional_table;
- THD::killed_state killed_status= THD::NOT_KILLED;
DBUG_ENTER("mysql_load");
#ifdef EMBEDDED_LIBRARY
@@ -455,7 +455,11 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
error=1;
thd->killed= THD::KILL_QUERY;
};);
- killed_status= (error == 0)? THD::NOT_KILLED : thd->killed;
+
+#ifndef EMBEDDED_LIBRARY
+ killed_status= (error == 0) ? THD::NOT_KILLED : thd->killed;
+#endif
+
/*
We must invalidate the table in query cache before binlog writing and
ha_autocommit_...
@@ -1202,29 +1206,6 @@ int READ_INFO::read_field()
while ( to < end_of_buff)
{
chr = GET;
-#ifdef USE_MB
- if ((my_mbcharlen(read_charset, chr) > 1) &&
- to+my_mbcharlen(read_charset, chr) <= end_of_buff)
- {
- uchar* p = (uchar*)to;
- *to++ = chr;
- int ml = my_mbcharlen(read_charset, chr);
- int i;
- for (i=1; i<ml; i++) {
- chr = GET;
- if (chr == my_b_EOF)
- goto found_eof;
- *to++ = chr;
- }
- if (my_ismbchar(read_charset,
- (const char *)p,
- (const char *)to))
- continue;
- for (i=0; i<ml; i++)
- PUSH((uchar) *--to);
- chr = GET;
- }
-#endif
if (chr == my_b_EOF)
goto found_eof;
if (chr == escape_char)
@@ -1309,6 +1290,39 @@ int READ_INFO::read_field()
return 0;
}
}
+#ifdef USE_MB
+ if (my_mbcharlen(read_charset, chr) > 1 &&
+ to + my_mbcharlen(read_charset, chr) <= end_of_buff)
+ {
+ uchar* p= (uchar*) to;
+ int ml, i;
+ *to++ = chr;
+
+ ml= my_mbcharlen(read_charset, chr);
+
+ for (i= 1; i < ml; i++)
+ {
+ chr= GET;
+ if (chr == my_b_EOF)
+ {
+ /*
+ Need to back up the bytes already ready from illformed
+ multi-byte char
+ */
+ to-= i;
+ goto found_eof;
+ }
+ *to++ = chr;
+ }
+ if (my_ismbchar(read_charset,
+ (const char *)p,
+ (const char *)to))
+ continue;
+ for (i= 0; i < ml; i++)
+ PUSH((uchar) *--to);
+ chr= GET;
+ }
+#endif
*to++ = (uchar) chr;
}
/*
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index af66c9447b0..407c2f5bb93 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -476,6 +476,7 @@ static void handle_bootstrap_impl(THD *thd)
buff= (char*) thd->net.buff;
if (!fgets(buff + length, thd->net.max_packet - length, file))
{
+ net_end_statement(thd);
bootstrap_error= 1;
break;
}
@@ -1000,7 +1001,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
NET *net= &thd->net;
bool error= 0;
DBUG_ENTER("dispatch_command");
- DBUG_PRINT("info",("packet: '%*.s'; command: %d", packet_length, packet, command));
+ DBUG_PRINT("info", ("command: %d", command));
thd->command=command;
/*
@@ -1264,7 +1265,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
char *fields, *packet_end= packet + packet_length, *wildcard;
/* Locked closure of all tables */
TABLE_LIST table_list;
- char db_buff[NAME_LEN+1];
+ char db_buff[SAFE_NAME_LEN+1];
uint32 db_length;
uint dummy_errors, query_length;
@@ -1283,7 +1284,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
db_length= wildcard - packet;
wildcard++;
query_length= (uint) (packet_end - wildcard); // Don't count end \0
- if (db_length > NAME_LEN || query_length > NAME_LEN)
+ if (db_length > SAFE_NAME_LEN || query_length > NAME_LEN)
{
my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
break;
@@ -1533,13 +1534,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
(sf_malloc_max_memory+1023L)/1024L);
}
#endif
-#ifdef EMBEDDED_LIBRARY
- /* Store the buffer in permanent memory */
- my_ok(thd, 0, 0, buff);
-#else
+#ifndef EMBEDDED_LIBRARY
VOID(my_net_write(net, (uchar*) buff, length));
VOID(net_flush(net));
thd->main_da.disable_status();
+#else
+ /* Store the buffer in permanent memory */
+ my_ok(thd, 0, 0, buff);
#endif
break;
}
@@ -4741,7 +4742,7 @@ create_sp_error:
my_error(ER_XAER_NOTA, MYF(0));
break;
}
- thd->transaction.xid_state.xa_state=XA_ACTIVE;
+ thd->transaction.xid_state.xa_state= XA_ACTIVE;
my_ok(thd);
break;
}
@@ -4761,16 +4762,16 @@ create_sp_error:
my_error(ER_XAER_OUTSIDE, MYF(0));
break;
}
- if (xid_cache_search(thd->lex->xid))
- {
- my_error(ER_XAER_DUPID, MYF(0));
- break;
- }
DBUG_ASSERT(thd->transaction.xid_state.xid.is_null());
- thd->transaction.xid_state.xa_state=XA_ACTIVE;
+ thd->transaction.xid_state.xa_state= XA_ACTIVE;
thd->transaction.xid_state.rm_error= 0;
thd->transaction.xid_state.xid.set(thd->lex->xid);
- xid_cache_insert(&thd->transaction.xid_state);
+ if (xid_cache_insert(&thd->transaction.xid_state))
+ {
+ thd->transaction.xid_state.xa_state= XA_NOTR;
+ thd->transaction.xid_state.xid.null();
+ break;
+ }
thd->transaction.all.modified_non_trans_table= FALSE;
thd->options= ((thd->options & ~(OPTION_KEEP_LOG)) | OPTION_BEGIN);
thd->server_status|= SERVER_STATUS_IN_TRANS;
@@ -4824,6 +4825,16 @@ create_sp_error:
case SQLCOM_XA_COMMIT:
if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
+ /*
+ xid_state.in_thd is always true beside of xa recovery
+ procedure. Note, that there is no race condition here
+ between xid_cache_search and xid_cache_delete, since we're always
+ deleting our own XID (thd->lex->xid == thd->transaction.xid_state.xid).
+ The only case when thd->lex->xid != thd->transaction.xid_state.xid
+ and xid_state->in_thd == 0 is in ha_recover() functionality,
+ which is called before starting client connections, and thus is
+ always single-threaded.
+ */
XID_STATE *xs=xid_cache_search(thd->lex->xid);
if (!xs || xs->in_thd)
my_error(ER_XAER_NOTA, MYF(0));
@@ -5970,13 +5981,13 @@ void mysql_init_multi_delete(LEX *lex)
Parse a query.
@param thd Current thread
- @param inBuf Begining of the query text
+ @param rawbuf Begining of the query text
@param length Length of the query text
@param[out] found_semicolon For multi queries, position of the character of
the next query in the query text.
*/
-void mysql_parse(THD *thd, const char *inBuf, uint length,
+void mysql_parse(THD *thd, char *rawbuf, uint length,
const char ** found_semicolon)
{
DBUG_ENTER("mysql_parse");
@@ -6001,7 +6012,7 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
lex_start(thd);
mysql_reset_thd_for_next_command(thd, opt_userstat_running);
- if (query_cache_send_result_to_client(thd, (char*) inBuf, length) <= 0)
+ if (query_cache_send_result_to_client(thd, rawbuf, length) <= 0)
{
LEX *lex= thd->lex;
@@ -6010,7 +6021,7 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
Parser_state parser_state;
bool err;
- if (!(err= parser_state.init(thd, inBuf, length)))
+ if (!(err= parser_state.init(thd, rawbuf, length)))
{
err= parse_sql(thd, & parser_state, NULL);
*found_semicolon= parser_state.m_lip.found_semicolon;
@@ -6097,14 +6108,14 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
1 can be ignored
*/
-bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length)
+bool mysql_test_parse_for_slave(THD *thd, char *rawbuf, uint length)
{
LEX *lex= thd->lex;
bool error= 0;
DBUG_ENTER("mysql_test_parse_for_slave");
Parser_state parser_state;
- if (!(error= parser_state.init(thd, inBuf, length)))
+ if (!(error= parser_state.init(thd, rawbuf, length)))
{
lex_start(thd);
mysql_reset_thd_for_next_command(thd, opt_userstat_running);
@@ -7732,7 +7743,7 @@ LEX_USER *create_default_definer(THD *thd)
if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
return 0;
- get_default_definer(thd, definer);
+ thd->get_definer(definer);
return definer;
}
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 6058db4aad4..551f19694ef 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -3877,7 +3877,7 @@ void get_partition_set(const TABLE *table, uchar *buf, const uint index,
*/
bool mysql_unpack_partition(THD *thd,
- const char *part_buf, uint part_info_len,
+ char *part_buf, uint part_info_len,
const char *part_state, uint part_state_len,
TABLE* table, bool is_create_table_ind,
handlerton *default_db_type,
diff --git a/sql/sql_partition.h b/sql/sql_partition.h
index b9efbf25a00..02a5ead1117 100644
--- a/sql/sql_partition.h
+++ b/sql/sql_partition.h
@@ -78,7 +78,7 @@ void get_full_part_id_from_key(const TABLE *table, uchar *buf,
KEY *key_info,
const key_range *key_spec,
part_id_range *part_spec);
-bool mysql_unpack_partition(THD *thd, const char *part_buf,
+bool mysql_unpack_partition(THD *thd, char *part_buf,
uint part_info_len,
const char *part_state, uint part_state_len,
TABLE *table, bool is_create_table_ind,
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 600c140c776..d5e53651e18 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -263,8 +263,11 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
&stmt->lex->param_list,
Protocol::SEND_EOF);
}
- /* Flag that a response has already been sent */
- thd->main_da.disable_status();
+
+ if (!error)
+ /* Flag that a response has already been sent */
+ thd->main_da.disable_status();
+
DBUG_RETURN(error);
}
#else
@@ -790,7 +793,7 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array,
type (the types are supplied at execute). Check that the
supplied type of placeholder can accept a data stream.
*/
- else if (!is_param_long_data_type(param))
+ else if (! is_param_long_data_type(param))
DBUG_RETURN(1);
res= param->query_val_str(&str);
if (param->convert_str_value(thd))
@@ -836,7 +839,7 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array,
type (the types are supplied at execute). Check that the
supplied type of placeholder can accept a data stream.
*/
- else if (is_param_long_data_type(param))
+ else if (! is_param_long_data_type(param))
DBUG_RETURN(1);
if (param->convert_str_value(stmt->thd))
DBUG_RETURN(1); /* out of memory */
@@ -3336,7 +3339,7 @@ reexecute:
bool
Prepared_statement::reprepare()
{
- char saved_cur_db_name_buf[NAME_LEN+1];
+ char saved_cur_db_name_buf[SAFE_NAME_LEN+1];
LEX_STRING saved_cur_db_name=
{ saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
LEX_STRING stmt_db_name= { db, db_length };
@@ -3497,7 +3500,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
Query_arena *old_stmt_arena;
bool error= TRUE;
- char saved_cur_db_name_buf[NAME_LEN+1];
+ char saved_cur_db_name_buf[SAFE_NAME_LEN+1];
LEX_STRING saved_cur_db_name=
{ saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
bool cur_db_changed;
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 1970287b06e..95e48c531be 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -218,8 +218,7 @@ bool log_in_use(const char* log_name)
if ((linfo = tmp->current_linfo))
{
pthread_mutex_lock(&linfo->lock);
- result = !bcmp((uchar*) log_name, (uchar*) linfo->log_file_name,
- log_name_len);
+ result = !memcmp(log_name, linfo->log_file_name, log_name_len);
pthread_mutex_unlock(&linfo->lock);
if (result)
break;
@@ -357,6 +356,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
#ifndef DBUG_OFF
int left_events = max_binlog_dump_events;
#endif
+ int old_max_allowed_packet= thd->variables.max_allowed_packet;
DBUG_ENTER("mysql_binlog_send");
DBUG_PRINT("enter",("log_ident: '%s' pos: %ld", log_ident, (long) pos));
@@ -762,6 +762,7 @@ end:
pthread_mutex_lock(&LOCK_thread_count);
thd->current_linfo = 0;
pthread_mutex_unlock(&LOCK_thread_count);
+ thd->variables.max_allowed_packet= old_max_allowed_packet;
DBUG_VOID_RETURN;
err:
@@ -779,6 +780,7 @@ err:
pthread_mutex_unlock(&LOCK_thread_count);
if (file >= 0)
(void) my_close(file, MYF(MY_WME));
+ thd->variables.max_allowed_packet= old_max_allowed_packet;
my_message(my_errno, errmsg, MYF(0));
DBUG_VOID_RETURN;
@@ -1419,6 +1421,7 @@ bool mysql_show_binlog_events(THD* thd)
bool ret = TRUE;
IO_CACHE log;
File file = -1;
+ int old_max_allowed_packet= thd->variables.max_allowed_packet;
DBUG_ENTER("mysql_show_binlog_events");
Log_event::init_show_field_list(&field_list);
@@ -1557,6 +1560,7 @@ err:
pthread_mutex_lock(&LOCK_thread_count);
thd->current_linfo = 0;
pthread_mutex_unlock(&LOCK_thread_count);
+ thd->variables.max_allowed_packet= old_max_allowed_packet;
DBUG_RETURN(ret);
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 2e966dbdde3..d7f92392c5e 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1128,6 +1128,30 @@ JOIN::optimize()
{
conds=new Item_int((longlong) 0,1); // Always false
}
+
+ /*
+ It's necessary to check const part of HAVING cond as there is a
+ chance that some cond parts may become const items after
+ make_join_statistics() (for example when Item is a reference to
+ cost table field from outer join).
+
+ This check is performed only for those conditions which do not use
+ aggregate functions. In such case temporary table may not be used
+ and const condition elements may be lost during further having
+ condition transformation in JOIN::exec.
+ */
+ if (having && const_table_map && !having->with_sum_func)
+ {
+ having->update_used_tables();
+ having= remove_eq_conds(thd, having, &having_value);
+ if (having_value == Item::COND_FALSE)
+ {
+ having= new Item_int((longlong) 0,1);
+ zero_result_cause= "Impossible HAVING noticed after reading const tables";
+ DBUG_RETURN(0);
+ }
+ }
+
if (make_join_select(this, select, conds))
{
zero_result_cause=
@@ -11888,6 +11912,7 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
enum_nested_loop_state rc= NESTED_LOOP_OK;
int error;
READ_RECORD *info;
+ SQL_SELECT *select;
join_tab->table->null_row= 0;
if (!join_tab->cache.records)
@@ -11902,7 +11927,7 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
join_tab->select->quick=0;
}
}
- /* read through all records */
+ /* read through all records */
if ((error=join_init_read_record(join_tab)))
{
reset_cache_write(&join_tab->cache);
@@ -11916,15 +11941,16 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
}
info= &join_tab->read_record;
+ select= join_tab->select;
+
do
{
+ int err= 0;
if (join->thd->killed)
{
join->thd->send_kill_message();
return NESTED_LOOP_KILLED; // Aborted by user /* purecov: inspected */
}
- int err= 0;
- SQL_SELECT *select=join_tab->select;
if (rc == NESTED_LOOP_OK)
update_virtual_fields(join->thd, join_tab->table);
if (rc == NESTED_LOOP_OK &&
@@ -11932,8 +11958,11 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
(err= join_tab->cache.select->skip_record(join->thd)) != 0 ))
{
if (err < 0)
+ {
+ reset_cache_write(&join_tab->cache);
return NESTED_LOOP_ERROR;
- rc= NESTED_LOOP_OK;
+ }
+
reset_cache_read(&join_tab->cache);
for (uint i= (join_tab->cache.records- (skip_last ? 1 : 0)) ; i-- > 0 ;)
{
@@ -11942,7 +11971,10 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
if (!select || (err= select->skip_record(join->thd)) != 0)
{
if (err < 0)
+ {
+ reset_cache_write(&join_tab->cache);
return NESTED_LOOP_ERROR;
+ }
rc= (join_tab->next_select)(join,join_tab+1,0);
if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS)
{
@@ -16695,7 +16727,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
the UNION to provide precise EXPLAIN information will hardly be
appreciated :)
*/
- char table_name_buffer[NAME_LEN];
+ char table_name_buffer[SAFE_NAME_LEN];
item_list.empty();
/* id */
item_list.push_back(new Item_null);
@@ -16768,7 +16800,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
char buff1[512], buff2[512], buff3[512];
char keylen_str_buf[64];
String extra(buff, sizeof(buff),cs);
- char table_name_buffer[NAME_LEN];
+ char table_name_buffer[SAFE_NAME_LEN];
String tmp1(buff1,sizeof(buff1),cs);
String tmp2(buff2,sizeof(buff2),cs);
String tmp3(buff3,sizeof(buff3),cs);
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index a2290cf0758..cc1e956939c 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1,4 +1,4 @@
-/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+/* Copyright 2000, 2010 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -9,9 +9,9 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
/* Function with list databases, tables or fields */
@@ -511,8 +511,6 @@ find_files(THD *thd, List<LEX_STRING> *files, const char *db,
wild_length= strlen(wild);
}
-
-
bzero((char*) &table_list,sizeof(table_list));
if (!(dirp = my_dir(path,MYF(dir ? MY_WANT_STAT : 0))))
@@ -526,7 +524,7 @@ find_files(THD *thd, List<LEX_STRING> *files, const char *db,
for (i=0 ; i < (uint) dirp->number_off_files ; i++)
{
- char uname[NAME_LEN + 1]; /* Unencoded name */
+ char uname[SAFE_NAME_LEN + 1]; /* Unencoded name */
file=dirp->dir_entry+i;
if (dir)
{ /* Return databases */
@@ -554,9 +552,20 @@ find_files(THD *thd, List<LEX_STRING> *files, const char *db,
continue;
file_name_len= filename_to_tablename(file->name, uname, sizeof(uname));
- if (wild && wild_compare(uname, wild, 0))
- continue;
- if (!(file_name=
+ if (wild)
+ {
+ if (lower_case_table_names)
+ {
+ if (my_wildcmp(files_charset_info,
+ uname, uname + file_name_len,
+ wild, wild + wild_length,
+ wild_prefix, wild_one, wild_many))
+ continue;
+ }
+ else if (wild_compare(uname, wild, 0))
+ continue;
+ }
+ if (!(file_name=
thd->make_lex_string(file_name, uname, file_name_len, TRUE)))
{
my_dirend(dirp);
@@ -2319,8 +2328,8 @@ static bool show_status_array(THD *thd, const char *wild,
bool ucase_names,
COND *cond)
{
- MY_ALIGNED_BYTE_ARRAY(buff_data, SHOW_VAR_FUNC_BUFF_SIZE, long);
- char * const buff= (char *) &buff_data;
+ my_aligned_storage<SHOW_VAR_FUNC_BUFF_SIZE, MY_ALIGNOF(long)> buffer;
+ char * const buff= buffer.data;
char *prefix_end;
/* the variable name should not be longer than 64 characters */
char name_buffer[64];
@@ -3124,36 +3133,54 @@ bool get_lookup_field_values(THD *thd, COND *cond, TABLE_LIST *tables,
{
LEX *lex= thd->lex;
const char *wild= lex->wild ? lex->wild->ptr() : NullS;
+ bool rc= 0;
+
bzero((char*) lookup_field_values, sizeof(LOOKUP_FIELD_VALUES));
switch (lex->sql_command) {
case SQLCOM_SHOW_DATABASES:
if (wild)
{
- lookup_field_values->db_value.str= (char*) wild;
- lookup_field_values->db_value.length= strlen(wild);
+ thd->make_lex_string(&lookup_field_values->db_value,
+ wild, strlen(wild), 0);
lookup_field_values->wild_db_value= 1;
}
- return 0;
+ break;
case SQLCOM_SHOW_TABLES:
case SQLCOM_SHOW_TABLE_STATUS:
case SQLCOM_SHOW_TRIGGERS:
case SQLCOM_SHOW_EVENTS:
- lookup_field_values->db_value.str= lex->select_lex.db;
- lookup_field_values->db_value.length=strlen(lex->select_lex.db);
+ thd->make_lex_string(&lookup_field_values->db_value,
+ lex->select_lex.db, strlen(lex->select_lex.db), 0);
if (wild)
{
- lookup_field_values->table_value.str= (char*)wild;
- lookup_field_values->table_value.length= strlen(wild);
+ thd->make_lex_string(&lookup_field_values->table_value,
+ wild, strlen(wild), 0);
lookup_field_values->wild_table_value= 1;
}
- return 0;
+ break;
default:
/*
The "default" is for queries over I_S.
All previous cases handle SHOW commands.
*/
- return calc_lookup_values_from_cond(thd, cond, tables, lookup_field_values);
+ rc= calc_lookup_values_from_cond(thd, cond, tables, lookup_field_values);
+ break;
}
+
+ if (lower_case_table_names && !rc)
+ {
+ /*
+ We can safely do in-place upgrades here since all of the above cases
+ are allocating a new memory buffer for these strings.
+ */
+ if (lookup_field_values->db_value.str && lookup_field_values->db_value.str[0])
+ my_casedn_str(system_charset_info, lookup_field_values->db_value.str);
+ if (lookup_field_values->table_value.str &&
+ lookup_field_values->table_value.str[0])
+ my_casedn_str(system_charset_info, lookup_field_values->table_value.str);
+ }
+
+ return rc;
}
@@ -3355,11 +3382,15 @@ make_table_name_list(THD *thd, List<LEX_STRING> *table_names, LEX *lex,
{
if (with_i_schema)
{
+ LEX_STRING *name;
ST_SCHEMA_TABLE *schema_table=
find_schema_table(thd, lookup_field_vals->table_value.str);
if (schema_table && !schema_table->hidden)
{
- if (table_names->push_back(&lookup_field_vals->table_value))
+ if (!(name=
+ thd->make_lex_string(NULL, schema_table->table_name,
+ strlen(schema_table->table_name), TRUE)) ||
+ table_names->push_back(name))
return 1;
}
}
@@ -3398,7 +3429,7 @@ make_table_name_list(THD *thd, List<LEX_STRING> *table_names, LEX *lex,
*/
if (res == FIND_FILES_DIR)
{
- if (lex->sql_command != SQLCOM_SELECT)
+ if (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND)
return 1;
thd->clear_error();
return 2;
@@ -3758,6 +3789,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
error= 0;
goto err;
}
+
DBUG_PRINT("INDEX VALUES",("db_name='%s', table_name='%s'",
STR_OR_NIL(lookup_field_vals.db_value.str),
STR_OR_NIL(lookup_field_vals.table_value.str)));
@@ -4285,7 +4317,6 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
uint flags=field->flags;
char tmp[MAX_FIELD_WIDTH];
String type(tmp,sizeof(tmp), system_charset_info);
- char *end;
int decimals, field_length;
if (wild && wild[0] &&
@@ -4306,7 +4337,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
field->field_name) & COL_ACLS;
if (!tables->schema_table && !col_access)
continue;
- end= tmp;
+ char *end= tmp;
for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
{
if (col_access & 1)
@@ -4382,10 +4413,13 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_LONG:
- case MYSQL_TYPE_LONGLONG:
case MYSQL_TYPE_INT24:
field_length= field->max_display_length() - 1;
break;
+ case MYSQL_TYPE_LONGLONG:
+ field_length= field->max_display_length() -
+ ((field->flags & UNSIGNED_FLAG) ? 0 : 1);
+ break;
case MYSQL_TYPE_BIT:
field_length= field->max_display_length();
decimals= -1; // return NULL
@@ -4429,7 +4463,6 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
table->field[15]->store((const char*) pos,
strlen((const char*) pos), cs);
- end= tmp;
if (field->unireg_check == Field::NEXT_NUMBER)
table->field[16]->store(STRING_WITH_LEN("auto_increment"), cs);
if (show_table->timestamp_field == field &&
@@ -4640,7 +4673,7 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
MYSQL_TIME time;
LEX *lex= thd->lex;
CHARSET_INFO *cs= system_charset_info;
- char sp_db_buff[NAME_LEN + 1], sp_name_buff[NAME_LEN + 1],
+ char sp_db_buff[SAFE_NAME_LEN + 1], sp_name_buff[SAFE_NAME_LEN + 1],
definer_buff[USERNAME_LENGTH + HOSTNAME_LENGTH + 2];
String sp_db(sp_db_buff, sizeof(sp_db_buff), cs);
String sp_name(sp_name_buff, sizeof(sp_name_buff), cs);
@@ -7134,8 +7167,8 @@ ST_FIELD_INFO table_names_fields_info[]=
{
{"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
{"TABLE_SCHEMA",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
- {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Tables_in_",
- SKIP_OPEN_TABLE},
+ {"TABLE_NAME", NAME_CHAR_LEN + MYSQL50_TABLE_NAME_PREFIX_LENGTH,
+ MYSQL_TYPE_STRING, 0, 0, "Tables_in_", SKIP_OPEN_TABLE},
{"TABLE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_type",
OPEN_FRM_ONLY},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index b9b5ff47cf6..3cec6c3b915 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -48,6 +48,7 @@ static int mysql_prepare_create_table(THD *, HA_CREATE_INFO *, Alter_info *,
bool, uint *, handler *, KEY **, uint *, int);
static bool mysql_prepare_alter_table(THD *, TABLE *, HA_CREATE_INFO *,
Alter_info *);
+static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list);
#ifndef DBUG_OFF
@@ -4219,7 +4220,7 @@ mysql_rename_table(handlerton *base, const char *old_db,
char from[FN_REFLEN + 1], to[FN_REFLEN + 1],
lc_from[FN_REFLEN + 1], lc_to[FN_REFLEN + 1];
char *from_base= from, *to_base= to;
- char tmp_name[NAME_LEN+1];
+ char tmp_name[SAFE_NAME_LEN+1];
handler *file;
int error=0;
DBUG_ENTER("mysql_rename_table");
@@ -4614,6 +4615,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
Protocol *protocol= thd->protocol;
LEX *lex= thd->lex;
int result_code;
+ bool need_repair_or_alter= 0;
DBUG_ENTER("mysql_admin_table");
if (end_active_trans(thd))
@@ -4634,7 +4636,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
for (table= tables; table; table= table->next_local)
{
- char table_name[NAME_LEN*2+2];
+ char table_name[SAFE_NAME_LEN*2+2];
char* db = table->db;
bool fatal_error=0;
@@ -4842,32 +4844,38 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (operator_func == &handler::ha_repair &&
!(check_opt->sql_flags & TT_USEFRM))
{
- if ((table->table->file->check_old_types() == HA_ADMIN_NEEDS_ALTER) ||
- (table->table->file->ha_check_for_upgrade(check_opt) ==
- HA_ADMIN_NEEDS_ALTER))
+ handler *file= table->table->file;
+ int check_old_types= file->check_old_types();
+ int check_for_upgrade= file->ha_check_for_upgrade(check_opt);
+
+ if (check_old_types == HA_ADMIN_NEEDS_ALTER ||
+ check_for_upgrade == HA_ADMIN_NEEDS_ALTER)
{
- DBUG_PRINT("admin", ("recreating table"));
- ha_autocommit_or_rollback(thd, 1);
- close_thread_tables(thd);
- tmp_disable_binlog(thd); // binlogging is done by caller if wanted
- result_code= mysql_recreate_table(thd, table);
- reenable_binlog(thd);
- /*
- mysql_recreate_table() can push OK or ERROR.
- Clear 'OK' status. If there is an error, keep it:
- we will store the error message in a result set row
- and then clear.
- */
- if (thd->main_da.is_ok())
- thd->main_da.reset_diagnostics_area();
+ /* We use extra_open_options to be able to open crashed tables */
+ thd->open_options|= extra_open_options;
+ result_code= admin_recreate_table(thd, table);
+ thd->open_options= ~extra_open_options;
goto send_result;
}
+ if (check_old_types || check_for_upgrade)
+ {
+ /* If repair is not implemented for the engine, run ALTER TABLE */
+ need_repair_or_alter= 1;
+ }
}
DBUG_PRINT("admin", ("calling operator_func '%s'", operator_name));
result_code = (table->table->file->*operator_func)(thd, check_opt);
DBUG_PRINT("admin", ("operator_func returned: %d", result_code));
+ if (result_code == HA_ADMIN_NOT_IMPLEMENTED && need_repair_or_alter)
+ {
+ /*
+ repair was not implemented and we need to upgrade the table
+ to a new version so we recreate the table with ALTER TABLE
+ */
+ result_code= admin_recreate_table(thd, table);
+ }
send_result:
lex->cleanup_after_one_table_open();
@@ -4967,23 +4975,13 @@ send_result_message:
system_charset_info);
if (protocol->write())
goto err;
- ha_autocommit_or_rollback(thd, 0);
- close_thread_tables(thd);
DBUG_PRINT("info", ("HA_ADMIN_TRY_ALTER, trying analyze..."));
TABLE_LIST *save_next_local= table->next_local,
*save_next_global= table->next_global;
table->next_local= table->next_global= 0;
- tmp_disable_binlog(thd); // binlogging is done by caller if wanted
- result_code= mysql_recreate_table(thd, table);
- reenable_binlog(thd);
- /*
- mysql_recreate_table() can push OK or ERROR.
- Clear 'OK' status. If there is an error, keep it:
- we will store the error message in a result set row
- and then clear.
- */
- if (thd->main_da.is_ok())
- thd->main_da.reset_diagnostics_area();
+
+ result_code= admin_recreate_table(thd, table);
+
ha_autocommit_or_rollback(thd, 0);
close_thread_tables(thd);
if (!result_code) // recreation went ok
@@ -6973,6 +6971,14 @@ view_err:
if (!error && (new_name != table_name || new_db != db))
{
thd_proc_info(thd, "rename");
+
+ /*
+ Workaround InnoDB ending the transaction when the table instance
+ is unlocked/closed (close_cached_table below), otherwise the trx
+ state will differ between the server and storage engine layers.
+ */
+ ha_autocommit_or_rollback(thd, 0);
+
/*
Then do a 'simple' rename of the table. First we need to close all
instances of 'source' table.
@@ -7520,6 +7526,11 @@ view_err:
mysql_unlock_tables(thd, thd->lock);
thd->lock=0;
}
+ /*
+ If LOCK TABLES list is not empty and contains this table,
+ unlock the table and remove the table from this list.
+ */
+ mysql_lock_remove(thd, thd->locked_tables, table, FALSE);
/* Remove link to old table and rename the new one */
close_temporary_table(thd, table, 1, 1);
/* Should pass the 'new_name' as we store table name in the cache */
@@ -8019,6 +8030,30 @@ err:
}
+/* Prepare, run and cleanup for mysql_recreate_table() */
+
+static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list)
+{
+ bool result_code;
+ DBUG_ENTER("admin_recreate_table");
+
+ ha_autocommit_or_rollback(thd, 1);
+ close_thread_tables(thd);
+ tmp_disable_binlog(thd); // binlogging is done by caller if wanted
+ result_code= mysql_recreate_table(thd, table_list);
+ reenable_binlog(thd);
+ /*
+ mysql_recreate_table() can push OK or ERROR.
+ Clear 'OK' status. If there is an error, keep it:
+ we will store the error message in a result set row
+ and then clear.
+ */
+ if (thd->main_da.is_ok())
+ thd->main_da.reset_diagnostics_area();
+ DBUG_RETURN(result_code);
+}
+
+
/*
Recreates tables by calling mysql_alter_table().
@@ -8075,7 +8110,7 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
/* Open one table after the other to keep lock time as short as possible. */
for (table= tables; table; table= table->next_local)
{
- char table_name[NAME_LEN*2+2];
+ char table_name[SAFE_NAME_LEN*2+2];
TABLE *t;
strxmov(table_name, table->db ,".", table->table_name, NullS);
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index bf4a46a4c67..e8a382ca8f6 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -1391,7 +1391,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
To remove this prefix we use check_n_cut_mysql50_prefix().
*/
- char fname[NAME_LEN + 1];
+ char fname[SAFE_NAME_LEN + 1];
DBUG_ASSERT((!my_strcasecmp(table_alias_charset, lex.query_tables->db, db) ||
(check_n_cut_mysql50_prefix(db, fname, sizeof(fname)) &&
!my_strcasecmp(table_alias_charset, lex.query_tables->db, fname))) &&
@@ -1917,7 +1917,7 @@ bool Table_triggers_list::change_table_name(THD *thd, const char *db,
*/
if (my_strcasecmp(table_alias_charset, db, new_db))
{
- char dbname[NAME_LEN + 1];
+ char dbname[SAFE_NAME_LEN + 1];
if (check_n_cut_mysql50_prefix(db, dbname, sizeof(dbname)) &&
!my_strcasecmp(table_alias_charset, dbname, new_db))
{
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index 7aa7571d5ee..754a6f18536 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -215,7 +215,7 @@ void udf_init()
}
tmp->dlhandle = dl;
{
- char buf[NAME_LEN+16], *missing;
+ char buf[SAFE_NAME_LEN+16], *missing;
if ((missing= init_syms(tmp, buf)))
{
sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), missing);
@@ -469,7 +469,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
}
udf->dlhandle=dl;
{
- char buf[NAME_LEN+16], *missing;
+ char buf[SAFE_NAME_LEN+16], *missing;
if ((missing= init_syms(udf, buf)))
{
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), missing);
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 15251e956be..60bbd0d886a 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -470,12 +470,11 @@ int mysql_update(THD *thd,
thd_proc_info(thd, "Searching rows for update");
ha_rows tmp_limit= limit;
- while (!(error=info.read_record(&info)) &&
- !thd->killed && !thd->is_error())
+ while (!(error=info.read_record(&info)) && !thd->killed)
{
update_virtual_fields(thd, table);
thd->examined_row_count++;
- if (!select || select->skip_record(thd) > 0)
+ if (!select || (error= select->skip_record(thd)) > 0)
{
if (table->file->was_semi_consistent_read())
continue; /* repeat the read of the same row if it still exists */
@@ -494,7 +493,15 @@ int mysql_update(THD *thd,
}
}
else
+ {
table->file->unlock_row();
+ if (error < 0)
+ {
+ /* Fatal error from select->skip_record() */
+ error= 1;
+ break;
+ }
+ }
}
if (thd->killed && !error)
error= 1; // Aborted
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 2112d9b1e1c..204100f6034 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1189,7 +1189,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
table->view= lex= thd->lex= (LEX*) new(thd->mem_root) st_lex_local;
{
- char old_db_buf[NAME_LEN+1];
+ char old_db_buf[SAFE_NAME_LEN+1];
LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) };
bool dbchanged;
Parser_state parser_state;
diff --git a/sql/table.cc b/sql/table.cc
index 81353514872..8b0d02407c9 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -878,7 +878,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
/* Read extra data segment */
uchar *next_chunk, *buff_end;
DBUG_PRINT("info", ("extra segment size is %u bytes", n_length));
- if (!(next_chunk= buff= (uchar*) my_malloc(n_length, MYF(MY_WME))))
+ if (!(next_chunk= buff= (uchar*) my_malloc(n_length+1, MYF(MY_WME))))
goto err;
if (my_pread(file, buff, n_length, record_offset + share->reclength,
MYF(MY_NABP)))
@@ -953,6 +953,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
{
/* purecov: begin inspected */
error= 8;
+ name.str[name.length]= 0;
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), name.str);
goto free_and_err;
/* purecov: end */
@@ -3157,15 +3158,15 @@ bool check_db_name(LEX_STRING *org_name)
uint name_length= org_name->length;
bool check_for_path_chars;
- if (!name_length || name_length > NAME_LEN)
- return 1;
-
if ((check_for_path_chars= check_mysql50_prefix(name)))
{
name+= MYSQL50_TABLE_NAME_PREFIX_LENGTH;
name_length-= MYSQL50_TABLE_NAME_PREFIX_LENGTH;
}
+ if (!name_length || name_length > NAME_LEN)
+ return 1;
+
if (lower_case_table_names && name != any_db)
my_casedn_str(files_charset_info, name);
@@ -3183,6 +3184,15 @@ bool check_table_name(const char *name, uint length, bool check_for_path_chars)
{
uint name_length= 0; // name length in symbols
const char *end= name+length;
+
+
+ if (!check_for_path_chars &&
+ (check_for_path_chars= check_mysql50_prefix(name)))
+ {
+ name+= MYSQL50_TABLE_NAME_PREFIX_LENGTH;
+ length-= MYSQL50_TABLE_NAME_PREFIX_LENGTH;
+ }
+
if (!length || length > NAME_LEN)
return 1;
#if defined(USE_MB) && defined(USE_MB_IDENT)
diff --git a/sql/table.h b/sql/table.h
index 9f6006c9adc..b8df0d8c0c4 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -58,7 +58,6 @@ typedef struct st_order {
struct st_order *next;
Item **item; /* Point at item in select fields */
Item *item_ptr; /* Storage for initial item */
- Item **item_copy; /* For SPs; the original item ptr */
int counter; /* position in SELECT list, correct
only if counter_used is true*/
bool asc; /* true if ascending */
@@ -461,7 +460,7 @@ typedef struct st_table_share
#ifdef WITH_PARTITION_STORAGE_ENGINE
/** @todo: Move into *ha_data for partitioning */
bool auto_partitioned;
- const char *partition_info;
+ char *partition_info;
uint partition_info_len;
uint partition_info_buffer_size;
const char *part_state;
diff --git a/sql/udf_example.c b/sql/udf_example.c
index 788582e32b6..979aebd4b23 100644
--- a/sql/udf_example.c
+++ b/sql/udf_example.c
@@ -1067,7 +1067,7 @@ char *myfunc_argument_name(UDF_INIT *initid __attribute__((unused)),
{
if (!args->attributes[0])
{
- null_value= 0;
+ *null_value= 1;
return 0;
}
(*length)--; /* space for ending \0 (for debugging purposes) */
diff --git a/sql/unireg.h b/sql/unireg.h
index ec4ecf6a10f..57a9038d5f7 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -129,8 +129,8 @@
#define SPECIAL_LOG_QUERIES_NOT_USING_INDEXES 4096 /* Obsolete */
/* Extern defines */
-#define store_record(A,B) bmove_align((A)->B,(A)->record[0],(size_t) (A)->s->reclength)
-#define restore_record(A,B) bmove_align((A)->record[0],(A)->B,(size_t) (A)->s->reclength)
+#define store_record(A,B) memcpy((A)->B,(A)->record[0],(size_t) (A)->s->reclength)
+#define restore_record(A,B) memcpy((A)->record[0],(A)->B,(size_t) (A)->s->reclength)
#define cmp_record(A,B) memcmp((A)->record[0],(A)->B,(size_t) (A)->s->reclength)
#define empty_record(A) { \
restore_record((A),s->default_values); \