Loading mysql-test/r/sp.result +25 −0 Original line number Diff line number Diff line Loading @@ -3073,4 +3073,29 @@ update v1 set data = 10| call bug9841()| drop view v1| drop procedure bug9841| drop procedure if exists bug5963| create procedure bug5963_1 () begin declare v int; set v = (select s1 from t3); select v; end;| create table t3 (s1 int)| insert into t3 values (5)| call bug5963_1()| v 5 call bug5963_1()| v 5 drop procedure bug5963_1| drop table t3| create procedure bug5963_2 (cfk_value int) begin if cfk_value in (select cpk from t3) then set @x = 5; end if; end; | create table t3 (cpk int)| insert into t3 values (1)| call bug5963_2(1)| call bug5963_2(1)| drop procedure bug5963_2| drop table t3| drop table t1,t2; mysql-test/t/sp.test +29 −0 Original line number Diff line number Diff line Loading @@ -3772,6 +3772,35 @@ drop view v1| drop procedure bug9841| # # BUG#5963 subqueries in SET/IF # --disable_warnings drop procedure if exists bug5963| --enable_warnings create procedure bug5963_1 () begin declare v int; set v = (select s1 from t3); select v; end;| create table t3 (s1 int)| insert into t3 values (5)| call bug5963_1()| call bug5963_1()| drop procedure bug5963_1| drop table t3| create procedure bug5963_2 (cfk_value int) begin if cfk_value in (select cpk from t3) then set @x = 5; end if; end; | create table t3 (cpk int)| insert into t3 values (1)| call bug5963_2(1)| call bug5963_2(1)| drop procedure bug5963_2| drop table t3| # # BUG#NNNN: New bug synopsis # Loading sql/item.cc +7 −0 Original line number Diff line number Diff line Loading @@ -740,6 +740,13 @@ Item_splocal::this_item() return thd->spcont->get_item(m_offset); } Item ** Item_splocal::this_item_addr(THD *thd, Item **addr) { return thd->spcont->get_item_addr(m_offset); } Item * Item_splocal::this_const_item() const { Loading sql/item.h +12 −2 Original line number Diff line number Diff line Loading @@ -526,7 +526,16 @@ class Item { virtual Item *set_no_const_sub(byte *arg) { return this; } virtual Item *replace_equal_field(byte * arg) { return this; } virtual Item *this_item() { return this; } /* For SPs mostly. */ /* For SP local variable returns pointer to Item representing its current value and pointer to current Item otherwise. */ virtual Item *this_item() { return this; } /* For SP local variable returns address of pointer to Item representing its current value and pointer passed via parameter otherwise. */ virtual Item **this_item_addr(THD *thd, Item **addr) { return addr; } virtual Item *this_const_item() const { return const_cast<Item*>(this); } /* For SPs mostly. */ // Row emulation Loading Loading @@ -573,6 +582,7 @@ class Item_splocal : public Item bool is_splocal() { return 1; } /* Needed for error checking */ Item *this_item(); Item **this_item_addr(THD *thd, Item **); Item *this_const_item() const; bool fix_fields(THD *, struct st_table_list *, Item **); Loading sql/sp_head.cc +42 −13 Original line number Diff line number Diff line Loading @@ -97,19 +97,48 @@ sp_multi_results_command(enum enum_sql_command cmd) } } /* Prepare Item for execution (call of fix_fields) SYNOPSIS sp_prepare_func_item() thd thread handler it_addr pointer on item refernce RETURN NULL error prepared item */ static Item * sp_prepare_func_item(THD* thd, Item **it_addr) { Item *it= *it_addr; DBUG_ENTER("sp_prepare_func_item"); it_addr= it->this_item_addr(thd, it_addr); if (!it->fixed && (*it_addr)->fix_fields(thd, 0, it_addr)) { DBUG_PRINT("info", ("fix_fields() failed")); DBUG_RETURN(NULL); } DBUG_RETURN(*it_addr); } /* Evaluate a (presumed) func item. Always returns an item, the parameter ** if nothing else. */ Item * sp_eval_func_item(THD *thd, Item *it, enum enum_field_types type) sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) { DBUG_ENTER("sp_eval_func_item"); it= it->this_item(); Item *it= sp_prepare_func_item(thd, it_addr); DBUG_PRINT("info", ("type: %d", type)); if (!it->fixed && it->fix_fields(thd, 0, &it)) if (!it) { DBUG_PRINT("info", ("fix_fields() failed")); DBUG_RETURN(NULL); } Loading Loading @@ -679,7 +708,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) for (i= 0 ; i < params && i < argcount ; i++) { sp_pvar_t *pvar = m_pcont->find_pvar(i); Item *it= sp_eval_func_item(thd, *argp++, pvar->type); Item *it= sp_eval_func_item(thd, argp++, pvar->type); if (it) nctx->push_item(it); Loading Loading @@ -761,7 +790,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) { Item_null *nit= NULL; // Re-use this, and only create if needed uint i; List_iterator_fast<Item> li(*args); List_iterator<Item> li(*args); Item *it; nctx= new sp_rcontext(csize, hmax, cmax); Loading Loading @@ -794,7 +823,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) } else { Item *it2= sp_eval_func_item(thd, it, pvar->type); Item *it2= sp_eval_func_item(thd, li.ref(), pvar->type); if (it2) nctx->push_item(it2); // IN or INOUT Loading Loading @@ -1439,7 +1468,7 @@ sp_instr_set::exec_core(THD *thd, uint *nextp) Item *it; int res; it= sp_eval_func_item(thd, m_value, m_type); it= sp_eval_func_item(thd, &m_value, m_type); if (! it) res= -1; else Loading Loading @@ -1569,13 +1598,13 @@ sp_instr_jump_if::exec_core(THD *thd, uint *nextp) Item *it; int res; it= sp_eval_func_item(thd, m_expr, MYSQL_TYPE_TINY); it= sp_prepare_func_item(thd, &m_expr); if (!it) res= -1; else { res= 0; if (it->val_int()) if (it->val_bool()) *nextp = m_dest; else *nextp = m_ip+1; Loading Loading @@ -1627,13 +1656,13 @@ sp_instr_jump_if_not::exec_core(THD *thd, uint *nextp) Item *it; int res; it= sp_eval_func_item(thd, m_expr, MYSQL_TYPE_TINY); it= sp_prepare_func_item(thd, &m_expr); if (! it) res= -1; else { res= 0; if (! it->val_int()) if (! it->val_bool()) *nextp = m_dest; else *nextp = m_ip+1; Loading Loading @@ -1685,7 +1714,7 @@ sp_instr_freturn::exec_core(THD *thd, uint *nextp) Item *it; int res; it= sp_eval_func_item(thd, m_value, m_type); it= sp_eval_func_item(thd, &m_value, m_type); if (! it) res= -1; else Loading Loading
mysql-test/r/sp.result +25 −0 Original line number Diff line number Diff line Loading @@ -3073,4 +3073,29 @@ update v1 set data = 10| call bug9841()| drop view v1| drop procedure bug9841| drop procedure if exists bug5963| create procedure bug5963_1 () begin declare v int; set v = (select s1 from t3); select v; end;| create table t3 (s1 int)| insert into t3 values (5)| call bug5963_1()| v 5 call bug5963_1()| v 5 drop procedure bug5963_1| drop table t3| create procedure bug5963_2 (cfk_value int) begin if cfk_value in (select cpk from t3) then set @x = 5; end if; end; | create table t3 (cpk int)| insert into t3 values (1)| call bug5963_2(1)| call bug5963_2(1)| drop procedure bug5963_2| drop table t3| drop table t1,t2;
mysql-test/t/sp.test +29 −0 Original line number Diff line number Diff line Loading @@ -3772,6 +3772,35 @@ drop view v1| drop procedure bug9841| # # BUG#5963 subqueries in SET/IF # --disable_warnings drop procedure if exists bug5963| --enable_warnings create procedure bug5963_1 () begin declare v int; set v = (select s1 from t3); select v; end;| create table t3 (s1 int)| insert into t3 values (5)| call bug5963_1()| call bug5963_1()| drop procedure bug5963_1| drop table t3| create procedure bug5963_2 (cfk_value int) begin if cfk_value in (select cpk from t3) then set @x = 5; end if; end; | create table t3 (cpk int)| insert into t3 values (1)| call bug5963_2(1)| call bug5963_2(1)| drop procedure bug5963_2| drop table t3| # # BUG#NNNN: New bug synopsis # Loading
sql/item.cc +7 −0 Original line number Diff line number Diff line Loading @@ -740,6 +740,13 @@ Item_splocal::this_item() return thd->spcont->get_item(m_offset); } Item ** Item_splocal::this_item_addr(THD *thd, Item **addr) { return thd->spcont->get_item_addr(m_offset); } Item * Item_splocal::this_const_item() const { Loading
sql/item.h +12 −2 Original line number Diff line number Diff line Loading @@ -526,7 +526,16 @@ class Item { virtual Item *set_no_const_sub(byte *arg) { return this; } virtual Item *replace_equal_field(byte * arg) { return this; } virtual Item *this_item() { return this; } /* For SPs mostly. */ /* For SP local variable returns pointer to Item representing its current value and pointer to current Item otherwise. */ virtual Item *this_item() { return this; } /* For SP local variable returns address of pointer to Item representing its current value and pointer passed via parameter otherwise. */ virtual Item **this_item_addr(THD *thd, Item **addr) { return addr; } virtual Item *this_const_item() const { return const_cast<Item*>(this); } /* For SPs mostly. */ // Row emulation Loading Loading @@ -573,6 +582,7 @@ class Item_splocal : public Item bool is_splocal() { return 1; } /* Needed for error checking */ Item *this_item(); Item **this_item_addr(THD *thd, Item **); Item *this_const_item() const; bool fix_fields(THD *, struct st_table_list *, Item **); Loading
sql/sp_head.cc +42 −13 Original line number Diff line number Diff line Loading @@ -97,19 +97,48 @@ sp_multi_results_command(enum enum_sql_command cmd) } } /* Prepare Item for execution (call of fix_fields) SYNOPSIS sp_prepare_func_item() thd thread handler it_addr pointer on item refernce RETURN NULL error prepared item */ static Item * sp_prepare_func_item(THD* thd, Item **it_addr) { Item *it= *it_addr; DBUG_ENTER("sp_prepare_func_item"); it_addr= it->this_item_addr(thd, it_addr); if (!it->fixed && (*it_addr)->fix_fields(thd, 0, it_addr)) { DBUG_PRINT("info", ("fix_fields() failed")); DBUG_RETURN(NULL); } DBUG_RETURN(*it_addr); } /* Evaluate a (presumed) func item. Always returns an item, the parameter ** if nothing else. */ Item * sp_eval_func_item(THD *thd, Item *it, enum enum_field_types type) sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) { DBUG_ENTER("sp_eval_func_item"); it= it->this_item(); Item *it= sp_prepare_func_item(thd, it_addr); DBUG_PRINT("info", ("type: %d", type)); if (!it->fixed && it->fix_fields(thd, 0, &it)) if (!it) { DBUG_PRINT("info", ("fix_fields() failed")); DBUG_RETURN(NULL); } Loading Loading @@ -679,7 +708,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) for (i= 0 ; i < params && i < argcount ; i++) { sp_pvar_t *pvar = m_pcont->find_pvar(i); Item *it= sp_eval_func_item(thd, *argp++, pvar->type); Item *it= sp_eval_func_item(thd, argp++, pvar->type); if (it) nctx->push_item(it); Loading Loading @@ -761,7 +790,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) { Item_null *nit= NULL; // Re-use this, and only create if needed uint i; List_iterator_fast<Item> li(*args); List_iterator<Item> li(*args); Item *it; nctx= new sp_rcontext(csize, hmax, cmax); Loading Loading @@ -794,7 +823,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) } else { Item *it2= sp_eval_func_item(thd, it, pvar->type); Item *it2= sp_eval_func_item(thd, li.ref(), pvar->type); if (it2) nctx->push_item(it2); // IN or INOUT Loading Loading @@ -1439,7 +1468,7 @@ sp_instr_set::exec_core(THD *thd, uint *nextp) Item *it; int res; it= sp_eval_func_item(thd, m_value, m_type); it= sp_eval_func_item(thd, &m_value, m_type); if (! it) res= -1; else Loading Loading @@ -1569,13 +1598,13 @@ sp_instr_jump_if::exec_core(THD *thd, uint *nextp) Item *it; int res; it= sp_eval_func_item(thd, m_expr, MYSQL_TYPE_TINY); it= sp_prepare_func_item(thd, &m_expr); if (!it) res= -1; else { res= 0; if (it->val_int()) if (it->val_bool()) *nextp = m_dest; else *nextp = m_ip+1; Loading Loading @@ -1627,13 +1656,13 @@ sp_instr_jump_if_not::exec_core(THD *thd, uint *nextp) Item *it; int res; it= sp_eval_func_item(thd, m_expr, MYSQL_TYPE_TINY); it= sp_prepare_func_item(thd, &m_expr); if (! it) res= -1; else { res= 0; if (! it->val_int()) if (! it->val_bool()) *nextp = m_dest; else *nextp = m_ip+1; Loading Loading @@ -1685,7 +1714,7 @@ sp_instr_freturn::exec_core(THD *thd, uint *nextp) Item *it; int res; it= sp_eval_func_item(thd, m_value, m_type); it= sp_eval_func_item(thd, &m_value, m_type); if (! it) res= -1; else Loading