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|
|
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|
|
|||||||
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,
|
|||||||
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 *
|
|||||||
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)
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
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:
|
|||||||
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:
|
|||||||
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));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user