Commit a2c26aa7 authored by unknown's avatar unknown

Merge sanja.is.com.ua:/home/bell/mysql/bk/work-bug2-5.0

into  sanja.is.com.ua:/home/bell/mysql/bk/work-merge-5.0


sql/item.h:
  Auto merged
sql/protocol.cc:
  Auto merged
sql/sp.cc:
  Auto merged
sql/sp_head.cc:
  Auto merged
sql/sql_class.cc:
  Auto merged
sql/sql_class.h:
  Auto merged
sql/sql_trigger.cc:
  Auto merged
sql/sql_yacc.yy:
  Auto merged
mysql-test/r/sp.result:
  merge
mysql-test/r/trigger.result:
  merge
mysql-test/t/sp.test:
  merge
mysql-test/t/trigger.test:
  merge
sql/item.cc:
  merge
sql/sp_rcontext.h:
  merge
parents 57e1c5aa 6574612d
......@@ -3667,4 +3667,21 @@ call bug14845()|
a
0
drop procedure bug14845|
drop procedure bug12589_1|
drop procedure bug12589_2|
drop procedure bug12589_3|
drop procedure if exists bug13549_1|
drop procedure if exists bug13549_2|
CREATE PROCEDURE `bug13549_2`()
begin
call bug13549_1();
end|
CREATE PROCEDURE `bug13549_1`()
begin
declare done int default 0;
set done= not done;
end|
CALL bug13549_2()|
drop procedure bug13549_2|
drop procedure bug13549_1|
drop table t1,t2;
......@@ -763,3 +763,17 @@ ERROR HY000: Table 't3' was not locked with LOCK TABLES
deallocate prepare stmt1;
drop procedure p1;
drop table t1, t2, t3;
create table t1 (a int);
drop procedure if exists p2;
CREATE PROCEDURE `p2`()
begin
insert into t1 values (1);
end//
create trigger trg before insert on t1 for each row
begin
declare done int default 0;
set done= not done;
end//
CALL p2();
drop procedure p2;
drop table t1;
......@@ -4291,6 +4291,9 @@ call bug12589_1()|
# No warnings here
call bug12589_2()|
call bug12589_3()|
drop procedure bug12589_1|
drop procedure bug12589_2|
drop procedure bug12589_3|
#
# BUG#7049: Stored procedure CALL errors are ignored
......@@ -4594,6 +4597,31 @@ end|
call bug14845()|
drop procedure bug14845|
#
# BUG#13549 "Server crash with nested stored procedures".
# Server should not crash when during execution of stored procedure
# we have to parse trigger/function definition and this new trigger/
# function has more local variables declared than invoking stored
# procedure and last of these variables is used in argument of NOT
# operator.
#
--disable_warnings
drop procedure if exists bug13549_1|
drop procedure if exists bug13549_2|
--enable_warnings
CREATE PROCEDURE `bug13549_2`()
begin
call bug13549_1();
end|
CREATE PROCEDURE `bug13549_1`()
begin
declare done int default 0;
set done= not done;
end|
CALL bug13549_2()|
drop procedure bug13549_2|
drop procedure bug13549_1|
#
# BUG#NNNN: New bug synopsis
#
......
......@@ -914,3 +914,31 @@ call p1();
deallocate prepare stmt1;
drop procedure p1;
drop table t1, t2, t3;
#
# BUG#13549 "Server crash with nested stored procedures".
# Server should not crash when during execution of stored procedure
# we have to parse trigger/function definition and this new trigger/
# function has more local variables declared than invoking stored
# procedure and last of these variables is used in argument of NOT
# operator.
#
create table t1 (a int);
--disable_warnings
drop procedure if exists p2;
--enable_warnings
DELIMITER //;
CREATE PROCEDURE `p2`()
begin
insert into t1 values (1);
end//
create trigger trg before insert on t1 for each row
begin
declare done int default 0;
set done= not done;
end//
DELIMITER ;//
CALL p2();
drop procedure p2;
drop table t1;
......@@ -894,6 +894,7 @@ bool Item_splocal::is_null()
Item *
Item_splocal::this_item()
{
DBUG_ASSERT(owner == thd->spcont->owner);
return thd->spcont->get_item(m_offset);
}
......@@ -901,12 +902,14 @@ Item_splocal::this_item()
Item **
Item_splocal::this_item_addr(THD *thd, Item **addr)
{
DBUG_ASSERT(owner == thd->spcont->owner);
return thd->spcont->get_item_addr(m_offset);
}
Item *
Item_splocal::this_const_item() const
{
DBUG_ASSERT(owner == thd->spcont->owner);
return thd->spcont->get_item(m_offset);
}
......@@ -914,7 +917,11 @@ Item::Type
Item_splocal::type() const
{
if (thd && thd->spcont)
{
DBUG_ASSERT(owner == thd->spcont->owner);
return thd->spcont->get_item(m_offset)->type();
}
}
return NULL_ITEM; // Anything but SUBSELECT_ITEM
}
......
......@@ -704,6 +704,8 @@ public:
};
class sp_head;
/*
A reference to local SP variable (incl. reference to SP parameter), used in
runtime.
......@@ -721,6 +723,13 @@ class Item_splocal : public Item
uint m_offset;
public:
#ifndef DBUG_OFF
/*
Routine to which this Item_splocal belongs. Used for checking if correct
runtime context is used for variable handling.
*/
sp_head *owner;
#endif
LEX_STRING m_name;
THD *thd;
......
......@@ -498,7 +498,7 @@ void Protocol::init(THD *thd_arg)
thd=thd_arg;
packet= &thd->packet;
convert= &thd->convert_buffer;
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
field_types= 0;
#endif
}
......@@ -551,7 +551,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
(void) my_net_write(&thd->net, buff,(uint) (pos-buff));
}
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
field_types= (enum_field_types*) thd->alloc(sizeof(field_types) *
list->elements);
uint count= 0;
......@@ -648,7 +648,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
item->send(&prot, &tmp); // Send default value
if (prot.write())
break; /* purecov: inspected */
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
field_types[count++]= field.type;
#endif
}
......@@ -732,14 +732,14 @@ bool Protocol::store(I_List<i_string>* str_list)
void Protocol_simple::prepare_for_resend()
{
packet->length(0);
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
field_pos= 0;
#endif
}
bool Protocol_simple::store_null()
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
field_pos++;
#endif
char buff[1];
......@@ -773,7 +773,7 @@ bool Protocol::store_string_aux(const char *from, uint length,
bool Protocol_simple::store(const char *from, uint length,
CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
field_types[field_pos] == MYSQL_TYPE_BIT ||
......@@ -790,7 +790,7 @@ bool Protocol_simple::store(const char *from, uint length,
CHARSET_INFO *fromcs)
{
CHARSET_INFO *tocs= this->thd->variables.character_set_results;
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
field_types[field_pos] == MYSQL_TYPE_BIT ||
......@@ -805,7 +805,7 @@ bool Protocol_simple::store(const char *from, uint length,
bool Protocol_simple::store_tiny(longlong from)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_TINY);
field_pos++;
#endif
......@@ -817,7 +817,7 @@ bool Protocol_simple::store_tiny(longlong from)
bool Protocol_simple::store_short(longlong from)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_YEAR ||
field_types[field_pos] == MYSQL_TYPE_SHORT);
......@@ -831,7 +831,7 @@ bool Protocol_simple::store_short(longlong from)
bool Protocol_simple::store_long(longlong from)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_INT24 ||
field_types[field_pos] == MYSQL_TYPE_LONG);
......@@ -845,7 +845,7 @@ bool Protocol_simple::store_long(longlong from)
bool Protocol_simple::store_longlong(longlong from, bool unsigned_flag)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_LONGLONG);
field_pos++;
......@@ -860,7 +860,7 @@ bool Protocol_simple::store_longlong(longlong from, bool unsigned_flag)
bool Protocol_simple::store_decimal(const my_decimal *d)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
field_pos++;
......@@ -874,7 +874,7 @@ bool Protocol_simple::store_decimal(const my_decimal *d)
bool Protocol_simple::store(float from, uint32 decimals, String *buffer)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_FLOAT);
field_pos++;
......@@ -886,7 +886,7 @@ bool Protocol_simple::store(float from, uint32 decimals, String *buffer)
bool Protocol_simple::store(double from, uint32 decimals, String *buffer)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DOUBLE);
field_pos++;
......@@ -900,7 +900,7 @@ bool Protocol_simple::store(Field *field)
{
if (field->is_null())
return store_null();
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
field_pos++;
#endif
char buff[MAX_FIELD_WIDTH];
......@@ -921,7 +921,7 @@ bool Protocol_simple::store(Field *field)
bool Protocol_simple::store(TIME *tm)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DATETIME ||
field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
......@@ -944,7 +944,7 @@ bool Protocol_simple::store(TIME *tm)
bool Protocol_simple::store_date(TIME *tm)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DATE);
field_pos++;
......@@ -963,7 +963,7 @@ bool Protocol_simple::store_date(TIME *tm)
bool Protocol_simple::store_time(TIME *tm)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_TIME);
field_pos++;
......@@ -1088,7 +1088,7 @@ bool Protocol_prep::store_longlong(longlong from, bool unsigned_flag)
bool Protocol_prep::store_decimal(const my_decimal *d)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
field_pos++;
......
......@@ -31,7 +31,7 @@ protected:
String *packet;
String *convert;
uint field_pos;
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
enum enum_field_types *field_types;
#endif
uint field_count;
......
......@@ -380,6 +380,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
{
String defstr;
LEX *oldlex= thd->lex;
sp_rcontext *save_spcont= thd->spcont;
char olddb[128];
bool dbchanged;
enum enum_sql_command oldcmd= thd->lex->sql_command;
......@@ -422,6 +423,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
thd->lex->found_semicolon= tmpfsc;
}
thd->spcont= 0;
if (yyparse(thd) || thd->is_fatal_error || thd->lex->sphead == NULL)
{
LEX *newlex= thd->lex;
......@@ -439,12 +441,14 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
else
{
if (dbchanged && (ret= mysql_change_db(thd, olddb, 1)))
goto done;
goto db_done;
*sphp= thd->lex->sphead;
(*sphp)->set_definer((char*) definer, (uint) strlen(definer));
(*sphp)->set_info(created, modified, &chistics, sql_mode);
(*sphp)->optimize();
}
db_done:
thd->spcont= save_spcont;
thd->lex->sql_command= oldcmd;
thd->variables.sql_mode= old_sql_mode;
thd->variables.select_limit= select_limit;
......
......@@ -1175,6 +1175,9 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
// QQ Should have some error checking here? (types, etc...)
if (!(nctx= new sp_rcontext(octx, csize, hmax, cmax)))
goto end;
#ifndef DBUG_OFF
nctx->owner= this;
#endif
for (i= 0 ; i < argcount ; i++)
{
sp_pvar_t *pvar = m_pcont->find_pvar(i);
......@@ -1319,6 +1322,9 @@ int sp_head::execute_procedure(THD *thd, List<Item> *args)
{ // Create a temporary old context
if (!(octx= new sp_rcontext(octx, csize, hmax, cmax)))
DBUG_RETURN(-1);
#ifndef DBUG_OFF
octx->owner= 0;
#endif
thd->spcont= octx;
/* set callers_arena to thd, for upper-level function to work */
......@@ -1330,6 +1336,9 @@ int sp_head::execute_procedure(THD *thd, List<Item> *args)
thd->spcont= save_spcont;
DBUG_RETURN(-1);
}
#ifndef DBUG_OFF
nctx->owner= this;
#endif
if (csize > 0 || hmax > 0 || cmax > 0)
{
......
......@@ -66,6 +66,14 @@ class sp_rcontext : public Sql_alloc
*/
Query_arena *callers_arena;
#ifndef DBUG_OFF
/*
Routine to which this Item_splocal belongs. Used for checking if correct
runtime context is used for variable handling.
*/
sp_head *owner;
#endif
sp_rcontext(sp_rcontext *prev, uint fsize, uint hmax, uint cmax);
~sp_rcontext()
......
......@@ -410,7 +410,7 @@ protected:
/*
The following functions are only used when debugging
We don't protect these with ifndef DEBUG_OFF to not have to recompile
We don't protect these with ifndef DBUG_OFF to not have to recompile
everything if we want to add checks of the cache at some places.
*/
void wreck(uint line, const char *message);
......
......@@ -1495,7 +1495,13 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
my_var *mv= gl++;
if (mv->local)
(void)local_vars.push_back(new Item_splocal(mv->s, mv->offset));
{
Item_splocal *var;
(void)local_vars.push_back(var= new Item_splocal(mv->s, mv->offset));
#ifndef DEBUG_OFF
var->owner= mv->owner;
#endif
}
else
{
Item_func_set_user_var *var= new Item_func_set_user_var(mv->s, item);
......
......@@ -2085,6 +2085,13 @@ public:
class my_var : public Sql_alloc {
public:
LEX_STRING s;
#ifndef DEBUG_OFF
/*
Routine to which this Item_splocal belongs. Used for checking if correct
runtime context is used for variable handling.
*/
sp_head *owner;
#endif
bool local;
uint offset;
enum_field_types type;
......
......@@ -816,6 +816,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
List_iterator_fast<LEX_STRING> it_definer(triggers->
definers_list);
LEX *old_lex= thd->lex, lex;
sp_rcontext *save_spcont= thd->spcont;
ulong save_sql_mode= thd->variables.sql_mode;
thd->lex= &lex;
......@@ -831,6 +832,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
thd->variables.sql_mode= (ulong)*trg_sql_mode;
lex_start(thd, (uchar*)trg_create_str->str, trg_create_str->length);
thd->spcont= 0;
if (yyparse((void *)thd) || thd->is_fatal_error)
{
/*
......@@ -919,6 +921,7 @@ err_with_lex_cleanup:
// QQ: anything else ?
lex_end(&lex);
thd->lex= old_lex;
thd->spcont= save_spcont;
thd->variables.sql_mode= save_sql_mode;
thd->db= save_db.str;
thd->db_length= save_db.length;
......
......@@ -2286,8 +2286,12 @@ sp_case:
ivar.str= (char *)"_tmp_";
ivar.length= 5;
Item *var= (Item*) new Item_splocal(ivar,
ctx->current_pvars()-1);
Item_splocal *var= new Item_splocal(ivar,
ctx->current_pvars()-1);
#ifndef DEBUG_OFF
if (var)
var->owner= sp;
#endif
Item *expr= new Item_func_eq(var, $2);
i= new sp_instr_jump_if_not(ip, ctx, expr, lex);
......@@ -5868,7 +5872,13 @@ select_var_ident:
YYABORT;
else
{
((select_dumpvar *)lex->result)->var_list.push_back( new my_var($1,1,t->offset,t->type));
my_var *var;
((select_dumpvar *)lex->result)->
var_list.push_back(var= new my_var($1,1,t->offset,t->type));
#ifndef DEBUG_OFF
if (var)
var->owner= lex->sphead;
#endif
}
}
;
......@@ -7171,6 +7181,10 @@ simple_ident:
Item_splocal *splocal;
splocal= new Item_splocal($1, spv->offset, lex->tok_start_prev -
lex->sphead->m_tmp_query);
#ifndef DEBUG_OFF
if (splocal)
splocal->owner= lex->sphead;
#endif
$$ = (Item*) splocal;
lex->variables_used= 1;
lex->safe_to_cache_query=0;
......
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