MWL#205 DELETE with result set (mdev-3814)
Includes all post-review fixes as well.
This commit is contained in:
parent
807fef40ff
commit
86d62605e8
235
mysql-test/r/delete_returning.result
Normal file
235
mysql-test/r/delete_returning.result
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
CREATE TABLE t1 (a int, b varchar(32));
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(7,'ggggggg'), (1,'a'), (3,'ccc'),
|
||||||
|
(4,'dddd'), (1,'A'), (2,'BB'), (4,'DDDD'),
|
||||||
|
(5,'EEEEE'), (7,'GGGGGGG'), (2,'bb');
|
||||||
|
CREATE TABLE t1c SELECT * FROM t1;
|
||||||
|
CREATE TABLE t2 (c int);
|
||||||
|
INSERT INTO t2 VALUES
|
||||||
|
(4), (5), (7), (1);
|
||||||
|
CREATE TABLE t2c SELECT * FROM t2;
|
||||||
|
CREATE VIEW v1 AS SELECT a, UPPER(b) FROM t1;
|
||||||
|
DELETE FROM t1 WHERE a=2 RETURNING * ;
|
||||||
|
a b
|
||||||
|
2 BB
|
||||||
|
2 bb
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b
|
||||||
|
7 ggggggg
|
||||||
|
1 a
|
||||||
|
3 ccc
|
||||||
|
4 dddd
|
||||||
|
1 A
|
||||||
|
4 DDDD
|
||||||
|
5 EEEEE
|
||||||
|
7 GGGGGGG
|
||||||
|
INSERT INTO t1 VALUES (2,'BB'), (2,'bb');
|
||||||
|
DELETE FROM t1 WHERE a=2 RETURNING b;
|
||||||
|
b
|
||||||
|
bb
|
||||||
|
BB
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b
|
||||||
|
7 ggggggg
|
||||||
|
1 a
|
||||||
|
3 ccc
|
||||||
|
4 dddd
|
||||||
|
1 A
|
||||||
|
4 DDDD
|
||||||
|
5 EEEEE
|
||||||
|
7 GGGGGGG
|
||||||
|
DELETE FROM t1 WHERE a=2 RETURNING c;
|
||||||
|
ERROR 42S22: Unknown column 'c' in 'field list'
|
||||||
|
INSERT INTO t1 VALUES (2,'BB'), (2,'bb');
|
||||||
|
DELETE FROM t1 WHERE a=2 RETURNING a, UPPER(b);
|
||||||
|
a UPPER(b)
|
||||||
|
2 BB
|
||||||
|
2 BB
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b
|
||||||
|
7 ggggggg
|
||||||
|
1 a
|
||||||
|
3 ccc
|
||||||
|
4 dddd
|
||||||
|
1 A
|
||||||
|
4 DDDD
|
||||||
|
5 EEEEE
|
||||||
|
7 GGGGGGG
|
||||||
|
INSERT INTO t1 VALUES (2,'BB'), (2,'bb');
|
||||||
|
DELETE FROM t1 WHERE a=6 RETURNING b;
|
||||||
|
b
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b
|
||||||
|
7 ggggggg
|
||||||
|
1 a
|
||||||
|
3 ccc
|
||||||
|
4 dddd
|
||||||
|
1 A
|
||||||
|
2 bb
|
||||||
|
4 DDDD
|
||||||
|
5 EEEEE
|
||||||
|
7 GGGGGGG
|
||||||
|
2 BB
|
||||||
|
DELETE FROM t1 WHERE a=2 RETURNING MAX(b);
|
||||||
|
ERROR HY000: Invalid use of group function
|
||||||
|
DELETE FROM t1 WHERE a < 5 RETURNING a, (SELECT MIN(c) FROM t2 WHERE c=a+1);
|
||||||
|
a (SELECT MIN(c) FROM t2 WHERE c=a+1)
|
||||||
|
1 NULL
|
||||||
|
3 4
|
||||||
|
4 5
|
||||||
|
1 NULL
|
||||||
|
2 NULL
|
||||||
|
4 5
|
||||||
|
2 NULL
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b
|
||||||
|
7 ggggggg
|
||||||
|
5 EEEEE
|
||||||
|
7 GGGGGGG
|
||||||
|
DELETE FROM t1;
|
||||||
|
INSERT INTO t1 SELECT * FROM t1c;
|
||||||
|
DELETE FROM t2 WHERE c < 5
|
||||||
|
RETURNING (SELECT GROUP_CONCAT(b) FROM t1 GROUP BY a HAVING a=c);
|
||||||
|
(SELECT GROUP_CONCAT(b) FROM t1 GROUP BY a HAVING a=c)
|
||||||
|
dddd,DDDD
|
||||||
|
a,A
|
||||||
|
SELECT * FROM t2;
|
||||||
|
c
|
||||||
|
5
|
||||||
|
7
|
||||||
|
DELETE FROM t2;
|
||||||
|
INSERT INTO t2 SELECT * FROM t2c;
|
||||||
|
CREATE FUNCTION f(arg INT) RETURNS TEXT
|
||||||
|
BEGIN
|
||||||
|
RETURN (SELECT GROUP_CONCAT(b) FROM t1 WHERE a=arg);
|
||||||
|
END|
|
||||||
|
DELETE FROM t2 WHERE c < 5 RETURNING f(c);
|
||||||
|
f(c)
|
||||||
|
dddd,DDDD
|
||||||
|
a,A
|
||||||
|
SELECT * FROM t2;
|
||||||
|
c
|
||||||
|
5
|
||||||
|
7
|
||||||
|
DELETE FROM t2;
|
||||||
|
INSERT INTO t2 SELECT * FROM t2c;
|
||||||
|
DROP FUNCTION f;
|
||||||
|
DELETE FROM v1 WHERE a < 5 RETURNING * ;
|
||||||
|
a UPPER(b)
|
||||||
|
1 A
|
||||||
|
3 CCC
|
||||||
|
4 DDDD
|
||||||
|
1 A
|
||||||
|
2 BB
|
||||||
|
4 DDDD
|
||||||
|
2 BB
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b
|
||||||
|
7 ggggggg
|
||||||
|
5 EEEEE
|
||||||
|
7 GGGGGGG
|
||||||
|
DELETE FROM t1;
|
||||||
|
INSERT INTO t1 SELECT * FROM t1c;
|
||||||
|
CREATE VIEW v11(a,c) AS SELECT a, COUNT(b) FROM t1 GROUP BY a;
|
||||||
|
DELETE FROM v11 WHERE a < 5 RETURNING * ;
|
||||||
|
ERROR HY000: The target table v11 of the DELETE is not updatable
|
||||||
|
DROP VIEW v11;
|
||||||
|
PREPARE stmt FROM
|
||||||
|
"DELETE FROM t1 WHERE a=2 ORDER BY b LIMIT 1 RETURNING a, UPPER(b)";
|
||||||
|
EXECUTE stmt;
|
||||||
|
a UPPER(b)
|
||||||
|
2 BB
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b
|
||||||
|
7 ggggggg
|
||||||
|
1 a
|
||||||
|
3 ccc
|
||||||
|
4 dddd
|
||||||
|
1 A
|
||||||
|
4 DDDD
|
||||||
|
5 EEEEE
|
||||||
|
7 GGGGGGG
|
||||||
|
2 bb
|
||||||
|
EXECUTE stmt;
|
||||||
|
a UPPER(b)
|
||||||
|
2 BB
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b
|
||||||
|
7 ggggggg
|
||||||
|
1 a
|
||||||
|
3 ccc
|
||||||
|
4 dddd
|
||||||
|
1 A
|
||||||
|
4 DDDD
|
||||||
|
5 EEEEE
|
||||||
|
7 GGGGGGG
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
DELETE FROM t1;
|
||||||
|
INSERT INTO t1 SELECT * FROM t1c;
|
||||||
|
FLUSH PRIVILEGES;
|
||||||
|
CREATE DATABASE mysqltest;
|
||||||
|
CREATE TABLE mysqltest.t1 SELECT * FROM t1;
|
||||||
|
GRANT DELETE ON mysqltest.* TO mysqltest_1@localhost;
|
||||||
|
GRANT SELECT(b) ON mysqltest.t1 TO mysqltest_1@localhost;
|
||||||
|
DELETE FROM mysqltest.t1 WHERE a=2 RETURNING b;
|
||||||
|
ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for column 'a' in table 't1'
|
||||||
|
DELETE FROM mysqltest.t1 RETURNING b;
|
||||||
|
b
|
||||||
|
ggggggg
|
||||||
|
a
|
||||||
|
ccc
|
||||||
|
dddd
|
||||||
|
A
|
||||||
|
BB
|
||||||
|
DDDD
|
||||||
|
EEEEE
|
||||||
|
GGGGGGG
|
||||||
|
bb
|
||||||
|
SELECT * FROM mysqltest.t1;
|
||||||
|
a b
|
||||||
|
INSERT INTO mysqltest.t1 SELECT * FROM t1;
|
||||||
|
GRANT SELECT(a) ON mysqltest.t1 TO mysqltest_1@localhost;
|
||||||
|
DELETE FROM mysqltest.t1 WHERE a=2 RETURNING b;
|
||||||
|
b
|
||||||
|
bb
|
||||||
|
BB
|
||||||
|
SELECT * FROM mysqltest.t1;
|
||||||
|
a b
|
||||||
|
7 GGGGGGG
|
||||||
|
5 EEEEE
|
||||||
|
4 DDDD
|
||||||
|
1 A
|
||||||
|
4 dddd
|
||||||
|
3 ccc
|
||||||
|
1 a
|
||||||
|
7 ggggggg
|
||||||
|
INSERT INTO mysqltest.t1 SELECT * FROM t1;
|
||||||
|
CREATE VIEW mysqltest.v1(a) AS SELECT a FROM mysqltest.t1;
|
||||||
|
GRANT SELECT, INSERT ON mysqltest.t1 TO mysqltest_1@localhost;
|
||||||
|
DELETE FROM mysqltest.v1;
|
||||||
|
SELECT * FROM mysqltest.t1;
|
||||||
|
a b
|
||||||
|
INSERT INTO mysqltest.t1 SELECT * FROM t1;
|
||||||
|
DELETE FROM mysqltest.v1 RETURNING a;
|
||||||
|
ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for column 'a' in table 'v1'
|
||||||
|
GRANT SELECT ON mysqltest.* TO mysqltest_1@localhost;
|
||||||
|
DELETE FROM mysqltest.v1 RETURNING a;
|
||||||
|
a
|
||||||
|
7
|
||||||
|
1
|
||||||
|
3
|
||||||
|
4
|
||||||
|
1
|
||||||
|
2
|
||||||
|
4
|
||||||
|
5
|
||||||
|
7
|
||||||
|
2
|
||||||
|
SELECT * FROM mysqltest.t1;
|
||||||
|
a b
|
||||||
|
INSERT INTO mysqltest.t1 SELECT * FROM t1;
|
||||||
|
DROP DATABASE mysqltest;
|
||||||
|
DROP USER mysqltest_1@localhost;
|
||||||
|
DROP VIEW v1;
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
DROP TABLE t1c,t2c;
|
189
mysql-test/t/delete_returning.test
Normal file
189
mysql-test/t/delete_returning.test
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
#
|
||||||
|
# Tests for DELETE FROM <table> ... RETURNING <expr>,...
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a int, b varchar(32));
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(7,'ggggggg'), (1,'a'), (3,'ccc'),
|
||||||
|
(4,'dddd'), (1,'A'), (2,'BB'), (4,'DDDD'),
|
||||||
|
(5,'EEEEE'), (7,'GGGGGGG'), (2,'bb');
|
||||||
|
|
||||||
|
CREATE TABLE t1c SELECT * FROM t1;
|
||||||
|
|
||||||
|
CREATE TABLE t2 (c int);
|
||||||
|
INSERT INTO t2 VALUES
|
||||||
|
(4), (5), (7), (1);
|
||||||
|
|
||||||
|
CREATE TABLE t2c SELECT * FROM t2;
|
||||||
|
|
||||||
|
CREATE VIEW v1 AS SELECT a, UPPER(b) FROM t1;
|
||||||
|
|
||||||
|
# DELETE FROM <table> ... RETURNING *
|
||||||
|
|
||||||
|
DELETE FROM t1 WHERE a=2 RETURNING * ;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (2,'BB'), (2,'bb');
|
||||||
|
|
||||||
|
# DELETE FROM <table> ... RETURNING <col>
|
||||||
|
|
||||||
|
DELETE FROM t1 WHERE a=2 RETURNING b;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
# DELETE FROM <table> ... RETURNING <not existing col>
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
DELETE FROM t1 WHERE a=2 RETURNING c;
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (2,'BB'), (2,'bb');
|
||||||
|
|
||||||
|
# DELETE FROM <table> ... RETURNING <col>, <expr>
|
||||||
|
|
||||||
|
DELETE FROM t1 WHERE a=2 RETURNING a, UPPER(b);
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (2,'BB'), (2,'bb');
|
||||||
|
|
||||||
|
# DELETE FROM <table> ... RETURNING <col> with no rows to be deleted
|
||||||
|
|
||||||
|
DELETE FROM t1 WHERE a=6 RETURNING b;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
# DELETE FROM <table> ... RETURNING <expr with aggr function>
|
||||||
|
|
||||||
|
--error ER_INVALID_GROUP_FUNC_USE
|
||||||
|
DELETE FROM t1 WHERE a=2 RETURNING MAX(b);
|
||||||
|
|
||||||
|
# DELETE FROM <table> ... RETURNING <expr with subquery>
|
||||||
|
|
||||||
|
DELETE FROM t1 WHERE a < 5 RETURNING a, (SELECT MIN(c) FROM t2 WHERE c=a+1);
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
DELETE FROM t1;
|
||||||
|
INSERT INTO t1 SELECT * FROM t1c;
|
||||||
|
|
||||||
|
DELETE FROM t2 WHERE c < 5
|
||||||
|
RETURNING (SELECT GROUP_CONCAT(b) FROM t1 GROUP BY a HAVING a=c);
|
||||||
|
SELECT * FROM t2;
|
||||||
|
|
||||||
|
DELETE FROM t2;
|
||||||
|
INSERT INTO t2 SELECT * FROM t2c;
|
||||||
|
|
||||||
|
# DELETE FROM <table> ... RETURNING <expr with function invocation>
|
||||||
|
|
||||||
|
DELIMITER |;
|
||||||
|
|
||||||
|
CREATE FUNCTION f(arg INT) RETURNS TEXT
|
||||||
|
BEGIN
|
||||||
|
RETURN (SELECT GROUP_CONCAT(b) FROM t1 WHERE a=arg);
|
||||||
|
END|
|
||||||
|
|
||||||
|
DELIMITER ;|
|
||||||
|
|
||||||
|
DELETE FROM t2 WHERE c < 5 RETURNING f(c);
|
||||||
|
SELECT * FROM t2;
|
||||||
|
|
||||||
|
DELETE FROM t2;
|
||||||
|
INSERT INTO t2 SELECT * FROM t2c;
|
||||||
|
|
||||||
|
DROP FUNCTION f;
|
||||||
|
|
||||||
|
# DELETE FROM <view> ... RETURNING <col>, <col>
|
||||||
|
|
||||||
|
DELETE FROM v1 WHERE a < 5 RETURNING * ;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
DELETE FROM t1;
|
||||||
|
INSERT INTO t1 SELECT * FROM t1c;
|
||||||
|
|
||||||
|
# DELETE FROM <view> ... RETURNING <expr>
|
||||||
|
|
||||||
|
CREATE VIEW v11(a,c) AS SELECT a, COUNT(b) FROM t1 GROUP BY a;
|
||||||
|
-- error ER_NON_UPDATABLE_TABLE
|
||||||
|
DELETE FROM v11 WHERE a < 5 RETURNING * ;
|
||||||
|
DROP VIEW v11;
|
||||||
|
|
||||||
|
# prepared DELETE FROM <table> ... RETURNING <expr>
|
||||||
|
|
||||||
|
PREPARE stmt FROM
|
||||||
|
"DELETE FROM t1 WHERE a=2 ORDER BY b LIMIT 1 RETURNING a, UPPER(b)";
|
||||||
|
EXECUTE stmt;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
EXECUTE stmt;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
DELETE FROM t1;
|
||||||
|
INSERT INTO t1 SELECT * FROM t1c;
|
||||||
|
|
||||||
|
# DELETE FROM <table> ... RETURNING ... with checking privileges
|
||||||
|
|
||||||
|
FLUSH PRIVILEGES;
|
||||||
|
|
||||||
|
connect (root,localhost,root,,test);
|
||||||
|
connection root;
|
||||||
|
--disable_warnings
|
||||||
|
CREATE DATABASE mysqltest;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
CREATE TABLE mysqltest.t1 SELECT * FROM t1;
|
||||||
|
GRANT DELETE ON mysqltest.* TO mysqltest_1@localhost;
|
||||||
|
|
||||||
|
GRANT SELECT(b) ON mysqltest.t1 TO mysqltest_1@localhost;
|
||||||
|
|
||||||
|
connect (user1,localhost,mysqltest_1,,test);
|
||||||
|
|
||||||
|
connection user1;
|
||||||
|
|
||||||
|
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||||
|
DELETE FROM mysqltest.t1 WHERE a=2 RETURNING b;
|
||||||
|
|
||||||
|
DELETE FROM mysqltest.t1 RETURNING b;
|
||||||
|
|
||||||
|
connection root;
|
||||||
|
SELECT * FROM mysqltest.t1;
|
||||||
|
INSERT INTO mysqltest.t1 SELECT * FROM t1;
|
||||||
|
|
||||||
|
GRANT SELECT(a) ON mysqltest.t1 TO mysqltest_1@localhost;
|
||||||
|
|
||||||
|
DELETE FROM mysqltest.t1 WHERE a=2 RETURNING b;
|
||||||
|
|
||||||
|
SELECT * FROM mysqltest.t1;
|
||||||
|
INSERT INTO mysqltest.t1 SELECT * FROM t1;
|
||||||
|
|
||||||
|
connection root;
|
||||||
|
CREATE VIEW mysqltest.v1(a) AS SELECT a FROM mysqltest.t1;
|
||||||
|
GRANT SELECT, INSERT ON mysqltest.t1 TO mysqltest_1@localhost;
|
||||||
|
|
||||||
|
connection user1;
|
||||||
|
|
||||||
|
DELETE FROM mysqltest.v1;
|
||||||
|
SELECT * FROM mysqltest.t1;
|
||||||
|
|
||||||
|
INSERT INTO mysqltest.t1 SELECT * FROM t1;
|
||||||
|
|
||||||
|
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||||
|
DELETE FROM mysqltest.v1 RETURNING a;
|
||||||
|
|
||||||
|
connection root;
|
||||||
|
GRANT SELECT ON mysqltest.* TO mysqltest_1@localhost;
|
||||||
|
|
||||||
|
connection user1;
|
||||||
|
DELETE FROM mysqltest.v1 RETURNING a;
|
||||||
|
SELECT * FROM mysqltest.t1;
|
||||||
|
|
||||||
|
INSERT INTO mysqltest.t1 SELECT * FROM t1;
|
||||||
|
|
||||||
|
connection root;
|
||||||
|
--disable_warnings
|
||||||
|
DROP DATABASE mysqltest;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
disconnect user1;
|
||||||
|
DROP USER mysqltest_1@localhost;
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
DROP VIEW v1;
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
DROP TABLE t1c,t2c;
|
||||||
|
|
||||||
|
|
@ -480,6 +480,7 @@ static SYMBOL symbols[] = {
|
|||||||
{ "RESTRICT", SYM(RESTRICT)},
|
{ "RESTRICT", SYM(RESTRICT)},
|
||||||
{ "RESUME", SYM(RESUME_SYM)},
|
{ "RESUME", SYM(RESUME_SYM)},
|
||||||
{ "RETURN", SYM(RETURN_SYM)},
|
{ "RETURN", SYM(RETURN_SYM)},
|
||||||
|
{ "RETURNING", SYM(RETURNING_SYM)},
|
||||||
{ "RETURNS", SYM(RETURNS_SYM)},
|
{ "RETURNS", SYM(RETURNS_SYM)},
|
||||||
{ "REVOKE", SYM(REVOKE)},
|
{ "REVOKE", SYM(REVOKE)},
|
||||||
{ "RIGHT", SYM(RIGHT)},
|
{ "RIGHT", SYM(RIGHT)},
|
||||||
|
@ -2281,7 +2281,8 @@ int select_send::send_data(List<Item> &items)
|
|||||||
Protocol *protocol= thd->protocol;
|
Protocol *protocol= thd->protocol;
|
||||||
DBUG_ENTER("select_send::send_data");
|
DBUG_ENTER("select_send::send_data");
|
||||||
|
|
||||||
if (unit->offset_limit_cnt)
|
/* unit is not set when using 'delete ... returning' */
|
||||||
|
if (unit && unit->offset_limit_cnt)
|
||||||
{ // using limit offset,count
|
{ // using limit offset,count
|
||||||
unit->offset_limit_cnt--;
|
unit->offset_limit_cnt--;
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
|
@ -48,7 +48,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
||||||
SQL_I_List<ORDER> *order_list, ha_rows limit, ulonglong options)
|
SQL_I_List<ORDER> *order_list, ha_rows limit,
|
||||||
|
ulonglong options, select_result *result)
|
||||||
{
|
{
|
||||||
bool will_batch;
|
bool will_batch;
|
||||||
int error, loc_error;
|
int error, loc_error;
|
||||||
@ -66,6 +67,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||||||
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
||||||
killed_state killed_status= NOT_KILLED;
|
killed_state killed_status= NOT_KILLED;
|
||||||
THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE;
|
THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE;
|
||||||
|
bool with_select= !select_lex->item_list.is_empty();
|
||||||
DBUG_ENTER("mysql_delete");
|
DBUG_ENTER("mysql_delete");
|
||||||
|
|
||||||
if (open_and_lock_tables(thd, table_list, TRUE, 0))
|
if (open_and_lock_tables(thd, table_list, TRUE, 0))
|
||||||
@ -90,9 +92,12 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||||||
thd_proc_info(thd, "init");
|
thd_proc_info(thd, "init");
|
||||||
table->map=1;
|
table->map=1;
|
||||||
|
|
||||||
if (mysql_prepare_delete(thd, table_list, &conds))
|
if (mysql_prepare_delete(thd, table_list, select_lex->with_wild,
|
||||||
|
select_lex->item_list, &conds))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
|
(void) result->prepare(select_lex->item_list, NULL);
|
||||||
|
|
||||||
if (thd->lex->current_select->first_cond_optimization)
|
if (thd->lex->current_select->first_cond_optimization)
|
||||||
{
|
{
|
||||||
thd->lex->current_select->save_leaf_tables(thd);
|
thd->lex->current_select->save_leaf_tables(thd);
|
||||||
@ -154,9 +159,9 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||||||
- We should not be binlogging this statement in row-based, and
|
- We should not be binlogging this statement in row-based, and
|
||||||
- there should be no delete triggers associated with the table.
|
- there should be no delete triggers associated with the table.
|
||||||
*/
|
*/
|
||||||
if (!using_limit && const_cond_result &&
|
if (!with_select && !using_limit && const_cond_result &&
|
||||||
(!thd->is_current_stmt_binlog_format_row() &&
|
(!thd->is_current_stmt_binlog_format_row() &&
|
||||||
!(table->triggers && table->triggers->has_delete_triggers())))
|
!(table->triggers && table->triggers->has_delete_triggers())))
|
||||||
{
|
{
|
||||||
/* Update the table->file->stats.records number */
|
/* Update the table->file->stats.records number */
|
||||||
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
||||||
@ -323,9 +328,16 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||||||
else
|
else
|
||||||
will_batch= !table->file->start_bulk_delete();
|
will_batch= !table->file->start_bulk_delete();
|
||||||
|
|
||||||
|
|
||||||
table->mark_columns_needed_for_delete();
|
table->mark_columns_needed_for_delete();
|
||||||
|
|
||||||
|
if (with_select)
|
||||||
|
{
|
||||||
|
if (result->send_result_set_metadata(select_lex->item_list,
|
||||||
|
Protocol::SEND_NUM_ROWS |
|
||||||
|
Protocol::SEND_EOF))
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
while (!(error=info.read_record(&info)) && !thd->killed &&
|
while (!(error=info.read_record(&info)) && !thd->killed &&
|
||||||
! thd->is_error())
|
! thd->is_error())
|
||||||
{
|
{
|
||||||
@ -343,6 +355,12 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (with_select && result->send_data(select_lex->item_list) < 0)
|
||||||
|
{
|
||||||
|
error=1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(error= table->file->ha_delete_row(table->record[0])))
|
if (!(error= table->file->ha_delete_row(table->record[0])))
|
||||||
{
|
{
|
||||||
deleted++;
|
deleted++;
|
||||||
@ -449,7 +467,10 @@ cleanup:
|
|||||||
if (error < 0 ||
|
if (error < 0 ||
|
||||||
(thd->lex->ignore && !thd->is_error() && !thd->is_fatal_error))
|
(thd->lex->ignore && !thd->is_error() && !thd->is_fatal_error))
|
||||||
{
|
{
|
||||||
my_ok(thd, deleted);
|
if (!with_select)
|
||||||
|
my_ok(thd, deleted);
|
||||||
|
else
|
||||||
|
result->send_eof();
|
||||||
DBUG_PRINT("info",("%ld records deleted",(long) deleted));
|
DBUG_PRINT("info",("%ld records deleted",(long) deleted));
|
||||||
}
|
}
|
||||||
DBUG_RETURN(error >= 0 || thd->is_error());
|
DBUG_RETURN(error >= 0 || thd->is_error());
|
||||||
@ -463,13 +484,16 @@ cleanup:
|
|||||||
mysql_prepare_delete()
|
mysql_prepare_delete()
|
||||||
thd - thread handler
|
thd - thread handler
|
||||||
table_list - global/local table list
|
table_list - global/local table list
|
||||||
|
wild_num - number of wildcards used in optional SELECT clause
|
||||||
|
field_list - list of items in optional SELECT clause
|
||||||
conds - conditions
|
conds - conditions
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
FALSE OK
|
FALSE OK
|
||||||
TRUE error
|
TRUE error
|
||||||
*/
|
*/
|
||||||
int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
|
int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list,
|
||||||
|
uint wild_num, List<Item> &field_list, Item **conds)
|
||||||
{
|
{
|
||||||
Item *fake_conds= 0;
|
Item *fake_conds= 0;
|
||||||
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
||||||
@ -481,7 +505,10 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
|
|||||||
&thd->lex->select_lex.top_join_list,
|
&thd->lex->select_lex.top_join_list,
|
||||||
table_list,
|
table_list,
|
||||||
select_lex->leaf_tables, FALSE,
|
select_lex->leaf_tables, FALSE,
|
||||||
DELETE_ACL, SELECT_ACL, TRUE) ||
|
DELETE_ACL, SELECT_ACL, TRUE))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
if ((wild_num && setup_wild(thd, table_list, field_list, NULL, wild_num)) ||
|
||||||
|
setup_fields(thd, NULL, field_list, MARK_COLUMNS_READ, NULL, 0) ||
|
||||||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
|
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
|
||||||
setup_ftfuncs(select_lex))
|
setup_ftfuncs(select_lex))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
@ -21,12 +21,15 @@
|
|||||||
class THD;
|
class THD;
|
||||||
struct TABLE_LIST;
|
struct TABLE_LIST;
|
||||||
class Item;
|
class Item;
|
||||||
|
class select_result;
|
||||||
|
|
||||||
typedef class Item COND;
|
typedef class Item COND;
|
||||||
template <typename T> class SQL_I_List;
|
template <typename T> class SQL_I_List;
|
||||||
|
|
||||||
int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds);
|
int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list,
|
||||||
|
uint wild_num, List<Item> &field_list, Item **conds);
|
||||||
bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
||||||
SQL_I_List<ORDER> *order, ha_rows rows, ulonglong options);
|
SQL_I_List<ORDER> *order, ha_rows rows,
|
||||||
|
ulonglong options, select_result *result);
|
||||||
|
|
||||||
#endif /* SQL_DELETE_INCLUDED */
|
#endif /* SQL_DELETE_INCLUDED */
|
||||||
|
@ -3169,6 +3169,7 @@ end_with_restore_list:
|
|||||||
}
|
}
|
||||||
case SQLCOM_DELETE:
|
case SQLCOM_DELETE:
|
||||||
{
|
{
|
||||||
|
select_result *sel_result=lex->result;
|
||||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||||
if ((res= delete_precheck(thd, all_tables)))
|
if ((res= delete_precheck(thd, all_tables)))
|
||||||
break;
|
break;
|
||||||
@ -3176,9 +3177,13 @@ end_with_restore_list:
|
|||||||
unit->set_limit(select_lex);
|
unit->set_limit(select_lex);
|
||||||
|
|
||||||
MYSQL_DELETE_START(thd->query());
|
MYSQL_DELETE_START(thd->query());
|
||||||
res = mysql_delete(thd, all_tables, select_lex->where,
|
if (!(sel_result= lex->result) && !(sel_result= new select_send()))
|
||||||
&select_lex->order_list,
|
return 1;
|
||||||
unit->select_limit_cnt, select_lex->options);
|
res = mysql_delete(thd, all_tables,
|
||||||
|
select_lex->where, &select_lex->order_list,
|
||||||
|
unit->select_limit_cnt, select_lex->options,
|
||||||
|
sel_result);
|
||||||
|
delete sel_result;
|
||||||
MYSQL_DELETE_DONE(res, (ulong) thd->get_row_count_func());
|
MYSQL_DELETE_DONE(res, (ulong) thd->get_row_count_func());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1451,7 +1451,10 @@ static bool mysql_test_delete(Prepared_statement *stmt,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_RETURN(mysql_prepare_delete(thd, table_list, &lex->select_lex.where));
|
DBUG_RETURN(mysql_prepare_delete(thd, table_list,
|
||||||
|
lex->select_lex.with_wild,
|
||||||
|
lex->select_lex.item_list,
|
||||||
|
&lex->select_lex.where));
|
||||||
error:
|
error:
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
@ -1256,6 +1256,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
|||||||
%token RESTORE_SYM
|
%token RESTORE_SYM
|
||||||
%token RESTRICT
|
%token RESTRICT
|
||||||
%token RESUME_SYM
|
%token RESUME_SYM
|
||||||
|
%token RETURNING_SYM
|
||||||
%token RETURNS_SYM /* SQL-2003-R */
|
%token RETURNS_SYM /* SQL-2003-R */
|
||||||
%token RETURN_SYM /* SQL-2003-R */
|
%token RETURN_SYM /* SQL-2003-R */
|
||||||
%token REVOKE /* SQL-2003-R */
|
%token REVOKE /* SQL-2003-R */
|
||||||
@ -11212,6 +11213,7 @@ single_multi:
|
|||||||
}
|
}
|
||||||
where_clause opt_order_clause
|
where_clause opt_order_clause
|
||||||
delete_limit_clause {}
|
delete_limit_clause {}
|
||||||
|
opt_select_expressions {}
|
||||||
| table_wild_list
|
| table_wild_list
|
||||||
{
|
{
|
||||||
mysql_init_multi_delete(Lex);
|
mysql_init_multi_delete(Lex);
|
||||||
@ -11236,6 +11238,11 @@ single_multi:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
opt_select_expressions:
|
||||||
|
/* empty */
|
||||||
|
| RETURNING_SYM select_item_list
|
||||||
|
;
|
||||||
|
|
||||||
table_wild_list:
|
table_wild_list:
|
||||||
table_wild_one
|
table_wild_one
|
||||||
| table_wild_list ',' table_wild_one
|
| table_wild_list ',' table_wild_one
|
||||||
|
Loading…
x
Reference in New Issue
Block a user