1 /* Copyright (c) 2000, 2021, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 /*
24 Delete of records tables.
25
26 Multi-table deletes were introduced by Monty and Sinisa
27 */
28
29 #include "sql_delete.h"
30
31 #include "binlog.h" // mysql_bin_log
32 #include "debug_sync.h" // DEBUG_SYNC
33 #include "opt_explain.h" // Modification_plan
34 #include "opt_trace.h" // Opt_trace_object
35 #include "records.h" // READ_RECORD
36 #include "sql_base.h" // open_tables_for_query
37 #include "sql_optimizer.h" // optimize_cond, substitute_gc
38 #include "sql_resolver.h" // setup_order
39 #include "sql_select.h" // free_underlaid_joins
40 #include "sql_view.h" // check_key_in_view
41 #include "table_trigger_dispatcher.h" // Table_trigger_dispatcher
42 #include "uniques.h" // Unique
43 #include "probes_mysql.h"
44 #include "auth_common.h"
45
46
47 /**
48 Implement DELETE SQL word.
49
50 @note Like implementations of other DDL/DML in MySQL, this function
51 relies on the caller to close the thread tables. This is done in the
52 end of dispatch_command().
53 */
54
mysql_delete(THD * thd,ha_rows limit)55 bool Sql_cmd_delete::mysql_delete(THD *thd, ha_rows limit)
56 {
57 DBUG_ENTER("mysql_delete");
58
59 myf error_flags= MYF(0); /**< Flag for fatal errors */
60 bool will_batch;
61 int error, loc_error;
62 READ_RECORD info;
63 const bool using_limit= limit != HA_POS_ERROR;
64 ha_rows deleted= 0;
65 bool reverse= false;
66 bool read_removal= false;
67 bool skip_record;
68 bool need_sort= false;
69 bool err= true;
70 bool transactional_table, const_cond_result, const_cond; // const
71
72 uint usable_index= MAX_KEY;
73 SELECT_LEX *const select_lex= thd->lex->select_lex;
74 ORDER *order= select_lex->order_list.first;
75 TABLE_LIST *const table_list= select_lex->get_table_list();
76 THD::killed_state killed_status= THD::NOT_KILLED;
77 THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE;
78
79 select_lex->make_active_options(0, 0);
80
81 const bool safe_update= thd->variables.option_bits & OPTION_SAFE_UPDATES;
82
83 if (open_tables_for_query(thd, table_list, 0))
84 DBUG_RETURN(TRUE);
85
86 THD_STAGE_INFO(thd, stage_init);
87
88 if (run_before_dml_hook(thd))
89 DBUG_RETURN(true);
90
91 if (mysql_prepare_delete(thd))
92 DBUG_RETURN(TRUE);
93
94 TABLE_LIST *const delete_table_ref= table_list->updatable_base_table();
95 TABLE *const table= delete_table_ref->table;
96
97 Item *conds;
98 if (select_lex->get_optimizable_conditions(thd, &conds, NULL))
99 DBUG_RETURN(TRUE);
100
101 /*
102 See if we can substitute expressions with equivalent generated
103 columns in the WHERE and ORDER BY clauses of the DELETE statement.
104 It is unclear if this is best to do before or after the other
105 substitutions performed by substitute_for_best_equal_field(). Do
106 it here for now, to keep it consistent with how multi-table
107 deletes are optimized in JOIN::optimize().
108 */
109 if (conds || order)
110 static_cast<void>(substitute_gc(thd, select_lex, conds, NULL, order));
111
112 QEP_TAB_standalone qep_tab_st;
113 QEP_TAB &qep_tab= qep_tab_st.as_QEP_TAB();
114
115 /*
116 Non delete tables are pruned in SELECT_LEX::prepare,
117 only the delete table needs this.
118 */
119 if (prune_partitions(thd, table, conds))
120 DBUG_RETURN(true);
121 if (table->all_partitions_pruned_away)
122 {
123 /* No matching records */
124 if (thd->lex->describe)
125 {
126 /*
127 Initialize plan only for regular EXPLAIN. Don't do it for EXPLAIN
128 FOR CONNECTION as the plan would exist for very short period of time
129 but will cost taking/releasing of a mutex, so it's not worth
130 bothering with. Same for similar cases below.
131 */
132 Modification_plan plan(thd, MT_DELETE, table,
133 "No matching rows after partition pruning",
134 true, 0);
135 err= explain_single_table_modification(thd, &plan, select_lex);
136 goto exit_without_my_ok;
137 }
138 my_ok(thd, 0);
139 DBUG_RETURN(0);
140 }
141
142 if (lock_tables(thd, table_list, thd->lex->table_count, 0))
143 DBUG_RETURN(true);
144
145 const_cond= (!conds || conds->const_item());
146 const_cond_result= const_cond && (!conds || conds->val_int());
147 if (thd->is_error())
148 {
149 /* Error evaluating val_int(). */
150 DBUG_RETURN(TRUE);
151 }
152 /*
153 We are passing HA_EXTRA_IGNORE_DUP_KEY flag here to recreate query with
154 IGNORE keyword within federated storage engine. If federated engine is
155 removed in the future, use of HA_EXTRA_IGNORE_DUP_KEY and
156 HA_EXTRA_NO_IGNORE_DUP_KEY flag should be removed from mysql_delete(),
157 Query_result_delete::initialize_tables() and
158 Query_result_delete destructor.
159 */
160 if (thd->lex->is_ignore())
161 table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
162
163 /*
164 Test if the user wants to delete all rows and deletion doesn't have
165 any side-effects (because of triggers), so we can use optimized
166 handler::delete_all_rows() method.
167
168 We can use delete_all_rows() if and only if:
169 - We allow new functions (not using option --skip-new)
170 - There is no limit clause
171 - The condition is constant
172 - If there is a condition, then it it produces a non-zero value
173 - If the current command is DELETE FROM with no where clause, then:
174 - We will not be binlogging this statement in row-based, and
175 - there should be no delete triggers associated with the table.
176 */
177 if (!using_limit && const_cond_result &&
178 !(specialflag & SPECIAL_NO_NEW_FUNC) &&
179 ((!thd->is_current_stmt_binlog_format_row() || /* not ROW binlog-format */
180 thd->is_current_stmt_binlog_disabled()) && /* no binlog for this command */
181 !(table->triggers && table->triggers->has_delete_triggers())))
182 {
183 /* Update the table->file->stats.records number */
184 table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
185 ha_rows const maybe_deleted= table->file->stats.records;
186
187 Modification_plan plan(thd, MT_DELETE, table,
188 "Deleting all rows", false, maybe_deleted);
189 if (thd->lex->describe)
190 {
191 err= explain_single_table_modification(thd, &plan, select_lex);
192 goto exit_without_my_ok;
193 }
194
195 /* Do not allow deletion of all records if safe_update is set. */
196 if (safe_update)
197 {
198 my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, MYF(0),
199 thd->get_stmt_da()->get_first_condition_message());
200 DBUG_RETURN(true);
201 }
202
203 DBUG_PRINT("debug", ("Trying to use delete_all_rows()"));
204 if (!(error=table->file->ha_delete_all_rows()))
205 {
206 /*
207 As delete_all_rows() was used, we have to log it in statement format.
208 */
209 query_type= THD::STMT_QUERY_TYPE;
210 error= -1;
211 deleted= maybe_deleted;
212 goto cleanup;
213 }
214 if (error != HA_ERR_WRONG_COMMAND)
215 {
216 if (table->file->is_fatal_error(error))
217 error_flags|= ME_FATALERROR;
218
219 table->file->print_error(error, error_flags);
220 error=0;
221 goto cleanup;
222 }
223 /* Handler didn't support fast delete; Delete rows one by one */
224 }
225
226 if (conds)
227 {
228 COND_EQUAL *cond_equal= NULL;
229 Item::cond_result result;
230
231 if (optimize_cond(thd, &conds, &cond_equal, select_lex->join_list,
232 &result))
233 DBUG_RETURN(true);
234 if (result == Item::COND_FALSE) // Impossible where
235 {
236 limit= 0;
237
238 if (thd->lex->describe)
239 {
240 Modification_plan plan(thd, MT_DELETE, table,
241 "Impossible WHERE", true, 0);
242 err= explain_single_table_modification(thd, &plan, select_lex);
243 goto exit_without_my_ok;
244 }
245 }
246 if (conds)
247 {
248 conds= substitute_for_best_equal_field(conds, cond_equal, 0);
249 if (conds == NULL)
250 {
251 err= true;
252 goto exit_without_my_ok;
253 }
254 conds->update_used_tables();
255 }
256 }
257
258 // Initialize the cost model that will be used for this table
259 table->init_cost_model(thd->cost_model());
260
261 /* Update the table->file->stats.records number */
262 table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
263
264 table->covering_keys.clear_all();
265 table->quick_keys.clear_all(); // Can't use 'only index'
266 table->possible_quick_keys.clear_all();
267
268 /* Prune a second time to be able to prune on subqueries in WHERE clause. */
269 if (prune_partitions(thd, table, conds))
270 DBUG_RETURN(true);
271 if (table->all_partitions_pruned_away)
272 {
273 /* No matching records */
274 if (thd->lex->describe)
275 {
276 Modification_plan plan(thd, MT_DELETE, table,
277 "No matching rows after partition pruning",
278 true, 0);
279 err= explain_single_table_modification(thd, &plan, select_lex);
280 goto exit_without_my_ok;
281 }
282 my_ok(thd, 0);
283 DBUG_RETURN(0);
284 }
285
286 error= 0;
287 qep_tab.set_table(table);
288 qep_tab.set_condition(conds);
289
290 { // Enter scope for optimizer trace wrapper
291 Opt_trace_object wrapper(&thd->opt_trace);
292 wrapper.add_utf8_table(delete_table_ref);
293 bool zero_rows= false; // True if it's sure that we'll find no rows
294 if (limit == 0)
295 zero_rows= true;
296 else if (conds != NULL)
297 {
298 key_map keys_to_use(key_map::ALL_BITS), needed_reg_dummy;
299 QUICK_SELECT_I *qck;
300 zero_rows= test_quick_select(thd, keys_to_use, 0, limit, safe_update,
301 ORDER::ORDER_NOT_RELEVANT, &qep_tab,
302 conds, &needed_reg_dummy, &qck,
303 qep_tab.table()->force_index) < 0;
304 qep_tab.set_quick(qck);
305 }
306 if (zero_rows)
307 {
308 if (thd->lex->describe && !error && !thd->is_error())
309 {
310 Modification_plan plan(thd, MT_DELETE, table,
311 "Impossible WHERE", true, 0);
312 err= explain_single_table_modification(thd, &plan, select_lex);
313 goto exit_without_my_ok;
314 }
315
316 free_underlaid_joins(thd, select_lex);
317 /*
318 Error was already created by quick select evaluation (check_quick()).
319 TODO: Add error code output parameter to Item::val_xxx() methods.
320 Currently they rely on the user checking DA for
321 errors when unwinding the stack after calling Item::val_xxx().
322 */
323 if (thd->is_error())
324 DBUG_RETURN(true);
325 my_ok(thd, 0);
326 DBUG_RETURN(false); // Nothing to delete
327 }
328 } // Ends scope for optimizer trace wrapper
329
330 /* If running in safe sql mode, don't allow updates without keys */
331 if (table->quick_keys.is_clear_all())
332 {
333 thd->server_status|= SERVER_QUERY_NO_INDEX_USED;
334
335 /*
336 Safe update error isn't returned if:
337 1) It is an EXPLAIN statement OR
338 2) LIMIT is present.
339
340 Append the first warning (if any) to the error message. This allows the
341 user to understand why index access couldn't be chosen.
342 */
343 if (!thd->lex->is_explain() && safe_update && !using_limit)
344 {
345 free_underlaid_joins(thd, select_lex);
346 my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, MYF(0),
347 thd->get_stmt_da()->get_first_condition_message());
348 DBUG_RETURN(true);
349 }
350 }
351
352 if (order)
353 {
354 table->update_const_key_parts(conds);
355 order= simple_remove_const(order, conds);
356
357 usable_index= get_index_for_order(order, &qep_tab, limit,
358 &need_sort, &reverse);
359 }
360
361 {
362 ha_rows rows;
363 if (qep_tab.quick())
364 rows= qep_tab.quick()->records;
365 else if (!conds && !need_sort && limit != HA_POS_ERROR)
366 rows= limit;
367 else
368 {
369 delete_table_ref->fetch_number_of_rows();
370 rows= table->file->stats.records;
371 }
372 qep_tab.set_quick_optim();
373 qep_tab.set_condition_optim();
374 Modification_plan plan(thd, MT_DELETE, &qep_tab,
375 usable_index, limit, false, need_sort,
376 false, rows);
377 DEBUG_SYNC(thd, "planned_single_delete");
378
379 if (thd->lex->describe)
380 {
381 err= explain_single_table_modification(thd, &plan, select_lex);
382 goto exit_without_my_ok;
383 }
384
385 if (select_lex->active_options() & OPTION_QUICK)
386 (void) table->file->extra(HA_EXTRA_QUICK);
387
388 if (need_sort)
389 {
390 ha_rows examined_rows, found_rows, returned_rows;
391
392 {
393 Filesort fsort(&qep_tab, order, HA_POS_ERROR);
394 assert(usable_index == MAX_KEY);
395 table->sort.io_cache= (IO_CACHE *) my_malloc(key_memory_TABLE_sort_io_cache,
396 sizeof(IO_CACHE),
397 MYF(MY_FAE | MY_ZEROFILL));
398
399 if (filesort(thd, &fsort, true,
400 &examined_rows, &found_rows, &returned_rows))
401 {
402 err= true;
403 goto exit_without_my_ok;
404 }
405 table->sort.found_records= returned_rows;
406 thd->inc_examined_row_count(examined_rows);
407 free_underlaid_joins(thd, select_lex);
408 /*
409 Filesort has already found and selected the rows we want to delete,
410 so we don't need the where clause
411 */
412 qep_tab.set_quick(NULL);
413 qep_tab.set_condition(NULL);
414 table->file->ha_index_or_rnd_end();
415 }
416 }
417
418 /* If quick select is used, initialize it before retrieving rows. */
419 if (qep_tab.quick() && (error= qep_tab.quick()->reset()))
420 {
421 if (table->file->is_fatal_error(error))
422 error_flags|= ME_FATALERROR;
423
424 table->file->print_error(error, error_flags);
425 err= true;
426 goto exit_without_my_ok;
427 }
428
429 if (usable_index==MAX_KEY || qep_tab.quick())
430 error= init_read_record(&info, thd, NULL, &qep_tab, 1, 1, FALSE);
431 else
432 error= init_read_record_idx(&info, thd, table, 1, usable_index, reverse);
433
434 if (error)
435 {
436 err= true; /* purecov: inspected */
437 goto exit_without_my_ok;
438 }
439
440 if (select_lex->has_ft_funcs() && init_ftfuncs(thd, select_lex))
441 goto exit_without_my_ok;
442
443 THD_STAGE_INFO(thd, stage_updating);
444
445 if (table->triggers &&
446 table->triggers->has_triggers(TRG_EVENT_DELETE,
447 TRG_ACTION_AFTER))
448 {
449 /*
450 The table has AFTER DELETE triggers that might access to subject table
451 and therefore might need delete to be done immediately. So we turn-off
452 the batching.
453 */
454 (void) table->file->extra(HA_EXTRA_DELETE_CANNOT_BATCH);
455 will_batch= FALSE;
456 }
457 else
458 will_batch= !table->file->start_bulk_delete();
459
460 table->mark_columns_needed_for_delete();
461 if (thd->is_error())
462 goto exit_without_my_ok;
463
464 if ((table->file->ha_table_flags() & HA_READ_BEFORE_WRITE_REMOVAL) &&
465 !using_limit &&
466 !(table->triggers && table->triggers->has_delete_triggers()) &&
467 qep_tab.quick() && qep_tab.quick()->index != MAX_KEY)
468 read_removal= table->check_read_removal(qep_tab.quick()->index);
469
470 while (!(error=info.read_record(&info)) && !thd->killed &&
471 ! thd->is_error())
472 {
473 thd->inc_examined_row_count(1);
474 // thd->is_error() is tested to disallow delete row on error
475 if (!qep_tab.skip_record(thd, &skip_record) && !skip_record)
476 {
477
478 if (table->triggers &&
479 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
480 TRG_ACTION_BEFORE, FALSE))
481 {
482 error= 1;
483 break;
484 }
485
486 if (!(error= table->file->ha_delete_row(table->record[0])))
487 {
488 deleted++;
489 if (table->triggers &&
490 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
491 TRG_ACTION_AFTER, FALSE))
492 {
493 error= 1;
494 break;
495 }
496 if (!--limit && using_limit)
497 {
498 error= -1;
499 break;
500 }
501 }
502 else
503 {
504 if (table->file->is_fatal_error(error))
505 error_flags|= ME_FATALERROR;
506
507 table->file->print_error(error, error_flags);
508 /*
509 In < 4.0.14 we set the error number to 0 here, but that
510 was not sensible, because then MySQL would not roll back the
511 failed DELETE, and also wrote it to the binlog. For MyISAM
512 tables a DELETE probably never should fail (?), but for
513 InnoDB it can fail in a FOREIGN KEY error or an
514 out-of-tablespace error.
515 */
516 if (thd->is_error()) // Could be downgraded to warning by IGNORE
517 {
518 error= 1;
519 break;
520 }
521 }
522 }
523 /*
524 Don't try unlocking the row if skip_record reported an error since in
525 this case the transaction might have been rolled back already.
526 */
527 else if (!thd->is_error())
528 table->file->unlock_row(); // Row failed selection, release lock on it
529 else
530 break;
531 }
532
533 killed_status= thd->killed;
534 if (killed_status != THD::NOT_KILLED || thd->is_error())
535 error= 1; // Aborted
536 if (will_batch && (loc_error= table->file->end_bulk_delete()))
537 {
538 /* purecov: begin inspected */
539 if (error != 1)
540 {
541 if (table->file->is_fatal_error(loc_error))
542 error_flags|= ME_FATALERROR;
543
544 table->file->print_error(loc_error, error_flags);
545 }
546 error=1;
547 /* purecov: end */
548 }
549 if (read_removal)
550 {
551 /* Only handler knows how many records were really written */
552 deleted= table->file->end_read_removal();
553 }
554 if (thd->lex->is_ignore())
555 table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
556 THD_STAGE_INFO(thd, stage_end);
557 end_read_record(&info);
558 if (select_lex->active_options() & OPTION_QUICK)
559 (void) table->file->extra(HA_EXTRA_NORMAL);
560 } // End of scope for Modification_plan
561
562 cleanup:
563 assert(!thd->lex->describe);
564 /*
565 Invalidate the table in the query cache if something changed. This must
566 be before binlog writing and ha_autocommit_...
567 */
568 if (deleted)
569 query_cache.invalidate_single(thd, delete_table_ref, true);
570
571 transactional_table= table->file->has_transactions();
572
573 if (!transactional_table && deleted > 0)
574 thd->get_transaction()->mark_modified_non_trans_table(
575 Transaction_ctx::STMT);
576
577 /* See similar binlogging code in sql_update.cc, for comments */
578 if ((error < 0) || thd->get_transaction()->cannot_safely_rollback(
579 Transaction_ctx::STMT))
580 {
581 if (mysql_bin_log.is_open())
582 {
583 int errcode= 0;
584 if (error < 0)
585 thd->clear_error();
586 else
587 errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
588
589 /*
590 [binlog]: As we don't allow the use of 'handler:delete_all_rows()' when
591 binlog_format == ROW, if 'handler::delete_all_rows()' was called
592 we replicate statement-based; otherwise, 'ha_delete_row()' was used to
593 delete specific rows which we might log row-based.
594 */
595 int log_result= thd->binlog_query(query_type,
596 thd->query().str, thd->query().length,
597 transactional_table, FALSE, FALSE,
598 errcode);
599
600 if (log_result)
601 {
602 error=1;
603 }
604 }
605 }
606 assert(transactional_table ||
607 !deleted ||
608 thd->get_transaction()->cannot_safely_rollback(
609 Transaction_ctx::STMT));
610 free_underlaid_joins(thd, select_lex);
611 if (error < 0)
612 {
613 my_ok(thd, deleted);
614 DBUG_PRINT("info",("%ld records deleted",(long) deleted));
615 }
616 DBUG_RETURN(thd->is_error() || thd->killed);
617
618 exit_without_my_ok:
619 free_underlaid_joins(thd, select_lex);
620 table->set_keyread(false);
621 DBUG_RETURN((err || thd->is_error() || thd->killed) ? 1 : 0);
622 }
623
624
625 /**
626 Prepare items in DELETE statement
627
628 @param thd - thread handler
629
630 @return false if success, true if error
631 */
632
mysql_prepare_delete(THD * thd)633 bool Sql_cmd_delete::mysql_prepare_delete(THD *thd)
634 {
635 DBUG_ENTER("mysql_prepare_delete");
636
637 List<Item> all_fields;
638 SELECT_LEX *const select= thd->lex->select_lex;
639 TABLE_LIST *const table_list= select->get_table_list();
640
641 if (select->setup_tables(thd, table_list, false))
642 DBUG_RETURN(true); /* purecov: inspected */
643
644 if (table_list->is_view() && select->resolve_derived(thd, false))
645 DBUG_RETURN(true); /* purecov: inspected */
646
647 if (!table_list->is_updatable())
648 {
649 my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE");
650 DBUG_RETURN(true);
651 }
652
653 if (table_list->is_multiple_tables())
654 {
655 my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
656 table_list->view_db.str, table_list->view_name.str);
657 DBUG_RETURN(TRUE);
658 }
659
660 TABLE_LIST *const delete_table_ref= table_list->updatable_base_table();
661
662 thd->lex->allow_sum_func= 0;
663 if (table_list->is_view() &&
664 select->check_view_privileges(thd, DELETE_ACL, SELECT_ACL))
665 DBUG_RETURN(true);
666
667 ulong want_privilege_saved= thd->want_privilege;
668 thd->want_privilege= SELECT_ACL;
669 enum enum_mark_columns mark_used_columns_saved= thd->mark_used_columns;
670 thd->mark_used_columns= MARK_COLUMNS_READ;
671
672 if (select->setup_conds(thd))
673 DBUG_RETURN(true);
674
675 // check ORDER BY even if it can be ignored
676 if (select->order_list.first)
677 {
678 TABLE_LIST tables;
679 List<Item> fields;
680 List<Item> all_fields;
681
682 tables.table = table_list->table;
683 tables.alias = table_list->alias;
684
685 assert(!select->group_list.elements);
686 if (select->setup_ref_array(thd))
687 DBUG_RETURN(true); /* purecov: inspected */
688 if (setup_order(thd, select->ref_pointer_array, &tables,
689 fields, all_fields, select->order_list.first))
690 DBUG_RETURN(true);
691 }
692
693 thd->want_privilege= want_privilege_saved;
694 thd->mark_used_columns= mark_used_columns_saved;
695
696 if (setup_ftfuncs(select))
697 DBUG_RETURN(true); /* purecov: inspected */
698
699 // check_key_in_view() may send an SQL note, but we only want it once.
700 if (select->first_execution &&
701 check_key_in_view(thd, table_list, delete_table_ref))
702 {
703 my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE");
704 DBUG_RETURN(true);
705 }
706
707 TABLE_LIST *const duplicate= unique_table(thd, delete_table_ref,
708 table_list->next_global, false);
709 if (duplicate)
710 {
711 update_non_unique_table_error(table_list, "DELETE", duplicate);
712 DBUG_RETURN(true);
713 }
714
715 if (select->inner_refs_list.elements && select->fix_inner_refs(thd))
716 DBUG_RETURN(true); /* purecov: inspected */
717
718 if (select->apply_local_transforms(thd, false))
719 DBUG_RETURN(true);
720
721 DBUG_RETURN(false);
722 }
723
724
725 /***************************************************************************
726 Delete multiple tables from join
727 ***************************************************************************/
728
729 #define MEM_STRIP_BUF_SIZE current_thd->variables.sortbuff_size
730
refpos_order_cmp(const void * arg,const void * a,const void * b)731 extern "C" int refpos_order_cmp(const void* arg, const void *a,const void *b)
732 {
733 handler *file= (handler*)arg;
734 return file->cmp_ref((const uchar*)a, (const uchar*)b);
735 }
736
737 /**
738 Make delete specific preparation and checks after opening tables.
739
740 @param thd Thread context.
741 @param[out] table_count Number of tables to be deleted from.
742
743 @retval false - success.
744 @retval true - error.
745 */
746
mysql_multi_delete_prepare(THD * thd,uint * table_count)747 int Sql_cmd_delete_multi::mysql_multi_delete_prepare(THD *thd,
748 uint *table_count)
749 {
750 DBUG_ENTER("mysql_multi_delete_prepare");
751
752 Prepare_error_tracker tracker(thd);
753
754 LEX *const lex= thd->lex;
755 SELECT_LEX *const select= lex->select_lex;
756
757 /*
758 setup_tables() need for VIEWs. SELECT_LEX::prepare() will not do it second
759 time.
760
761 lex->query_tables also point on local list of DELETE SELECT_LEX
762 */
763 if (select->setup_tables(thd, lex->query_tables, false))
764 DBUG_RETURN(true); /* purecov: inspected */
765
766 if (select->derived_table_count)
767 {
768 if (select->resolve_derived(thd, true))
769 DBUG_RETURN(true);
770
771 if (select->check_view_privileges(thd, DELETE_ACL, SELECT_ACL))
772 DBUG_RETURN(true);
773 }
774 *table_count= 0;
775
776 // Check the list of tables to be deleted from
777 for (TABLE_LIST *delete_target= lex->auxiliary_table_list.first;
778 delete_target;
779 delete_target= delete_target->next_local)
780 {
781 ++(*table_count);
782
783 TABLE_LIST *const table_ref= delete_target->correspondent_table;
784
785 if (!table_ref->is_updatable())
786 {
787 my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
788 delete_target->table_name, "DELETE");
789 DBUG_RETURN(true);
790 }
791
792 // DELETE does not allow deleting from multi-table views
793 if (table_ref->is_multiple_tables())
794 {
795 my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
796 table_ref->view_db.str, table_ref->view_name.str);
797 DBUG_RETURN(true);
798 }
799
800 if (check_key_in_view(thd, table_ref, table_ref->updatable_base_table()))
801 {
802 my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
803 delete_target->table_name, "DELETE");
804 DBUG_RETURN(true);
805 }
806
807 // A view must be merged, and thus cannot have a TABLE
808 assert(!table_ref->is_view() || table_ref->table == NULL);
809
810 // Enable the following code if allowing LIMIT with multi-table DELETE
811 assert(select->select_limit == 0);
812 }
813
814 DBUG_RETURN(false);
815 }
816
817
Query_result_delete(TABLE_LIST * dt,uint num_of_tables_arg)818 Query_result_delete::Query_result_delete(TABLE_LIST *dt,
819 uint num_of_tables_arg)
820 : delete_tables(dt), tempfiles(NULL), tables(NULL), deleted(0), found(0),
821 num_of_tables(num_of_tables_arg), error(0),
822 delete_table_map(0), delete_immediate(0),
823 transactional_table_map(0), non_transactional_table_map(0),
824 do_delete(0), non_transactional_deleted(false), error_handled(false)
825 {
826 }
827
828
prepare(List<Item> & values,SELECT_LEX_UNIT * u)829 int Query_result_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
830 {
831 DBUG_ENTER("Query_result_delete::prepare");
832 unit= u;
833 do_delete= true;
834 /*
835 Multi-delete can't be constructed over-union => we always have
836 single SELECT on top and have to check underlying SELECTs of it
837 */
838 SELECT_LEX *const select= unit->first_select();
839 select->exclude_from_table_unique_test= true;
840
841 for (TABLE_LIST *walk= delete_tables; walk; walk= walk->next_local)
842 {
843 if (walk->correspondent_table == NULL)
844 continue;
845
846 TABLE_LIST *ref= walk->correspondent_table->updatable_base_table();
847
848 // Don't use KEYREAD optimization on this table
849 ref->table->no_keyread= true;
850
851 /*
852 Check that table from which we delete is not used somewhere
853 inside subqueries/view.
854 */
855 TABLE_LIST *duplicate= unique_table(thd, ref,
856 thd->lex->query_tables, false);
857 if (duplicate)
858 {
859 update_non_unique_table_error(walk->correspondent_table,
860 "DELETE", duplicate);
861 DBUG_RETURN(1);
862 }
863 }
864
865 /*
866 Reset the exclude flag to false so it doesn't interfer
867 with further calls to unique_table
868 */
869 select->exclude_from_table_unique_test= false;
870
871 THD_STAGE_INFO(thd, stage_deleting_from_main_table);
872 DBUG_RETURN(0);
873 }
874
875
initialize_tables(JOIN * join)876 bool Query_result_delete::initialize_tables(JOIN *join)
877 {
878 DBUG_ENTER("Query_result_delete::initialize_tables");
879 ASSERT_BEST_REF_IN_JOIN_ORDER(join);
880
881 SELECT_LEX *const select= unit->first_select();
882 assert(join == select->join);
883
884 if ((thd->variables.option_bits & OPTION_SAFE_UPDATES) &&
885 error_if_full_join(join))
886 DBUG_RETURN(true);
887
888 if (!(tempfiles= (Unique **) sql_calloc(sizeof(Unique *) * num_of_tables)))
889 DBUG_RETURN(true); /* purecov: inspected */
890
891 if (!(tables= (TABLE **) sql_calloc(sizeof(TABLE *) * num_of_tables)))
892 DBUG_RETURN(true); /* purecov: inspected */
893
894 bool delete_while_scanning= true;
895 for (TABLE_LIST *walk= delete_tables; walk; walk= walk->next_local)
896 {
897 TABLE_LIST *const ref= walk->correspondent_table->updatable_base_table();
898 delete_table_map|= ref->map();
899 if (delete_while_scanning &&
900 unique_table(thd, ref, join->tables_list, false))
901 {
902 /*
903 If the table being deleted from is also referenced in the query,
904 defer delete so that the delete doesn't interfer with reading of this table.
905 */
906 delete_while_scanning= false;
907 }
908 }
909
910 for (uint i= 0; i < join->primary_tables; i++)
911 {
912 TABLE *const table= join->best_ref[i]->table();
913 const table_map map= join->best_ref[i]->table_ref->map();
914 if (!(map & delete_table_map))
915 continue;
916
917 // We are going to delete from this table
918 // Don't use record cache
919 table->no_cache= 1;
920 table->covering_keys.clear_all();
921 if (table->file->has_transactions())
922 transactional_table_map|= map;
923 else
924 non_transactional_table_map|= map;
925 if (table->triggers &&
926 table->triggers->has_triggers(TRG_EVENT_DELETE,
927 TRG_ACTION_AFTER))
928 {
929 /*
930 The table has AFTER DELETE triggers that might access the subject
931 table and therefore might need delete to be done immediately.
932 So we turn-off the batching.
933 */
934 (void) table->file->extra(HA_EXTRA_DELETE_CANNOT_BATCH);
935 }
936 if (thd->lex->is_ignore())
937 table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
938 table->prepare_for_position();
939 table->mark_columns_needed_for_delete();
940 if (thd->is_error())
941 DBUG_RETURN(true);
942 }
943 /*
944 In some cases, rows may be deleted from the first table(s) in the join order
945 while performing the join operation when "delete_while_scanning" is true and
946 1. deleting from one of the const tables, or
947 2. deleting from the first non-const table
948 */
949 table_map possible_tables= join->const_table_map; // 1
950 if (join->primary_tables > join->const_tables)
951 possible_tables|= join->best_ref[join->const_tables]->table_ref->map();// 2
952 if (delete_while_scanning)
953 delete_immediate= delete_table_map & possible_tables;
954
955 // Set up a Unique object for each table whose delete operation is deferred:
956
957 Unique **tempfile= tempfiles;
958 TABLE **table_ptr= tables;
959 for (uint i= 0; i < join->primary_tables; i++)
960 {
961 const table_map map= join->best_ref[i]->table_ref->map();
962
963 if (!(map & delete_table_map & ~delete_immediate))
964 continue;
965
966 TABLE *const table= join->best_ref[i]->table();
967 if (!(*tempfile++= new Unique(refpos_order_cmp,
968 (void *) table->file,
969 table->file->ref_length,
970 MEM_STRIP_BUF_SIZE)))
971 DBUG_RETURN(true); /* purecov: inspected */
972 *(table_ptr++)= table;
973 }
974 assert(select == thd->lex->current_select());
975
976 if (select->has_ft_funcs() && init_ftfuncs(thd, select))
977 DBUG_RETURN(true);
978
979 DBUG_RETURN(thd->is_fatal_error != 0);
980 }
981
982
~Query_result_delete()983 Query_result_delete::~Query_result_delete()
984 {
985 for (TABLE_LIST *tbl_ref= delete_tables; tbl_ref;
986 tbl_ref= tbl_ref->next_local)
987 {
988 TABLE *table= tbl_ref->correspondent_table->updatable_base_table()->table;
989 if (thd->lex->is_ignore())
990 table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
991 }
992
993 for (uint counter= 0; counter < num_of_tables; counter++)
994 {
995 if (tempfiles && tempfiles[counter])
996 delete tempfiles[counter];
997 }
998 }
999
1000
send_data(List<Item> & values)1001 bool Query_result_delete::send_data(List<Item> &values)
1002 {
1003 DBUG_ENTER("Query_result_delete::send_data");
1004
1005 JOIN *const join= unit->first_select()->join;
1006
1007 assert(thd->lex->current_select() == unit->first_select());
1008 int unique_counter= 0;
1009
1010 for (uint i= 0; i < join->primary_tables; i++)
1011 {
1012 const table_map map= join->qep_tab[i].table_ref->map();
1013
1014 // Check whether this table is being deleted from
1015 if (!(map & delete_table_map))
1016 continue;
1017
1018 const bool immediate= map & delete_immediate;
1019
1020 TABLE *const table= join->qep_tab[i].table();
1021
1022 assert(immediate || table == tables[unique_counter]);
1023
1024 /*
1025 If not doing immediate deletion, increment unique_counter and assign
1026 "tempfile" here, so that it is available when and if it is needed.
1027 */
1028 Unique *const tempfile= immediate ? NULL : tempfiles[unique_counter++];
1029
1030 // Check if using outer join and no row found, or row is already deleted
1031 if (table->status & (STATUS_NULL_ROW | STATUS_DELETED))
1032 continue;
1033
1034 table->file->position(table->record[0]);
1035 found++;
1036
1037 if (immediate)
1038 {
1039 // Rows from this table can be deleted immediately
1040 if (table->triggers &&
1041 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
1042 TRG_ACTION_BEFORE, FALSE))
1043 DBUG_RETURN(true);
1044 table->status|= STATUS_DELETED;
1045 if (map & non_transactional_table_map)
1046 non_transactional_deleted= true;
1047 if (!(error=table->file->ha_delete_row(table->record[0])))
1048 {
1049 deleted++;
1050 if (!table->file->has_transactions())
1051 thd->get_transaction()->mark_modified_non_trans_table(
1052 Transaction_ctx::STMT);
1053 if (table->triggers &&
1054 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
1055 TRG_ACTION_AFTER, FALSE))
1056 DBUG_RETURN(true);
1057 }
1058 else
1059 {
1060 myf error_flags= MYF(0);
1061 if (table->file->is_fatal_error(error))
1062 error_flags|= ME_FATALERROR;
1063 table->file->print_error(error, error_flags);
1064
1065 /*
1066 If IGNORE option is used errors caused by ha_delete_row will
1067 be downgraded to warnings and don't have to stop the iteration.
1068 */
1069 if (thd->is_error())
1070 DBUG_RETURN(true);
1071
1072 /*
1073 If IGNORE keyword is used, then 'error' variable will have the error
1074 number which is ignored. Reset the 'error' variable if IGNORE is used.
1075 This is necessary to call my_ok().
1076 */
1077 error= 0;
1078 }
1079 }
1080 else
1081 {
1082 // Save deletes in a Unique object, to be carried out later.
1083 error= tempfile->unique_add((char*) table->file->ref);
1084 if (error)
1085 {
1086 /* purecov: begin inspected */
1087 error= 1;
1088 DBUG_RETURN(true);
1089 /* purecov: end */
1090 }
1091 }
1092 }
1093 DBUG_RETURN(false);
1094 }
1095
1096
send_error(uint errcode,const char * err)1097 void Query_result_delete::send_error(uint errcode,const char *err)
1098 {
1099 DBUG_ENTER("Query_result_delete::send_error");
1100
1101 /* First send error what ever it is ... */
1102 my_message(errcode, err, MYF(0));
1103
1104 DBUG_VOID_RETURN;
1105 }
1106
1107
1108 /**
1109 Wrapper function for query cache invalidation.
1110
1111 @param thd THD pointer
1112 @param delete_tables Pointer to list of tables to invalidate cache for.
1113 */
1114
invalidate_delete_tables(THD * thd,TABLE_LIST * delete_tables)1115 static void invalidate_delete_tables(THD *thd, TABLE_LIST *delete_tables)
1116 {
1117 for (TABLE_LIST *tl= delete_tables; tl != NULL; tl= tl->next_local)
1118 {
1119 query_cache.invalidate_single(thd,
1120 tl->correspondent_table->updatable_base_table(), 1);
1121 }
1122 }
1123
1124
abort_result_set()1125 void Query_result_delete::abort_result_set()
1126 {
1127 DBUG_ENTER("Query_result_delete::abort_result_set");
1128
1129 /* the error was handled or nothing deleted and no side effects return */
1130 if (error_handled ||
1131 (!thd->get_transaction()->cannot_safely_rollback(
1132 Transaction_ctx::STMT) && !deleted))
1133 DBUG_VOID_RETURN;
1134
1135 /* Something already deleted so we have to invalidate cache */
1136 if (deleted)
1137 invalidate_delete_tables(thd, delete_tables);
1138
1139 /*
1140 If rows from the first table only has been deleted and it is
1141 transactional, just do rollback.
1142 The same if all tables are transactional, regardless of where we are.
1143 In all other cases do attempt deletes ...
1144 */
1145 if (do_delete && non_transactional_deleted)
1146 {
1147 /*
1148 We have to execute the recorded do_deletes() and write info into the
1149 error log
1150 */
1151 error= 1;
1152 send_eof();
1153 assert(error_handled);
1154 DBUG_VOID_RETURN;
1155 }
1156
1157 if (thd->get_transaction()->cannot_safely_rollback(Transaction_ctx::STMT))
1158 {
1159 /*
1160 there is only side effects; to binlog with the error
1161 */
1162 if (mysql_bin_log.is_open())
1163 {
1164 int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
1165 /* possible error of writing binary log is ignored deliberately */
1166 (void) thd->binlog_query(THD::ROW_QUERY_TYPE,
1167 thd->query().str, thd->query().length,
1168 transactional_table_map != 0, FALSE, FALSE,
1169 errcode);
1170 }
1171 }
1172 DBUG_VOID_RETURN;
1173 }
1174
1175
1176
1177 /**
1178 Do delete from other tables.
1179
1180 @retval 0 ok
1181 @retval 1 error
1182
1183 @todo Is there any reason not use the normal nested-loops join? If not, and
1184 there is no documentation supporting it, this method and callee should be
1185 removed and there should be hooks within normal execution.
1186 */
1187
do_deletes()1188 int Query_result_delete::do_deletes()
1189 {
1190 DBUG_ENTER("Query_result_delete::do_deletes");
1191 assert(do_delete);
1192
1193 assert(thd->lex->current_select() == unit->first_select());
1194 do_delete= false; // Mark called
1195 if (!found)
1196 DBUG_RETURN(0);
1197
1198 for (uint counter= 0; counter < num_of_tables; counter++)
1199 {
1200 TABLE *const table= tables[counter];
1201 if (table == NULL)
1202 break;
1203
1204 if (tempfiles[counter]->get(table))
1205 DBUG_RETURN(1);
1206
1207 int local_error= do_table_deletes(table);
1208
1209 if (thd->killed && !local_error)
1210 DBUG_RETURN(1);
1211
1212 if (local_error == -1) // End of file
1213 local_error = 0;
1214
1215 if (local_error)
1216 DBUG_RETURN(local_error);
1217 }
1218 DBUG_RETURN(0);
1219 }
1220
1221
1222 /**
1223 Implements the inner loop of nested-loops join within multi-DELETE
1224 execution.
1225
1226 @param table The table from which to delete.
1227
1228 @return Status code
1229
1230 @retval 0 All ok.
1231 @retval 1 Triggers or handler reported error.
1232 @retval -1 End of file from handler.
1233 */
do_table_deletes(TABLE * table)1234 int Query_result_delete::do_table_deletes(TABLE *table)
1235 {
1236 myf error_flags= MYF(0); /**< Flag for fatal errors */
1237 int local_error= 0;
1238 READ_RECORD info;
1239 ha_rows last_deleted= deleted;
1240 DBUG_ENTER("do_deletes_for_table");
1241 if (init_read_record(&info, thd, table, NULL, 0, 1, FALSE))
1242 DBUG_RETURN(1);
1243 /*
1244 Ignore any rows not found in reference tables as they may already have
1245 been deleted by foreign key handling
1246 */
1247 info.ignore_not_found_rows= 1;
1248 bool will_batch= !table->file->start_bulk_delete();
1249 while (!(local_error= info.read_record(&info)) && !thd->killed)
1250 {
1251 if (table->triggers &&
1252 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
1253 TRG_ACTION_BEFORE, FALSE))
1254 {
1255 local_error= 1;
1256 break;
1257 }
1258
1259 local_error= table->file->ha_delete_row(table->record[0]);
1260 if (local_error)
1261 {
1262 if (table->file->is_fatal_error(local_error))
1263 error_flags|= ME_FATALERROR;
1264
1265 table->file->print_error(local_error, error_flags);
1266 /*
1267 If IGNORE option is used errors caused by ha_delete_row will
1268 be downgraded to warnings and don't have to stop the iteration.
1269 */
1270 if (thd->is_error())
1271 break;
1272 }
1273
1274 /*
1275 Increase the reported number of deleted rows only if no error occurred
1276 during ha_delete_row.
1277 Also, don't execute the AFTER trigger if the row operation failed.
1278 */
1279 if (!local_error)
1280 {
1281 deleted++;
1282 if (table->pos_in_table_list->map() & non_transactional_table_map)
1283 non_transactional_deleted= true;
1284
1285 if (table->triggers &&
1286 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
1287 TRG_ACTION_AFTER, FALSE))
1288 {
1289 local_error= 1;
1290 break;
1291 }
1292 }
1293 }
1294 if (will_batch)
1295 {
1296 int tmp_error= table->file->end_bulk_delete();
1297 if (tmp_error && !local_error)
1298 {
1299 local_error= tmp_error;
1300 if (table->file->is_fatal_error(local_error))
1301 error_flags|= ME_FATALERROR;
1302
1303 table->file->print_error(local_error, error_flags);
1304 }
1305 }
1306 if (last_deleted != deleted && !table->file->has_transactions())
1307 thd->get_transaction()->mark_modified_non_trans_table(
1308 Transaction_ctx::STMT);
1309
1310 end_read_record(&info);
1311
1312 DBUG_RETURN(local_error);
1313 }
1314
1315 /**
1316 Send ok to the client
1317
1318 The function has to perform all deferred deletes that have been queued up.
1319
1320 @return false if success, true if error
1321 */
1322
send_eof()1323 bool Query_result_delete::send_eof()
1324 {
1325 THD::killed_state killed_status= THD::NOT_KILLED;
1326 THD_STAGE_INFO(thd, stage_deleting_from_reference_tables);
1327
1328 /* Does deletes for the last n - 1 tables, returns 0 if ok */
1329 int local_error= do_deletes(); // returns 0 if success
1330
1331 /* compute a total error to know if something failed */
1332 local_error= local_error || error;
1333 killed_status= (local_error == 0)? THD::NOT_KILLED : thd->killed;
1334 /* reset used flags */
1335 THD_STAGE_INFO(thd, stage_end);
1336
1337 /*
1338 We must invalidate the query cache before binlog writing and
1339 ha_autocommit_...
1340 */
1341 if (deleted)
1342 invalidate_delete_tables(thd, delete_tables);
1343
1344 if ((local_error == 0) ||
1345 thd->get_transaction()->cannot_safely_rollback(Transaction_ctx::STMT))
1346 {
1347 if (mysql_bin_log.is_open())
1348 {
1349 int errcode= 0;
1350 if (local_error == 0)
1351 thd->clear_error();
1352 else
1353 errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
1354 thd->thread_specific_used= TRUE;
1355 if (thd->binlog_query(THD::ROW_QUERY_TYPE,
1356 thd->query().str, thd->query().length,
1357 transactional_table_map != 0, FALSE, FALSE,
1358 errcode) &&
1359 !non_transactional_table_map)
1360 {
1361 local_error=1; // Log write failed: roll back the SQL statement
1362 }
1363 }
1364 }
1365 if (local_error != 0)
1366 error_handled= TRUE; // to force early leave from ::send_error()
1367
1368 if (!local_error)
1369 {
1370 ::my_ok(thd, deleted);
1371 }
1372 return 0;
1373 }
1374
1375
execute(THD * thd)1376 bool Sql_cmd_delete::execute(THD *thd)
1377 {
1378 assert(thd->lex->sql_command == SQLCOM_DELETE);
1379
1380 LEX *const lex= thd->lex;
1381 SELECT_LEX *const select_lex= lex->select_lex;
1382 SELECT_LEX_UNIT *const unit= lex->unit;
1383 TABLE_LIST *const first_table= select_lex->get_table_list();
1384 TABLE_LIST *const all_tables= first_table;
1385
1386 if (delete_precheck(thd, all_tables))
1387 return true;
1388 assert(select_lex->offset_limit == 0);
1389 unit->set_limit(select_lex);
1390
1391 /* Push ignore / strict error handler */
1392 Ignore_error_handler ignore_handler;
1393 Strict_error_handler strict_handler;
1394 if (thd->lex->is_ignore())
1395 thd->push_internal_handler(&ignore_handler);
1396 else if (thd->is_strict_mode())
1397 thd->push_internal_handler(&strict_handler);
1398
1399 MYSQL_DELETE_START(const_cast<char*>(thd->query().str));
1400 bool res = mysql_delete(thd, unit->select_limit_cnt);
1401 MYSQL_DELETE_DONE(res, (ulong) thd->get_row_count_func());
1402
1403 /* Pop ignore / strict error handler */
1404 if (thd->lex->is_ignore() || thd->is_strict_mode())
1405 thd->pop_internal_handler();
1406
1407 return res;
1408 }
1409
1410
execute(THD * thd)1411 bool Sql_cmd_delete_multi::execute(THD *thd)
1412 {
1413 assert(thd->lex->sql_command == SQLCOM_DELETE_MULTI);
1414
1415 bool res= false;
1416 LEX *const lex= thd->lex;
1417 SELECT_LEX *const select_lex= lex->select_lex;
1418 TABLE_LIST *const first_table= select_lex->get_table_list();
1419 TABLE_LIST *const all_tables= first_table;
1420
1421 TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first;
1422 uint del_table_count;
1423 Query_result_delete *del_result;
1424
1425 if (multi_delete_precheck(thd, all_tables))
1426 return true;
1427
1428 /* condition will be TRUE on SP re-excuting */
1429 if (select_lex->item_list.elements != 0)
1430 select_lex->item_list.empty();
1431 if (add_item_to_list(thd, new Item_null()))
1432 return true;
1433
1434 THD_STAGE_INFO(thd, stage_init);
1435 if ((res= open_tables_for_query(thd, all_tables, 0)))
1436 return true;
1437
1438 if (run_before_dml_hook(thd))
1439 return true;
1440
1441 MYSQL_MULTI_DELETE_START(const_cast<char*>(thd->query().str));
1442 if (mysql_multi_delete_prepare(thd, &del_table_count))
1443 {
1444 MYSQL_MULTI_DELETE_DONE(1, 0);
1445 return true;
1446 }
1447
1448 if (!thd->is_fatal_error &&
1449 (del_result= new Query_result_delete(aux_tables, del_table_count)))
1450 {
1451 assert(select_lex->having_cond() == NULL &&
1452 !select_lex->order_list.elements &&
1453 !select_lex->group_list.elements);
1454
1455 Ignore_error_handler ignore_handler;
1456 Strict_error_handler strict_handler;
1457 if (thd->lex->is_ignore())
1458 thd->push_internal_handler(&ignore_handler);
1459 else if (thd->is_strict_mode())
1460 thd->push_internal_handler(&strict_handler);
1461
1462 res= handle_query(thd, lex, del_result,
1463 SELECT_NO_JOIN_CACHE |
1464 SELECT_NO_UNLOCK |
1465 OPTION_SETUP_TABLES_DONE,
1466 OPTION_BUFFER_RESULT);
1467
1468 if (thd->lex->is_ignore() || thd->is_strict_mode())
1469 thd->pop_internal_handler();
1470
1471 if (res)
1472 del_result->abort_result_set();
1473
1474 MYSQL_MULTI_DELETE_DONE(res, del_result->num_deleted());
1475 delete del_result;
1476 }
1477 else
1478 {
1479 res= true; // Error
1480 MYSQL_MULTI_DELETE_DONE(1, 0);
1481 }
1482
1483 return res;
1484 }
1485