Commit 9bf92ed6 authored by unknown's avatar unknown

Bug#9102 - Stored proccedures: function which returns blob causes crash

  Initialization of fields for sp return type was not complete.


mysql-test/r/sp.result:
  Bug#9102
    Test for bug
mysql-test/t/sp.test:
  Bug#9102
    Test for bug
sql/mysql_priv.h:
  Bug#9102
    new function: sp_prepare_create_field()
sql/sp_head.cc:
  Strip spaces and do charset conversion for sp function typelibs
sql/sql_table.cc:
  Bug#9102
    new function - sp_prepare_create_field()
    prepares create_field in similar way to mysql_prepare_table()
sql/sql_yacc.yy:
  Bug#9102
parent d0eecb39
...@@ -2958,4 +2958,10 @@ select @x| ...@@ -2958,4 +2958,10 @@ select @x|
set global query_cache_size = @qcs1| set global query_cache_size = @qcs1|
delete from t1| delete from t1|
drop function bug9902| drop function bug9902|
drop function if exists bug9102|
create function bug9102() returns blob return 'a'|
select bug9102();
drop function bug9102|
bug9102()
a
drop table t1,t2; drop table t1,t2;
...@@ -3627,6 +3627,15 @@ set global query_cache_size = @qcs1| ...@@ -3627,6 +3627,15 @@ set global query_cache_size = @qcs1|
delete from t1| delete from t1|
drop function bug9902| drop function bug9902|
#
# BUG#9102: New bug synopsis
#
--disable_warnings
drop function if exists bug9102|
--enable_warnings
create function bug9102() returns blob return 'a'|
select bug9102();
drop function bug9102|
# #
# BUG#NNNN: New bug synopsis # BUG#NNNN: New bug synopsis
......
...@@ -647,6 +647,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, ...@@ -647,6 +647,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item ***copy_func, Field **from_field, Item ***copy_func, Field **from_field,
bool group, bool modify_item, bool group, bool modify_item,
uint convert_blob_length); uint convert_blob_length);
void sp_prepare_create_field(THD *thd, create_field *sql_field);
int prepare_create_field(create_field *sql_field, int prepare_create_field(create_field *sql_field,
uint *blob_columns, uint *blob_columns,
int *timestamps, int *timestamps_with_niladic, int *timestamps, int *timestamps_with_niladic,
......
...@@ -370,6 +370,7 @@ TYPELIB * ...@@ -370,6 +370,7 @@ TYPELIB *
sp_head::create_typelib(List<String> *src) sp_head::create_typelib(List<String> *src)
{ {
TYPELIB *result= NULL; TYPELIB *result= NULL;
CHARSET_INFO *cs= m_returns_cs;
DBUG_ENTER("sp_head::clone_typelib"); DBUG_ENTER("sp_head::clone_typelib");
if (src->elements) if (src->elements)
{ {
...@@ -380,8 +381,31 @@ sp_head::create_typelib(List<String> *src) ...@@ -380,8 +381,31 @@ sp_head::create_typelib(List<String> *src)
alloc_root(mem_root,sizeof(char *)*(result->count+1)))) alloc_root(mem_root,sizeof(char *)*(result->count+1))))
return 0; return 0;
List_iterator<String> it(*src); List_iterator<String> it(*src);
String conv, *tmp;
uint32 dummy;
for (uint i=0; i<result->count; i++) for (uint i=0; i<result->count; i++)
result->type_names[i]= strdup_root(mem_root, (it++)->c_ptr()); {
tmp = it++;
if (String::needs_conversion(tmp->length(), tmp->charset(),
cs, &dummy))
{
uint cnv_errs;
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
char *buf= (char*) alloc_root(mem_root,conv.length()+1);
memcpy(buf, conv.ptr(), conv.length());
buf[conv.length()]= '\0';
result->type_names[i]= buf;
result->type_lengths[i]= conv.length();
}
else
result->type_names[i]= strdup_root(mem_root, tmp->c_ptr());
// Strip trailing spaces.
uint lengthsp= cs->cset->lengthsp(cs, result->type_names[i],
result->type_lengths[i]);
result->type_lengths[i]= lengthsp;
((uchar *)result->type_names[i])[lengthsp]= '\0';
}
result->type_names[result->count]= 0; result->type_names[result->count]= 0;
} }
return result; return result;
......
...@@ -1351,6 +1351,77 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -1351,6 +1351,77 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
} }
/*
Preparation of create_field for SP function return values.
Based on code used in the inner loop of mysql_prepare_table() above
SYNOPSIS
sp_prepare_create_field()
thd Thread object
sql_field Field to prepare
DESCRIPTION
Prepares the field structures for field creation.
*/
void sp_prepare_create_field(THD *thd, create_field *sql_field)
{
if (sql_field->sql_type == FIELD_TYPE_SET ||
sql_field->sql_type == FIELD_TYPE_ENUM)
{
uint32 field_length, dummy;
if (sql_field->sql_type == FIELD_TYPE_SET)
{
calculate_interval_lengths(sql_field->charset,
sql_field->interval, &dummy,
&field_length);
sql_field->length= field_length +
(sql_field->interval->count - 1);
}
else /* FIELD_TYPE_ENUM */
{
calculate_interval_lengths(sql_field->charset,
sql_field->interval,
&field_length, &dummy);
sql_field->length= field_length;
}
set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
}
if (sql_field->sql_type == FIELD_TYPE_BIT)
{
sql_field->pack_flag= FIELDFLAG_NUMBER |
FIELDFLAG_TREAT_BIT_AS_CHAR;
}
sql_field->create_length_to_internal_length();
if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
!(sql_field->flags & BLOB_FLAG))
{
/* Convert long VARCHAR columns to TEXT or BLOB */
char warn_buff[MYSQL_ERRMSG_SIZE];
sql_field->sql_type= FIELD_TYPE_BLOB;
sql_field->flags|= BLOB_FLAG;
sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name,
"VARCHAR",
(sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
warn_buff);
}
if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
{
if (sql_field->sql_type == FIELD_TYPE_BLOB)
{
/* The user has given a length to the blob column */
sql_field->sql_type= get_blob_type_from_length(sql_field->length);
sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
}
sql_field->length= 0; // Probably from an item
}
}
/* /*
Create a table Create a table
......
...@@ -1407,6 +1407,16 @@ create_function_tail: ...@@ -1407,6 +1407,16 @@ create_function_tail:
lex->uint_geom_type))) lex->uint_geom_type)))
YYABORT; YYABORT;
sp->m_returns_cs= new_field->charset;
if (new_field->sql_type == FIELD_TYPE_SET ||
new_field->sql_type == FIELD_TYPE_ENUM)
{
new_field->interval=
sp->create_typelib(&new_field->interval_list);
}
sp_prepare_create_field(YYTHD, new_field);
if (prepare_create_field(new_field, &unused1, &unused2, &unused2, if (prepare_create_field(new_field, &unused1, &unused2, &unused2,
0)) 0))
YYABORT; YYABORT;
...@@ -1415,8 +1425,8 @@ create_function_tail: ...@@ -1415,8 +1425,8 @@ create_function_tail:
sp->m_returns_cs= new_field->charset; sp->m_returns_cs= new_field->charset;
sp->m_returns_len= new_field->length; sp->m_returns_len= new_field->length;
sp->m_returns_pack= new_field->pack_flag; sp->m_returns_pack= new_field->pack_flag;
sp->m_returns_typelib= sp->m_returns_typelib= new_field->interval;
sp->create_typelib(&new_field->interval_list); new_field->interval= NULL;
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
} }
......
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