Commit 86d62605 authored by Igor Babaev's avatar Igor Babaev

MWL#205 DELETE with result set (mdev-3814)

Includes all post-review fixes as well. 
parent 807fef40
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;
#
# 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[] = { ...@@ -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) ...@@ -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 @@ ...@@ -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, ...@@ -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, ...@@ -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,7 +159,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ...@@ -154,7 +159,7 @@ 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())))
{ {
...@@ -323,9 +328,16 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ...@@ -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, ...@@ -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: ...@@ -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))
{ {
if (!with_select)
my_ok(thd, deleted); 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: ...@@ -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) ...@@ -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 @@ ...@@ -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: ...@@ -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: ...@@ -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, ...@@ -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); ...@@ -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: ...@@ -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: ...@@ -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
......
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