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()|
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)
......
......@@ -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
......
......@@ -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,10 +282,23 @@ 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;
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);
m_defstr.length= lex->end_of_query - lex->buf;
......@@ -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);
}
......
......@@ -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)
......
......@@ -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
......
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