From: Date: April 20 2005 7:09pm Subject: bk commit into 5.0 tree (acurtis:1.1856) BUG#9775 List-Archive: http://lists.mysql.com/internals/24171 X-Bug: 9775 Message-Id: <200504201709.j3KH91BP007790@ltantony.xiphis.org> Below is the list of changes that have just been committed into a local 5.0 repository of acurtis. When acurtis does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet 1.1856 05/04/20 18:08:42 acurtis@stripped +5 -0 Bug#9775 - Stored procedures: crash if create function that returns enum or set Fix bug and implement return type casting. sql/sp_head.cc 1.128 05/04/20 18:08:28 acurtis@stripped +6 -2 Bug#9775 missing initialiation for type_lengths in sp_head::create_typelib() sql/item_func.h 1.106 05/04/20 18:08:27 acurtis@stripped +17 -41 Bug#9775 results for Item_func_sp pass through a Field of the return type. new method Item_func_sp::execute(Field **) sql/item_func.cc 1.181 05/04/20 18:08:27 acurtis@stripped +48 -14 Bug#9775 new method Item_func_sp::execute(Field **) some optimizations. mysql-test/t/sp.test 1.111 05/04/20 18:08:27 acurtis@stripped +22 -1 Bug#9775 Test for bug + feature Fix previous tests mysql-test/r/sp.result 1.116 05/04/20 18:08:26 acurtis@stripped +24 -3 Bug#9775 Test for bug + feature Fix previous tests # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: acurtis # Host: ltantony.xiphis.org # Root: /.amd_mnt/bk.anubis/host/work-acurtis/bug9102 --- 1.180/sql/item_func.cc 2005-03-28 10:15:07 +01:00 +++ 1.181/sql/item_func.cc 2005-04-20 18:08:27 +01:00 @@ -4461,7 +4461,7 @@ Item_func_sp::Item_func_sp(sp_name *name) - :Item_func(), m_name(name), m_sp(NULL) + :Item_func(), m_name(name), m_sp(NULL), result_field(NULL) { maybe_null= 1; m_name->init_qname(current_thd); @@ -4470,7 +4470,7 @@ Item_func_sp::Item_func_sp(sp_name *name, List &list) - :Item_func(list), m_name(name), m_sp(NULL) + :Item_func(list), m_name(name), m_sp(NULL), result_field(NULL) { maybe_null= 1; m_name->init_qname(current_thd); @@ -4527,6 +4527,29 @@ int +Item_func_sp::execute(Field **flp) +{ + Item *it; + Field *f; + if (execute(&it)) + { + null_value= 1; + return 1; + } + if (!(f= *flp)) + { + *flp= f= sp_result_field(); + f->move_field((f->pack_length() > sizeof(result_buf)) ? + sql_alloc(f->pack_length()) : result_buf); + f->null_ptr= (uchar *)&null_value; + f->null_bit= 1; + } + it->save_in_field(f, 1); + return f->is_null(); +} + + +int Item_func_sp::execute(Item **itp) { DBUG_ENTER("Item_func_sp::execute"); @@ -4601,6 +4624,8 @@ Field *field= 0; DBUG_ENTER("Item_func_sp::field_type"); + if (result_field) + DBUG_RETURN(result_field->type()); if (! m_sp) m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only if ((field= sp_result_field())) @@ -4621,6 +4646,8 @@ DBUG_ENTER("Item_func_sp::result_type"); DBUG_PRINT("info", ("m_sp = %p", m_sp)); + if (result_field) + DBUG_RETURN(result_field->result_type()); if (! m_sp) m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only if ((field= sp_result_field())) @@ -4636,8 +4663,16 @@ void Item_func_sp::fix_length_and_dec() { + Field *field= result_field; DBUG_ENTER("Item_func_sp::fix_length_and_dec"); + if (result_field) + { + decimals= result_field->decimals(); + max_length= result_field->representation_length(); + DBUG_VOID_RETURN; + } + if (! m_sp) m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only if (! m_sp) @@ -4646,29 +4681,28 @@ } else { - switch (result_type()) { + if (!field) + field= sp_result_field(); + + decimals= field->decimals(); + max_length= field->representation_length(); + + switch (field->result_type()) { case STRING_RESULT: maybe_null= 1; - max_length= MAX_BLOB_WIDTH; - break; case REAL_RESULT: - decimals= NOT_FIXED_DEC; - max_length= float_length(decimals); - break; case INT_RESULT: - decimals= 0; - max_length= 21; - break; case DECIMAL_RESULT: - // TODO: where to find real precision and scale? - decimals= min(DECIMAL_MAX_LENGTH / 2, NOT_FIXED_DEC - 1); - max_length= DECIMAL_MAX_LENGTH; + break; case ROW_RESULT: default: // This case should never be chosen DBUG_ASSERT(0); break; } + + if (field != result_field) + delete field; } DBUG_VOID_RETURN; } --- 1.105/sql/item_func.h 2005-04-19 10:50:59 +01:00 +++ 1.106/sql/item_func.h 2005-04-20 18:08:27 +01:00 @@ -1283,8 +1283,11 @@ sp_name *m_name; mutable sp_head *m_sp; TABLE *dummy_table; + Field *result_field; + char result_buf[64]; int execute(Item **itp); + int execute(Field **flp); Field *sp_result_field(void) const; public: @@ -1296,6 +1299,12 @@ virtual ~Item_func_sp() {} + void cleanup() + { + Item_func::cleanup(); + result_field= NULL; + } + const char *func_name() const; enum enum_field_types field_type() const; @@ -1308,63 +1317,30 @@ longlong val_int() { - Item *it; - longlong l; - - if (execute(&it)) - { - null_value= 1; + if (execute(&result_field)) return 0LL; - } - l= it->val_int(); - null_value= it->null_value; - return l; + return result_field->val_int(); } double val_real() { - Item *it; - double d; - - if (execute(&it)) - { - null_value= 1; + if (execute(&result_field)) return 0.0; - } - d= it->val_real(); - null_value= it->null_value; - return d; + return result_field->val_real(); } my_decimal *val_decimal(my_decimal *dec_buf) { - Item *it; - my_decimal *result; - - if (execute(&it)) - { - null_value= 1; + if (execute(&result_field)) return NULL; - } - result= it->val_decimal(dec_buf); - null_value= it->null_value; - return result; + return result_field->val_decimal(dec_buf); } - String *val_str(String *str) { - Item *it; - String *s; - - if (execute(&it)) - { - null_value= 1; + if (execute(&result_field)) return NULL; - } - s= it->val_str(str); - null_value= it->null_value; - return s; + return result_field->val_str(str); } void fix_length_and_dec(); --- 1.115/mysql-test/r/sp.result 2005-04-19 10:50:58 +01:00 +++ 1.116/mysql-test/r/sp.result 2005-04-20 18:08:26 +01:00 @@ -2960,14 +2960,35 @@ drop function bug9902| drop function if exists bug9102| create function bug9102() returns blob return 'a'| -select bug9102(); -drop function bug9102| +select bug9102()| bug9102() a -drop procedure if exists bug7648| +drop function bug9102| +drop function if exists bug7648| create function bug7648() returns bit(8) return 'a'| select bug7648()| bug7648() a drop function bug7648| +drop function if exists bug9775| +create function bug9775(v1 char(1)) returns enum('a','b') return v1| +select bug9775('a'),bug9775('b'),bug9775('c')| +bug9775('a') bug9775('b') bug9775('c') +a b +drop function bug9775| +create function bug9775(v1 int) returns enum('a','b') return v1| +select bug9775(1),bug9775(2),bug9775(3)| +bug9775(1) bug9775(2) bug9775(3) +a b +drop function bug9775| +create function bug9775(v1 char(1)) returns set('a','b') return v1| +select bug9775('a'),bug9775('b'),bug9775('a,b'),bug9775('c')| +bug9775('a') bug9775('b') bug9775('a,b') bug9775('c') +a b a,b +drop function bug9775| +create function bug9775(v1 int) returns set('a','b') return v1| +select bug9775(1),bug9775(2),bug9775(3),bug9775(4)| +bug9775(1) bug9775(2) bug9775(3) bug9775(4) +a b a,b +drop function bug9775| drop table t1,t2; --- 1.110/mysql-test/t/sp.test 2005-04-19 10:50:59 +01:00 +++ 1.111/mysql-test/t/sp.test 2005-04-20 18:08:27 +01:00 @@ -3643,11 +3643,32 @@ # BUG#7648: Stored procedure crash when invoking a function that returns a bit # --disable_warnings -drop procedure if exists bug7648| +drop function if exists bug7648| --enable_warnings create function bug7648() returns bit(8) return 'a'| select bug7648()| drop function bug7648| + + +# +# BUG#9775: crash if create function that returns enum or set +# +--disable_warnings +drop function if exists bug9775| +--enable_warnings +create function bug9775(v1 char(1)) returns enum('a','b') return v1| +select bug9775('a'),bug9775('b'),bug9775('c')| +drop function bug9775| +create function bug9775(v1 int) returns enum('a','b') return v1| +select bug9775(1),bug9775(2),bug9775(3)| +drop function bug9775| + +create function bug9775(v1 char(1)) returns set('a','b') return v1| +select bug9775('a'),bug9775('b'),bug9775('a,b'),bug9775('c')| +drop function bug9775| +create function bug9775(v1 int) returns set('a','b') return v1| +select bug9775(1),bug9775(2),bug9775(3),bug9775(4)| +drop function bug9775| # --- 1.127/sql/sp_head.cc 2005-04-19 09:09:11 +01:00 +++ 1.128/sql/sp_head.cc 2005-04-20 18:08:28 +01:00 @@ -378,8 +378,9 @@ result->count= src->elements; result->name= ""; if (!(result->type_names=(const char **) - alloc_root(mem_root,sizeof(char *)*(result->count+1)))) + alloc_root(mem_root,(sizeof(char *)+sizeof(int))*(result->count+1)))) return 0; + result->type_lengths= (unsigned int *)(result->type_names + result->count+1); List_iterator it(*src); String conv, *tmp; uint32 dummy; @@ -397,8 +398,10 @@ result->type_names[i]= buf; result->type_lengths[i]= conv.length(); } - else + else { result->type_names[i]= strdup_root(mem_root, tmp->c_ptr()); + result->type_lengths[i]= tmp->length(); + } // Strip trailing spaces. uint lengthsp= cs->cset->lengthsp(cs, result->type_names[i], @@ -407,6 +410,7 @@ ((uchar *)result->type_names[i])[lengthsp]= '\0'; } result->type_names[result->count]= 0; + result->type_lengths[result->count]= 0; } return result; }