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