Commit d1d58b5f authored by evgen@moonbone.local's avatar evgen@moonbone.local
Browse files

Bug#27563: Stored functions and triggers wasn't throwing an error when killed.

If a stored function or a trigger was killed it had aborted but no error
was thrown. This allows the caller statement to continue without a notice.
This may lead to a wrong data being inserted/updated to/deleted as in such
cases the correct result of a stored function isn't guaranteed. In the case
of triggers it allows the caller statement to ignore kill signal and to
waste time because of re-evaluation of triggers that always will fail
because thd->killed flag is still on.

Now the Item_func_sp::execute() and the sp_head::execute_trigger() functions
check whether a function or a trigger were killed during execution and
throws an appropriate error if so.
Now the fill_record() function stops filling record if an error was reported
through thd->net.report_error.
parent 835189cb
Loading
Loading
Loading
Loading
+82 −0
Original line number Diff line number Diff line
@@ -41,3 +41,85 @@ select 1;
select RELEASE_LOCK("a");
RELEASE_LOCK("a")
1
create table t1(f1 int);
create function bug27563() returns int(11)
deterministic
begin
declare continue handler for sqlstate '70100' set @a:= 'killed';
declare continue handler for sqlexception set @a:= 'exception';
set @a= get_lock("lock27563", 10);
return 1;
end|
select get_lock("lock27563",10);
get_lock("lock27563",10)
1
insert into t1 values (bug27563());
ERROR 70100: Query execution was interrupted
select @a;
@a
NULL
select * from t1;
f1
insert into t1 values(0);
update t1 set f1= bug27563();
ERROR 70100: Query execution was interrupted
select @a;
@a
NULL
select * from t1;
f1
0
insert into t1 values(1);
delete from t1 where bug27563() is null;
ERROR 70100: Query execution was interrupted
select @a;
@a
NULL
select * from t1;
f1
0
1
select * from t1 where f1= bug27563();
ERROR 70100: Query execution was interrupted
select @a;
@a
NULL
create procedure proc27563()
begin
declare continue handler for sqlstate '70100' set @a:= 'killed';
declare continue handler for sqlexception set @a:= 'exception';
select get_lock("lock27563",10);
select "shouldn't be selected";
end|
call proc27563();
get_lock("lock27563",10)
NULL
ERROR 70100: Query execution was interrupted
select @a;
@a
NULL
create table t2 (f2 int);
create trigger trg27563 before insert on t1 for each row 
begin 
declare continue handler for sqlstate '70100' set @a:= 'killed';
declare continue handler for sqlexception set @a:= 'exception';
set @a:= get_lock("lock27563",10);
insert into t2 values(1);
end|
insert into t1 values(2),(3);
ERROR 70100: Query execution was interrupted
select @a;
@a
NULL
select * from t1;
f1
0
1
select * from t2;
f2
select release_lock("lock27563");
release_lock("lock27563")
1
drop table t1, t2;
drop function bug27563;
drop procedure proc27563;
+132 −0
Original line number Diff line number Diff line
@@ -117,3 +117,135 @@ reap;
select 1;
connection con1;
select RELEASE_LOCK("a");

#
# Bug#27563: Stored functions and triggers wasn't throwing an error when killed.
#
create table t1(f1 int);
delimiter |;
create function bug27563() returns int(11)
deterministic
begin
  declare continue handler for sqlstate '70100' set @a:= 'killed';
  declare continue handler for sqlexception set @a:= 'exception';
  set @a= get_lock("lock27563", 10);
  return 1;
end|
delimiter ;|
# Test stored functions
# Test INSERT
connection con1;
select get_lock("lock27563",10);
connection con2;
let $ID= `select connection_id()`;
send insert into t1 values (bug27563());
real_sleep 2;
connection con1;
disable_query_log;
eval kill query $ID;
enable_query_log;
connection con2;
--error 1317
reap;
select @a;
connection con1;
select * from t1;

# Test UPDATE
insert into t1 values(0);
connection con2;
send update t1 set f1= bug27563();
real_sleep 2;
connection con1;
disable_query_log;
eval kill query $ID;
enable_query_log;
connection con2;
--error 1317
reap;
select @a;
connection con1;
select * from t1;

# Test DELETE
insert into t1 values(1);
connection con2;
send delete from t1 where bug27563() is null;
real_sleep 2;
connection con1;
disable_query_log;
eval kill query $ID;
enable_query_log;
connection con2;
--error 1317
reap;
select @a;
connection con1;
select * from t1;

# Test SELECT
connection con2;
send select * from t1 where f1= bug27563();
real_sleep 2;
connection con1;
disable_query_log;
eval kill query $ID;
enable_query_log;
connection con2;
--error 1317
reap;
select @a;

# Test PROCEDURE
connection con2;
delimiter |;
create procedure proc27563()
begin
  declare continue handler for sqlstate '70100' set @a:= 'killed';
  declare continue handler for sqlexception set @a:= 'exception';
  select get_lock("lock27563",10);
  select "shouldn't be selected";
end|
delimiter ;|
send call proc27563();
real_sleep 2;
connection con1;
disable_query_log;
eval kill query $ID;
enable_query_log;
connection con2;
--error 1317
reap;
select @a;

# Test TRIGGERS
connection con2;
create table t2 (f2 int);
delimiter |;
create trigger trg27563 before insert on t1 for each row 
begin 
  declare continue handler for sqlstate '70100' set @a:= 'killed';
  declare continue handler for sqlexception set @a:= 'exception';
  set @a:= get_lock("lock27563",10);
  insert into t2 values(1);
end|
delimiter ;|
send insert into t1 values(2),(3);
real_sleep 2;
connection con1;
disable_query_log;
eval kill query $ID;
enable_query_log;
connection con2;
--error 1317
reap;
select @a;
connection con1;
select * from t1;
select * from t2;

# Cleanup
select release_lock("lock27563");
drop table t1, t2;
drop function bug27563;
drop procedure proc27563;
+2 −0
Original line number Diff line number Diff line
@@ -5347,6 +5347,8 @@ Item_func_sp::execute()
  {
    null_value= 1;
    context->process_error(thd);
    if (thd->killed)
      thd->send_kill_message();
    return TRUE;
  }

+3 −0
Original line number Diff line number Diff line
@@ -1318,6 +1318,9 @@ sp_head::execute_trigger(THD *thd, const char *db, const char *table,
  free_root(&call_mem_root, MYF(0));
  thd->spcont= octx;

  if (thd->killed)
    thd->send_kill_message();

  DBUG_RETURN(err_status);
}

+1 −1
Original line number Diff line number Diff line
@@ -5444,7 +5444,7 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors)
    table= (*ptr)->table;
    table->auto_increment_field_not_null= FALSE;
  }
  while ((field = *ptr++))
  while ((field = *ptr++) && !thd->net.report_error)
  {
    value=v++;
    table= field->table;