Commit f57dffe4 authored by konstantin@mysql.com's avatar konstantin@mysql.com

A fix and a test case for Bug#14410 "Crash in Enum or Set type in

CREATE TABLE and PS/SP": make sure that 'typelib' object for
ENUM values and 'Item_string' object for DEFAULT clause are 
created in the statement memory root.
parent 6d5ef98a
...@@ -699,3 +699,22 @@ execute stmt; ...@@ -699,3 +699,22 @@ execute stmt;
@@tx_isolation @@tx_isolation
REPEATABLE-READ REPEATABLE-READ
deallocate prepare stmt; deallocate prepare stmt;
prepare stmt from "create temporary table t1 (letter enum('','a','b','c')
not null)";
execute stmt;
drop table t1;
execute stmt;
drop table t1;
execute stmt;
drop table t1;
set names latin1;
prepare stmt from "create table t1 (a enum('test') default 'test')
character set utf8";
execute stmt;
drop table t1;
execute stmt;
drop table t1;
execute stmt;
drop table t1;
set names default;
deallocate prepare stmt;
...@@ -718,4 +718,33 @@ set @@tx_isolation=default; ...@@ -718,4 +718,33 @@ set @@tx_isolation=default;
execute stmt; execute stmt;
deallocate prepare stmt; deallocate prepare stmt;
#
# Bug#14410 "Crash in Enum or Set type in CREATE TABLE and PS/SP"
#
# Part I. Make sure the typelib for ENUM is created in the statement memory
# root.
prepare stmt from "create temporary table t1 (letter enum('','a','b','c')
not null)";
execute stmt;
drop table t1;
execute stmt;
drop table t1;
execute stmt;
drop table t1;
# Part II. Make sure that when the default value is converted to UTF-8,
# the new item is # created in the statement memory root.
set names latin1;
prepare stmt from "create table t1 (a enum('test') default 'test')
character set utf8";
execute stmt;
drop table t1;
execute stmt;
drop table t1;
execute stmt;
drop table t1;
# Cleanup
set names default;
deallocate prepare stmt;
# End of 4.1 tests # End of 4.1 tests
...@@ -1119,7 +1119,7 @@ int calc_weekday(long daynr,bool sunday_first_day_of_week); ...@@ -1119,7 +1119,7 @@ int calc_weekday(long daynr,bool sunday_first_day_of_week);
uint calc_week(TIME *l_time, uint week_behaviour, uint *year); uint calc_week(TIME *l_time, uint week_behaviour, uint *year);
void find_date(char *pos,uint *vek,uint flag); void find_date(char *pos,uint *vek,uint flag);
TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end); TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end);
TYPELIB *typelib(List<String> &strings); TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings);
ulong get_form_pos(File file, uchar *head, TYPELIB *save_names); ulong get_form_pos(File file, uchar *head, TYPELIB *save_names);
ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames, ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames,
const char *newname); const char *newname);
......
...@@ -524,7 +524,14 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -524,7 +524,14 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
*/ */
if (!interval) if (!interval)
{ {
interval= sql_field->interval= typelib(sql_field->interval_list); /*
Create the typelib in prepared statement memory if we're
executing one.
*/
MEM_ROOT *stmt_root= thd->current_arena->mem_root;
interval= sql_field->interval= typelib(stmt_root,
sql_field->interval_list);
List_iterator<String> it(sql_field->interval_list); List_iterator<String> it(sql_field->interval_list);
String conv, *tmp; String conv, *tmp;
for (uint i= 0; (tmp= it++); i++) for (uint i= 0; (tmp= it++); i++)
...@@ -534,7 +541,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -534,7 +541,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
{ {
uint cnv_errs; uint cnv_errs;
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs); conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
char *buf= (char*) sql_alloc(conv.length()+1); char *buf= (char*) alloc_root(stmt_root, conv.length()+1);
memcpy(buf, conv.ptr(), conv.length()); memcpy(buf, conv.ptr(), conv.length());
buf[conv.length()]= '\0'; buf[conv.length()]= '\0';
interval->type_names[i]= buf; interval->type_names[i]= buf;
...@@ -556,8 +563,22 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -556,8 +563,22 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
*/ */
if (sql_field->def && cs != sql_field->def->collation.collation) if (sql_field->def && cs != sql_field->def->collation.collation)
{ {
if (!(sql_field->def= Item_arena backup_arena;
sql_field->def->safe_charset_converter(cs))) bool need_to_change_arena=
!thd->current_arena->is_conventional_execution();
if (need_to_change_arena)
{
/* Asser that we don't do that at every PS execute */
DBUG_ASSERT(thd->current_arena->is_first_stmt_execute());
thd->set_n_backup_item_arena(thd->current_arena, &backup_arena);
}
sql_field->def= sql_field->def->safe_charset_converter(cs);
if (need_to_change_arena)
thd->restore_backup_item_arena(thd->current_arena, &backup_arena);
if (! sql_field->def)
{ {
/* Could not convert */ /* Could not convert */
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
......
...@@ -1099,15 +1099,15 @@ fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types, ...@@ -1099,15 +1099,15 @@ fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types,
} /* fix_type_pointers */ } /* fix_type_pointers */
TYPELIB *typelib(List<String> &strings) TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings)
{ {
TYPELIB *result=(TYPELIB*) sql_alloc(sizeof(TYPELIB)); TYPELIB *result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB));
if (!result) if (!result)
return 0; return 0;
result->count=strings.elements; result->count=strings.elements;
result->name=""; result->name="";
uint nbytes= (sizeof(char*) + sizeof(uint)) * (result->count + 1); uint nbytes= (sizeof(char*) + sizeof(uint)) * (result->count + 1);
if (!(result->type_names= (const char**) sql_alloc(nbytes))) if (!(result->type_names= (const char**) alloc_root(mem_root, nbytes)))
return 0; return 0;
result->type_lengths= (uint*) (result->type_names + result->count + 1); result->type_lengths= (uint*) (result->type_names + result->count + 1);
List_iterator<String> it(strings); List_iterator<String> it(strings);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment