diff options
author | Igor Babaev <igor@askmonty.org> | 2013-08-06 13:33:18 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2013-08-06 13:33:18 -0700 |
commit | f08946c0376cd2a116116685febe758ad5592741 (patch) | |
tree | 3d664545b4d913d2dea62d58fc6b561e9afe6d9c /sql | |
parent | 97e640b9ae83e07b444fceede6b0524256c7a3cc (diff) | |
parent | 86d62605e88d0bee2c4b1970ae8320c11af078d6 (diff) | |
download | mariadb-git-f08946c0376cd2a116116685febe758ad5592741.tar.gz |
Merge
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 e269c3e4040..a4bbf74e715 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -483,6 +483,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 75c422ecbf0..08e8fbe7361 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2344,7 +2344,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 32215e91225..62aa20e90f4 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -49,7 +49,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; @@ -67,6 +68,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)) @@ -91,9 +93,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); @@ -155,9 +160,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); @@ -326,9 +331,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()) { @@ -348,6 +360,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++; @@ -454,7 +472,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()); @@ -468,13 +489,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; @@ -486,7 +510,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 97bc98a5b67..5a4f3ad0907 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3243,6 +3243,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; @@ -3250,9 +3251,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 331a84c5955..e8965842140 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1459,7 +1459,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 f3abc872587..a10612e7266 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1261,6 +1261,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 */ @@ -11428,6 +11429,7 @@ single_multi: } where_clause opt_order_clause delete_limit_clause {} + opt_select_expressions {} | table_wild_list { mysql_init_multi_delete(Lex); @@ -11452,6 +11454,11 @@ single_multi: } ; +opt_select_expressions: + /* empty */ + | RETURNING_SYM select_item_list + ; + table_wild_list: table_wild_one | table_wild_list ',' table_wild_one |