diff options
author | Igor Babaev <igor@askmonty.org> | 2013-08-06 13:31:38 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2013-08-06 13:31:38 -0700 |
commit | 86d62605e88d0bee2c4b1970ae8320c11af078d6 (patch) | |
tree | aa1c68294c338c283fe917437550924a687d3594 /sql | |
parent | 807fef40fffbbb8e92564a52b902b504ba8cfcdc (diff) | |
download | mariadb-git-86d62605e88d0bee2c4b1970ae8320c11af078d6.tar.gz |
MWL#205 DELETE with result set (mdev-3814)
Includes all post-review fixes as well.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/lex.h | 1 | ||||
-rw-r--r-- | sql/sql_class.cc | 3 | ||||
-rw-r--r-- | sql/sql_delete.cc | 45 | ||||
-rw-r--r-- | sql/sql_delete.h | 7 | ||||
-rw-r--r-- | sql/sql_parse.cc | 11 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 5 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 7 |
7 files changed, 63 insertions, 16 deletions
diff --git a/sql/lex.h b/sql/lex.h index dab9e2adbc4..79a9d5f5278 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -480,6 +480,7 @@ static SYMBOL symbols[] = { { "RESTRICT", SYM(RESTRICT)}, { "RESUME", SYM(RESUME_SYM)}, { "RETURN", SYM(RETURN_SYM)}, + { "RETURNING", SYM(RETURNING_SYM)}, { "RETURNS", SYM(RETURNS_SYM)}, { "REVOKE", SYM(REVOKE)}, { "RIGHT", SYM(RIGHT)}, diff --git a/sql/sql_class.cc b/sql/sql_class.cc index c2e8d17c355..34b1cb5da5a 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2281,7 +2281,8 @@ int select_send::send_data(List<Item> &items) Protocol *protocol= thd->protocol; 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 unit->offset_limit_cnt--; DBUG_RETURN(FALSE); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 5dff27b2f89..5af4509162e 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -48,7 +48,8 @@ */ 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; 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; killed_state killed_status= NOT_KILLED; THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE; + bool with_select= !select_lex->item_list.is_empty(); DBUG_ENTER("mysql_delete"); 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"); 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); + (void) result->prepare(select_lex->item_list, NULL); + if (thd->lex->current_select->first_cond_optimization) { 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 - there should be no delete triggers associated with the table. */ - if (!using_limit && const_cond_result && - (!thd->is_current_stmt_binlog_format_row() && - !(table->triggers && table->triggers->has_delete_triggers()))) + if (!with_select && !using_limit && const_cond_result && + (!thd->is_current_stmt_binlog_format_row() && + !(table->triggers && table->triggers->has_delete_triggers()))) { /* Update the table->file->stats.records number */ 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 will_batch= !table->file->start_bulk_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 && ! thd->is_error()) { @@ -343,6 +355,12 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, 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]))) { deleted++; @@ -449,7 +467,10 @@ cleanup: if (error < 0 || (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_RETURN(error >= 0 || thd->is_error()); @@ -463,13 +484,16 @@ cleanup: mysql_prepare_delete() thd - thread handler 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 RETURN VALUE FALSE OK 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; 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, table_list, 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_ftfuncs(select_lex)) DBUG_RETURN(TRUE); diff --git a/sql/sql_delete.h b/sql/sql_delete.h index 6147e0ea367..9cd09dc5722 100644 --- a/sql/sql_delete.h +++ b/sql/sql_delete.h @@ -21,12 +21,15 @@ class THD; struct TABLE_LIST; class Item; +class select_result; typedef class Item COND; 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, - 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 */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 49d41614cc5..7985052f512 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3169,6 +3169,7 @@ end_with_restore_list: } case SQLCOM_DELETE: { + select_result *sel_result=lex->result; DBUG_ASSERT(first_table == all_tables && first_table != 0); if ((res= delete_precheck(thd, all_tables))) break; @@ -3176,9 +3177,13 @@ end_with_restore_list: unit->set_limit(select_lex); MYSQL_DELETE_START(thd->query()); - res = mysql_delete(thd, all_tables, select_lex->where, - &select_lex->order_list, - unit->select_limit_cnt, select_lex->options); + if (!(sel_result= lex->result) && !(sel_result= new select_send())) + return 1; + 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()); break; } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index d3e3195081d..90f693b4ca3 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1451,7 +1451,10 @@ static bool mysql_test_delete(Prepared_statement *stmt, 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: DBUG_RETURN(TRUE); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2eb2fe6911a..d45d77c9fb9 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1256,6 +1256,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token RESTORE_SYM %token RESTRICT %token RESUME_SYM +%token RETURNING_SYM %token RETURNS_SYM /* SQL-2003-R */ %token RETURN_SYM /* SQL-2003-R */ %token REVOKE /* SQL-2003-R */ @@ -11212,6 +11213,7 @@ single_multi: } where_clause opt_order_clause delete_limit_clause {} + opt_select_expressions {} | table_wild_list { 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_one | table_wild_list ',' table_wild_one |