summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <acurtis@xiphis.org>2005-04-19 09:09:25 +0100
committerunknown <acurtis@xiphis.org>2005-04-19 09:09:25 +0100
commit9bf92ed6fe303ef0fd758616d336eec4b786cd7f (patch)
tree709bf359df4b898f4ff4afeebc82f4a97b3d3fdd
parentd0eecb394daad2900b732e056845041792fbdbef (diff)
downloadmariadb-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.result6
-rw-r--r--mysql-test/t/sp.test9
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/sp_head.cc26
-rw-r--r--sql/sql_table.cc71
-rw-r--r--sql/sql_yacc.yy14
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));
}