Commit ddf63bbb authored by unknown's avatar unknown

Fixed BUG#6807: Stored procedure crash if CREATE PROCEDURE ... KILL QUERY

...and for PURGE BEFORE too. (Don't fix_fields in the parser!)


mysql-test/r/sp-error.result:
  New test case for BUG#6807
mysql-test/t/sp-error.test:
  New test case for BUG#6807
sql/sql_lex.h:
  Purge and kill query args not needed in lex. (Using value_list instead)
sql/sql_parse.cc:
  Evaluate purge before and kill query args in mysql_execute_command
  instead of in the parser. (Makes it work with stored procedures)
sql/sql_yacc.yy:
  Don't evaluate (fix_fields) args in the parser for purge before and kill query.
  (Doesn't work with stored procedures)
parent bfe57bf8
...@@ -460,4 +460,17 @@ end| ...@@ -460,4 +460,17 @@ end|
call bug3294()| call bug3294()|
ERROR 42S02: Unknown table 't5' ERROR 42S02: Unknown table 't5'
drop procedure bug3294| drop procedure bug3294|
drop procedure if exists bug6807|
create procedure bug6807()
begin
declare id int;
set id = connection_id();
kill query id;
select 'Not reached';
end|
call bug6807()|
ERROR 70100: Query execution was interrupted
call bug6807()|
ERROR 70100: Query execution was interrupted
drop procedure bug6807|
drop table t1| drop table t1|
...@@ -632,6 +632,28 @@ end| ...@@ -632,6 +632,28 @@ end|
call bug3294()| call bug3294()|
drop procedure bug3294| drop procedure bug3294|
#
# BUG#6807: Stored procedure crash if CREATE PROCEDURE ... KILL QUERY
#
--disable_warnings
drop procedure if exists bug6807|
--enable_warnings
create procedure bug6807()
begin
declare id int;
set id = connection_id();
kill query id;
select 'Not reached';
end|
--error 1317
call bug6807()|
--error 1317
call bug6807()|
drop procedure bug6807|
drop table t1| drop table t1|
......
...@@ -650,7 +650,6 @@ typedef struct st_lex ...@@ -650,7 +650,6 @@ typedef struct st_lex
char *help_arg; char *help_arg;
char *backup_dir; /* For RESTORE/BACKUP */ char *backup_dir; /* For RESTORE/BACKUP */
char* to_log; /* For PURGE MASTER LOGS TO */ char* to_log; /* For PURGE MASTER LOGS TO */
time_t purge_time; /* For PURGE MASTER LOGS BEFORE */
char* x509_subject,*x509_issuer,*ssl_cipher; char* x509_subject,*x509_issuer,*ssl_cipher;
char* found_colon; /* For multi queries - next query */ char* found_colon; /* For multi queries - next query */
String *wild; String *wild;
...@@ -694,7 +693,7 @@ typedef struct st_lex ...@@ -694,7 +693,7 @@ typedef struct st_lex
HA_CREATE_INFO create_info; HA_CREATE_INFO create_info;
LEX_MASTER_INFO mi; // used by CHANGE MASTER LEX_MASTER_INFO mi; // used by CHANGE MASTER
USER_RESOURCES mqh; USER_RESOURCES mqh;
ulong thread_id,type; ulong type;
enum_sql_command sql_command, orig_sql_command; enum_sql_command sql_command, orig_sql_command;
thr_lock_type lock_option, multi_lock_option; thr_lock_type lock_option, multi_lock_option;
enum SSL_type ssl_type; /* defined in violite.h */ enum SSL_type ssl_type; /* defined in violite.h */
......
...@@ -2327,10 +2327,24 @@ mysql_execute_command(THD *thd) ...@@ -2327,10 +2327,24 @@ mysql_execute_command(THD *thd)
} }
case SQLCOM_PURGE_BEFORE: case SQLCOM_PURGE_BEFORE:
{ {
Item *it;
if (check_global_access(thd, SUPER_ACL)) if (check_global_access(thd, SUPER_ACL))
goto error; goto error;
/* PURGE MASTER LOGS BEFORE 'data' */ /* PURGE MASTER LOGS BEFORE 'data' */
res = purge_master_logs_before_date(thd, lex->purge_time); it= (Item *)lex->value_list.head();
if (it->check_cols(1) || it->fix_fields(lex->thd, 0, &it))
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE");
goto error;
}
it= new Item_func_unix_timestamp(it);
/*
it is OK only emulate fix_fieds, because we need only
value of constant
*/
it->quick_fix_field();
res = purge_master_logs_before_date(thd, (ulong)it->val_int());
break; break;
} }
#endif #endif
...@@ -3505,8 +3519,18 @@ mysql_execute_command(THD *thd) ...@@ -3505,8 +3519,18 @@ mysql_execute_command(THD *thd)
break; break;
} }
case SQLCOM_KILL: case SQLCOM_KILL:
kill_one_thread(thd,lex->thread_id, lex->type & ONLY_KILL_QUERY); {
Item *it= (Item *)lex->value_list.head();
if (it->fix_fields(lex->thd, 0, &it) || it->check_cols(1))
{
my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY),
MYF(0));
goto error;
}
kill_one_thread(thd, (ulong)it->val_int(), lex->type & ONLY_KILL_QUERY);
break; break;
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
case SQLCOM_SHOW_GRANTS: case SQLCOM_SHOW_GRANTS:
if ((thd->priv_user && if ((thd->priv_user &&
......
...@@ -6280,19 +6280,10 @@ purge_option: ...@@ -6280,19 +6280,10 @@ purge_option:
} }
| BEFORE_SYM expr | BEFORE_SYM expr
{ {
if ($2->check_cols(1) || $2->fix_fields(Lex->thd, 0, &$2)) LEX *lex= Lex;
{ lex->value_list.empty();
my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE"); lex->value_list.push_front($2);
YYABORT; lex->sql_command= SQLCOM_PURGE_BEFORE;
}
Item *tmp= new Item_func_unix_timestamp($2);
/*
it is OK only emulate fix_fieds, because we need only
value of constant
*/
tmp->quick_fix_field();
Lex->sql_command = SQLCOM_PURGE_BEFORE;
Lex->purge_time= (ulong) tmp->val_int();
} }
; ;
...@@ -6302,14 +6293,9 @@ kill: ...@@ -6302,14 +6293,9 @@ kill:
KILL_SYM kill_option expr KILL_SYM kill_option expr
{ {
LEX *lex=Lex; LEX *lex=Lex;
if ($3->fix_fields(lex->thd, 0, &$3) || $3->check_cols(1)) lex->value_list.empty();
{ lex->value_list.push_front($3);
my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), lex->sql_command= SQLCOM_KILL;
MYF(0));
YYABORT;
}
lex->sql_command=SQLCOM_KILL;
lex->thread_id= (ulong) $3->val_int();
}; };
kill_option: kill_option:
......
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