1 /*
2 Copyright (c) 2000, 2019, Oracle and/or its affiliates.
3 Copyright (c) 2010, 2021, MariaDB
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; version 2 of the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
17
18 /*
19 Delete of records tables.
20
21 Multi-table deletes were introduced by Monty and Sinisa
22 */
23
24 #include "mariadb.h"
25 #include "sql_priv.h"
26 #include "unireg.h"
27 #include "sql_delete.h"
28 #include "sql_cache.h" // query_cache_*
29 #include "sql_base.h" // open_temprary_table
30 #include "lock.h" // unlock_table_name
31 #include "sql_view.h" // check_key_in_view, mysql_frm_type
32 #include "sql_parse.h" // mysql_init_select
33 #include "sql_acl.h" // *_ACL
34 #include "filesort.h" // filesort
35 #include "sql_handler.h" // mysql_ha_rm_tables
36 #include "sql_select.h"
37 #include "sp_head.h"
38 #include "sql_trigger.h"
39 #include "sql_statistics.h"
40 #include "transaction.h"
41 #include "records.h" // init_read_record,
42 #include "filesort.h"
43 #include "uniques.h"
44 #include "sql_derived.h" // mysql_handle_derived
45 // end_read_record
46 #include "sql_partition.h" // make_used_partitions_str
47
48 #define MEM_STRIP_BUF_SIZE ((size_t) thd->variables.sortbuff_size)
49
50 /*
51 @brief
52 Print query plan of a single-table DELETE command
53
54 @detail
55 This function is used by EXPLAIN DELETE and by SHOW EXPLAIN when it is
56 invoked on a running DELETE statement.
57 */
58
save_explain_delete_data(MEM_ROOT * mem_root,THD * thd)59 Explain_delete* Delete_plan::save_explain_delete_data(MEM_ROOT *mem_root, THD *thd)
60 {
61 Explain_query *query= thd->lex->explain;
62 Explain_delete *explain=
63 new (mem_root) Explain_delete(mem_root, thd->lex->analyze_stmt);
64 if (!explain)
65 return 0;
66
67 if (deleting_all_rows)
68 {
69 explain->deleting_all_rows= true;
70 explain->select_type= "SIMPLE";
71 explain->rows= scanned_rows;
72 }
73 else
74 {
75 explain->deleting_all_rows= false;
76 if (Update_plan::save_explain_data_intern(mem_root, explain,
77 thd->lex->analyze_stmt))
78 return 0;
79 }
80
81 query->add_upd_del_plan(explain);
82 return explain;
83 }
84
85
86 Explain_update*
save_explain_update_data(MEM_ROOT * mem_root,THD * thd)87 Update_plan::save_explain_update_data(MEM_ROOT *mem_root, THD *thd)
88 {
89 Explain_query *query= thd->lex->explain;
90 Explain_update* explain=
91 new (mem_root) Explain_update(mem_root, thd->lex->analyze_stmt);
92 if (!explain)
93 return 0;
94 if (save_explain_data_intern(mem_root, explain, thd->lex->analyze_stmt))
95 return 0;
96 query->add_upd_del_plan(explain);
97 return explain;
98 }
99
100
save_explain_data_intern(MEM_ROOT * mem_root,Explain_update * explain,bool is_analyze)101 bool Update_plan::save_explain_data_intern(MEM_ROOT *mem_root,
102 Explain_update *explain,
103 bool is_analyze)
104 {
105 explain->select_type= "SIMPLE";
106 explain->table_name.append(&table->pos_in_table_list->alias);
107
108 explain->impossible_where= false;
109 explain->no_partitions= false;
110
111 if (impossible_where)
112 {
113 explain->impossible_where= true;
114 return 0;
115 }
116
117 if (no_partitions)
118 {
119 explain->no_partitions= true;
120 return 0;
121 }
122
123 if (is_analyze)
124 table->file->set_time_tracker(&explain->table_tracker);
125
126 select_lex->set_explain_type(TRUE);
127 explain->select_type= select_lex->type;
128 /* Partitions */
129 {
130 #ifdef WITH_PARTITION_STORAGE_ENGINE
131 partition_info *part_info;
132 if ((part_info= table->part_info))
133 {
134 make_used_partitions_str(mem_root, part_info, &explain->used_partitions,
135 explain->used_partitions_list);
136 explain->used_partitions_set= true;
137 }
138 else
139 explain->used_partitions_set= false;
140 #else
141 /* just produce empty column if partitioning is not compiled in */
142 explain->used_partitions_set= false;
143 #endif
144 }
145
146
147 /* Set jtype */
148 if (select && select->quick)
149 {
150 int quick_type= select->quick->get_type();
151 if ((quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE) ||
152 (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_INTERSECT) ||
153 (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT) ||
154 (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION))
155 explain->jtype= JT_INDEX_MERGE;
156 else
157 explain->jtype= JT_RANGE;
158 }
159 else
160 {
161 if (index == MAX_KEY)
162 explain->jtype= JT_ALL;
163 else
164 explain->jtype= JT_NEXT;
165 }
166
167 explain->using_where= MY_TEST(select && select->cond);
168 explain->where_cond= select? select->cond: NULL;
169
170 if (using_filesort)
171 if (!(explain->filesort_tracker= new (mem_root) Filesort_tracker(is_analyze)))
172 return 1;
173 explain->using_io_buffer= using_io_buffer;
174
175 append_possible_keys(mem_root, explain->possible_keys, table,
176 possible_keys);
177
178 explain->quick_info= NULL;
179
180 /* Calculate key_len */
181 if (select && select->quick)
182 {
183 explain->quick_info= select->quick->get_explain(mem_root);
184 }
185 else
186 {
187 if (index != MAX_KEY)
188 {
189 explain->key.set(mem_root, &table->key_info[index],
190 table->key_info[index].key_length);
191 }
192 }
193 explain->rows= scanned_rows;
194
195 if (select && select->quick &&
196 select->quick->get_type() == QUICK_SELECT_I::QS_TYPE_RANGE)
197 {
198 explain_append_mrr_info((QUICK_RANGE_SELECT*)select->quick,
199 &explain->mrr_type);
200 }
201
202 bool skip= updating_a_view;
203
204 /* Save subquery children */
205 for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit();
206 unit;
207 unit= unit->next_unit())
208 {
209 if (skip)
210 {
211 skip= false;
212 continue;
213 }
214 /*
215 Display subqueries only if they are not parts of eliminated WHERE/ON
216 clauses.
217 */
218 if (!(unit->item && unit->item->eliminated))
219 explain->add_child(unit->first_select()->select_number);
220 }
221 return 0;
222 }
223
224
record_should_be_deleted(THD * thd,TABLE * table,SQL_SELECT * sel,Explain_delete * explain,bool truncate_history)225 static bool record_should_be_deleted(THD *thd, TABLE *table, SQL_SELECT *sel,
226 Explain_delete *explain, bool truncate_history)
227 {
228 explain->tracker.on_record_read();
229 thd->inc_examined_row_count(1);
230 if (table->vfield)
231 (void) table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_DELETE);
232 if (!sel || sel->skip_record(thd) > 0)
233 {
234 explain->tracker.on_record_after_where();
235 return true;
236 }
237 return false;
238 }
239
240 static
update_portion_of_time(THD * thd,TABLE * table,const vers_select_conds_t & period_conds,bool * inside_period)241 int update_portion_of_time(THD *thd, TABLE *table,
242 const vers_select_conds_t &period_conds,
243 bool *inside_period)
244 {
245 bool lcond= period_conds.field_start->val_datetime_packed(thd)
246 < period_conds.start.item->val_datetime_packed(thd);
247 bool rcond= period_conds.field_end->val_datetime_packed(thd)
248 > period_conds.end.item->val_datetime_packed(thd);
249
250 *inside_period= !lcond && !rcond;
251 if (*inside_period)
252 return 0;
253
254 DBUG_ASSERT(!table->triggers
255 || !table->triggers->has_triggers(TRG_EVENT_INSERT,
256 TRG_ACTION_BEFORE));
257
258 int res= 0;
259 Item *src= lcond ? period_conds.start.item : period_conds.end.item;
260 uint dst_fieldno= lcond ? table->s->period.end_fieldno
261 : table->s->period.start_fieldno;
262
263 ulonglong prev_insert_id= table->file->next_insert_id;
264 store_record(table, record[1]);
265 if (likely(!res))
266 res= src->save_in_field(table->field[dst_fieldno], true);
267
268 if (likely(!res))
269 res= table->update_generated_fields();
270
271 if(likely(!res))
272 res= table->file->ha_update_row(table->record[1], table->record[0]);
273
274 if (likely(!res) && table->triggers)
275 res= table->triggers->process_triggers(thd, TRG_EVENT_INSERT,
276 TRG_ACTION_AFTER, true);
277 restore_record(table, record[1]);
278 if (res)
279 table->file->restore_auto_increment(prev_insert_id);
280
281 if (likely(!res) && lcond && rcond)
282 res= table->period_make_insert(period_conds.end.item,
283 table->field[table->s->period.start_fieldno]);
284
285 return res;
286 }
287
288 inline
delete_row()289 int TABLE::delete_row()
290 {
291 if (!versioned(VERS_TIMESTAMP) || !vers_end_field()->is_max())
292 return file->ha_delete_row(record[0]);
293
294 store_record(this, record[1]);
295 vers_update_end();
296 int err= file->ha_update_row(record[1], record[0]);
297 /*
298 MDEV-23644: we get HA_ERR_FOREIGN_DUPLICATE_KEY iff we already got history
299 row with same trx_id which is the result of foreign key action, so we
300 don't need one more history row.
301 */
302 if (err == HA_ERR_FOREIGN_DUPLICATE_KEY)
303 return file->ha_delete_row(record[0]);
304 return err;
305 }
306
307
308 /**
309 Implement DELETE SQL word.
310
311 @note Like implementations of other DDL/DML in MySQL, this function
312 relies on the caller to close the thread tables. This is done in the
313 end of dispatch_command().
314 */
315
mysql_delete(THD * thd,TABLE_LIST * table_list,COND * conds,SQL_I_List<ORDER> * order_list,ha_rows limit,ulonglong options,select_result * result)316 bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
317 SQL_I_List<ORDER> *order_list, ha_rows limit,
318 ulonglong options, select_result *result)
319 {
320 bool will_batch= FALSE;
321 int error, loc_error;
322 TABLE *table;
323 SQL_SELECT *select=0;
324 SORT_INFO *file_sort= 0;
325 READ_RECORD info;
326 bool using_limit=limit != HA_POS_ERROR;
327 bool transactional_table, safe_update, const_cond;
328 bool const_cond_result;
329 bool return_error= 0;
330 ha_rows deleted= 0;
331 bool reverse= FALSE;
332 bool has_triggers= false;
333 ORDER *order= (ORDER *) ((order_list && order_list->elements) ?
334 order_list->first : NULL);
335 SELECT_LEX *select_lex= thd->lex->first_select_lex();
336 killed_state killed_status= NOT_KILLED;
337 THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE;
338 bool binlog_is_row;
339 bool with_select= !select_lex->item_list.is_empty();
340 Explain_delete *explain;
341 Delete_plan query_plan(thd->mem_root);
342 Unique * deltempfile= NULL;
343 bool delete_record= false;
344 bool delete_while_scanning;
345 bool portion_of_time_through_update;
346 DBUG_ENTER("mysql_delete");
347
348 query_plan.index= MAX_KEY;
349 query_plan.using_filesort= FALSE;
350
351 create_explain_query(thd->lex, thd->mem_root);
352 if (open_and_lock_tables(thd, table_list, TRUE, 0))
353 DBUG_RETURN(TRUE);
354
355 THD_STAGE_INFO(thd, stage_init_update);
356
357 const bool delete_history= table_list->vers_conditions.delete_history;
358 DBUG_ASSERT(!(delete_history && table_list->period_conditions.is_set()));
359
360 if (thd->lex->handle_list_of_derived(table_list, DT_MERGE_FOR_INSERT))
361 DBUG_RETURN(TRUE);
362 if (thd->lex->handle_list_of_derived(table_list, DT_PREPARE))
363 DBUG_RETURN(TRUE);
364
365 if (!table_list->single_table_updatable())
366 {
367 my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE");
368 DBUG_RETURN(TRUE);
369 }
370 if (!(table= table_list->table) || !table->is_created())
371 {
372 my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
373 table_list->view_db.str, table_list->view_name.str);
374 DBUG_RETURN(TRUE);
375 }
376 table->map=1;
377 query_plan.select_lex= thd->lex->first_select_lex();
378 query_plan.table= table;
379 query_plan.updating_a_view= MY_TEST(table_list->view);
380
381 promote_select_describe_flag_if_needed(thd->lex);
382
383 if (mysql_prepare_delete(thd, table_list, select_lex->with_wild,
384 select_lex->item_list, &conds,
385 &delete_while_scanning))
386 DBUG_RETURN(TRUE);
387
388 if (delete_history)
389 table->vers_write= false;
390
391 if (with_select)
392 (void) result->prepare(select_lex->item_list, NULL);
393
394 if (thd->lex->current_select->first_cond_optimization)
395 {
396 thd->lex->current_select->save_leaf_tables(thd);
397 thd->lex->current_select->first_cond_optimization= 0;
398 }
399 /* check ORDER BY even if it can be ignored */
400 if (order)
401 {
402 TABLE_LIST tables;
403 List<Item> fields;
404 List<Item> all_fields;
405
406 bzero((char*) &tables,sizeof(tables));
407 tables.table = table;
408 tables.alias = table_list->alias;
409
410 if (select_lex->setup_ref_array(thd, order_list->elements) ||
411 setup_order(thd, select_lex->ref_pointer_array, &tables,
412 fields, all_fields, order))
413 {
414 free_underlaid_joins(thd, thd->lex->first_select_lex());
415 DBUG_RETURN(TRUE);
416 }
417 }
418
419 /* Apply the IN=>EXISTS transformation to all subqueries and optimize them. */
420 if (select_lex->optimize_unflattened_subqueries(false))
421 DBUG_RETURN(TRUE);
422
423 const_cond= (!conds || conds->const_item());
424 safe_update= MY_TEST(thd->variables.option_bits & OPTION_SAFE_UPDATES);
425 if (safe_update && const_cond)
426 {
427 my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
428 ER_THD(thd, ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
429 DBUG_RETURN(TRUE);
430 }
431
432 const_cond_result= const_cond && (!conds || conds->val_int());
433 if (unlikely(thd->is_error()))
434 {
435 /* Error evaluating val_int(). */
436 DBUG_RETURN(TRUE);
437 }
438
439 /*
440 Test if the user wants to delete all rows and deletion doesn't have
441 any side-effects (because of triggers), so we can use optimized
442 handler::delete_all_rows() method.
443
444 We can use delete_all_rows() if and only if:
445 - We allow new functions (not using option --skip-new), and are
446 not in safe mode (not using option --safe-mode)
447 - There is no limit clause
448 - The condition is constant
449 - If there is a condition, then it it produces a non-zero value
450 - If the current command is DELETE FROM with no where clause, then:
451 - We should not be binlogging this statement in row-based, and
452 - there should be no delete triggers associated with the table.
453 */
454
455 has_triggers= table->triggers && table->triggers->has_delete_triggers();
456
457 if (!with_select && !using_limit && const_cond_result &&
458 (!thd->is_current_stmt_binlog_format_row() &&
459 !has_triggers)
460 && !table->versioned(VERS_TIMESTAMP) && !table_list->has_period())
461 {
462 /* Update the table->file->stats.records number */
463 table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
464 ha_rows const maybe_deleted= table->file->stats.records;
465 DBUG_PRINT("debug", ("Trying to use delete_all_rows()"));
466
467 query_plan.set_delete_all_rows(maybe_deleted);
468 if (thd->lex->describe)
469 goto produce_explain_and_leave;
470
471 if (likely(!(error=table->file->ha_delete_all_rows())))
472 {
473 /*
474 If delete_all_rows() is used, it is not possible to log the
475 query in row format, so we have to log it in statement format.
476 */
477 query_type= THD::STMT_QUERY_TYPE;
478 error= -1;
479 deleted= maybe_deleted;
480 if (!query_plan.save_explain_delete_data(thd->mem_root, thd))
481 error= 1;
482 goto cleanup;
483 }
484 if (error != HA_ERR_WRONG_COMMAND)
485 {
486 table->file->print_error(error,MYF(0));
487 error=0;
488 goto cleanup;
489 }
490 /* Handler didn't support fast delete; Delete rows one by one */
491 query_plan.cancel_delete_all_rows();
492 }
493 if (conds)
494 {
495 Item::cond_result result;
496 conds= conds->remove_eq_conds(thd, &result, true);
497 if (result == Item::COND_FALSE) // Impossible where
498 {
499 limit= 0;
500 query_plan.set_impossible_where();
501 if (thd->lex->describe || thd->lex->analyze_stmt)
502 goto produce_explain_and_leave;
503 }
504 }
505
506 #ifdef WITH_PARTITION_STORAGE_ENGINE
507 if (prune_partitions(thd, table, conds))
508 {
509 free_underlaid_joins(thd, select_lex);
510
511 query_plan.set_no_partitions();
512 if (thd->lex->describe || thd->lex->analyze_stmt)
513 goto produce_explain_and_leave;
514
515 my_ok(thd, 0);
516 DBUG_RETURN(0);
517 }
518 #endif
519 /* Update the table->file->stats.records number */
520 table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
521 set_statistics_for_table(thd, table);
522
523 table->covering_keys.clear_all();
524 table->quick_keys.clear_all(); // Can't use 'only index'
525
526 select=make_select(table, 0, 0, conds, (SORT_INFO*) 0, 0, &error);
527 if (unlikely(error))
528 DBUG_RETURN(TRUE);
529 if ((select && select->check_quick(thd, safe_update, limit)) || !limit)
530 {
531 query_plan.set_impossible_where();
532 if (thd->lex->describe || thd->lex->analyze_stmt)
533 goto produce_explain_and_leave;
534
535 delete select;
536 free_underlaid_joins(thd, select_lex);
537 /*
538 Error was already created by quick select evaluation (check_quick()).
539 TODO: Add error code output parameter to Item::val_xxx() methods.
540 Currently they rely on the user checking DA for
541 errors when unwinding the stack after calling Item::val_xxx().
542 */
543 if (unlikely(thd->is_error()))
544 DBUG_RETURN(TRUE);
545 my_ok(thd, 0);
546 DBUG_RETURN(0); // Nothing to delete
547 }
548
549 /* If running in safe sql mode, don't allow updates without keys */
550 if (table->quick_keys.is_clear_all())
551 {
552 thd->set_status_no_index_used();
553 if (safe_update && !using_limit)
554 {
555 delete select;
556 free_underlaid_joins(thd, select_lex);
557 my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
558 ER_THD(thd, ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
559 DBUG_RETURN(TRUE);
560 }
561 }
562 if (options & OPTION_QUICK)
563 (void) table->file->extra(HA_EXTRA_QUICK);
564
565 query_plan.scanned_rows= select? select->records: table->file->stats.records;
566 if (order)
567 {
568 table->update_const_key_parts(conds);
569 order= simple_remove_const(order, conds);
570
571 if (select && select->quick && select->quick->unique_key_range())
572 { // Single row select (always "ordered")
573 query_plan.using_filesort= FALSE;
574 query_plan.index= MAX_KEY;
575 }
576 else
577 {
578 ha_rows scanned_limit= query_plan.scanned_rows;
579 query_plan.index= get_index_for_order(order, table, select, limit,
580 &scanned_limit,
581 &query_plan.using_filesort,
582 &reverse);
583 if (!query_plan.using_filesort)
584 query_plan.scanned_rows= scanned_limit;
585 }
586 }
587
588 query_plan.select= select;
589 query_plan.possible_keys= select? select->possible_keys: key_map(0);
590
591 /*
592 Ok, we have generated a query plan for the DELETE.
593 - if we're running EXPLAIN DELETE, goto produce explain output
594 - otherwise, execute the query plan
595 */
596 if (thd->lex->describe)
597 goto produce_explain_and_leave;
598
599 if (!(explain= query_plan.save_explain_delete_data(thd->mem_root, thd)))
600 goto got_error;
601 ANALYZE_START_TRACKING(&explain->command_tracker);
602
603 DBUG_EXECUTE_IF("show_explain_probe_delete_exec_start",
604 dbug_serve_apcs(thd, 1););
605
606 if (!(select && select->quick))
607 status_var_increment(thd->status_var.delete_scan_count);
608
609 binlog_is_row= thd->is_current_stmt_binlog_format_row();
610 DBUG_PRINT("info", ("binlog_is_row: %s", binlog_is_row ? "TRUE" : "FALSE"));
611
612 /*
613 We can use direct delete (delete that is done silently in the handler)
614 if none of the following conditions are true:
615 - There are triggers
616 - There is binary logging
617 - There is a virtual not stored column in the WHERE clause
618 - ORDER BY or LIMIT
619 - As this requires the rows to be deleted in a specific order
620 - Note that Spider can handle ORDER BY and LIMIT in a cluster with
621 one data node. These conditions are therefore checked in
622 direct_delete_rows_init().
623
624 Direct delete does not require a WHERE clause
625
626 Later we also ensure that we are only using one table (no sub queries)
627 */
628
629 if ((table->file->ha_table_flags() & HA_CAN_DIRECT_UPDATE_AND_DELETE) &&
630 !has_triggers && !binlog_is_row && !with_select &&
631 !table_list->has_period())
632 {
633 table->mark_columns_needed_for_delete();
634 if (!table->check_virtual_columns_marked_for_read())
635 {
636 DBUG_PRINT("info", ("Trying direct delete"));
637 bool use_direct_delete= !select || !select->cond;
638 if (!use_direct_delete &&
639 (select->cond->used_tables() & ~RAND_TABLE_BIT) == table->map)
640 {
641 DBUG_ASSERT(!table->file->pushed_cond);
642 if (!table->file->cond_push(select->cond))
643 {
644 use_direct_delete= TRUE;
645 table->file->pushed_cond= select->cond;
646 }
647 }
648 if (use_direct_delete && !table->file->direct_delete_rows_init())
649 {
650 /* Direct deleting is supported */
651 DBUG_PRINT("info", ("Using direct delete"));
652 THD_STAGE_INFO(thd, stage_updating);
653 if (!(error= table->file->ha_direct_delete_rows(&deleted)))
654 error= -1;
655 goto terminate_delete;
656 }
657 }
658 }
659
660 if (query_plan.using_filesort)
661 {
662 {
663 Filesort fsort(order, HA_POS_ERROR, true, select);
664 DBUG_ASSERT(query_plan.index == MAX_KEY);
665
666 Filesort_tracker *fs_tracker=
667 thd->lex->explain->get_upd_del_plan()->filesort_tracker;
668
669 if (!(file_sort= filesort(thd, table, &fsort, fs_tracker)))
670 goto got_error;
671
672 thd->inc_examined_row_count(file_sort->examined_rows);
673 /*
674 Filesort has already found and selected the rows we want to delete,
675 so we don't need the where clause
676 */
677 delete select;
678
679 /*
680 If we are not in DELETE ... RETURNING, we can free subqueries. (in
681 DELETE ... RETURNING we can't, because the RETURNING part may have
682 a subquery in it)
683 */
684 if (!with_select)
685 free_underlaid_joins(thd, select_lex);
686 select= 0;
687 }
688 }
689
690 /* If quick select is used, initialize it before retrieving rows. */
691 if (select && select->quick && select->quick->reset())
692 goto got_error;
693
694 if (query_plan.index == MAX_KEY || (select && select->quick))
695 error= init_read_record(&info, thd, table, select, file_sort, 1, 1, FALSE);
696 else
697 error= init_read_record_idx(&info, thd, table, 1, query_plan.index,
698 reverse);
699 if (unlikely(error))
700 goto got_error;
701
702 if (unlikely(init_ftfuncs(thd, select_lex, 1)))
703 goto got_error;
704
705 if (table_list->has_period())
706 {
707 table->use_all_columns();
708 table->rpl_write_set= table->write_set;
709 }
710 else
711 {
712 table->mark_columns_needed_for_delete();
713 }
714
715 if ((table->file->ha_table_flags() & HA_CAN_FORCE_BULK_DELETE) &&
716 !table->prepare_triggers_for_delete_stmt_or_event())
717 will_batch= !table->file->start_bulk_delete();
718
719 if (with_select)
720 {
721 if (unlikely(result->send_result_set_metadata(select_lex->item_list,
722 Protocol::SEND_NUM_ROWS |
723 Protocol::SEND_EOF)))
724 goto cleanup;
725 }
726
727 explain= (Explain_delete*)thd->lex->explain->get_upd_del_plan();
728 explain->tracker.on_scan_init();
729
730 if (!delete_while_scanning)
731 {
732 /*
733 The table we are going to delete appears in subqueries in the where
734 clause. Instead of deleting the rows, first mark them deleted.
735 */
736 ha_rows tmplimit=limit;
737 deltempfile= new (thd->mem_root) Unique (refpos_order_cmp, table->file,
738 table->file->ref_length,
739 MEM_STRIP_BUF_SIZE);
740
741 THD_STAGE_INFO(thd, stage_searching_rows_for_update);
742 while (!(error=info.read_record()) && !thd->killed &&
743 ! thd->is_error())
744 {
745 if (record_should_be_deleted(thd, table, select, explain, delete_history))
746 {
747 table->file->position(table->record[0]);
748 if (unlikely((error=
749 deltempfile->unique_add((char*) table->file->ref))))
750 {
751 error= 1;
752 goto terminate_delete;
753 }
754 if (!--tmplimit && using_limit)
755 break;
756 }
757 }
758 end_read_record(&info);
759 if (unlikely(deltempfile->get(table)) ||
760 unlikely(table->file->ha_index_or_rnd_end()) ||
761 unlikely(init_read_record(&info, thd, table, 0, &deltempfile->sort, 0,
762 1, false)))
763 {
764 error= 1;
765 goto terminate_delete;
766 }
767 delete_record= true;
768 }
769
770 /*
771 From SQL2016, Part 2, 15.7 <Effect of deleting rows from base table>,
772 General Rules, 8), we can conclude that DELETE FOR PORTTION OF time performs
773 0-2 INSERTS + DELETE. We can substitute INSERT+DELETE with one UPDATE, with
774 a condition of no side effects. The side effect is possible if there is a
775 BEFORE INSERT trigger, since it is the only one splitting DELETE and INSERT
776 operations.
777 Another possible side effect is related to tables of non-transactional
778 engines, since UPDATE is anyway atomic, and DELETE+INSERT is not.
779
780 This optimization is not possible for system-versioned table.
781 */
782 portion_of_time_through_update=
783 !(table->triggers && table->triggers->has_triggers(TRG_EVENT_INSERT,
784 TRG_ACTION_BEFORE))
785 && !table->versioned()
786 && table->file->has_transactions();
787
788 THD_STAGE_INFO(thd, stage_updating);
789 while (likely(!(error=info.read_record())) && likely(!thd->killed) &&
790 likely(!thd->is_error()))
791 {
792 if (delete_while_scanning)
793 delete_record= record_should_be_deleted(thd, table, select, explain,
794 delete_history);
795 if (delete_record)
796 {
797 if (!delete_history && table->triggers &&
798 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
799 TRG_ACTION_BEFORE, FALSE))
800 {
801 error= 1;
802 break;
803 }
804
805 if (with_select && result->send_data(select_lex->item_list) < 0)
806 {
807 error=1;
808 break;
809 }
810
811 if (table_list->has_period() && portion_of_time_through_update)
812 {
813 bool need_delete= true;
814 error= update_portion_of_time(thd, table, table_list->period_conditions,
815 &need_delete);
816 if (likely(!error) && need_delete)
817 error= table->delete_row();
818 }
819 else
820 {
821 error= table->delete_row();
822
823 ha_rows rows_inserted;
824 if (likely(!error) && table_list->has_period()
825 && !portion_of_time_through_update)
826 error= table->insert_portion_of_time(thd, table_list->period_conditions,
827 &rows_inserted);
828 }
829
830 if (likely(!error))
831 {
832 deleted++;
833 if (!delete_history && table->triggers &&
834 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
835 TRG_ACTION_AFTER, FALSE))
836 {
837 error= 1;
838 break;
839 }
840 if (!--limit && using_limit)
841 {
842 error= -1;
843 break;
844 }
845 }
846 else
847 {
848 table->file->print_error(error,
849 MYF(thd->lex->ignore ? ME_WARNING : 0));
850 if (thd->is_error())
851 {
852 error= 1;
853 break;
854 }
855 }
856 }
857 /*
858 Don't try unlocking the row if skip_record reported an error since in
859 this case the transaction might have been rolled back already.
860 */
861 else if (likely(!thd->is_error()))
862 table->file->unlock_row(); // Row failed selection, release lock on it
863 else
864 break;
865 }
866
867 terminate_delete:
868 killed_status= thd->killed;
869 if (unlikely(killed_status != NOT_KILLED || thd->is_error()))
870 error= 1; // Aborted
871 if (will_batch && unlikely((loc_error= table->file->end_bulk_delete())))
872 {
873 if (error != 1)
874 table->file->print_error(loc_error,MYF(0));
875 error=1;
876 }
877 THD_STAGE_INFO(thd, stage_end);
878 end_read_record(&info);
879 if (table_list->has_period())
880 table->file->ha_release_auto_increment();
881 if (options & OPTION_QUICK)
882 (void) table->file->extra(HA_EXTRA_NORMAL);
883 ANALYZE_STOP_TRACKING(&explain->command_tracker);
884
885 cleanup:
886 /*
887 Invalidate the table in the query cache if something changed. This must
888 be before binlog writing and ha_autocommit_...
889 */
890 if (deleted)
891 {
892 query_cache_invalidate3(thd, table_list, 1);
893 }
894
895 if (thd->lex->current_select->first_cond_optimization)
896 {
897 thd->lex->current_select->save_leaf_tables(thd);
898 thd->lex->current_select->first_cond_optimization= 0;
899 }
900
901 delete deltempfile;
902 deltempfile=NULL;
903 delete select;
904 select= NULL;
905 transactional_table= table->file->has_transactions();
906
907 if (!transactional_table && deleted > 0)
908 thd->transaction.stmt.modified_non_trans_table=
909 thd->transaction.all.modified_non_trans_table= TRUE;
910
911 /* See similar binlogging code in sql_update.cc, for comments */
912 if (likely((error < 0) || thd->transaction.stmt.modified_non_trans_table))
913 {
914 if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open())
915 {
916 int errcode= 0;
917 if (error < 0)
918 thd->clear_error();
919 else
920 errcode= query_error_code(thd, killed_status == NOT_KILLED);
921
922 ScopedStatementReplication scoped_stmt_rpl(
923 table->versioned(VERS_TRX_ID) ? thd : NULL);
924 /*
925 [binlog]: If 'handler::delete_all_rows()' was called and the
926 storage engine does not inject the rows itself, we replicate
927 statement-based; otherwise, 'ha_delete_row()' was used to
928 delete specific rows which we might log row-based.
929 */
930 int log_result= thd->binlog_query(query_type,
931 thd->query(), thd->query_length(),
932 transactional_table, FALSE, FALSE,
933 errcode);
934
935 if (log_result > 0)
936 {
937 error=1;
938 }
939 }
940 }
941 DBUG_ASSERT(transactional_table || !deleted || thd->transaction.stmt.modified_non_trans_table);
942
943 if (likely(error < 0) ||
944 (thd->lex->ignore && !thd->is_error() && !thd->is_fatal_error))
945 {
946 if (thd->lex->analyze_stmt)
947 goto send_nothing_and_leave;
948
949 if (with_select)
950 result->send_eof();
951 else
952 my_ok(thd, deleted);
953 DBUG_PRINT("info",("%ld records deleted",(long) deleted));
954 }
955 delete file_sort;
956 free_underlaid_joins(thd, select_lex);
957 if (table->file->pushed_cond)
958 table->file->cond_pop();
959 DBUG_RETURN(error >= 0 || thd->is_error());
960
961 /* Special exits */
962 produce_explain_and_leave:
963 /*
964 We come here for various "degenerate" query plans: impossible WHERE,
965 no-partitions-used, impossible-range, etc.
966 */
967 if (!(query_plan.save_explain_delete_data(thd->mem_root, thd)))
968 goto got_error;
969
970 send_nothing_and_leave:
971 /*
972 ANALYZE DELETE jumps here. We can't send explain right here, because
973 we might be using ANALYZE DELETE ...RETURNING, in which case we have
974 Protocol_discard active.
975 */
976
977 delete select;
978 delete file_sort;
979 free_underlaid_joins(thd, select_lex);
980 if (table->file->pushed_cond)
981 table->file->cond_pop();
982
983 DBUG_ASSERT(!return_error || thd->is_error() || thd->killed);
984 DBUG_RETURN((return_error || thd->is_error() || thd->killed) ? 1 : 0);
985
986 got_error:
987 return_error= 1;
988 goto send_nothing_and_leave;
989 }
990
991
992 /*
993 Prepare items in DELETE statement
994
995 SYNOPSIS
996 mysql_prepare_delete()
997 thd - thread handler
998 table_list - global/local table list
999 wild_num - number of wildcards used in optional SELECT clause
1000 field_list - list of items in optional SELECT clause
1001 conds - conditions
1002
1003 RETURN VALUE
1004 FALSE OK
1005 TRUE error
1006 */
mysql_prepare_delete(THD * thd,TABLE_LIST * table_list,uint wild_num,List<Item> & field_list,Item ** conds,bool * delete_while_scanning)1007 int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list,
1008 uint wild_num, List<Item> &field_list, Item **conds,
1009 bool *delete_while_scanning)
1010 {
1011 Item *fake_conds= 0;
1012 SELECT_LEX *select_lex= thd->lex->first_select_lex();
1013 DBUG_ENTER("mysql_prepare_delete");
1014 List<Item> all_fields;
1015
1016 *delete_while_scanning= true;
1017 thd->lex->allow_sum_func.clear_all();
1018 if (setup_tables_and_check_access(thd,
1019 &thd->lex->first_select_lex()->context,
1020 &thd->lex->first_select_lex()->
1021 top_join_list,
1022 table_list,
1023 select_lex->leaf_tables, FALSE,
1024 DELETE_ACL, SELECT_ACL, TRUE))
1025 DBUG_RETURN(TRUE);
1026
1027 if (table_list->vers_conditions.is_set() && table_list->is_view_or_derived())
1028 {
1029 my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
1030 DBUG_RETURN(true);
1031 }
1032
1033 if (table_list->has_period())
1034 {
1035 if (table_list->is_view_or_derived())
1036 {
1037 my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
1038 DBUG_RETURN(true);
1039 }
1040
1041 if (select_lex->period_setup_conds(thd, table_list))
1042 DBUG_RETURN(true);
1043 }
1044
1045 DBUG_ASSERT(table_list->table);
1046 // conds could be cached from previous SP call
1047 DBUG_ASSERT(!table_list->vers_conditions.need_setup() ||
1048 !*conds || thd->stmt_arena->is_stmt_execute());
1049 if (select_lex->vers_setup_conds(thd, table_list))
1050 DBUG_RETURN(TRUE);
1051
1052 *conds= select_lex->where;
1053
1054 if ((wild_num && setup_wild(thd, table_list, field_list, NULL, wild_num,
1055 &select_lex->hidden_bit_fields)) ||
1056 setup_fields(thd, Ref_ptr_array(),
1057 field_list, MARK_COLUMNS_READ, NULL, NULL, 0) ||
1058 setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
1059 setup_ftfuncs(select_lex))
1060 DBUG_RETURN(TRUE);
1061 if (!table_list->single_table_updatable() ||
1062 check_key_in_view(thd, table_list))
1063 {
1064 my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE");
1065 DBUG_RETURN(TRUE);
1066 }
1067
1068 /*
1069 Application-time periods: if FOR PORTION OF ... syntax used, DELETE
1070 statement could issue delete_row's mixed with write_row's. This causes
1071 problems for myisam and corrupts table, if deleting while scanning.
1072 */
1073 if (table_list->has_period()
1074 || unique_table(thd, table_list, table_list->next_global, 0))
1075 *delete_while_scanning= false;
1076
1077 if (select_lex->inner_refs_list.elements &&
1078 fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
1079 DBUG_RETURN(TRUE);
1080
1081 select_lex->fix_prepare_information(thd, conds, &fake_conds);
1082 DBUG_RETURN(FALSE);
1083 }
1084
1085
1086 /***************************************************************************
1087 Delete multiple tables from join
1088 ***************************************************************************/
1089
1090
refpos_order_cmp(void * arg,const void * a,const void * b)1091 extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
1092 {
1093 handler *file= (handler*)arg;
1094 return file->cmp_ref((const uchar*)a, (const uchar*)b);
1095 }
1096
1097 /*
1098 make delete specific preparation and checks after opening tables
1099
1100 SYNOPSIS
1101 mysql_multi_delete_prepare()
1102 thd thread handler
1103
1104 RETURN
1105 FALSE OK
1106 TRUE Error
1107 */
1108
mysql_multi_delete_prepare(THD * thd)1109 int mysql_multi_delete_prepare(THD *thd)
1110 {
1111 LEX *lex= thd->lex;
1112 TABLE_LIST *aux_tables= lex->auxiliary_table_list.first;
1113 TABLE_LIST *target_tbl;
1114 DBUG_ENTER("mysql_multi_delete_prepare");
1115
1116 if (mysql_handle_derived(lex, DT_INIT))
1117 DBUG_RETURN(TRUE);
1118 if (mysql_handle_derived(lex, DT_MERGE_FOR_INSERT))
1119 DBUG_RETURN(TRUE);
1120 if (mysql_handle_derived(lex, DT_PREPARE))
1121 DBUG_RETURN(TRUE);
1122 /*
1123 setup_tables() need for VIEWs. JOIN::prepare() will not do it second
1124 time.
1125
1126 lex->query_tables also point on local list of DELETE SELECT_LEX
1127 */
1128 if (setup_tables_and_check_access(thd,
1129 &thd->lex->first_select_lex()->context,
1130 &thd->lex->first_select_lex()->
1131 top_join_list,
1132 lex->query_tables,
1133 lex->first_select_lex()->leaf_tables,
1134 FALSE, DELETE_ACL, SELECT_ACL, FALSE))
1135 DBUG_RETURN(TRUE);
1136
1137 /*
1138 Multi-delete can't be constructed over-union => we always have
1139 single SELECT on top and have to check underlying SELECTs of it
1140 */
1141 lex->first_select_lex()->set_unique_exclude();
1142 /* Fix tables-to-be-deleted-from list to point at opened tables */
1143 for (target_tbl= (TABLE_LIST*) aux_tables;
1144 target_tbl;
1145 target_tbl= target_tbl->next_local)
1146 {
1147
1148 target_tbl->table= target_tbl->correspondent_table->table;
1149 if (target_tbl->correspondent_table->is_multitable())
1150 {
1151 my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
1152 target_tbl->correspondent_table->view_db.str,
1153 target_tbl->correspondent_table->view_name.str);
1154 DBUG_RETURN(TRUE);
1155 }
1156
1157 if (!target_tbl->correspondent_table->single_table_updatable() ||
1158 check_key_in_view(thd, target_tbl->correspondent_table))
1159 {
1160 my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
1161 target_tbl->table_name.str, "DELETE");
1162 DBUG_RETURN(TRUE);
1163 }
1164 }
1165
1166 for (target_tbl= (TABLE_LIST*) aux_tables;
1167 target_tbl;
1168 target_tbl= target_tbl->next_local)
1169 {
1170 /*
1171 Check that table from which we delete is not used somewhere
1172 inside subqueries/view.
1173 */
1174 {
1175 TABLE_LIST *duplicate;
1176 if ((duplicate= unique_table(thd, target_tbl->correspondent_table,
1177 lex->query_tables, 0)))
1178 {
1179 update_non_unique_table_error(target_tbl->correspondent_table,
1180 "DELETE", duplicate);
1181 DBUG_RETURN(TRUE);
1182 }
1183 }
1184 }
1185 /*
1186 Reset the exclude flag to false so it doesn't interfare
1187 with further calls to unique_table
1188 */
1189 lex->first_select_lex()->exclude_from_table_unique_test= FALSE;
1190
1191 if (lex->save_prep_leaf_tables())
1192 DBUG_RETURN(TRUE);
1193
1194 DBUG_RETURN(FALSE);
1195 }
1196
1197
multi_delete(THD * thd_arg,TABLE_LIST * dt,uint num_of_tables_arg)1198 multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt, uint num_of_tables_arg):
1199 select_result_interceptor(thd_arg), delete_tables(dt), deleted(0), found(0),
1200 num_of_tables(num_of_tables_arg), error(0),
1201 do_delete(0), transactional_tables(0), normal_tables(0), error_handled(0)
1202 {
1203 tempfiles= (Unique **) thd_arg->calloc(sizeof(Unique *) * num_of_tables);
1204 }
1205
1206
1207 int
prepare(List<Item> & values,SELECT_LEX_UNIT * u)1208 multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
1209 {
1210 DBUG_ENTER("multi_delete::prepare");
1211 unit= u;
1212 do_delete= 1;
1213 THD_STAGE_INFO(thd, stage_deleting_from_main_table);
1214 DBUG_RETURN(0);
1215 }
1216
prepare_to_read_rows()1217 void multi_delete::prepare_to_read_rows()
1218 {
1219 /* see multi_update::prepare_to_read_rows() */
1220 for (TABLE_LIST *walk= delete_tables; walk; walk= walk->next_local)
1221 {
1222 TABLE_LIST *tbl= walk->correspondent_table->find_table_for_update();
1223 tbl->table->mark_columns_needed_for_delete();
1224 }
1225 }
1226
1227 bool
initialize_tables(JOIN * join)1228 multi_delete::initialize_tables(JOIN *join)
1229 {
1230 TABLE_LIST *walk;
1231 Unique **tempfiles_ptr;
1232 DBUG_ENTER("initialize_tables");
1233
1234 if (unlikely((thd->variables.option_bits & OPTION_SAFE_UPDATES) &&
1235 error_if_full_join(join)))
1236 DBUG_RETURN(1);
1237
1238 table_map tables_to_delete_from=0;
1239 delete_while_scanning= true;
1240 for (walk= delete_tables; walk; walk= walk->next_local)
1241 {
1242 TABLE_LIST *tbl= walk->correspondent_table->find_table_for_update();
1243 tables_to_delete_from|= tbl->table->map;
1244 if (delete_while_scanning &&
1245 unique_table(thd, tbl, join->tables_list, 0))
1246 {
1247 /*
1248 If the table we are going to delete from appears
1249 in join, we need to defer delete. So the delete
1250 doesn't interfers with the scaning of results.
1251 */
1252 delete_while_scanning= false;
1253 }
1254 }
1255
1256 walk= delete_tables;
1257
1258 for (JOIN_TAB *tab= first_linear_tab(join, WITHOUT_BUSH_ROOTS,
1259 WITH_CONST_TABLES);
1260 tab;
1261 tab= next_linear_tab(join, tab, WITHOUT_BUSH_ROOTS))
1262 {
1263 if (!tab->bush_children && tab->table->map & tables_to_delete_from)
1264 {
1265 /* We are going to delete from this table */
1266 TABLE *tbl=walk->table=tab->table;
1267 walk= walk->next_local;
1268 /* Don't use KEYREAD optimization on this table */
1269 tbl->no_keyread=1;
1270 /* Don't use record cache */
1271 tbl->no_cache= 1;
1272 tbl->covering_keys.clear_all();
1273 if (tbl->file->has_transactions())
1274 transactional_tables= 1;
1275 else
1276 normal_tables= 1;
1277 tbl->prepare_triggers_for_delete_stmt_or_event();
1278 tbl->prepare_for_position();
1279 }
1280 else if ((tab->type != JT_SYSTEM && tab->type != JT_CONST) &&
1281 walk == delete_tables)
1282 {
1283 /*
1284 We are not deleting from the table we are scanning. In this
1285 case send_data() shouldn't delete any rows a we may touch
1286 the rows in the deleted table many times
1287 */
1288 delete_while_scanning= false;
1289 }
1290 }
1291 walk= delete_tables;
1292 tempfiles_ptr= tempfiles;
1293 if (delete_while_scanning)
1294 {
1295 table_being_deleted= delete_tables;
1296 walk= walk->next_local;
1297 }
1298 for (;walk ;walk= walk->next_local)
1299 {
1300 TABLE *table=walk->table;
1301 *tempfiles_ptr++= new (thd->mem_root) Unique (refpos_order_cmp, table->file,
1302 table->file->ref_length,
1303 MEM_STRIP_BUF_SIZE);
1304 }
1305 init_ftfuncs(thd, thd->lex->current_select, 1);
1306 DBUG_RETURN(thd->is_fatal_error);
1307 }
1308
1309
~multi_delete()1310 multi_delete::~multi_delete()
1311 {
1312 for (table_being_deleted= delete_tables;
1313 table_being_deleted;
1314 table_being_deleted= table_being_deleted->next_local)
1315 {
1316 TABLE *table= table_being_deleted->table;
1317 table->no_keyread=0;
1318 table->no_cache= 0;
1319 }
1320
1321 for (uint counter= 0; counter < num_of_tables; counter++)
1322 {
1323 if (tempfiles[counter])
1324 delete tempfiles[counter];
1325 }
1326 }
1327
1328
send_data(List<Item> & values)1329 int multi_delete::send_data(List<Item> &values)
1330 {
1331 int secure_counter= delete_while_scanning ? -1 : 0;
1332 TABLE_LIST *del_table;
1333 DBUG_ENTER("multi_delete::send_data");
1334
1335 bool ignore= thd->lex->ignore;
1336
1337 for (del_table= delete_tables;
1338 del_table;
1339 del_table= del_table->next_local, secure_counter++)
1340 {
1341 TABLE *table= del_table->table;
1342
1343 /* Check if we are using outer join and we didn't find the row */
1344 if (table->status & (STATUS_NULL_ROW | STATUS_DELETED))
1345 continue;
1346
1347 table->file->position(table->record[0]);
1348 found++;
1349
1350 if (secure_counter < 0)
1351 {
1352 /* We are scanning the current table */
1353 DBUG_ASSERT(del_table == table_being_deleted);
1354 if (table->triggers &&
1355 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
1356 TRG_ACTION_BEFORE, FALSE))
1357 DBUG_RETURN(1);
1358 table->status|= STATUS_DELETED;
1359
1360 error= table->delete_row();
1361 if (likely(!error))
1362 {
1363 deleted++;
1364 if (!table->file->has_transactions())
1365 thd->transaction.stmt.modified_non_trans_table= TRUE;
1366 if (table->triggers &&
1367 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
1368 TRG_ACTION_AFTER, FALSE))
1369 DBUG_RETURN(1);
1370 }
1371 else if (!ignore)
1372 {
1373 /*
1374 If the IGNORE option is used errors caused by ha_delete_row don't
1375 have to stop the iteration.
1376 */
1377 table->file->print_error(error,MYF(0));
1378 DBUG_RETURN(1);
1379 }
1380 }
1381 else
1382 {
1383 error=tempfiles[secure_counter]->unique_add((char*) table->file->ref);
1384 if (unlikely(error))
1385 {
1386 error= 1; // Fatal error
1387 DBUG_RETURN(1);
1388 }
1389 }
1390 }
1391 DBUG_RETURN(0);
1392 }
1393
1394
abort_result_set()1395 void multi_delete::abort_result_set()
1396 {
1397 DBUG_ENTER("multi_delete::abort_result_set");
1398
1399 /* the error was handled or nothing deleted and no side effects return */
1400 if (error_handled ||
1401 (!thd->transaction.stmt.modified_non_trans_table && !deleted))
1402 DBUG_VOID_RETURN;
1403
1404 /* Something already deleted so we have to invalidate cache */
1405 if (deleted)
1406 query_cache_invalidate3(thd, delete_tables, 1);
1407
1408 if (thd->transaction.stmt.modified_non_trans_table)
1409 thd->transaction.all.modified_non_trans_table= TRUE;
1410 thd->transaction.all.m_unsafe_rollback_flags|=
1411 (thd->transaction.stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT);
1412
1413 /*
1414 If rows from the first table only has been deleted and it is
1415 transactional, just do rollback.
1416 The same if all tables are transactional, regardless of where we are.
1417 In all other cases do attempt deletes ...
1418 */
1419 if (do_delete && normal_tables &&
1420 (table_being_deleted != delete_tables ||
1421 !table_being_deleted->table->file->has_transactions()))
1422 {
1423 /*
1424 We have to execute the recorded do_deletes() and write info into the
1425 error log
1426 */
1427 error= 1;
1428 send_eof();
1429 DBUG_ASSERT(error_handled);
1430 DBUG_VOID_RETURN;
1431 }
1432
1433 if (thd->transaction.stmt.modified_non_trans_table)
1434 {
1435 /*
1436 there is only side effects; to binlog with the error
1437 */
1438 if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open())
1439 {
1440 int errcode= query_error_code(thd, thd->killed == NOT_KILLED);
1441 /* possible error of writing binary log is ignored deliberately */
1442 (void) thd->binlog_query(THD::ROW_QUERY_TYPE,
1443 thd->query(), thd->query_length(),
1444 transactional_tables, FALSE, FALSE, errcode);
1445 }
1446 }
1447 DBUG_VOID_RETURN;
1448 }
1449
1450
1451
1452 /**
1453 Do delete from other tables.
1454
1455 @retval 0 ok
1456 @retval 1 error
1457
1458 @todo Is there any reason not use the normal nested-loops join? If not, and
1459 there is no documentation supporting it, this method and callee should be
1460 removed and there should be hooks within normal execution.
1461 */
1462
do_deletes()1463 int multi_delete::do_deletes()
1464 {
1465 DBUG_ENTER("do_deletes");
1466 DBUG_ASSERT(do_delete);
1467
1468 do_delete= 0; // Mark called
1469 if (!found)
1470 DBUG_RETURN(0);
1471
1472 table_being_deleted= (delete_while_scanning ? delete_tables->next_local :
1473 delete_tables);
1474
1475 for (uint counter= 0; table_being_deleted;
1476 table_being_deleted= table_being_deleted->next_local, counter++)
1477 {
1478 TABLE *table = table_being_deleted->table;
1479 int local_error;
1480 if (unlikely(tempfiles[counter]->get(table)))
1481 DBUG_RETURN(1);
1482
1483 local_error= do_table_deletes(table, &tempfiles[counter]->sort,
1484 thd->lex->ignore);
1485
1486 if (unlikely(thd->killed) && likely(!local_error))
1487 DBUG_RETURN(1);
1488
1489 if (unlikely(local_error == -1)) // End of file
1490 local_error= 0;
1491
1492 if (unlikely(local_error))
1493 DBUG_RETURN(local_error);
1494 }
1495 DBUG_RETURN(0);
1496 }
1497
1498
1499 /**
1500 Implements the inner loop of nested-loops join within multi-DELETE
1501 execution.
1502
1503 @param table The table from which to delete.
1504
1505 @param ignore If used, all non fatal errors will be translated
1506 to warnings and we should not break the row-by-row iteration.
1507
1508 @return Status code
1509
1510 @retval 0 All ok.
1511 @retval 1 Triggers or handler reported error.
1512 @retval -1 End of file from handler.
1513 */
do_table_deletes(TABLE * table,SORT_INFO * sort_info,bool ignore)1514 int multi_delete::do_table_deletes(TABLE *table, SORT_INFO *sort_info,
1515 bool ignore)
1516 {
1517 int local_error= 0;
1518 READ_RECORD info;
1519 ha_rows last_deleted= deleted;
1520 DBUG_ENTER("do_deletes_for_table");
1521
1522 if (unlikely(init_read_record(&info, thd, table, NULL, sort_info, 0, 1,
1523 FALSE)))
1524 DBUG_RETURN(1);
1525
1526 bool will_batch= !table->file->start_bulk_delete();
1527 while (likely(!(local_error= info.read_record())) && likely(!thd->killed))
1528 {
1529 if (table->triggers &&
1530 unlikely(table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
1531 TRG_ACTION_BEFORE, FALSE)))
1532 {
1533 local_error= 1;
1534 break;
1535 }
1536
1537 local_error= table->delete_row();
1538 if (unlikely(local_error) && !ignore)
1539 {
1540 table->file->print_error(local_error, MYF(0));
1541 break;
1542 }
1543
1544 /*
1545 Increase the reported number of deleted rows only if no error occurred
1546 during ha_delete_row.
1547 Also, don't execute the AFTER trigger if the row operation failed.
1548 */
1549 if (unlikely(!local_error))
1550 {
1551 deleted++;
1552 if (table->triggers &&
1553 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
1554 TRG_ACTION_AFTER, FALSE))
1555 {
1556 local_error= 1;
1557 break;
1558 }
1559 }
1560 }
1561 if (will_batch)
1562 {
1563 int tmp_error= table->file->end_bulk_delete();
1564 if (unlikely(tmp_error) && !local_error)
1565 {
1566 local_error= tmp_error;
1567 table->file->print_error(local_error, MYF(0));
1568 }
1569 }
1570 if (last_deleted != deleted && !table->file->has_transactions())
1571 thd->transaction.stmt.modified_non_trans_table= TRUE;
1572
1573 end_read_record(&info);
1574
1575 DBUG_RETURN(local_error);
1576 }
1577
1578 /*
1579 Send ok to the client
1580
1581 return: 0 sucess
1582 1 error
1583 */
1584
send_eof()1585 bool multi_delete::send_eof()
1586 {
1587 killed_state killed_status= NOT_KILLED;
1588 THD_STAGE_INFO(thd, stage_deleting_from_reference_tables);
1589
1590 /* Does deletes for the last n - 1 tables, returns 0 if ok */
1591 int local_error= do_deletes(); // returns 0 if success
1592
1593 /* compute a total error to know if something failed */
1594 local_error= local_error || error;
1595 killed_status= (local_error == 0)? NOT_KILLED : thd->killed;
1596 /* reset used flags */
1597 THD_STAGE_INFO(thd, stage_end);
1598
1599 if (thd->transaction.stmt.modified_non_trans_table)
1600 thd->transaction.all.modified_non_trans_table= TRUE;
1601 thd->transaction.all.m_unsafe_rollback_flags|=
1602 (thd->transaction.stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT);
1603
1604 /*
1605 We must invalidate the query cache before binlog writing and
1606 ha_autocommit_...
1607 */
1608 if (deleted)
1609 {
1610 query_cache_invalidate3(thd, delete_tables, 1);
1611 }
1612 if (likely((local_error == 0) ||
1613 thd->transaction.stmt.modified_non_trans_table))
1614 {
1615 if(WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open())
1616 {
1617 int errcode= 0;
1618 if (likely(local_error == 0))
1619 thd->clear_error();
1620 else
1621 errcode= query_error_code(thd, killed_status == NOT_KILLED);
1622 thd->thread_specific_used= TRUE;
1623 if (unlikely(thd->binlog_query(THD::ROW_QUERY_TYPE,
1624 thd->query(), thd->query_length(),
1625 transactional_tables, FALSE, FALSE,
1626 errcode) > 0) &&
1627 !normal_tables)
1628 {
1629 local_error=1; // Log write failed: roll back the SQL statement
1630 }
1631 }
1632 }
1633 if (unlikely(local_error != 0))
1634 error_handled= TRUE; // to force early leave from ::abort_result_set()
1635
1636 if (likely(!local_error && !thd->lex->analyze_stmt))
1637 {
1638 ::my_ok(thd, deleted);
1639 }
1640 return 0;
1641 }
1642