diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index bfcf4064cf2..8c72186e618 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -1015,6 +1015,12 @@ call bUG3259_3()| drop procedure bUg3259_1| drop procedure BuG3259_2| drop procedure BUG3259_3| +create function bug2772() returns char(10) character set latin2 +return 'a'| +select bug2772()| +bug2772() +a +drop function bug2772| drop table if exists fac| create table fac (n int unsigned not null primary key, f bigint unsigned)| create procedure ifac(n int unsigned) diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 7e5b734d959..9e31bdb5f14 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -1152,7 +1152,6 @@ drop procedure bug2614| # # BUG#2674 # - create function bug2674 () returns int return @@sort_buffer_size| @@ -1165,7 +1164,6 @@ set @@sort_buffer_size = @osbs| # # BUG#3259 # - create procedure bug3259_1 () begin end| create procedure BUG3259_2 () begin end| create procedure Bug3259_3 () begin end| @@ -1181,6 +1179,15 @@ drop procedure bUg3259_1| drop procedure BuG3259_2| drop procedure BUG3259_3| +# +# BUG##2772 +# +create function bug2772() returns char(10) character set latin2 + return 'a'| + +select bug2772()| +drop function bug2772| + # # Some "real" examples diff --git a/sql/sp_head.cc b/sql/sp_head.cc index dfc3e8190fe..063474fc960 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -207,7 +207,7 @@ sp_head::operator delete(void *ptr, size_t size) sp_head::sp_head() : Sql_alloc(), m_has_return(FALSE), m_simple_case(FALSE), - m_multi_results(FALSE), m_free_list(NULL) + m_multi_results(FALSE), m_free_list(NULL), m_returns_cs(NULL) { DBUG_ENTER("sp_head::sp_head"); @@ -228,6 +228,7 @@ sp_head::init(LEX *lex) m_body.str= m_defstr.str= 0; m_qname.length= m_db.length= m_name.length= m_params.length= m_retstr.length= m_body.length= m_defstr.length= 0; + m_returns_cs= NULL; DBUG_VOID_RETURN; } @@ -266,7 +267,10 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name) if (m_returns_begin && m_returns_end) { /* QQ KLUDGE: We can't seem to cut out just the type in the parser - (without the RETURNS), so we'll have to do it here. :-( */ + (without the RETURNS), so we'll have to do it here. :-( + Furthermore, if there's a character type as well, it's not include + (beyond the m_returns_end pointer), in which case we need + m_returns_cs. */ char *p= (char *)m_returns_begin+strspn((char *)m_returns_begin,"\t\n\r "); p+= strcspn(p, "\t\n\r "); p+= strspn(p, "\t\n\r "); @@ -278,9 +282,22 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name) (*p == '\t' || *p == '\n' || *p == '\r' || *p == ' ')) p-= 1; m_returns_end= (uchar *)p+1; - m_retstr.length= m_returns_end - m_returns_begin; - m_retstr.str= strmake_root(root, - (char *)m_returns_begin, m_retstr.length); + if (m_returns_cs) + { + String s((char *)m_returns_begin, m_returns_end - m_returns_begin, + system_charset_info); + + s.append(' '); + s.append(m_returns_cs->csname); + m_retstr.length= s.length(); + m_retstr.str= strmake_root(root, s.ptr(), m_retstr.length); + } + else + { + m_retstr.length= m_returns_end - m_returns_begin; + m_retstr.str= strmake_root(root, + (char *)m_returns_begin, m_retstr.length); + } } m_body.length= lex->end_of_query - m_body_begin; m_body.str= strmake_root(root, (char *)m_body_begin, m_body.length); @@ -894,7 +911,7 @@ sp_instr_stmt::print(String *str) { str->reserve(12); str->append("stmt "); - str->qs_append(m_lex->sql_command); + str->qs_append((uint)m_lex->sql_command); } @@ -1117,7 +1134,7 @@ sp_instr_freturn::print(String *str) { str->reserve(12); str->append("freturn "); - str->qs_append(m_type); + str->qs_append((uint)m_type); str->append(' '); m_value->print(str); } diff --git a/sql/sp_head.h b/sql/sp_head.h index 3aebd80d686..cb2e56adabe 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -79,6 +79,7 @@ public: int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE enum enum_field_types m_returns; // For FUNCTIONs only + CHARSET_INFO *m_returns_cs; // For FUNCTIONs only my_bool m_has_return; // For FUNCTIONs only my_bool m_simple_case; // TRUE if parsing simple case, FALSE otherwise my_bool m_multi_results; // TRUE if a procedure with SELECT(s) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 6a0d254a90c..4060554706d 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1145,14 +1145,20 @@ create_function_tail: } RETURNS_SYM { - Lex->sphead->m_returns_begin= Lex->tok_start; + LEX *lex= Lex; + sp_head *sp= lex->sphead; + + sp->m_returns_begin= lex->tok_start; + sp->m_returns_cs= lex->charset= NULL; } type { LEX *lex= Lex; + sp_head *sp= lex->sphead; - lex->sphead->m_returns_end= lex->tok_start; - lex->sphead->m_returns= (enum enum_field_types)$8; + sp->m_returns_end= lex->tok_start; + sp->m_returns= (enum enum_field_types)$8; + sp->m_returns_cs= lex->charset; bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); } sp_c_chistics