Commit 1220069c authored by unknown's avatar unknown
Browse files

Bug#3788

  Crashes with stored procedure return non-string values
  Also fixes Bug#2773


mysql-test/r/information_schema.result:
  Bug#3788
    Fix results for bugfix
mysql-test/r/sp.result:
  Bug#3788
    Tests for Bug
    Fix results for bugfix
mysql-test/t/sp.test:
  Bug#3788
    New tests for bug
sql/item.cc:
  Fix unrelated crash in view test with --ps-protocol.
sql/item_func.cc:
  Bug#3788
    Alter how SP function result types are handled.
sql/item_func.h:
  Bug#3788
    Alter how SP function result types are handled.
sql/mysql_priv.h:
  Bug#3788
    Prototypes for new global functions
sql/sp.cc:
  Bug#3788
    Alter how function return type is reported
sql/sp_head.cc:
  Bug#3788
    Change how function return types are stored for SPs
sql/sp_head.h:
  Bug#3788
    Change how function return types are stored for SPs
sql/sql_parse.cc:
  Bug#3788
    Split out field construction into its own function
sql/sql_table.cc:
  Bug#3788
    Split out field preparation code into its own function
sql/sql_yacc.yy:
  Bug#3788
    Change how function return types are stored for SPs
sql/unireg.cc:
  Bug#3788
    Add assertion check
parent 5abbffd7
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -202,7 +202,7 @@ select parameter_style, sql_data_access, dtd_identifier
from information_schema.routines;
parameter_style	sql_data_access	dtd_identifier
SQL	CONTAINS SQL	NULL
SQL	CONTAINS SQL	int
SQL	CONTAINS SQL	int(11)
show procedure status;
Db	Name	Type	Definer	Modified	Created	Security_type	Comment
test	sel2	PROCEDURE	root@localhost	#	#	DEFINER	
+27 −5
Original line number Diff line number Diff line
@@ -951,7 +951,7 @@ comment 'Characteristics procedure test'
  return 42|
show create function chistics|
Function	sql_mode	Create Function
chistics		CREATE FUNCTION `test`.`chistics`() RETURNS int
chistics		CREATE FUNCTION `test`.`chistics`() RETURNS int(11)
    DETERMINISTIC
    SQL SECURITY INVOKER
    COMMENT 'Characteristics procedure test'
@@ -964,7 +964,7 @@ no sql
comment 'Characteristics function test'|
show create function chistics|
Function	sql_mode	Create Function
chistics		CREATE FUNCTION `test`.`chistics`() RETURNS int
chistics		CREATE FUNCTION `test`.`chistics`() RETURNS int(11)
    NO SQL
    DETERMINISTIC
    SQL SECURITY INVOKER
@@ -1214,7 +1214,7 @@ show procedure status;
end
call bug2267_4()|
Function	sql_mode	Create Function
fac		CREATE FUNCTION `test`.`fac`(n int unsigned) RETURNS bigint unsigned
fac		CREATE FUNCTION `test`.`fac`(n int unsigned) RETURNS bigint(20) unsigned
begin
declare f bigint unsigned default 1;
while n > 1 do
@@ -1576,11 +1576,11 @@ bug2564_2 ANSI_QUOTES CREATE PROCEDURE "test"."bug2564_2"()
insert into "t1" values ('foo', 1)
show create function bug2564_3|
Function	sql_mode	Create Function
bug2564_3		CREATE FUNCTION `test`.`bug2564_3`(x int, y int) RETURNS int
bug2564_3		CREATE FUNCTION `test`.`bug2564_3`(x int, y int) RETURNS int(11)
return x || y
show create function bug2564_4|
Function	sql_mode	Create Function
bug2564_4	REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,ANSI	CREATE FUNCTION "test"."bug2564_4"(x int, y int) RETURNS int
bug2564_4	REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,ANSI	CREATE FUNCTION "test"."bug2564_4"(x int, y int) RETURNS int(11)
return x || y
drop procedure bug2564_1|
drop procedure bug2564_2|
@@ -1645,6 +1645,28 @@ drop procedure bug4579_1|
drop procedure bug4579_2|
drop table t3|
drop table if exists t3|
drop procedure if exists bug2773|
create function bug2773() returns int return null|
create table t3 as select bug2773()|
show create table t3|
Table	Create Table
t3	CREATE TABLE `t3` (
  `bug2773()` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t3|
drop function bug2773|
drop procedure if exists bug3788|
create function bug3788() returns date return cast("2005-03-04" as date)|
select bug3788()|
bug3788()
2005-03-04
drop function bug3788|
create function bug3788() returns binary(5) return 5|
select bug3788()|
bug3788()
5
drop function bug3788|
drop table if exists t3|
create table t3 (f1 int, f2 int, f3 int)|
insert into t3 values (1,1,1)|
drop procedure if exists bug4726|
+29 −0
Original line number Diff line number Diff line
@@ -2063,6 +2063,35 @@ drop procedure bug4579_1|
drop procedure bug4579_2|
drop table t3|

#
# BUG#2773: Function's data type ignored in stored procedures
#
--disable_warnings
drop table if exists t3|
drop procedure if exists bug2773|
--enable_warnings

create function bug2773() returns int return null|
create table t3 as select bug2773()|
show create table t3|
drop table t3|
drop function bug2773|

#
# BUG#3788: Stored procedure packet error
#
--disable_warnings
drop procedure if exists bug3788|
--enable_warnings

create function bug3788() returns date return cast("2005-03-04" as date)|
select bug3788()|
drop function bug3788|

create function bug3788() returns binary(5) return 5|
select bug3788()|
drop function bug3788|
 

#
# BUG#4726
+1 −1
Original line number Diff line number Diff line
@@ -3524,7 +3524,7 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
  enum_parsing_place place= NO_MATTER;
  SELECT_LEX *current_sel= thd->lex->current_select;

  if (!ref)
  if (!ref || ref == not_found_item)
  {
    SELECT_LEX_UNIT *prev_unit= current_sel->master_unit();
    SELECT_LEX *outer_sel= prev_unit->outer_select();
+78 −6
Original line number Diff line number Diff line
@@ -4318,13 +4318,33 @@ longlong Item_func_row_count::val_int()
Item_func_sp::Item_func_sp(sp_name *name)
  :Item_func(), m_name(name), m_sp(NULL)
{
  char *empty_name= (char *) "";
  maybe_null= 1;
  m_name->init_qname(current_thd);
  bzero(&dummy_table, sizeof(dummy_table));
  dummy_table.share.table_cache_key = empty_name;
  dummy_table.share.table_name = empty_name;
  dummy_table.table.alias = empty_name;
  dummy_table.share.table_name = empty_name;
  dummy_table.table.maybe_null = maybe_null;
  dummy_table.table.in_use= current_thd;
  dummy_table.table.s = &dummy_table.share;
}

Item_func_sp::Item_func_sp(sp_name *name, List<Item> &list)
  :Item_func(list), m_name(name), m_sp(NULL)
{
  char *empty_name= (char *) "";
  maybe_null= 1;
  m_name->init_qname(current_thd);
  bzero(&dummy_table, sizeof(dummy_table));
  dummy_table.share.table_cache_key = empty_name;
  dummy_table.share.table_name = empty_name;
  dummy_table.table.alias = empty_name;
  dummy_table.share.table_name = empty_name;
  dummy_table.table.maybe_null = maybe_null;
  dummy_table.table.in_use= current_thd;
  dummy_table.table.s = &dummy_table.share;
}

const char *
@@ -4349,6 +4369,18 @@ Item_func_sp::func_name() const
}


Field *
Item_func_sp::sp_result_field(void) const
{
  Field *field= 0;
  THD *thd= current_thd;
  DBUG_ENTER("Item_func_sp::sp_result_field");
  if (m_sp)
    field= m_sp->make_field(max_length, name, &dummy_table.table);
  DBUG_RETURN(field);
}


int
Item_func_sp::execute(Item **itp)
{
@@ -4404,17 +4436,38 @@ Item_func_sp::execute(Item **itp)
}


void
Item_func_sp::make_field(Send_field *tmp_field)
{
  Field *field;
  DBUG_ENTER("Item_func_sp::make_field");
  if (! m_sp)
    m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
  if ((field= sp_result_field()))
  {
    field->make_field(tmp_field);
    delete field;
    DBUG_VOID_RETURN;
  }
  my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
  init_make_field(tmp_field, MYSQL_TYPE_VARCHAR);  
  DBUG_VOID_RETURN;
}


enum enum_field_types
Item_func_sp::field_type() const
{
  Field *field= 0;
  DBUG_ENTER("Item_func_sp::field_type");

  if (! m_sp)
    m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
  if (m_sp)
  if ((field= sp_result_field()))
  {
    DBUG_PRINT("info", ("m_returns = %d", m_sp->m_returns));
    DBUG_RETURN(m_sp->m_returns);
    enum_field_types result= field->type();
    delete field;
    DBUG_RETURN(result);
  }
  my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
  DBUG_RETURN(MYSQL_TYPE_VARCHAR);
@@ -4424,14 +4477,17 @@ Item_func_sp::field_type() const
Item_result
Item_func_sp::result_type() const
{
  Field *field= 0;
  DBUG_ENTER("Item_func_sp::result_type");
  DBUG_PRINT("info", ("m_sp = %p", m_sp));

  if (! m_sp)
    m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
  if (m_sp)
  if ((field= sp_result_field()))
  {
    DBUG_RETURN(m_sp->result());
    Item_result result= field->result_type();
    delete field;
    DBUG_RETURN(result);
  }
  my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
  DBUG_RETURN(STRING_RESULT);
@@ -4450,7 +4506,7 @@ Item_func_sp::fix_length_and_dec()
  }
  else
  {
    switch (m_sp->result()) {
    switch (result_type()) {
    case STRING_RESULT:
      maybe_null= 1;
      max_length= MAX_BLOB_WIDTH;
@@ -4485,3 +4541,19 @@ longlong Item_func_found_rows::val_int()

  return thd->found_rows();
}

Field *
Item_func_sp::tmp_table_field(TABLE *t_arg)
{
  Field *res= 0;
  enum_field_types ftype;
  DBUG_ENTER("Item_func_sp::tmp_table_field");

  if (m_sp)
    res= m_sp->make_field(max_length, (const char *)name, t_arg);
  
  if (!res) 
    res= Item_func::tmp_table_field(t_arg);

  DBUG_RETURN(res);
}
Loading