Commit 91dcd011 authored by unknown's avatar unknown

Fixed BUG#2772: Function with character set clause fails in stored procedures.

Complex return types were not stored correctly in the mysql.proc table.


mysql-test/r/sp.result:
  New testcase for BUG2772.
mysql-test/t/sp.test:
  New testcase for BUG2772.
sql/sp_head.cc:
  Pick up character set for "returns" types in functions and add it separately,
  since it's missed when extracting the type during the parser. (Due to LALR
  behaviour.)
sql/sp_head.h:
  Save the character set for returns clause in functions.
sql/sql_yacc.yy:
  Pick up character set for "returns" types in functions since it's missed otherwise.
  (Due to LALR behaviour.)
parent 4a7c72e9
...@@ -1015,6 +1015,12 @@ call bUG3259_3()| ...@@ -1015,6 +1015,12 @@ call bUG3259_3()|
drop procedure bUg3259_1| drop procedure bUg3259_1|
drop procedure BuG3259_2| drop procedure BuG3259_2|
drop procedure BUG3259_3| 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| drop table if exists fac|
create table fac (n int unsigned not null primary key, f bigint unsigned)| create table fac (n int unsigned not null primary key, f bigint unsigned)|
create procedure ifac(n int unsigned) create procedure ifac(n int unsigned)
......
...@@ -1152,7 +1152,6 @@ drop procedure bug2614| ...@@ -1152,7 +1152,6 @@ drop procedure bug2614|
# #
# BUG#2674 # BUG#2674
# #
create function bug2674 () returns int create function bug2674 () returns int
return @@sort_buffer_size| return @@sort_buffer_size|
...@@ -1165,7 +1164,6 @@ set @@sort_buffer_size = @osbs| ...@@ -1165,7 +1164,6 @@ set @@sort_buffer_size = @osbs|
# #
# BUG#3259 # BUG#3259
# #
create procedure bug3259_1 () begin end| create procedure bug3259_1 () begin end|
create procedure BUG3259_2 () begin end| create procedure BUG3259_2 () begin end|
create procedure Bug3259_3 () begin end| create procedure Bug3259_3 () begin end|
...@@ -1181,6 +1179,15 @@ drop procedure bUg3259_1| ...@@ -1181,6 +1179,15 @@ drop procedure bUg3259_1|
drop procedure BuG3259_2| drop procedure BuG3259_2|
drop procedure BUG3259_3| 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 # Some "real" examples
......
...@@ -207,7 +207,7 @@ sp_head::operator delete(void *ptr, size_t size) ...@@ -207,7 +207,7 @@ sp_head::operator delete(void *ptr, size_t size)
sp_head::sp_head() sp_head::sp_head()
: Sql_alloc(), m_has_return(FALSE), m_simple_case(FALSE), : 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"); DBUG_ENTER("sp_head::sp_head");
...@@ -228,6 +228,7 @@ sp_head::init(LEX *lex) ...@@ -228,6 +228,7 @@ sp_head::init(LEX *lex)
m_body.str= m_defstr.str= 0; m_body.str= m_defstr.str= 0;
m_qname.length= m_db.length= m_name.length= m_params.length= m_qname.length= m_db.length= m_name.length= m_params.length=
m_retstr.length= m_body.length= m_defstr.length= 0; m_retstr.length= m_body.length= m_defstr.length= 0;
m_returns_cs= NULL;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -266,7 +267,10 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name) ...@@ -266,7 +267,10 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
if (m_returns_begin && m_returns_end) if (m_returns_begin && m_returns_end)
{ {
/* QQ KLUDGE: We can't seem to cut out just the type in the parser /* 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 "); char *p= (char *)m_returns_begin+strspn((char *)m_returns_begin,"\t\n\r ");
p+= strcspn(p, "\t\n\r "); p+= strcspn(p, "\t\n\r ");
p+= strspn(p, "\t\n\r "); p+= strspn(p, "\t\n\r ");
...@@ -278,10 +282,23 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name) ...@@ -278,10 +282,23 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
(*p == '\t' || *p == '\n' || *p == '\r' || *p == ' ')) (*p == '\t' || *p == '\n' || *p == '\r' || *p == ' '))
p-= 1; p-= 1;
m_returns_end= (uchar *)p+1; m_returns_end= (uchar *)p+1;
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.length= m_returns_end - m_returns_begin;
m_retstr.str= strmake_root(root, m_retstr.str= strmake_root(root,
(char *)m_returns_begin, m_retstr.length); (char *)m_returns_begin, m_retstr.length);
} }
}
m_body.length= lex->end_of_query - m_body_begin; m_body.length= lex->end_of_query - m_body_begin;
m_body.str= strmake_root(root, (char *)m_body_begin, m_body.length); m_body.str= strmake_root(root, (char *)m_body_begin, m_body.length);
m_defstr.length= lex->end_of_query - lex->buf; m_defstr.length= lex->end_of_query - lex->buf;
...@@ -894,7 +911,7 @@ sp_instr_stmt::print(String *str) ...@@ -894,7 +911,7 @@ sp_instr_stmt::print(String *str)
{ {
str->reserve(12); str->reserve(12);
str->append("stmt "); 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) ...@@ -1117,7 +1134,7 @@ sp_instr_freturn::print(String *str)
{ {
str->reserve(12); str->reserve(12);
str->append("freturn "); str->append("freturn ");
str->qs_append(m_type); str->qs_append((uint)m_type);
str->append(' '); str->append(' ');
m_value->print(str); m_value->print(str);
} }
......
...@@ -79,6 +79,7 @@ public: ...@@ -79,6 +79,7 @@ public:
int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE
enum enum_field_types m_returns; // For FUNCTIONs only 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_has_return; // For FUNCTIONs only
my_bool m_simple_case; // TRUE if parsing simple case, FALSE otherwise my_bool m_simple_case; // TRUE if parsing simple case, FALSE otherwise
my_bool m_multi_results; // TRUE if a procedure with SELECT(s) my_bool m_multi_results; // TRUE if a procedure with SELECT(s)
......
...@@ -1145,14 +1145,20 @@ create_function_tail: ...@@ -1145,14 +1145,20 @@ create_function_tail:
} }
RETURNS_SYM 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 type
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_head *sp= lex->sphead;
lex->sphead->m_returns_end= lex->tok_start; sp->m_returns_end= lex->tok_start;
lex->sphead->m_returns= (enum enum_field_types)$8; sp->m_returns= (enum enum_field_types)$8;
sp->m_returns_cs= lex->charset;
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
} }
sp_c_chistics sp_c_chistics
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment