summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc2
-rw-r--r--sql/handler.h12
-rw-r--r--sql/item.cc239
-rw-r--r--sql/item.h199
-rw-r--r--sql/item_cmpfunc.cc10
-rw-r--r--sql/item_func.cc67
-rw-r--r--sql/item_func.h6
-rw-r--r--sql/item_strfunc.cc29
-rw-r--r--sql/log_event.cc7
-rw-r--r--sql/rpl_rli.cc13
-rw-r--r--sql/share/errmsg.txt2
-rw-r--r--sql/slave.cc20
-rw-r--r--sql/sql_acl.cc11
-rw-r--r--sql/sql_base.cc7
-rw-r--r--sql/sql_class.cc2
-rw-r--r--sql/sql_delete.cc20
-rw-r--r--sql/sql_parse.cc8
-rw-r--r--sql/sql_plugin.cc346
-rw-r--r--sql/sql_plugin.h1
-rw-r--r--sql/sql_prepare.cc3
-rw-r--r--sql/sql_rename.cc2
-rw-r--r--sql/sql_select.cc24
-rw-r--r--sql/sql_string.cc3
-rw-r--r--sql/sql_table.cc16
-rw-r--r--sql/sql_union.cc16
-rw-r--r--sql/sql_update.cc51
-rw-r--r--sql/table.cc2
-rw-r--r--sql/unireg.cc3
28 files changed, 881 insertions, 240 deletions
diff --git a/sql/field.cc b/sql/field.cc
index d11b509075b..98b3b91fcbd 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -5307,7 +5307,7 @@ bool Field_time::get_time(MYSQL_TIME *ltime)
ltime->neg= 1;
tmp=-tmp;
}
- ltime->day= 0;
+ ltime->year= ltime->month= ltime->day= 0;
ltime->hour= (int) (tmp/10000);
tmp-=ltime->hour*10000;
ltime->minute= (int) tmp/100;
diff --git a/sql/handler.h b/sql/handler.h
index d43fc4725dd..5c7cfa4d58b 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -876,9 +876,9 @@ typedef struct {
ulonglong delete_length;
ha_rows records;
ulong mean_rec_length;
- time_t create_time;
- time_t check_time;
- time_t update_time;
+ ulong create_time;
+ ulong check_time;
+ ulong update_time;
ulonglong check_sum;
} PARTITION_INFO;
@@ -1037,9 +1037,9 @@ public:
ha_rows records;
ha_rows deleted; /* Deleted records */
ulong mean_rec_length; /* physical reclength */
- time_t create_time; /* When table was created */
- time_t check_time;
- time_t update_time;
+ ulong create_time; /* When table was created */
+ ulong check_time;
+ ulong update_time;
uint block_size; /* index block size */
ha_statistics():
diff --git a/sql/item.cc b/sql/item.cc
index d1418b9a137..768af47d660 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -2472,8 +2472,9 @@ longlong_from_string_with_check (CHARSET_INFO *cs, const char *cptr, char *end)
TODO: Give error if we wanted a signed integer and we got an unsigned
one
*/
- if (err > 0 ||
- (end != org_end && !check_if_only_end_space(cs, end, org_end)))
+ if (!current_thd->no_errors &&
+ (err > 0 ||
+ (end != org_end && !check_if_only_end_space(cs, end, org_end))))
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE,
@@ -3268,9 +3269,57 @@ Item_param::set_param_type_and_swap_value(Item_param *src)
}
/****************************************************************************
+ Item_copy
+****************************************************************************/
+Item_copy *Item_copy::create (Item *item)
+{
+ switch (item->result_type())
+ {
+ case STRING_RESULT:
+ return new Item_copy_string (item);
+ case REAL_RESULT:
+ return new Item_copy_float (item);
+ case INT_RESULT:
+ return item->unsigned_flag ?
+ new Item_copy_uint (item) : new Item_copy_int (item);
+ case DECIMAL_RESULT:
+ return new Item_copy_decimal (item);
+
+ case ROW_RESULT:
+ DBUG_ASSERT (0);
+ }
+ /* should not happen */
+ return NULL;
+}
+
+/****************************************************************************
Item_copy_string
****************************************************************************/
+double Item_copy_string::val_real()
+{
+ int err_not_used;
+ char *end_not_used;
+ return (null_value ? 0.0 :
+ my_strntod(str_value.charset(), (char*) str_value.ptr(),
+ str_value.length(), &end_not_used, &err_not_used));
+}
+
+longlong Item_copy_string::val_int()
+{
+ int err;
+ return null_value ? LL(0) : my_strntoll(str_value.charset(),str_value.ptr(),
+ str_value.length(),10, (char**) 0,
+ &err);
+}
+
+
+int Item_copy_string::save_in_field(Field *field, bool no_conversions)
+{
+ return save_str_value_in_field(field, &str_value);
+}
+
+
void Item_copy_string::copy()
{
String *res=item->val_str(&str_value);
@@ -3293,12 +3342,163 @@ my_decimal *Item_copy_string::val_decimal(my_decimal *decimal_value)
{
// Item_copy_string is used without fix_fields call
if (null_value)
- return 0;
+ return (my_decimal *) 0;
string2my_decimal(E_DEC_FATAL_ERROR, &str_value, decimal_value);
return (decimal_value);
}
+/****************************************************************************
+ Item_copy_int
+****************************************************************************/
+
+void Item_copy_int::copy()
+{
+ cached_value= item->val_int();
+ null_value=item->null_value;
+}
+
+static int save_int_value_in_field (Field *field, longlong nr,
+ bool null_value, bool unsigned_flag);
+
+int Item_copy_int::save_in_field(Field *field, bool no_conversions)
+{
+ return save_int_value_in_field(field, cached_value,
+ null_value, unsigned_flag);
+}
+
+
+String *Item_copy_int::val_str(String *str)
+{
+ if (null_value)
+ return (String *) 0;
+
+ str->set(cached_value, &my_charset_bin);
+ return str;
+}
+
+
+my_decimal *Item_copy_int::val_decimal(my_decimal *decimal_value)
+{
+ if (null_value)
+ return (my_decimal *) 0;
+
+ int2my_decimal(E_DEC_FATAL_ERROR, cached_value, unsigned_flag, decimal_value);
+ return decimal_value;
+}
+
+
+/****************************************************************************
+ Item_copy_uint
+****************************************************************************/
+
+String *Item_copy_uint::val_str(String *str)
+{
+ if (null_value)
+ return (String *) 0;
+
+ str->set((ulonglong) cached_value, &my_charset_bin);
+ return str;
+}
+
+
+/****************************************************************************
+ Item_copy_float
+****************************************************************************/
+
+String *Item_copy_float::val_str(String *str)
+{
+ if (null_value)
+ return (String *) 0;
+ else
+ {
+ double nr= val_real();
+ str->set_real(nr,decimals, &my_charset_bin);
+ return str;
+ }
+}
+
+
+my_decimal *Item_copy_float::val_decimal(my_decimal *decimal_value)
+{
+ if (null_value)
+ return (my_decimal *) 0;
+ else
+ {
+ double nr= val_real();
+ double2my_decimal(E_DEC_FATAL_ERROR, nr, decimal_value);
+ return decimal_value;
+ }
+}
+
+
+int Item_copy_float::save_in_field(Field *field, bool no_conversions)
+{
+ if (null_value)
+ return set_field_to_null(field);
+ field->set_notnull();
+ return field->store(cached_value);
+}
+
+
+/****************************************************************************
+ Item_copy_decimal
+****************************************************************************/
+
+int Item_copy_decimal::save_in_field(Field *field, bool no_conversions)
+{
+ if (null_value)
+ return set_field_to_null(field);
+ field->set_notnull();
+ return field->store_decimal(&cached_value);
+}
+
+
+String *Item_copy_decimal::val_str(String *result)
+{
+ if (null_value)
+ return (String *) 0;
+ result->set_charset(&my_charset_bin);
+ my_decimal2string(E_DEC_FATAL_ERROR, &cached_value, 0, 0, 0, result);
+ return result;
+}
+
+
+double Item_copy_decimal::val_real()
+{
+ if (null_value)
+ return 0.0;
+ else
+ {
+ double result;
+ my_decimal2double(E_DEC_FATAL_ERROR, &cached_value, &result);
+ return result;
+ }
+}
+
+
+longlong Item_copy_decimal::val_int()
+{
+ if (null_value)
+ return LL(0);
+ else
+ {
+ longlong result;
+ my_decimal2int(E_DEC_FATAL_ERROR, &cached_value, unsigned_flag, &result);
+ return result;
+ }
+}
+
+
+void Item_copy_decimal::copy()
+{
+ my_decimal *nr= item->val_decimal(&cached_value);
+ if (nr && nr != &cached_value)
+ memcpy (&cached_value, nr, sizeof (my_decimal));
+ null_value= item->null_value;
+}
+
+
/*
Functions to convert item to field (for send_fields)
*/
@@ -3390,14 +3590,12 @@ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
current->mark_as_dependent(last);
if (thd->lex->describe & DESCRIBE_EXTENDED)
{
- char warn_buff[MYSQL_ERRMSG_SIZE];
- sprintf(warn_buff, ER(ER_WARN_FIELD_RESOLVED),
- db_name, (db_name[0] ? "." : ""),
- table_name, (table_name [0] ? "." : ""),
- resolved_item->field_name,
- current->select_number, last->select_number);
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
- ER_WARN_FIELD_RESOLVED, warn_buff);
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_WARN_FIELD_RESOLVED, ER(ER_WARN_FIELD_RESOLVED),
+ db_name, (db_name[0] ? "." : ""),
+ table_name, (table_name [0] ? "." : ""),
+ resolved_item->field_name,
+ current->select_number, last->select_number);
}
}
@@ -4875,7 +5073,10 @@ int Item_null::save_safe_in_field(Field *field)
/*
This implementation can lose str_value content, so if the
Item uses str_value to store something, it should
- reimplement it's ::save_in_field() as Item_string, for example, does
+ reimplement it's ::save_in_field() as Item_string, for example, does.
+
+ Note: all Item_XXX::val_str(str) methods must NOT rely on the fact that
+ str != str_value. For example, see fix for bug #44743.
*/
int Item::save_in_field(Field *field, bool no_conversions)
@@ -4945,10 +5146,9 @@ int Item_uint::save_in_field(Field *field, bool no_conversions)
return Item_int::save_in_field(field, no_conversions);
}
-
-int Item_int::save_in_field(Field *field, bool no_conversions)
+static int save_int_value_in_field (Field *field, longlong nr,
+ bool null_value, bool unsigned_flag)
{
- longlong nr=val_int();
if (null_value)
return set_field_to_null(field);
field->set_notnull();
@@ -4956,6 +5156,12 @@ int Item_int::save_in_field(Field *field, bool no_conversions)
}
+int Item_int::save_in_field(Field *field, bool no_conversions)
+{
+ return save_int_value_in_field (field, val_int(), null_value, unsigned_flag);
+}
+
+
int Item_decimal::save_in_field(Field *field, bool no_conversions)
{
field->set_notnull();
@@ -5812,7 +6018,8 @@ void Item_ref::print(String *str, enum_query_type query_type)
!table_name && name && alias_name_used)
{
THD *thd= current_thd;
- append_identifier(thd, str, name, (uint) strlen(name));
+ append_identifier(thd, str, (*ref)->real_item()->name,
+ (*ref)->real_item()->name_length);
}
else
(*ref)->print(str, query_type);
diff --git a/sql/item.h b/sql/item.h
index 96a4e9f7a31..3dfcd7c2612 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2443,48 +2443,203 @@ public:
#include "item_xmlfunc.h"
#endif
-class Item_copy_string :public Item
+/**
+ Base class to implement typed value caching Item classes
+
+ Item_copy_ classes are very similar to the corresponding Item_
+ classes (e.g. Item_copy_int is similar to Item_int) but they add
+ the following additional functionality to Item_ :
+ 1. Nullability
+ 2. Possibility to store the value not only on instantiation time,
+ but also later.
+ Item_copy_ classes are a functionality subset of Item_cache_
+ classes, as e.g. they don't support comparisons with the original Item
+ as Item_cache_ classes do.
+ Item_copy_ classes are used in GROUP BY calculation.
+ TODO: Item_copy should be made an abstract interface and Item_copy_
+ classes should inherit both the respective Item_ class and the interface.
+ Ideally we should drop Item_copy_ classes altogether and merge
+ their functionality to Item_cache_ (and these should be made to inherit
+ from Item_).
+*/
+
+class Item_copy :public Item
{
+protected:
+
+ /**
+ Stores the type of the resulting field that would be used to store the data
+ in the cache. This is to avoid calls to the original item.
+ */
enum enum_field_types cached_field_type;
-public:
+
+ /** The original item that is copied */
Item *item;
- Item_copy_string(Item *i) :item(i)
+
+ /**
+ Stores the result type of the original item, so it can be returned
+ without calling the original item's method
+ */
+ Item_result cached_result_type;
+
+ /**
+ Constructor of the Item_copy class
+
+ stores metadata information about the original class as well as a
+ pointer to it.
+ */
+ Item_copy(Item *i)
{
+ item= i;
null_value=maybe_null=item->maybe_null;
decimals=item->decimals;
max_length=item->max_length;
name=item->name;
cached_field_type= item->field_type();
+ cached_result_type= item->result_type();
+ unsigned_flag= item->unsigned_flag;
}
+
+public:
+ /**
+ Factory method to create the appropriate subclass dependent on the type of
+ the original item.
+
+ @param item the original item.
+ */
+ static Item_copy *create (Item *item);
+
+ /**
+ Update the cache with the value of the original item
+
+ This is the method that updates the cached value.
+ It must be explicitly called by the user of this class to store the value
+ of the orginal item in the cache.
+ */
+ virtual void copy() = 0;
+
+ Item *get_item() { return item; }
+ /** All of the subclasses should have the same type tag */
enum Type type() const { return COPY_STR_ITEM; }
- enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return cached_field_type; }
- double val_real()
+ enum Item_result result_type () const { return cached_result_type; }
+
+ void make_field(Send_field *field) { item->make_field(field); }
+ table_map used_tables() const { return (table_map) 1L; }
+ bool const_item() const { return 0; }
+ bool is_null() { return null_value; }
+
+ /*
+ Override the methods below as pure virtual to make sure all the
+ sub-classes implement them.
+ */
+
+ virtual String *val_str(String*) = 0;
+ virtual my_decimal *val_decimal(my_decimal *) = 0;
+ virtual double val_real() = 0;
+ virtual longlong val_int() = 0;
+ virtual int save_in_field(Field *field, bool no_conversions) = 0;
+};
+
+/**
+ Implementation of a string cache.
+
+ Uses Item::str_value for storage
+*/
+class Item_copy_string : public Item_copy
+{
+public:
+ Item_copy_string (Item *item) : Item_copy(item) {}
+
+ String *val_str(String*);
+ my_decimal *val_decimal(my_decimal *);
+ double val_real();
+ longlong val_int();
+ void copy();
+ int save_in_field(Field *field, bool no_conversions);
+};
+
+
+class Item_copy_int : public Item_copy
+{
+protected:
+ longlong cached_value;
+public:
+ Item_copy_int (Item *i) : Item_copy(i) {}
+ int save_in_field(Field *field, bool no_conversions);
+
+ virtual String *val_str(String*);
+ virtual my_decimal *val_decimal(my_decimal *);
+ virtual double val_real()
{
- int err_not_used;
- char *end_not_used;
- return (null_value ? 0.0 :
- my_strntod(str_value.charset(), (char*) str_value.ptr(),
- str_value.length(), &end_not_used, &err_not_used));
+ return null_value ? 0.0 : (double) cached_value;
}
- longlong val_int()
+ virtual longlong val_int()
+ {
+ return null_value ? LL(0) : cached_value;
+ }
+ virtual void copy();
+};
+
+
+class Item_copy_uint : public Item_copy_int
+{
+public:
+ Item_copy_uint (Item *item) : Item_copy_int(item)
+ {
+ unsigned_flag= 1;
+ }
+
+ String *val_str(String*);
+ double val_real()
{
- int err;
- return null_value ? LL(0) : my_strntoll(str_value.charset(),str_value.ptr(),
- str_value.length(),10, (char**) 0,
- &err);
+ return null_value ? 0.0 : (double) (ulonglong) cached_value;
}
+};
+
+
+class Item_copy_float : public Item_copy
+{
+protected:
+ double cached_value;
+public:
+ Item_copy_float (Item *i) : Item_copy(i) {}
+ int save_in_field(Field *field, bool no_conversions);
+
String *val_str(String*);
my_decimal *val_decimal(my_decimal *);
- void make_field(Send_field *field) { item->make_field(field); }
- void copy();
- int save_in_field(Field *field, bool no_conversions)
+ double val_real()
{
- return save_str_value_in_field(field, &str_value);
+ return null_value ? 0.0 : cached_value;
}
- table_map used_tables() const { return (table_map) 1L; }
- bool const_item() const { return 0; }
- bool is_null() { return null_value; }
+ longlong val_int()
+ {
+ return (longlong) rint(val_real());
+ }
+ void copy()
+ {
+ cached_value= item->val_real();
+ null_value= item->null_value;
+ }
+};
+
+
+class Item_copy_decimal : public Item_copy
+{
+protected:
+ my_decimal cached_value;
+public:
+ Item_copy_decimal (Item *i) : Item_copy(i) {}
+ int save_in_field(Field *field, bool no_conversions);
+
+ String *val_str(String*);
+ my_decimal *val_decimal(my_decimal *)
+ {
+ return null_value ? NULL: &cached_value;
+ }
+ double val_real();
+ longlong val_int();
+ void copy();
};
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index a9bfea1b806..ee823517df8 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -2724,16 +2724,6 @@ void Item_func_case::fix_length_and_dec()
nagg++;
if (!(found_types= collect_cmp_types(agg, nagg)))
return;
- if (with_sum_func || current_thd->lex->current_select->group_list.elements)
- {
- /*
- See TODO commentary in the setup_copy_fields function:
- item in a group may be wrapped with an Item_copy_string item.
- That item has a STRING_RESULT result type, so we need
- to take this type into account.
- */
- found_types |= (1 << item_cmp_type(left_result_type, STRING_RESULT));
- }
for (i= 0; i <= (uint)DECIMAL_RESULT; i++)
{
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 876aee719a3..0c8f236a27c 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2143,9 +2143,6 @@ bool Item_func_rand::fix_fields(THD *thd,Item **ref)
if (!rand && !(rand= (struct rand_struct*)
thd->stmt_arena->alloc(sizeof(*rand))))
return TRUE;
-
- if (args[0]->const_item())
- seed_random (args[0]);
}
else
{
@@ -2175,8 +2172,21 @@ void Item_func_rand::update_used_tables()
double Item_func_rand::val_real()
{
DBUG_ASSERT(fixed == 1);
- if (arg_count && !args[0]->const_item())
- seed_random (args[0]);
+ if (arg_count)
+ {
+ if (!args[0]->const_item())
+ seed_random(args[0]);
+ else if (first_eval)
+ {
+ /*
+ Constantness of args[0] may be set during JOIN::optimize(), if arg[0]
+ is a field item of "constant" table. Thus, we have to evaluate
+ seed_random() for constant arg there but not at the fix_fields method.
+ */
+ first_eval= FALSE;
+ seed_random(args[0]);
+ }
+ }
return my_rnd(rand);
}
@@ -4178,6 +4188,41 @@ Item_func_set_user_var::check(bool use_result_field)
/**
+ @brief Evaluate and store item's result.
+ This function is invoked on "SELECT ... INTO @var ...".
+
+ @param item An item to get value from.
+*/
+
+void Item_func_set_user_var::save_item_result(Item *item)
+{
+ DBUG_ENTER("Item_func_set_user_var::save_item_result");
+
+ switch (cached_result_type) {
+ case REAL_RESULT:
+ save_result.vreal= item->val_result();
+ break;
+ case INT_RESULT:
+ save_result.vint= item->val_int_result();
+ unsigned_flag= item->unsigned_flag;
+ break;
+ case STRING_RESULT:
+ save_result.vstr= item->str_result(&value);
+ break;
+ case DECIMAL_RESULT:
+ save_result.vdec= item->val_decimal_result(&decimal_buff);
+ break;
+ case ROW_RESULT:
+ default:
+ // Should never happen
+ DBUG_ASSERT(0);
+ break;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/**
This functions is invoked on
SET \@variable or \@variable:= expression.
@@ -4835,10 +4880,20 @@ bool Item_func_get_system_var::is_written_to_binlog()
}
+void Item_func_get_system_var::update_null_value()
+{
+ THD *thd= current_thd;
+ int save_no_errors= thd->no_errors;
+ thd->no_errors= TRUE;
+ Item::update_null_value();
+ thd->no_errors= save_no_errors;
+}
+
+
void Item_func_get_system_var::fix_length_and_dec()
{
char *cptr;
- maybe_null=0;
+ maybe_null= TRUE;
max_length= 0;
if (var->check_type(var_type))
diff --git a/sql/item_func.h b/sql/item_func.h
index d23d821baf6..67049af81a2 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -696,14 +696,16 @@ public:
class Item_func_rand :public Item_real_func
{
struct rand_struct *rand;
+ bool first_eval; // TRUE if val_real() is called 1st time
public:
- Item_func_rand(Item *a) :Item_real_func(a), rand(0) {}
+ Item_func_rand(Item *a) :Item_real_func(a), rand(0), first_eval(TRUE) {}
Item_func_rand() :Item_real_func() {}
double val_real();
const char *func_name() const { return "rand"; }
bool const_item() const { return 0; }
void update_used_tables();
bool fix_fields(THD *thd, Item **ref);
+ void cleanup() { first_eval= TRUE; Item_real_func::cleanup(); }
private:
void seed_random (Item * val);
};
@@ -1341,6 +1343,7 @@ public:
bool send(Protocol *protocol, String *str_arg);
void make_field(Send_field *tmp_field);
bool check(bool use_result_field);
+ void save_item_result(Item *item);
bool update();
enum Item_result result_type () const { return cached_result_type; }
bool fix_fields(THD *thd, Item **ref);
@@ -1452,6 +1455,7 @@ public:
LEX_STRING *component_arg, const char *name_arg,
size_t name_len_arg);
enum Functype functype() const { return GSYSVAR_FUNC; }
+ void update_null_value();
void fix_length_and_dec();
void print(String *str, enum_query_type query_type);
bool const_item() const { return true; }
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 267036e4a3d..f9210c842bb 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -2706,8 +2706,15 @@ String *Item_func_conv_charset::val_str(String *str)
DBUG_ASSERT(fixed == 1);
if (use_cached_value)
return null_value ? 0 : &str_value;
- String *arg= args[0]->val_str(str);
+ /*
+ Here we don't pass 'str' as a parameter to args[0]->val_str()
+ as 'str' may points to 'str_value' (e.g. see Item::save_in_field()),
+ which we use below to convert string.
+ Use argument's 'str_value' instead.
+ */
+ String *arg= args[0]->val_str(&args[0]->str_value);;
uint dummy_errors;
+ arg= args[0]->val_str(&args[0]->str_value);
if (!arg)
{
null_value=1;
@@ -2943,7 +2950,7 @@ String *Item_load_file::val_str(String *str)
)
goto err;
- (void) fn_format(path, file_name->c_ptr(), mysql_real_data_home, "",
+ (void) fn_format(path, file_name->c_ptr_safe(), mysql_real_data_home, "",
MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
/* Read only allowed from within dir specified by secure_file_priv */
@@ -2969,7 +2976,7 @@ String *Item_load_file::val_str(String *str)
}
if (tmp_value.alloc(stat_info.st_size))
goto err;
- if ((file = my_open(file_name->c_ptr(), O_RDONLY, MYF(0))) < 0)
+ if ((file = my_open(file_name->ptr(), O_RDONLY, MYF(0))) < 0)
goto err;
if (my_read(file, (uchar*) tmp_value.ptr(), stat_info.st_size, MYF(MY_NABP)))
{
@@ -3219,7 +3226,21 @@ longlong Item_func_uncompressed_length::val_int()
if (res->is_empty()) return 0;
/*
- res->ptr() using is safe because we have tested that string is not empty,
+ If length is <= 4 bytes, data is corrupt. This is the best we can do
+ to detect garbage input without decompressing it.
+ */
+ if (res->length() <= 4)
+ {
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ ER_ZLIB_Z_DATA_ERROR,
+ ER(ER_ZLIB_Z_DATA_ERROR));
+ null_value= 1;
+ return 0;
+ }
+
+ /*
+ res->ptr() using is safe because we have tested that string is at least
+ 5 bytes long.
res->c_ptr() is not used because:
- we do not need \0 terminated string to get first 4 bytes
- c_ptr() tests simbol after string end (uninitialiozed memory) which
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 1a8cb8ee4fa..651cd1418e3 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -7862,10 +7862,11 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid,
/*
Now set the size of the data to the size of the field metadata array
- plus one or two bytes for number of elements in the field metadata array.
+ plus one or three bytes (see pack.c:net_store_length) for number of
+ elements in the field metadata array.
*/
if (m_field_metadata_size > 255)
- m_data_size+= m_field_metadata_size + 2;
+ m_data_size+= m_field_metadata_size + 3;
else
m_data_size+= m_field_metadata_size + 1;
@@ -9312,7 +9313,7 @@ Incident_log_event::print(FILE *file,
Write_on_release_cache cache(&print_event_info->head_cache, file);
print_header(&cache, print_event_info, FALSE);
- my_b_printf(&cache, "\n# Incident: %s", description());
+ my_b_printf(&cache, "\n# Incident: %s\nRELOAD DATABASE; # Shall generate syntax error\n", description());
}
#endif
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index e93417374fe..45c0efb10c2 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -104,9 +104,16 @@ int init_relay_log_info(Relay_log_info* rli,
rli->tables_to_lock= 0;
rli->tables_to_lock_count= 0;
- fn_format(rli->slave_patternload_file, PREFIX_SQL_LOAD, slave_load_tmpdir, "",
- MY_PACK_FILENAME | MY_UNPACK_FILENAME |
- MY_RETURN_REAL_PATH);
+ char pattern[FN_REFLEN];
+ if (fn_format(pattern, PREFIX_SQL_LOAD, slave_load_tmpdir, "",
+ MY_SAFE_PATH | MY_RETURN_REAL_PATH) == NullS)
+ {
+ pthread_mutex_unlock(&rli->data_lock);
+ sql_print_error("Unable to use slave's temporary directory %s",
+ slave_load_tmpdir);
+ DBUG_RETURN(1);
+ }
+ unpack_filename(rli->slave_patternload_file, pattern);
rli->slave_patternload_file_size= strlen(rli->slave_patternload_file);
/*
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index f9b66990e93..2dfc5310643 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -6076,7 +6076,7 @@ ER_SLAVE_INCIDENT
ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT
eng "Table has no partition for some existing values"
ER_BINLOG_UNSAFE_STATEMENT
- eng "Statement is not safe to log in statement format."
+ eng "Statement may not be safe to log in statement format."
swe "Detta är inte säkert att logga i statement-format."
ER_SLAVE_FATAL_ERROR
eng "Fatal error: %s"
diff --git a/sql/slave.cc b/sql/slave.cc
index 81c18c5e04b..c379a67201a 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -389,6 +389,13 @@ void init_slave_skip_errors(const char* arg)
DBUG_VOID_RETURN;
}
+static void set_thd_in_use_temporary_tables(Relay_log_info *rli)
+{
+ TABLE *table;
+
+ for (table= rli->save_temporary_tables ; table ; table= table->next)
+ table->in_use= rli->sql_thd;
+}
int terminate_slave_threads(Master_info* mi,int thread_mask,bool skip_lock)
{
@@ -2668,14 +2675,21 @@ err:
LOAD DATA INFILE.
*/
static
-int check_temp_dir(char* tmp_dir, char *tmp_file)
+int check_temp_dir(char* tmp_file)
{
int fd;
MY_DIR *dirp;
+ char tmp_dir[FN_REFLEN];
+ size_t tmp_dir_size;
DBUG_ENTER("check_temp_dir");
/*
+ Get the directory from the temporary file.
+ */
+ dirname_part(tmp_dir, tmp_file, &tmp_dir_size);
+
+ /*
Check if the directory exists.
*/
if (!(dirp=my_dir(tmp_dir,MYF(MY_WME))))
@@ -2750,6 +2764,7 @@ pthread_handler_t handle_slave_sql(void *arg)
}
thd->init_for_queries();
thd->temporary_tables = rli->save_temporary_tables; // restore temp tables
+ set_thd_in_use_temporary_tables(rli); // (re)set sql_thd in use for saved temp tables
pthread_mutex_lock(&LOCK_thread_count);
threads.append(thd);
pthread_mutex_unlock(&LOCK_thread_count);
@@ -2830,7 +2845,7 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME,
llstr(rli->group_master_log_pos,llbuff),rli->group_relay_log_name,
llstr(rli->group_relay_log_pos,llbuff1));
- if (check_temp_dir(slave_load_tmpdir, rli->slave_patternload_file))
+ if (check_temp_dir(rli->slave_patternload_file))
{
rli->report(ERROR_LEVEL, thd->main_da.sql_errno(),
"Unable to use slave's temporary directory %s - %s",
@@ -2996,6 +3011,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
DBUG_ASSERT(rli->sql_thd == thd);
THD_CHECK_SENTRY(thd);
rli->sql_thd= 0;
+ set_thd_in_use_temporary_tables(rli); // (re)set sql_thd in use for saved temp tables
pthread_mutex_lock(&LOCK_thread_count);
THD_CHECK_SENTRY(thd);
delete thd;
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index b1dbb7031ce..4d4e4d24684 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -936,6 +936,7 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh,
#ifdef HAVE_OPENSSL
Vio *vio=thd->net.vio;
SSL *ssl= (SSL*) vio->ssl_arg;
+ X509 *cert;
#endif
/*
@@ -964,8 +965,11 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh,
*/
if (vio_type(vio) == VIO_TYPE_SSL &&
SSL_get_verify_result(ssl) == X509_V_OK &&
- SSL_get_peer_certificate(ssl))
+ (cert= SSL_get_peer_certificate(ssl)))
+ {
user_access= acl_user->access;
+ X509_free(cert);
+ }
break;
case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */
/*
@@ -974,7 +978,6 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh,
If cipher name is specified, we compare it to actual cipher in
use.
*/
- X509 *cert;
if (vio_type(vio) != VIO_TYPE_SSL ||
SSL_get_verify_result(ssl) != X509_V_OK)
break;
@@ -1014,6 +1017,7 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh,
sql_print_information("X509 issuer mismatch: should be '%s' "
"but is '%s'", acl_user->x509_issuer, ptr);
free(ptr);
+ X509_free(cert);
user_access=NO_ACCESS;
break;
}
@@ -1033,12 +1037,15 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh,
sql_print_information("X509 subject mismatch: should be '%s' but is '%s'",
acl_user->x509_subject, ptr);
free(ptr);
+ X509_free(cert);
user_access=NO_ACCESS;
break;
}
user_access= acl_user->access;
free(ptr);
}
+ /* Deallocate the X509 certificate. */
+ X509_free(cert);
break;
#else /* HAVE_OPENSSL */
default:
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 0dc29f7e3c2..d4d813d0fbd 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -5585,6 +5585,13 @@ static void update_field_dependencies(THD *thd, Field *field, TABLE *table)
other_bitmap= table->read_set;
}
+ /*
+ The test-and-set mechanism in the bitmap is not reliable during
+ multi-UPDATE statements under MARK_COLUMNS_READ mode
+ (thd->mark_used_columns == MARK_COLUMNS_READ), as this bitmap contains
+ 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 (thd->mark_used_columns == MARK_COLUMNS_WRITE)
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index b73822f5a48..cf5fdcf27a7 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2599,7 +2599,7 @@ bool select_dumpvar::send_data(List<Item> &items)
{
Item_func_set_user_var *suv= new Item_func_set_user_var(mv->s, item);
suv->fix_fields(thd, 0);
- suv->check(0);
+ suv->save_item_result(item);
suv->update();
}
}
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 1b42e522491..7b967206305 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -582,6 +582,11 @@ int mysql_multi_delete_prepare(THD *thd)
}
}
}
+ /*
+ Reset the exclude flag to false so it doesn't interfare
+ with further calls to unique_table
+ */
+ lex->select_lex.exclude_from_table_unique_test= FALSE;
DBUG_RETURN(FALSE);
}
@@ -617,11 +622,24 @@ multi_delete::initialize_tables(JOIN *join)
DBUG_RETURN(1);
table_map tables_to_delete_from=0;
+ delete_while_scanning= 1;
for (walk= delete_tables; walk; walk= walk->next_local)
+ {
tables_to_delete_from|= walk->table->map;
+ if (delete_while_scanning &&
+ unique_table(thd, walk, join->tables_list, false))
+ {
+ /*
+ If the table we are going to delete from appears
+ in join, we need to defer delete. So the delete
+ doesn't interfers with the scaning of results.
+ */
+ delete_while_scanning= 0;
+ }
+ }
+
walk= delete_tables;
- delete_while_scanning= 1;
for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
tab < end;
tab++)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 6dbe4a4fd8d..8f1d3842245 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -195,11 +195,8 @@ bool begin_trans(THD *thd)
error= -1;
else
{
- LEX *lex= thd->lex;
thd->options|= OPTION_BEGIN;
thd->server_status|= SERVER_STATUS_IN_TRANS;
- if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
- error= ha_start_consistent_snapshot(thd);
}
return error;
}
@@ -4027,6 +4024,11 @@ end_with_restore_list:
}
if (begin_trans(thd))
goto error;
+ if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
+ {
+ if (ha_start_consistent_snapshot(thd))
+ goto error;
+ }
my_ok(thd);
break;
case SQLCOM_COMMIT:
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 1465b6d2d30..da168d36429 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -29,6 +29,18 @@
extern struct st_mysql_plugin *mysqld_builtins[];
+/**
+ @note The order of the enumeration is critical.
+ @see construct_options
+*/
+static const char *global_plugin_typelib_names[]=
+ { "OFF", "ON", "FORCE", NULL };
+enum enum_plugin_load_policy {PLUGIN_OFF, PLUGIN_ON, PLUGIN_FORCE};
+static TYPELIB global_plugin_typelib=
+ { array_elements(global_plugin_typelib_names)-1,
+ "", global_plugin_typelib_names, NULL };
+
+
char *opt_plugin_load= NULL;
char *opt_plugin_dir_ptr;
char opt_plugin_dir[FN_REFLEN];
@@ -192,7 +204,7 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv);
static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
const char *list);
static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *,
- int *, char **, my_bool);
+ int *, char **);
static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *,
struct st_plugin_int **);
static void unlock_variables(THD *thd, struct system_variables *vars);
@@ -751,7 +763,7 @@ static bool plugin_add(MEM_ROOT *tmp_root,
tmp.name.length= name_len;
tmp.ref_count= 0;
tmp.state= PLUGIN_IS_UNINITIALIZED;
- if (test_plugin_options(tmp_root, &tmp, argc, argv, true))
+ if (test_plugin_options(tmp_root, &tmp, argc, argv))
tmp.state= PLUGIN_IS_DISABLED;
if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
@@ -997,7 +1009,6 @@ static int plugin_initialize(struct st_plugin_int *plugin)
DBUG_ENTER("plugin_initialize");
safe_mutex_assert_owner(&LOCK_plugin);
-
if (plugin_type_initialize[plugin->plugin->type])
{
if ((*plugin_type_initialize[plugin->plugin->type])(plugin))
@@ -1083,6 +1094,20 @@ uchar *get_bookmark_hash_key(const uchar *buff, size_t *length,
return (uchar*) var->key;
}
+static inline void convert_dash_to_underscore(char *str, int len)
+{
+ for (char *p= str; p <= str+len; p++)
+ if (*p == '-')
+ *p= '_';
+}
+
+static inline void convert_underscore_to_dash(char *str, int len)
+{
+ for (char *p= str; p <= str+len; p++)
+ if (*p == '_')
+ *p= '-';
+}
+
/*
The logic is that we first load and initialize all compiled in plugins.
@@ -1094,11 +1119,12 @@ uchar *get_bookmark_hash_key(const uchar *buff, size_t *length,
int plugin_init(int *argc, char **argv, int flags)
{
uint i;
- bool def_enabled, is_myisam;
+ bool is_myisam;
struct st_mysql_plugin **builtins;
struct st_mysql_plugin *plugin;
struct st_plugin_int tmp, *plugin_ptr, **reap;
MEM_ROOT tmp_root;
+ bool reaped_mandatory_plugin= FALSE;
DBUG_ENTER("plugin_init");
if (initialized)
@@ -1142,17 +1168,13 @@ int plugin_init(int *argc, char **argv, int flags)
!my_strnncoll(&my_charset_latin1, (const uchar*) plugin->name,
6, (const uchar*) "InnoDB", 6))
continue;
- /* by default, ndbcluster and federated are disabled */
- def_enabled=
- my_strcasecmp(&my_charset_latin1, plugin->name, "NDBCLUSTER") != 0 &&
- my_strcasecmp(&my_charset_latin1, plugin->name, "FEDERATED") != 0;
bzero(&tmp, sizeof(tmp));
tmp.plugin= plugin;
tmp.name.str= (char *)plugin->name;
tmp.name.length= strlen(plugin->name);
tmp.state= 0;
free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE));
- if (test_plugin_options(&tmp_root, &tmp, argc, argv, def_enabled))
+ if (test_plugin_options(&tmp_root, &tmp, argc, argv))
tmp.state= PLUGIN_IS_DISABLED;
else
tmp.state= PLUGIN_IS_UNINITIALIZED;
@@ -1227,6 +1249,8 @@ int plugin_init(int *argc, char **argv, int flags)
while ((plugin_ptr= *(--reap)))
{
pthread_mutex_unlock(&LOCK_plugin);
+ if (plugin_ptr->is_mandatory)
+ reaped_mandatory_plugin= TRUE;
plugin_deinitialize(plugin_ptr, true);
pthread_mutex_lock(&LOCK_plugin);
plugin_del(plugin_ptr);
@@ -1234,6 +1258,8 @@ int plugin_init(int *argc, char **argv, int flags)
pthread_mutex_unlock(&LOCK_plugin);
my_afree(reap);
+ if (reaped_mandatory_plugin)
+ goto err;
end:
free_root(&tmp_root, MYF(0));
@@ -1299,7 +1325,7 @@ bool plugin_register_builtin(THD *thd, struct st_mysql_plugin *plugin)
pthread_mutex_lock(&LOCK_plugin);
rw_wrlock(&LOCK_system_variables_hash);
- if (test_plugin_options(thd->mem_root, &tmp, &dummy_argc, NULL, true))
+ if (test_plugin_options(thd->mem_root, &tmp, &dummy_argc, NULL))
goto end;
tmp.state= PLUGIN_IS_UNINITIALIZED;
if ((result= register_builtin(plugin, &tmp, &ptr)))
@@ -2889,59 +2915,78 @@ my_bool get_one_plugin_option(int optid __attribute__((unused)),
}
+/**
+ Creates a set of my_option objects associated with a specified plugin-
+ handle.
+
+ @param mem_root Memory allocator to be used.
+ @param tmp A pointer to a plugin handle
+ @param[out] options A pointer to a pre-allocated static array
+
+ The set is stored in the pre-allocated static array supplied to the function.
+ The size of the array is calculated as (number_of_plugin_varaibles*2+3). The
+ reason is that each option can have a prefix '--plugin-' in addtion to the
+ shorter form '--&lt;plugin-name&gt;'. There is also space allocated for
+ terminating NULL pointers.
+
+ @return
+ @retval -1 An error occurred
+ @retval 0 Success
+*/
+
static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
- my_option *options, my_bool **enabled,
- bool can_disable)
+ my_option *options)
{
const char *plugin_name= tmp->plugin->name;
- uint namelen= strlen(plugin_name), optnamelen;
- uint buffer_length= namelen * 4 + (can_disable ? 75 : 10);
- char *name= (char*) alloc_root(mem_root, buffer_length) + 1;
- char *optname, *p;
+ const LEX_STRING plugin_dash = { C_STRING_WITH_LEN("plugin-") };
+ uint plugin_name_len= strlen(plugin_name);
+ uint optnamelen;
+ const int max_comment_len= 180;
+ char *comment= (char *) alloc_root(mem_root, max_comment_len + 1);
+ char *optname;
+
int index= 0, offset= 0;
st_mysql_sys_var *opt, **plugin_option;
st_bookmark *v;
+
+ /** Used to circumvent the const attribute on my_option::name */
+ char *plugin_name_ptr, *plugin_name_with_prefix_ptr;
+
DBUG_ENTER("construct_options");
- DBUG_PRINT("plugin", ("plugin: '%s' enabled: %d can_disable: %d",
- plugin_name, **enabled, can_disable));
+ options[0].name= plugin_name_ptr= (char*) alloc_root(mem_root,
+ plugin_name_len + 1);
+ strcpy(plugin_name_ptr, plugin_name);
+ my_casedn_str(&my_charset_latin1, plugin_name_ptr);
+ convert_underscore_to_dash(plugin_name_ptr, plugin_name_len);
/* support --skip-plugin-foo syntax */
- memcpy(name, plugin_name, namelen + 1);
- my_casedn_str(&my_charset_latin1, name);
- strxmov(name + namelen + 1, "plugin-", name, NullS);
- /* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */
-
- for (p= name + namelen*2 + 8; p > name; p--)
- if (*p == '_')
- *p= '-';
+ options[1].name= plugin_name_with_prefix_ptr= (char*) alloc_root(mem_root,
+ plugin_name_len +
+ plugin_dash.length + 1);
+ strxmov(plugin_name_with_prefix_ptr, plugin_dash.str, options[0].name, NullS);
- if (can_disable)
- {
- strxmov(name + namelen*2 + 10, "Enable ", plugin_name, " plugin. "
- "Disable with --skip-", name," (will save memory).", NullS);
- /*
- Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
- 20 + namelen + 20 + 1 == namelen * 4 + 67.
- */
+ options[0].id= options[1].id= 256; /* must be >255. dup id ok */
+ options[0].var_type= options[1].var_type= GET_ENUM;
+ options[0].arg_type= options[1].arg_type= OPT_ARG;
+ options[0].def_value= options[1].def_value= 1; /* ON */
+ options[0].typelib= options[1].typelib= &global_plugin_typelib;
- options[0].comment= name + namelen*2 + 10;
- }
+ strxnmov(comment, max_comment_len, "Enable or disable ", plugin_name,
+ " plugin. Possible values are ON, OFF, FORCE (don't start "
+ "if the plugin fails to load).", NullS);
+ options[0].comment= comment;
/*
- NOTE: 'name' is one char above the allocated buffer!
- NOTE: This code assumes that 'my_bool' and 'char' are of same size.
+ Allocate temporary space for the value of the tristate.
+ This option will have a limited lifetime and is not used beyond
+ server initialization.
+ GET_ENUM value is an integer.
*/
- *((my_bool *)(name -1))= **enabled;
- *enabled= (my_bool *)(name - 1);
-
+ options[0].value= options[1].value= (uchar **)alloc_root(mem_root,
+ sizeof(int));
+ *((uint*) options[0].value)= *((uint*) options[1].value)=
+ (uint) options[0].def_value;
- options[1].name= (options[0].name= name) + namelen + 1;
- options[0].id= options[1].id= 256; /* must be >255. dup id ok */
- options[0].var_type= options[1].var_type= GET_BOOL;
- options[0].arg_type= options[1].arg_type= NO_ARG;
- options[0].def_value= options[1].def_value= **enabled;
- options[0].value= options[0].u_max_value=
- options[1].value= options[1].u_max_value= (uchar**) (name - 1);
options+= 2;
/*
@@ -2955,7 +3000,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
opt= *plugin_option;
if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
continue;
- if (!(register_var(name, opt->name, opt->flags)))
+ if (!(register_var(plugin_name_ptr, opt->name, opt->flags)))
continue;
switch (opt->flags & PLUGIN_VAR_TYPEMASK) {
case PLUGIN_VAR_BOOL:
@@ -3020,7 +3065,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
if (!opt->update)
{
opt->update= update_func_str;
- if (!(opt->flags & PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY))
+ if (!(opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)))
{
opt->flags|= PLUGIN_VAR_READONLY;
sql_print_warning("Server variable %s of plugin %s was forced "
@@ -3062,14 +3107,14 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
{
optnamelen= strlen(opt->name);
- optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
- strxmov(optname, name, "-", opt->name, NullS);
- optnamelen= namelen + optnamelen + 1;
+ optname= (char*) alloc_root(mem_root, plugin_name_len + optnamelen + 2);
+ strxmov(optname, plugin_name_ptr, "-", opt->name, NullS);
+ optnamelen= plugin_name_len + optnamelen + 1;
}
else
{
/* this should not fail because register_var should create entry */
- if (!(v= find_bookmark(name, opt->name, opt->flags)))
+ if (!(v= find_bookmark(plugin_name_ptr, opt->name, opt->flags)))
{
sql_print_error("Thread local variable '%s' not allocated "
"in plugin '%s'.", opt->name, plugin_name);
@@ -3085,10 +3130,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
(optnamelen= v->name_len) + 1);
}
- /* convert '_' to '-' */
- for (p= optname; *p; p++)
- if (*p == '_')
- *p= '-';
+ convert_underscore_to_dash(optname, optnamelen);
options->name= optname;
options->comment= opt->comment;
@@ -3103,10 +3145,13 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
else
options->value= options->u_max_value= *(uchar***) (opt + 1);
+ char *option_name_ptr;
options[1]= options[0];
- options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
- options[1].comment= 0; // hidden
- strxmov(p, "plugin-", optname, NullS);
+ options[1].name= option_name_ptr= (char*) alloc_root(mem_root,
+ plugin_dash.length +
+ optnamelen + 1);
+ options[1].comment= 0; /* Hidden from the help text */
+ strxmov(option_name_ptr, plugin_dash.str, optname, NullS);
options+= 2;
}
@@ -3120,55 +3165,57 @@ static my_option *construct_help_options(MEM_ROOT *mem_root,
{
st_mysql_sys_var **opt;
my_option *opts;
- my_bool dummy, can_disable;
- my_bool *dummy2= &dummy;
uint count= EXTRA_OPTIONS;
DBUG_ENTER("construct_help_options");
- for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2);
+ for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2)
+ ;
if (!(opts= (my_option*) alloc_root(mem_root, sizeof(my_option) * count)))
DBUG_RETURN(NULL);
bzero(opts, sizeof(my_option) * count);
- dummy= TRUE; /* plugin is enabled. */
-
- can_disable=
- my_strcasecmp(&my_charset_latin1, p->name.str, "MyISAM") &&
- my_strcasecmp(&my_charset_latin1, p->name.str, "MEMORY");
-
- if (construct_options(mem_root, p, opts, &dummy2, can_disable))
+ if (construct_options(mem_root, p, opts))
DBUG_RETURN(NULL);
DBUG_RETURN(opts);
}
-/*
- SYNOPSIS
- test_plugin_options()
- tmp_root temporary scratch space
- plugin internal plugin structure
- argc user supplied arguments
- argv user supplied arguments
- default_enabled default plugin enable status
- RETURNS:
- 0 SUCCESS - plugin should be enabled/loaded
- NOTE:
- Requires that a write-lock is held on LOCK_system_variables_hash
+/**
+ Create and register system variables supplied from the plugin and
+ assigns initial values from corresponding command line arguments.
+
+ @param tmp_root Temporary scratch space
+ @param[out] plugin Internal plugin structure
+ @param argc Number of command line arguments
+ @param argv Command line argument vector
+
+ The plugin will be updated with a policy on how to handle errors during
+ initialization.
+
+ @note Requires that a write-lock is held on LOCK_system_variables_hash
+
+ @return How initialization of the plugin should be handled.
+ @retval 0 Initialization should proceed.
+ @retval 1 Plugin is disabled.
+ @retval -1 An error has occurred.
*/
+
static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp,
- int *argc, char **argv, my_bool default_enabled)
+ int *argc, char **argv)
{
struct sys_var_chain chain= { NULL, NULL };
- my_bool enabled_saved= default_enabled, can_disable;
- my_bool *enabled= &default_enabled;
+ my_bool can_disable;
+ bool disable_plugin;
+ enum_plugin_load_policy plugin_load_policy= PLUGIN_ON;
+
MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ?
&tmp->mem_root : &plugin_mem_root;
st_mysql_sys_var **opt;
my_option *opts= NULL;
- char *p, *varname;
+ char *varname;
int error;
st_mysql_sys_var *o;
sys_var *v;
@@ -3177,13 +3224,17 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp,
DBUG_ENTER("test_plugin_options");
DBUG_ASSERT(tmp->plugin && tmp->name.str);
+ /*
+ The 'federated' and 'ndbcluster' storage engines are always disabled by
+ default.
+ */
+ if (!(my_strcasecmp(&my_charset_latin1, tmp->name.str, "federated") &&
+ my_strcasecmp(&my_charset_latin1, tmp->name.str, "ndbcluster")))
+ plugin_load_policy= PLUGIN_OFF;
+
for (opt= tmp->plugin->system_vars; opt && *opt; opt++)
count+= 2; /* --{plugin}-{optname} and --plugin-{plugin}-{optname} */
- can_disable=
- my_strcasecmp(&my_charset_latin1, tmp->name.str, "MyISAM") &&
- my_strcasecmp(&my_charset_latin1, tmp->name.str, "MEMORY");
-
if (count > EXTRA_OPTIONS || (*argc > 1))
{
if (!(opts= (my_option*) alloc_root(tmp_root, sizeof(my_option) * count)))
@@ -3193,12 +3244,18 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp,
}
bzero(opts, sizeof(my_option) * count);
- if (construct_options(tmp_root, tmp, opts, &enabled, can_disable))
+ if (construct_options(tmp_root, tmp, opts))
{
sql_print_error("Bad options for plugin '%s'.", tmp->name.str);
DBUG_RETURN(-1);
}
+ /*
+ We adjust the default value to account for the hardcoded exceptions
+ we have set for the federated and ndbcluster storage engines.
+ */
+ opts[0].def_value= opts[1].def_value= (int)plugin_load_policy;
+
error= handle_options(argc, &argv, opts, get_one_plugin_option);
(*argc)++; /* add back one for the program name */
@@ -3208,64 +3265,79 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp,
tmp->name.str);
goto err;
}
+ /*
+ Set plugin loading policy from option value. First element in the option
+ list is always the <plugin name> option value.
+ */
+ plugin_load_policy= (enum_plugin_load_policy)*(uint*)opts[0].value;
}
- if (!*enabled && !can_disable)
+ disable_plugin= (plugin_load_policy == PLUGIN_OFF);
+ /*
+ The 'MyISAM' and 'Memory' storage engines currently can't be disabled.
+ */
+ can_disable=
+ my_strcasecmp(&my_charset_latin1, tmp->name.str, "MyISAM") &&
+ my_strcasecmp(&my_charset_latin1, tmp->name.str, "MEMORY");
+
+ tmp->is_mandatory= (plugin_load_policy == PLUGIN_FORCE) || !can_disable;
+
+ if (disable_plugin && !can_disable)
{
sql_print_warning("Plugin '%s' cannot be disabled", tmp->name.str);
- *enabled= TRUE;
+ disable_plugin= FALSE;
}
- error= 1;
+ /*
+ If the plugin is disabled it should not be initialized.
+ */
+ if (disable_plugin)
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_information("Plugin '%s' is disabled.",
+ tmp->name.str);
+ if (opts)
+ my_cleanup_options(opts);
+ DBUG_RETURN(1);
+ }
- if (*enabled)
+ error= 1;
+ for (opt= tmp->plugin->system_vars; opt && *opt; opt++)
{
- for (opt= tmp->plugin->system_vars; opt && *opt; opt++)
+ if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
+ continue;
+ if ((var= find_bookmark(tmp->name.str, o->name, o->flags)))
+ v= new (mem_root) sys_var_pluginvar(var->key + 1, o);
+ else
{
- if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
- continue;
-
- if ((var= find_bookmark(tmp->name.str, o->name, o->flags)))
- v= new (mem_root) sys_var_pluginvar(var->key + 1, o);
- else
- {
- len= tmp->name.length + strlen(o->name) + 2;
- varname= (char*) alloc_root(mem_root, len);
- strxmov(varname, tmp->name.str, "-", o->name, NullS);
- my_casedn_str(&my_charset_latin1, varname);
-
- for (p= varname; *p; p++)
- if (*p == '-')
- *p= '_';
-
- v= new (mem_root) sys_var_pluginvar(varname, o);
- }
- DBUG_ASSERT(v); /* check that an object was actually constructed */
-
- /*
- Add to the chain of variables.
- Done like this for easier debugging so that the
- pointer to v is not lost on optimized builds.
- */
- v->chain_sys_var(&chain);
+ len= tmp->name.length + strlen(o->name) + 2;
+ varname= (char*) alloc_root(mem_root, len);
+ strxmov(varname, tmp->name.str, "-", o->name, NullS);
+ my_casedn_str(&my_charset_latin1, varname);
+ convert_dash_to_underscore(varname, len-1);
+ v= new (mem_root) sys_var_pluginvar(varname, o);
}
- if (chain.first)
+ DBUG_ASSERT(v); /* check that an object was actually constructed */
+ /*
+ Add to the chain of variables.
+ Done like this for easier debugging so that the
+ pointer to v is not lost on optimized builds.
+ */
+ v->chain_sys_var(&chain);
+ } /* end for */
+ if (chain.first)
+ {
+ chain.last->next = NULL;
+ if (mysql_add_sys_var_chain(chain.first, NULL))
{
- chain.last->next = NULL;
- if (mysql_add_sys_var_chain(chain.first, NULL))
- {
- sql_print_error("Plugin '%s' has conflicting system variables",
- tmp->name.str);
- goto err;
- }
- tmp->system_vars= chain.first;
+ sql_print_error("Plugin '%s' has conflicting system variables",
+ tmp->name.str);
+ goto err;
}
- DBUG_RETURN(0);
+ tmp->system_vars= chain.first;
}
-
- if (enabled_saved && global_system_variables.log_warnings)
- sql_print_information("Plugin '%s' disabled by command line option",
- tmp->name.str);
+ DBUG_RETURN(0);
+
err:
if (opts)
my_cleanup_options(opts);
diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h
index 8ae38d58845..004d0d5abb7 100644
--- a/sql/sql_plugin.h
+++ b/sql/sql_plugin.h
@@ -79,6 +79,7 @@ struct st_plugin_int
void *data; /* plugin type specific, e.g. handlerton */
MEM_ROOT mem_root; /* memory for dynamic plugin structures */
sys_var *system_vars; /* server variables for this plugin */
+ bool is_mandatory; /* If true then plugin must not fail to load */
};
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index cd11b6d4c24..cc7ea75dbbf 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2461,6 +2461,9 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
stmt->execute_loop(&expanded_query, open_cursor, packet, packet_end);
+ /* Close connection socket; for use with client testing (Bug#43560). */
+ DBUG_EXECUTE_IF("close_conn_after_stmt_execute", vio_close(thd->net.vio););
+
DBUG_VOID_RETURN;
}
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index d4331b12cd4..7cc9130cc4a 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -261,6 +261,8 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name,
old_alias= ren_table->table_name;
new_alias= new_table_name;
}
+ DBUG_ASSERT(new_alias);
+
build_table_filename(name, sizeof(name),
new_db, new_alias, reg_ext, 0);
if (!access(name,F_OK))
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 21d22e250ec..fad533986d6 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -2248,6 +2248,14 @@ JOIN::destroy()
cond_equal= 0;
cleanup(1);
+ /* Cleanup items referencing temporary table columns */
+ if (!tmp_all_fields3.is_empty())
+ {
+ List_iterator_fast<Item> it(tmp_all_fields3);
+ Item *item;
+ while ((item= it++))
+ item->cleanup();
+ }
if (exec_tmp_table1)
free_tmp_table(thd, exec_tmp_table1);
if (exec_tmp_table2)
@@ -7084,15 +7092,17 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
if (!(result->send_fields(fields,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)))
{
+ bool send_error= FALSE;
if (send_row)
{
List_iterator_fast<Item> it(fields);
Item *item;
while ((item= it++))
item->no_rows_in_result();
- result->send_data(fields);
+ send_error= result->send_data(fields);
}
- result->send_eof(); // Should be safe
+ if (!send_error)
+ result->send_eof(); // Should be safe
}
/* Update results for FOUND_ROWS */
join->thd->limit_found_rows= join->thd->examined_row_count= 0;
@@ -13845,7 +13855,7 @@ SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length,
pos->field= ((Item_sum*) item)->get_tmp_table_field();
else if (item->type() == Item::COPY_STR_ITEM)
{ // Blob patch
- pos->item= ((Item_copy_string*) item)->item;
+ pos->item= ((Item_copy*) item)->get_item();
}
else
pos->item= *order->item;
@@ -14916,7 +14926,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
pos= item;
if (item->field->flags & BLOB_FLAG)
{
- if (!(pos= new Item_copy_string(pos)))
+ if (!(pos= Item_copy::create(pos)))
goto err;
/*
Item_copy_string::copy for function can call
@@ -14970,7 +14980,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
on how the value is to be used: In some cases this may be an
argument in a group function, like: IF(ISNULL(col),0,COUNT(*))
*/
- if (!(pos=new Item_copy_string(pos)))
+ if (!(pos= Item_copy::create(pos)))
goto err;
if (i < border) // HAVING, ORDER and GROUP BY
{
@@ -15023,8 +15033,8 @@ copy_fields(TMP_TABLE_PARAM *param)
(*ptr->do_copy)(ptr);
List_iterator_fast<Item> it(param->copy_funcs);
- Item_copy_string *item;
- while ((item = (Item_copy_string*) it++))
+ Item_copy *item;
+ while ((item = (Item_copy*) it++))
item->copy();
}
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 1dd7b55d136..61731f3b984 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -328,6 +328,9 @@ bool String::copy(const char *str, uint32 arg_length,
CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, uint *errors)
{
uint32 offset;
+
+ DBUG_ASSERT(str != Ptr);
+
if (!needs_conversion(arg_length, from_cs, to_cs, &offset))
{
*errors= 0;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 29d43155778..5397128855a 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -3126,7 +3126,7 @@ static bool prepare_blob_field(THD *thd, Create_field *sql_field)
}
sql_field->sql_type= MYSQL_TYPE_BLOB;
sql_field->flags|= BLOB_FLAG;
- sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name,
+ my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_AUTO_CONVERT), sql_field->field_name,
(sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR",
(sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
@@ -6140,6 +6140,20 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (frm_type == FRMTYPE_VIEW && !(alter_info->flags & ~ALTER_RENAME))
{
/*
+ The following branch handles "ALTER VIEW v1 /no arguments/;"
+ This feature is not documented one.
+ However, before "OPTIMIZE TABLE t1;" was implemented,
+ ALTER TABLE with no alter_specifications was used to force-rebuild
+ the table. That's why this grammar is allowed. That's why we ignore
+ it for views. So just do nothing in such a case.
+ */
+ if (!new_name)
+ {
+ my_ok(thd);
+ DBUG_RETURN(FALSE);
+ }
+
+ /*
Avoid problems with a rename on a table that we have locked or
if the user is trying to to do this in a transcation context
*/
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index fd3036e3d80..cbf94ad7181 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -653,10 +653,22 @@ bool st_select_lex_unit::cleanup()
join->tables= 0;
}
error|= fake_select_lex->cleanup();
- if (fake_select_lex->order_list.elements)
+ /*
+ There are two cases when we should clean order items:
+ 1. UNION with SELECTs which all enclosed into braces
+ in this case global_parameters == fake_select_lex
+ 2. UNION where last SELECT is not enclosed into braces
+ in this case global_parameters == 'last select'
+ So we should use global_parameters->order_list for
+ proper order list clean up.
+ Note: global_parameters and fake_select_lex are always
+ initialized for UNION
+ */
+ DBUG_ASSERT(global_parameters);
+ if (global_parameters->order_list.elements)
{
ORDER *ord;
- for (ord= (ORDER*)fake_select_lex->order_list.first; ord; ord= ord->next)
+ for (ord= (ORDER*)global_parameters->order_list.first; ord; ord= ord->next)
(*ord->item)->cleanup();
}
}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index b3bd5d0bc57..dcccf7f147f 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -818,7 +818,7 @@ int mysql_update(THD *thd,
if (error < 0)
{
char buff[STRING_BUFFER_USUAL_SIZE];
- sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
+ my_snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
(ulong) thd->cuted_fields);
thd->row_count_func=
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
@@ -1031,7 +1031,6 @@ reopen_tables:
DBUG_RETURN(TRUE);
}
- table->mark_columns_needed_for_update();
DBUG_PRINT("info",("setting table `%s` for update", tl->alias));
/*
If table will be updated we should not downgrade lock for it and
@@ -1275,12 +1274,40 @@ int multi_update::prepare(List<Item> &not_used_values,
}
/*
+ We gather the set of columns read during evaluation of SET expression in
+ TABLE::tmp_set by pointing TABLE::read_set to it and then restore it after
+ setup_fields().
+ */
+ for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf)
+ {
+ TABLE *table= table_ref->table;
+ if (tables_to_update & table->map)
+ {
+ DBUG_ASSERT(table->read_set == &table->def_read_set);
+ table->read_set= &table->tmp_set;
+ bitmap_clear_all(table->read_set);
+ }
+ }
+
+ /*
We have to check values after setup_tables to get covering_keys right in
reference tables
*/
- if (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0))
- DBUG_RETURN(1);
+ int error= setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0);
+
+ for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf)
+ {
+ TABLE *table= table_ref->table;
+ if (tables_to_update & table->map)
+ {
+ table->read_set= &table->def_read_set;
+ bitmap_union(table->read_set, &table->tmp_set);
+ }
+ }
+
+ if (error)
+ DBUG_RETURN(1);
/*
Save tables beeing updated in update_tables
@@ -1375,6 +1402,8 @@ int multi_update::prepare(List<Item> &not_used_values,
a row in this table will never be read twice. This is true under
the following conditions:
+ - No column is both written to and read in SET expressions.
+
- We are doing a table scan and the data is in a separate file (MyISAM) or
if we don't update a clustered key.
@@ -1389,6 +1418,9 @@ int multi_update::prepare(List<Item> &not_used_values,
WARNING
This code is a bit dependent of how make_join_readinfo() works.
+ The field table->tmp_set is used for keeping track of which fields are
+ read during evaluation of the SET expression. See multi_update::prepare.
+
RETURN
0 Not safe to update
1 Safe to update
@@ -1409,6 +1441,8 @@ static bool safe_update_on_fly(THD *thd, JOIN_TAB *join_tab,
case JT_REF_OR_NULL:
return !is_key_used(table, join_tab->ref.key, table->write_set);
case JT_ALL:
+ if (bitmap_is_overlapping(&table->tmp_set, table->write_set))
+ return FALSE;
/* If range search on index */
if (join_tab->quick)
return !join_tab->quick->is_keys_used(table->write_set);
@@ -1464,17 +1498,18 @@ multi_update::initialize_tables(JOIN *join)
ORDER group;
TMP_TABLE_PARAM *tmp_param;
- table->mark_columns_needed_for_update();
if (ignore)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
if (table == main_table) // First table in join
{
if (safe_update_on_fly(thd, join->join_tab, table_ref, all_tables))
{
- table_to_update= main_table; // Update table on the fly
+ table->mark_columns_needed_for_update();
+ table_to_update= table; // Update table on the fly
continue;
}
}
+ table->mark_columns_needed_for_update();
table->prepare_for_position();
/*
@@ -2066,8 +2101,8 @@ bool multi_update::send_eof()
id= thd->arg_of_last_insert_id_function ?
thd->first_successful_insert_id_in_prev_stmt : 0;
- sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
- (ulong) thd->cuted_fields);
+ my_snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO),
+ (ulong) found, (ulong) updated, (ulong) thd->cuted_fields);
thd->row_count_func=
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
::my_ok(thd, (ulong) thd->row_count_func, id, buff);
diff --git a/sql/table.cc b/sql/table.cc
index d24ee4c6a27..066bbc953fa 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -779,7 +779,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
strpos=disk_buff+6;
if (!(rec_per_key= (ulong*) alloc_root(&share->mem_root,
- sizeof(ulong*)*key_parts)))
+ sizeof(ulong)*key_parts)))
goto err;
for (i=0 ; i < keys ; i++, keyinfo++)
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 51293184ad8..68a352e4a44 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -37,8 +37,7 @@ static bool pack_header(uchar *forminfo,enum legacy_db_type table_type,
List<Create_field> &create_fields,
uint info_length, uint screens, uint table_options,
ulong data_offset, handler *file);
-static uint get_interval_id(uint *int_count,List<Create_field> &create_fields,
- Create_field *last_field);
+static uint get_interval_id(uint *,List<Create_field> &, Create_field *);
static bool pack_fields(File file, List<Create_field> &create_fields,
ulong data_offset);
static bool make_empty_rec(THD *thd, int file, enum legacy_db_type table_type,