diff options
author | unknown <acurtis@xiphis.org> | 2005-04-19 09:09:25 +0100 |
---|---|---|
committer | unknown <acurtis@xiphis.org> | 2005-04-19 09:09:25 +0100 |
commit | 9bf92ed6fe303ef0fd758616d336eec4b786cd7f (patch) | |
tree | 709bf359df4b898f4ff4afeebc82f4a97b3d3fdd | |
parent | d0eecb394daad2900b732e056845041792fbdbef (diff) | |
download | mariadb-git-9bf92ed6fe303ef0fd758616d336eec4b786cd7f.tar.gz |
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
-rw-r--r-- | mysql-test/r/sp.result | 6 | ||||
-rw-r--r-- | mysql-test/t/sp.test | 9 | ||||
-rw-r--r-- | sql/mysql_priv.h | 1 | ||||
-rw-r--r-- | sql/sp_head.cc | 26 | ||||
-rw-r--r-- | sql/sql_table.cc | 71 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 14 |
6 files changed, 124 insertions, 3 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 4bb1640f0eb..4cc59679ce5 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -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; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 4101a7a4bfa..3934e8ad17a 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -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 diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index a854f8c45d3..56fbd993aed 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -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, diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 0fe9c449540..d1486cb234e 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -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; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 8753f62ab89..18c90d549ec 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1352,6 +1352,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 SYNOPSIS diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 9aa5d7fb4fc..40529312493 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -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)); } |