A fix for Bug#32030 "DELETE does not return an error and deletes rows if
error evaluating WHERE" DELETE with a subquery in WHERE clause would sometimes ignore subquery evaluation error and proceed with deletion. The fix is to check for an error after evaluation of the WHERE clause in DELETE. Addressed review comments.
This commit is contained in:
parent
6bd9f5c1cb
commit
2ce9194411
@ -2299,8 +2299,7 @@ Handler_read_next 0
|
||||
FLUSH STATUS;
|
||||
DELETE FROM t3 WHERE (SELECT (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) x
|
||||
FROM t1) > 10000;
|
||||
Warnings:
|
||||
Error 1242 Subquery returns more than 1 row
|
||||
ERROR 21000: Subquery returns more than 1 row
|
||||
SHOW STATUS LIKE 'handler_read__e%';
|
||||
Variable_name Value
|
||||
Handler_read_key 8
|
||||
|
@ -2680,4 +2680,24 @@ t1 CREATE TABLE `t1` (
|
||||
KEY `c` (`c`(10))
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
drop table if exists t1, t2;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
Note 1051 Unknown table 't2'
|
||||
create table t1 (a int, b int);
|
||||
create table t2 like t1;
|
||||
insert into t1 (a, b) values (1,1), (1,2), (1,3), (1,4), (1,5),
|
||||
(2,2), (2,3), (2,1), (3,1), (4,1), (4,2), (4,3), (4,4), (4,5), (4,6);
|
||||
insert into t2 select a, max(b) from t1 group by a;
|
||||
prepare stmt from "delete from t2 where (select (select max(b) from t1 group
|
||||
by a having a < 2) x from t1) > 10000";
|
||||
delete from t2 where (select (select max(b) from t1 group
|
||||
by a having a < 2) x from t1) > 10000;
|
||||
ERROR 21000: Subquery returns more than 1 row
|
||||
execute stmt;
|
||||
ERROR 21000: Subquery returns more than 1 row
|
||||
execute stmt;
|
||||
ERROR 21000: Subquery returns more than 1 row
|
||||
deallocate prepare stmt;
|
||||
drop table t1, t2;
|
||||
End of 5.1 tests.
|
||||
|
@ -890,6 +890,7 @@ FLUSH STATUS;
|
||||
DELETE FROM t3 WHERE (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) > 10000;
|
||||
SHOW STATUS LIKE 'handler_read__e%';
|
||||
FLUSH STATUS;
|
||||
--error ER_SUBQUERY_NO_1_ROW
|
||||
DELETE FROM t3 WHERE (SELECT (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) x
|
||||
FROM t1) > 10000;
|
||||
SHOW STATUS LIKE 'handler_read__e%';
|
||||
|
@ -2778,4 +2778,37 @@ execute stmt;
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug #32030 DELETE does not return an error and deletes rows if error
|
||||
# evaluating WHERE
|
||||
#
|
||||
# Test that there is an error for prepared delete just like for the normal
|
||||
# one.
|
||||
#
|
||||
|
||||
drop table if exists t1, t2;
|
||||
create table t1 (a int, b int);
|
||||
create table t2 like t1;
|
||||
|
||||
insert into t1 (a, b) values (1,1), (1,2), (1,3), (1,4), (1,5),
|
||||
(2,2), (2,3), (2,1), (3,1), (4,1), (4,2), (4,3), (4,4), (4,5), (4,6);
|
||||
|
||||
insert into t2 select a, max(b) from t1 group by a;
|
||||
|
||||
prepare stmt from "delete from t2 where (select (select max(b) from t1 group
|
||||
by a having a < 2) x from t1) > 10000";
|
||||
|
||||
--error ER_SUBQUERY_NO_1_ROW
|
||||
delete from t2 where (select (select max(b) from t1 group
|
||||
by a having a < 2) x from t1) > 10000;
|
||||
--error ER_SUBQUERY_NO_1_ROW
|
||||
execute stmt;
|
||||
--error ER_SUBQUERY_NO_1_ROW
|
||||
execute stmt;
|
||||
|
||||
deallocate prepare stmt;
|
||||
drop table t1, t2;
|
||||
|
||||
|
||||
|
||||
--echo End of 5.1 tests.
|
||||
|
@ -35,6 +35,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
||||
READ_RECORD info;
|
||||
bool using_limit=limit != HA_POS_ERROR;
|
||||
bool transactional_table, safe_update, const_cond;
|
||||
bool const_cond_result;
|
||||
ha_rows deleted= 0;
|
||||
uint usable_index= MAX_KEY;
|
||||
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
||||
@ -86,6 +87,12 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
||||
|
||||
select_lex->no_error= thd->lex->ignore;
|
||||
|
||||
const_cond_result= const_cond && (!conds || conds->val_int());
|
||||
if (thd->is_error())
|
||||
{
|
||||
/* Error evaluating val_int(). */
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
/*
|
||||
Test if the user wants to delete all rows and deletion doesn't have
|
||||
any side-effects (because of triggers), so we can use optimized
|
||||
@ -105,7 +112,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
||||
- We should not be binlogging this statement row-based, and
|
||||
- there should be no delete triggers associated with the table.
|
||||
*/
|
||||
if (!using_limit && const_cond && (!conds || conds->val_int()) &&
|
||||
if (!using_limit && const_cond_result &&
|
||||
!(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) &&
|
||||
(thd->lex->sql_command == SQLCOM_TRUNCATE ||
|
||||
(!thd->current_stmt_binlog_row_based &&
|
||||
@ -300,7 +307,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
||||
else
|
||||
table->file->unlock_row(); // Row failed selection, release lock on it
|
||||
}
|
||||
if (thd->killed && !error)
|
||||
if (thd->killed || thd->is_error())
|
||||
error= 1; // Aborted
|
||||
if (will_batch && (loc_error= table->file->end_bulk_delete()))
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user