mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
Bug#9102 - Stored proccedures: function which returns blob causes crash
Initialization of fields for sp return type was not complete.
This commit is contained in:
@@ -2958,4 +2958,10 @@ select @x|
|
||||
set global query_cache_size = @qcs1|
|
||||
delete from t1|
|
||||
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;
|
||||
|
@@ -3627,6 +3627,15 @@ set global query_cache_size = @qcs1|
|
||||
delete from t1|
|
||||
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
|
||||
|
@@ -647,6 +647,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
||||
Item ***copy_func, Field **from_field,
|
||||
bool group, bool modify_item,
|
||||
uint convert_blob_length);
|
||||
void sp_prepare_create_field(THD *thd, create_field *sql_field);
|
||||
int prepare_create_field(create_field *sql_field,
|
||||
uint *blob_columns,
|
||||
int *timestamps, int *timestamps_with_niladic,
|
||||
|
@@ -370,6 +370,7 @@ TYPELIB *
|
||||
sp_head::create_typelib(List<String> *src)
|
||||
{
|
||||
TYPELIB *result= NULL;
|
||||
CHARSET_INFO *cs= m_returns_cs;
|
||||
DBUG_ENTER("sp_head::clone_typelib");
|
||||
if (src->elements)
|
||||
{
|
||||
@@ -380,8 +381,31 @@ sp_head::create_typelib(List<String> *src)
|
||||
alloc_root(mem_root,sizeof(char *)*(result->count+1))))
|
||||
return 0;
|
||||
List_iterator<String> it(*src);
|
||||
String conv, *tmp;
|
||||
uint32 dummy;
|
||||
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;
|
||||
}
|
||||
return result;
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -1407,6 +1407,16 @@ create_function_tail:
|
||||
lex->uint_geom_type)))
|
||||
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,
|
||||
0))
|
||||
YYABORT;
|
||||
@@ -1415,8 +1425,8 @@ create_function_tail:
|
||||
sp->m_returns_cs= new_field->charset;
|
||||
sp->m_returns_len= new_field->length;
|
||||
sp->m_returns_pack= new_field->pack_flag;
|
||||
sp->m_returns_typelib=
|
||||
sp->create_typelib(&new_field->interval_list);
|
||||
sp->m_returns_typelib= new_field->interval;
|
||||
new_field->interval= NULL;
|
||||
|
||||
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
|
||||
}
|
||||
|
Reference in New Issue
Block a user