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
617 thd->updated_row_count+= deleted;
618
619 DBUG_RETURN(thd->is_error() || thd->killed);
620
621 exit_without_my_ok:
622 free_underlaid_joins(thd, select_lex);
623 table->set_keyread(false);
624 DBUG_RETURN((err || thd->is_error() || thd->killed) ? 1 : 0);
625 }
626
627
628 /**
629 Prepare items in DELETE statement
630
631 @param thd - thread handler
632
633 @return false if success, true if error
634 */
635
mysql_prepare_delete(THD * thd)636 bool Sql_cmd_delete::mysql_prepare_delete(THD *thd)
637 {
638 DBUG_ENTER("mysql_prepare_delete");
639
640 List<Item> all_fields;
641 SELECT_LEX *const select= thd->lex->select_lex;
642 TABLE_LIST *const table_list= select->get_table_list();
643
644 if (select->setup_tables(thd, table_list, false))
645 DBUG_RETURN(true); /* purecov: inspected */
646
647 if (table_list->is_view() && select->resolve_derived(thd, false))
648 DBUG_RETURN(true); /* purecov: inspected */
649
650 if (!table_list->is_updatable())
651 {
652 my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE");
653 DBUG_RETURN(true);
654 }
655
656 if (table_list->is_multiple_tables())
657 {
658 my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
659 table_list->view_db.str, table_list->view_name.str);
660 DBUG_RETURN(TRUE);
661 }
662
663 TABLE_LIST *const delete_table_ref= table_list->updatable_base_table();
664
665 thd->lex->allow_sum_func= 0;
666 if (table_list->is_view() &&
667 select->check_view_privileges(thd, DELETE_ACL, SELECT_ACL))
668 DBUG_RETURN(true);
669
670 ulong want_privilege_saved= thd->want_privilege;
671 thd->want_privilege= SELECT_ACL;
672 enum enum_mark_columns mark_used_columns_saved= thd->mark_used_columns;
673 thd->mark_used_columns= MARK_COLUMNS_READ;
674
675 if (select->setup_conds(thd))
676 DBUG_RETURN(true);
677
678 // check ORDER BY even if it can be ignored
679 if (select->order_list.first)
680 {
681 TABLE_LIST tables;
682 List<Item> fields;
683 List<Item> all_fields;
684
685 tables.table = table_list->table;
686 tables.alias = table_list->alias;
687
688 assert(!select->group_list.elements);
689 if (select->setup_ref_array(thd))
690 DBUG_RETURN(true); /* purecov: inspected */
691 if (setup_order(thd, select->ref_pointer_array, &tables,
692 fields, all_fields, select->order_list.first))
693 DBUG_RETURN(true);
694 }
695
696 thd->want_privilege= want_privilege_saved;
697 thd->mark_used_columns= mark_used_columns_saved;
698
699 if (setup_ftfuncs(select))
700 DBUG_RETURN(true); /* purecov: inspected */
701
702 // check_key_in_view() may send an SQL note, but we only want it once.
703 if (select->first_execution &&
704 check_key_in_view(thd, table_list, delete_table_ref))
705 {
706 my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE");
707 DBUG_RETURN(true);
708 }
709
710 TABLE_LIST *const duplicate= unique_table(thd, delete_table_ref,
711 table_list->next_global, false);
712 if (duplicate)
713 {
714 update_non_unique_table_error(table_list, "DELETE", duplicate);
715 DBUG_RETURN(true);
716 }
717
718 if (select->inner_refs_list.elements && select->fix_inner_refs(thd))
719 DBUG_RETURN(true); /* purecov: inspected */
720
721 if (select->apply_local_transforms(thd, false))
722 DBUG_RETURN(true);
723
724 DBUG_RETURN(false);
725 }
726
727
728 /***************************************************************************
729 Delete multiple tables from join
730 ***************************************************************************/
731
732 #define MEM_STRIP_BUF_SIZE current_thd->variables.sortbuff_size
733
refpos_order_cmp(const void * arg,const void * a,const void * b)734 extern "C" int refpos_order_cmp(const void* arg, const void *a,const void *b)
735 {
736 handler *file= (handler*)arg;
737 return file->cmp_ref((const uchar*)a, (const uchar*)b);
738 }
739
740 /**
741 Make delete specific preparation and checks after opening tables.
742
743 @param thd Thread context.
744 @param[out] table_count Number of tables to be deleted from.
745
746 @retval false - success.
747 @retval true - error.
748 */
749
mysql_multi_delete_prepare(THD * thd,uint * table_count)750 int Sql_cmd_delete_multi::mysql_multi_delete_prepare(THD *thd,
751 uint *table_count)
752 {
753 DBUG_ENTER("mysql_multi_delete_prepare");
754
755 Prepare_error_tracker tracker(thd);
756
757 LEX *const lex= thd->lex;
758 SELECT_LEX *const select= lex->select_lex;
759
760 /*
761 setup_tables() need for VIEWs. SELECT_LEX::prepare() will not do it second
762 time.
763
764 lex->query_tables also point on local list of DELETE SELECT_LEX
765 */
766 if (select->setup_tables(thd, lex->query_tables, false))
767 DBUG_RETURN(true); /* purecov: inspected */
768
769 if (select->derived_table_count)
770 {
771 if (select->resolve_derived(thd, true))
772 DBUG_RETURN(true);
773
774 if (select->check_view_privileges(thd, DELETE_ACL, SELECT_ACL))
775 DBUG_RETURN(true);
776 }
777 *table_count= 0;
778
779 // Check the list of tables to be deleted from
780 for (TABLE_LIST *delete_target= lex->auxiliary_table_list.first;
781 delete_target;
782 delete_target= delete_target->next_local)
783 {
784 ++(*table_count);
785
786 TABLE_LIST *const table_ref= delete_target->correspondent_table;
787
788 if (!table_ref->is_updatable())
789 {
790 my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
791 delete_target->table_name, "DELETE");
792 DBUG_RETURN(true);
793 }
794
795 // DELETE does not allow deleting from multi-table views
796 if (table_ref->is_multiple_tables())
797 {
798 my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
799 table_ref->view_db.str, table_ref->view_name.str);
800 DBUG_RETURN(true);
801 }
802
803 if (check_key_in_view(thd, table_ref, table_ref->updatable_base_table()))
804 {
805 my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
806 delete_target->table_name, "DELETE");
807 DBUG_RETURN(true);
808 }
809
810 // A view must be merged, and thus cannot have a TABLE
811 assert(!table_ref->is_view() || table_ref->table == NULL);
812
813 // Enable the following code if allowing LIMIT with multi-table DELETE
814 assert(select->select_limit == 0);
815 }
816
817 DBUG_RETURN(false);
818 }
819
820
Query_result_delete(TABLE_LIST * dt,uint num_of_tables_arg)821 Query_result_delete::Query_result_delete(TABLE_LIST *dt,
822 uint num_of_tables_arg)
823 : delete_tables(dt), tempfiles(NULL), tables(NULL), deleted(0), found(0),
824 num_of_tables(num_of_tables_arg), error(0),
825 delete_table_map(0), delete_immediate(0),
826 transactional_table_map(0), non_transactional_table_map(0),
827 do_delete(0), non_transactional_deleted(false), error_handled(false)
828 {
829 }
830
831
prepare(List<Item> & values,SELECT_LEX_UNIT * u)832 int Query_result_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
833 {
834 DBUG_ENTER("Query_result_delete::prepare");
835 unit= u;
836 do_delete= true;
837 /*
838 Multi-delete can't be constructed over-union => we always have
839 single SELECT on top and have to check underlying SELECTs of it
840 */
841 SELECT_LEX *const select= unit->first_select();
842 select->exclude_from_table_unique_test= true;
843
844 for (TABLE_LIST *walk= delete_tables; walk; walk= walk->next_local)
845 {
846 if (walk->correspondent_table == NULL)
847 continue;
848
849 TABLE_LIST *ref= walk->correspondent_table->updatable_base_table();
850
851 // Don't use KEYREAD optimization on this table
852 ref->table->no_keyread= true;
853
854 /*
855 Check that table from which we delete is not used somewhere
856 inside subqueries/view.
857 */
858 TABLE_LIST *duplicate= unique_table(thd, ref,
859 thd->lex->query_tables, false);
860 if (duplicate)
861 {
862 update_non_unique_table_error(walk->correspondent_table,
863 "DELETE", duplicate);
864 DBUG_RETURN(1);
865 }
866 }
867
868 /*
869 Reset the exclude flag to false so it doesn't interfer
870 with further calls to unique_table
871 */
872 select->exclude_from_table_unique_test= false;
873
874 THD_STAGE_INFO(thd, stage_deleting_from_main_table);
875 DBUG_RETURN(0);
876 }
877
878 /**
879 Test that the two strings are equal, accoding to the lower_case_table_names
880 setting.
881
882 @param a A table or database name
883 @param b A table or database name
884 @retval bool True if the two names are equal
885 */
db_or_table_name_equals(const char * a,const char * b)886 static bool db_or_table_name_equals(const char* a, const char *b) {
887 return lower_case_table_names ?
888 my_strcasecmp(files_charset_info, a, b) == 0 :
889 strcmp(a, b) == 0;
890 }
891
892 /**
893 Test that the subject table (of DELETE) has a cascade foreign key
894 parent present in the query.
895
896 @param thd thread handle
897 @param table table to be checked (must be updatable base table)
898 @param table_list List of tables to check against
899
900 @retval bool True if cascade parent found.
901 */
has_cascade_dependency(THD * thd,const TABLE_LIST & table,TABLE_LIST * table_list)902 static bool has_cascade_dependency(THD *thd, const TABLE_LIST &table,
903 TABLE_LIST *table_list)
904 {
905 assert(&table == const_cast<TABLE_LIST &>(table).updatable_base_table());
906
907 List <st_handler_tablename> fk_table_list;
908 List_iterator<st_handler_tablename> fk_table_list_it(fk_table_list);
909
910 table.table->file->get_cascade_foreign_key_table_list(thd, &fk_table_list);
911
912 st_handler_tablename *tbl_name;
913 while ((tbl_name= fk_table_list_it++))
914 {
915 for (TABLE_LIST* curr= table_list; curr; curr= curr->next_local)
916 {
917 const bool same_table_name=
918 db_or_table_name_equals(curr->table_name, tbl_name->tablename);
919 const bool same_db_name=
920 db_or_table_name_equals(curr->db, tbl_name->db);
921 if (same_table_name && same_db_name)
922 {
923 return true;
924 }
925 }
926 }
927
928 return false;
929 }
930
initialize_tables(JOIN * join)931 bool Query_result_delete::initialize_tables(JOIN *join)
932 {
933 DBUG_ENTER("Query_result_delete::initialize_tables");
934 ASSERT_BEST_REF_IN_JOIN_ORDER(join);
935
936 SELECT_LEX *const select= unit->first_select();
937 assert(join == select->join);
938
939 if ((thd->variables.option_bits & OPTION_SAFE_UPDATES) &&
940 error_if_full_join(join))
941 DBUG_RETURN(true);
942
943 if (!(tempfiles= (Unique **) sql_calloc(sizeof(Unique *) * num_of_tables)))
944 DBUG_RETURN(true); /* purecov: inspected */
945
946 if (!(tables= (TABLE **) sql_calloc(sizeof(TABLE *) * num_of_tables)))
947 DBUG_RETURN(true); /* purecov: inspected */
948
949 bool delete_while_scanning= true;
950 for (TABLE_LIST *walk= delete_tables; walk; walk= walk->next_local)
951 {
952 TABLE_LIST *const ref= walk->correspondent_table->updatable_base_table();
953 delete_table_map|= ref->map();
954 if (delete_while_scanning &&
955 (unique_table(thd, ref, join->tables_list, false) ||
956 has_cascade_dependency(thd, *ref, join->tables_list)))
957 {
958 /*
959 If the table being deleted from is also referenced in the query,
960 defer delete so that the delete doesn't interfer with reading of this table.
961 */
962 delete_while_scanning= false;
963 }
964 }
965
966 for (uint i= 0; i < join->primary_tables; i++)
967 {
968 TABLE *const table= join->best_ref[i]->table();
969 const table_map map= join->best_ref[i]->table_ref->map();
970 if (!(map & delete_table_map))
971 continue;
972
973 // We are going to delete from this table
974 // Don't use record cache
975 table->no_cache= 1;
976 table->covering_keys.clear_all();
977 if (table->file->has_transactions())
978 transactional_table_map|= map;
979 else
980 non_transactional_table_map|= map;
981 if (table->triggers &&
982 table->triggers->has_triggers(TRG_EVENT_DELETE,
983 TRG_ACTION_AFTER))
984 {
985 /*
986 The table has AFTER DELETE triggers that might access the subject
987 table and therefore might need delete to be done immediately.
988 So we turn-off the batching.
989 */
990 (void) table->file->extra(HA_EXTRA_DELETE_CANNOT_BATCH);
991 }
992 if (thd->lex->is_ignore())
993 table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
994 table->prepare_for_position();
995 table->mark_columns_needed_for_delete();
996 if (thd->is_error())
997 DBUG_RETURN(true);
998 }
999 /*
1000 In some cases, rows may be deleted from the first table(s) in the join order
1001 while performing the join operation when "delete_while_scanning" is true and
1002 1. deleting from one of the const tables, or
1003 2. deleting from the first non-const table
1004 */
1005 table_map possible_tables= join->const_table_map; // 1
1006 if (join->primary_tables > join->const_tables)
1007 possible_tables|= join->best_ref[join->const_tables]->table_ref->map();// 2
1008 if (delete_while_scanning)
1009 delete_immediate= delete_table_map & possible_tables;
1010
1011 // Set up a Unique object for each table whose delete operation is deferred:
1012
1013 Unique **tempfile= tempfiles;
1014 TABLE **table_ptr= tables;
1015 for (uint i= 0; i < join->primary_tables; i++)
1016 {
1017 const table_map map= join->best_ref[i]->table_ref->map();
1018
1019 if (!(map & delete_table_map & ~delete_immediate))
1020 continue;
1021
1022 TABLE *const table= join->best_ref[i]->table();
1023 if (!(*tempfile++= new Unique(refpos_order_cmp,
1024 (void *) table->file,
1025 table->file->ref_length,
1026 MEM_STRIP_BUF_SIZE)))
1027 DBUG_RETURN(true); /* purecov: inspected */
1028 *(table_ptr++)= table;
1029 }
1030 assert(select == thd->lex->current_select());
1031
1032 if (select->has_ft_funcs() && init_ftfuncs(thd, select))
1033 DBUG_RETURN(true);
1034
1035 DBUG_RETURN(thd->is_fatal_error != 0);
1036 }
1037
1038
~Query_result_delete()1039 Query_result_delete::~Query_result_delete()
1040 {
1041 for (TABLE_LIST *tbl_ref= delete_tables; tbl_ref;
1042 tbl_ref= tbl_ref->next_local)
1043 {
1044 TABLE *table= tbl_ref->correspondent_table->updatable_base_table()->table;
1045 if (thd->lex->is_ignore())
1046 table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
1047 }
1048
1049 for (uint counter= 0; counter < num_of_tables; counter++)
1050 {
1051 if (tempfiles && tempfiles[counter])
1052 delete tempfiles[counter];
1053 }
1054 }
1055
1056
send_data(List<Item> & values)1057 bool Query_result_delete::send_data(List<Item> &values)
1058 {
1059 DBUG_ENTER("Query_result_delete::send_data");
1060
1061 JOIN *const join= unit->first_select()->join;
1062
1063 assert(thd->lex->current_select() == unit->first_select());
1064 int unique_counter= 0;
1065
1066 for (uint i= 0; i < join->primary_tables; i++)
1067 {
1068 const table_map map= join->qep_tab[i].table_ref->map();
1069
1070 // Check whether this table is being deleted from
1071 if (!(map & delete_table_map))
1072 continue;
1073
1074 const bool immediate= map & delete_immediate;
1075
1076 TABLE *const table= join->qep_tab[i].table();
1077
1078 assert(immediate || table == tables[unique_counter]);
1079
1080 /*
1081 If not doing immediate deletion, increment unique_counter and assign
1082 "tempfile" here, so that it is available when and if it is needed.
1083 */
1084 Unique *const tempfile= immediate ? NULL : tempfiles[unique_counter++];
1085
1086 // Check if using outer join and no row found, or row is already deleted
1087 if (table->status & (STATUS_NULL_ROW | STATUS_DELETED))
1088 continue;
1089
1090 table->file->position(table->record[0]);
1091 found++;
1092
1093 if (immediate)
1094 {
1095 // Rows from this table can be deleted immediately
1096 if (table->triggers &&
1097 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
1098 TRG_ACTION_BEFORE, FALSE))
1099 DBUG_RETURN(true);
1100 table->status|= STATUS_DELETED;
1101 if (map & non_transactional_table_map)
1102 non_transactional_deleted= true;
1103 if (!(error=table->file->ha_delete_row(table->record[0])))
1104 {
1105 deleted++;
1106 if (!table->file->has_transactions())
1107 thd->get_transaction()->mark_modified_non_trans_table(
1108 Transaction_ctx::STMT);
1109 if (table->triggers &&
1110 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
1111 TRG_ACTION_AFTER, FALSE))
1112 DBUG_RETURN(true);
1113 }
1114 else
1115 {
1116 myf error_flags= MYF(0);
1117 if (table->file->is_fatal_error(error))
1118 error_flags|= ME_FATALERROR;
1119 table->file->print_error(error, error_flags);
1120
1121 /*
1122 If IGNORE option is used errors caused by ha_delete_row will
1123 be downgraded to warnings and don't have to stop the iteration.
1124 */
1125 if (thd->is_error())
1126 DBUG_RETURN(true);
1127
1128 /*
1129 If IGNORE keyword is used, then 'error' variable will have the error
1130 number which is ignored. Reset the 'error' variable if IGNORE is used.
1131 This is necessary to call my_ok().
1132 */
1133 error= 0;
1134 }
1135 }
1136 else
1137 {
1138 // Save deletes in a Unique object, to be carried out later.
1139 error= tempfile->unique_add((char*) table->file->ref);
1140 if (error)
1141 {
1142 /* purecov: begin inspected */
1143 error= 1;
1144 DBUG_RETURN(true);
1145 /* purecov: end */
1146 }
1147 }
1148 }
1149 DBUG_RETURN(false);
1150 }
1151
1152
send_error(uint errcode,const char * err)1153 void Query_result_delete::send_error(uint errcode,const char *err)
1154 {
1155 DBUG_ENTER("Query_result_delete::send_error");
1156
1157 /* First send error what ever it is ... */
1158 my_message(errcode, err, MYF(0));
1159
1160 DBUG_VOID_RETURN;
1161 }
1162
1163
1164 /**
1165 Wrapper function for query cache invalidation.
1166
1167 @param thd THD pointer
1168 @param delete_tables Pointer to list of tables to invalidate cache for.
1169 */
1170
invalidate_delete_tables(THD * thd,TABLE_LIST * delete_tables)1171 static void invalidate_delete_tables(THD *thd, TABLE_LIST *delete_tables)
1172 {
1173 for (TABLE_LIST *tl= delete_tables; tl != NULL; tl= tl->next_local)
1174 {
1175 query_cache.invalidate_single(thd,
1176 tl->correspondent_table->updatable_base_table(), 1);
1177 }
1178 }
1179
1180
abort_result_set()1181 void Query_result_delete::abort_result_set()
1182 {
1183 DBUG_ENTER("Query_result_delete::abort_result_set");
1184
1185 /* the error was handled or nothing deleted and no side effects return */
1186 if (error_handled ||
1187 (!thd->get_transaction()->cannot_safely_rollback(
1188 Transaction_ctx::STMT) && !deleted))
1189 DBUG_VOID_RETURN;
1190
1191 /* Something already deleted so we have to invalidate cache */
1192 if (deleted)
1193 invalidate_delete_tables(thd, delete_tables);
1194
1195 /*
1196 If rows from the first table only has been deleted and it is
1197 transactional, just do rollback.
1198 The same if all tables are transactional, regardless of where we are.
1199 In all other cases do attempt deletes ...
1200 */
1201 if (do_delete && non_transactional_deleted)
1202 {
1203 /*
1204 We have to execute the recorded do_deletes() and write info into the
1205 error log
1206 */
1207 error= 1;
1208 send_eof();
1209 assert(error_handled);
1210 DBUG_VOID_RETURN;
1211 }
1212
1213 if (thd->get_transaction()->cannot_safely_rollback(Transaction_ctx::STMT))
1214 {
1215 /*
1216 there is only side effects; to binlog with the error
1217 */
1218 if (mysql_bin_log.is_open())
1219 {
1220 int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
1221 /* possible error of writing binary log is ignored deliberately */
1222 (void) thd->binlog_query(THD::ROW_QUERY_TYPE,
1223 thd->query().str, thd->query().length,
1224 transactional_table_map != 0, FALSE, FALSE,
1225 errcode);
1226 }
1227 }
1228 DBUG_VOID_RETURN;
1229 }
1230
1231
1232
1233 /**
1234 Do delete from other tables.
1235
1236 @retval 0 ok
1237 @retval 1 error
1238
1239 @todo Is there any reason not use the normal nested-loops join? If not, and
1240 there is no documentation supporting it, this method and callee should be
1241 removed and there should be hooks within normal execution.
1242 */
1243
do_deletes()1244 int Query_result_delete::do_deletes()
1245 {
1246 DBUG_ENTER("Query_result_delete::do_deletes");
1247 assert(do_delete);
1248
1249 assert(thd->lex->current_select() == unit->first_select());
1250 do_delete= false; // Mark called
1251 if (!found)
1252 DBUG_RETURN(0);
1253
1254 for (uint counter= 0; counter < num_of_tables; counter++)
1255 {
1256 TABLE *const table= tables[counter];
1257 if (table == NULL)
1258 break;
1259
1260 if (tempfiles[counter]->get(table))
1261 DBUG_RETURN(1);
1262
1263 int local_error= do_table_deletes(table);
1264
1265 if (thd->killed && !local_error)
1266 DBUG_RETURN(1);
1267
1268 if (local_error == -1) // End of file
1269 local_error = 0;
1270
1271 if (local_error)
1272 DBUG_RETURN(local_error);
1273 }
1274 DBUG_RETURN(0);
1275 }
1276
1277
1278 /**
1279 Implements the inner loop of nested-loops join within multi-DELETE
1280 execution.
1281
1282 @param table The table from which to delete.
1283
1284 @return Status code
1285
1286 @retval 0 All ok.
1287 @retval 1 Triggers or handler reported error.
1288 @retval -1 End of file from handler.
1289 */
do_table_deletes(TABLE * table)1290 int Query_result_delete::do_table_deletes(TABLE *table)
1291 {
1292 myf error_flags= MYF(0); /**< Flag for fatal errors */
1293 int local_error= 0;
1294 READ_RECORD info;
1295 ha_rows last_deleted= deleted;
1296 DBUG_ENTER("do_deletes_for_table");
1297 if (init_read_record(&info, thd, table, NULL, 0, 1, FALSE))
1298 DBUG_RETURN(1);
1299 /*
1300 Ignore any rows not found in reference tables as they may already have
1301 been deleted by foreign key handling
1302 */
1303 info.ignore_not_found_rows= 1;
1304 bool will_batch= !table->file->start_bulk_delete();
1305 while (!(local_error= info.read_record(&info)) && !thd->killed)
1306 {
1307 if (table->triggers &&
1308 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
1309 TRG_ACTION_BEFORE, FALSE))
1310 {
1311 local_error= 1;
1312 break;
1313 }
1314
1315 local_error= table->file->ha_delete_row(table->record[0]);
1316 if (local_error)
1317 {
1318 if (table->file->is_fatal_error(local_error))
1319 error_flags|= ME_FATALERROR;
1320
1321 table->file->print_error(local_error, error_flags);
1322 /*
1323 If IGNORE option is used errors caused by ha_delete_row will
1324 be downgraded to warnings and don't have to stop the iteration.
1325 */
1326 if (thd->is_error())
1327 break;
1328 }
1329
1330 /*
1331 Increase the reported number of deleted rows only if no error occurred
1332 during ha_delete_row.
1333 Also, don't execute the AFTER trigger if the row operation failed.
1334 */
1335 if (!local_error)
1336 {
1337 deleted++;
1338 if (table->pos_in_table_list->map() & non_transactional_table_map)
1339 non_transactional_deleted= true;
1340
1341 if (table->triggers &&
1342 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
1343 TRG_ACTION_AFTER, FALSE))
1344 {
1345 local_error= 1;
1346 break;
1347 }
1348 }
1349 }
1350 if (will_batch)
1351 {
1352 int tmp_error= table->file->end_bulk_delete();
1353 if (tmp_error && !local_error)
1354 {
1355 local_error= tmp_error;
1356 if (table->file->is_fatal_error(local_error))
1357 error_flags|= ME_FATALERROR;
1358
1359 table->file->print_error(local_error, error_flags);
1360 }
1361 }
1362 if (last_deleted != deleted && !table->file->has_transactions())
1363 thd->get_transaction()->mark_modified_non_trans_table(
1364 Transaction_ctx::STMT);
1365
1366 end_read_record(&info);
1367
1368 DBUG_RETURN(local_error);
1369 }
1370
1371 /**
1372 Send ok to the client
1373
1374 The function has to perform all deferred deletes that have been queued up.
1375
1376 @return false if success, true if error
1377 */
1378
send_eof()1379 bool Query_result_delete::send_eof()
1380 {
1381 THD::killed_state killed_status= THD::NOT_KILLED;
1382 THD_STAGE_INFO(thd, stage_deleting_from_reference_tables);
1383
1384 /* Does deletes for the last n - 1 tables, returns 0 if ok */
1385 int local_error= do_deletes(); // returns 0 if success
1386
1387 /* compute a total error to know if something failed */
1388 local_error= local_error || error;
1389 killed_status= (local_error == 0)? THD::NOT_KILLED : thd->killed;
1390 /* reset used flags */
1391 THD_STAGE_INFO(thd, stage_end);
1392
1393 /*
1394 We must invalidate the query cache before binlog writing and
1395 ha_autocommit_...
1396 */
1397 if (deleted)
1398 invalidate_delete_tables(thd, delete_tables);
1399
1400 if ((local_error == 0) ||
1401 thd->get_transaction()->cannot_safely_rollback(Transaction_ctx::STMT))
1402 {
1403 if (mysql_bin_log.is_open())
1404 {
1405 int errcode= 0;
1406 if (local_error == 0)
1407 thd->clear_error();
1408 else
1409 errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
1410 thd->thread_specific_used= TRUE;
1411 if (thd->binlog_query(THD::ROW_QUERY_TYPE,
1412 thd->query().str, thd->query().length,
1413 transactional_table_map != 0, FALSE, FALSE,
1414 errcode) &&
1415 !non_transactional_table_map)
1416 {
1417 local_error=1; // Log write failed: roll back the SQL statement
1418 }
1419 }
1420 }
1421 if (local_error != 0)
1422 error_handled= TRUE; // to force early leave from ::send_error()
1423
1424 if (!local_error)
1425 {
1426 ::my_ok(thd, deleted);
1427 }
1428 thd->updated_row_count+= deleted;
1429 return 0;
1430 }
1431
1432
execute(THD * thd)1433 bool Sql_cmd_delete::execute(THD *thd)
1434 {
1435 assert(thd->lex->sql_command == SQLCOM_DELETE);
1436
1437 LEX *const lex= thd->lex;
1438 SELECT_LEX *const select_lex= lex->select_lex;
1439 SELECT_LEX_UNIT *const unit= lex->unit;
1440 TABLE_LIST *const first_table= select_lex->get_table_list();
1441 TABLE_LIST *const all_tables= first_table;
1442
1443 if (delete_precheck(thd, all_tables))
1444 return true;
1445 assert(select_lex->offset_limit == 0);
1446 unit->set_limit(select_lex);
1447
1448 /* Push ignore / strict error handler */
1449 Ignore_error_handler ignore_handler;
1450 Strict_error_handler strict_handler;
1451 if (thd->lex->is_ignore())
1452 thd->push_internal_handler(&ignore_handler);
1453 else if (thd->is_strict_mode())
1454 thd->push_internal_handler(&strict_handler);
1455
1456 MYSQL_DELETE_START(const_cast<char*>(thd->query().str));
1457 bool res = mysql_delete(thd, unit->select_limit_cnt);
1458 MYSQL_DELETE_DONE(res, (ulong) thd->get_row_count_func());
1459
1460 /* Pop ignore / strict error handler */
1461 if (thd->lex->is_ignore() || thd->is_strict_mode())
1462 thd->pop_internal_handler();
1463
1464 return res;
1465 }
1466
1467
execute(THD * thd)1468 bool Sql_cmd_delete_multi::execute(THD *thd)
1469 {
1470 assert(thd->lex->sql_command == SQLCOM_DELETE_MULTI);
1471
1472 bool res= false;
1473 LEX *const lex= thd->lex;
1474 SELECT_LEX *const select_lex= lex->select_lex;
1475 TABLE_LIST *const first_table= select_lex->get_table_list();
1476 TABLE_LIST *const all_tables= first_table;
1477
1478 TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first;
1479 uint del_table_count;
1480 Query_result_delete *del_result;
1481
1482 if (multi_delete_precheck(thd, all_tables))
1483 return true;
1484
1485 /* condition will be TRUE on SP re-excuting */
1486 if (select_lex->item_list.elements != 0)
1487 select_lex->item_list.empty();
1488 if (add_item_to_list(thd, new Item_null()))
1489 return true;
1490
1491 THD_STAGE_INFO(thd, stage_init);
1492 if ((res= open_tables_for_query(thd, all_tables, 0)))
1493 return true;
1494
1495 if (run_before_dml_hook(thd))
1496 return true;
1497
1498 MYSQL_MULTI_DELETE_START(const_cast<char*>(thd->query().str));
1499 if (mysql_multi_delete_prepare(thd, &del_table_count))
1500 {
1501 MYSQL_MULTI_DELETE_DONE(1, 0);
1502 return true;
1503 }
1504
1505 if (!thd->is_fatal_error &&
1506 (del_result= new Query_result_delete(aux_tables, del_table_count)))
1507 {
1508 assert(select_lex->having_cond() == NULL &&
1509 !select_lex->order_list.elements &&
1510 !select_lex->group_list.elements);
1511
1512 Ignore_error_handler ignore_handler;
1513 Strict_error_handler strict_handler;
1514 if (thd->lex->is_ignore())
1515 thd->push_internal_handler(&ignore_handler);
1516 else if (thd->is_strict_mode())
1517 thd->push_internal_handler(&strict_handler);
1518
1519 res= handle_query(thd, lex, del_result,
1520 SELECT_NO_JOIN_CACHE |
1521 SELECT_NO_UNLOCK |
1522 OPTION_SETUP_TABLES_DONE,
1523 OPTION_BUFFER_RESULT);
1524
1525 if (thd->lex->is_ignore() || thd->is_strict_mode())
1526 thd->pop_internal_handler();
1527
1528 if (res)
1529 del_result->abort_result_set();
1530
1531 MYSQL_MULTI_DELETE_DONE(res, del_result->num_deleted());
1532 delete del_result;
1533 }
1534 else
1535 {
1536 res= true; // Error
1537 MYSQL_MULTI_DELETE_DONE(1, 0);
1538 }
1539
1540 return res;
1541 }
1542