1 /* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
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_priv.h"
30 #include "unireg.h"
31 #include "sql_delete.h"
32 #include "sql_cache.h" // query_cache_*
33 #include "sql_base.h" // open_temprary_table
34 #include "sql_table.h" // build_table_filename
35 #include "sql_view.h" // check_key_in_view, mysql_frm_type
36 #include "sql_acl.h" // *_ACL
37 #include "filesort.h" // filesort
38 #include "sql_select.h"
39 #include "opt_trace.h" // Opt_trace_object
40 #include "opt_explain.h"
41 #include "records.h" // init_read_record,
42 // end_read_record
43 #include "sql_optimizer.h" // remove_eq_conds
44 #include "sql_resolver.h" // setup_order, fix_inner_refs
45
46 /**
47 Implement DELETE SQL word.
48
49 @note Like implementations of other DDL/DML in MySQL, this function
50 relies on the caller to close the thread tables. This is done in the
51 end of dispatch_command().
52 */
53
mysql_delete(THD * thd,TABLE_LIST * table_list,Item * conds,SQL_I_List<ORDER> * order_list,ha_rows limit,ulonglong options)54 bool mysql_delete(THD *thd, TABLE_LIST *table_list, Item *conds,
55 SQL_I_List<ORDER> *order_list, ha_rows limit, ulonglong options)
56 {
57 bool will_batch;
58 int error, loc_error;
59 TABLE *table;
60 SQL_SELECT *select=0;
61 READ_RECORD info;
62 bool using_limit=limit != HA_POS_ERROR;
63 bool transactional_table, safe_update, const_cond;
64 bool const_cond_result;
65 ha_rows deleted= 0;
66 bool reverse= FALSE;
67 bool read_removal= false;
68 bool skip_record;
69 bool need_sort= FALSE;
70 bool err= true;
71 ORDER *order= (ORDER *) ((order_list && order_list->elements) ?
72 order_list->first : NULL);
73 uint usable_index= MAX_KEY;
74 SELECT_LEX *select_lex= &thd->lex->select_lex;
75 THD::killed_state killed_status= THD::NOT_KILLED;
76 THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE;
77 DBUG_ENTER("mysql_delete");
78
79 if (open_normal_and_derived_tables(thd, table_list, 0))
80 DBUG_RETURN(TRUE);
81
82 if (!(table= table_list->table))
83 {
84 my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
85 table_list->view_db.str, table_list->view_name.str);
86 DBUG_RETURN(TRUE);
87 }
88 THD_STAGE_INFO(thd, stage_init);
89 table->map=1;
90
91 if (mysql_prepare_delete(thd, table_list, &conds))
92 DBUG_RETURN(TRUE);
93
94 /* check ORDER BY even if it can be ignored */
95 if (order)
96 {
97 TABLE_LIST tables;
98 List<Item> fields;
99 List<Item> all_fields;
100
101 memset(&tables, 0, sizeof(tables));
102 tables.table = table;
103 tables.alias = table_list->alias;
104
105 if (select_lex->setup_ref_array(thd, order_list->elements) ||
106 setup_order(thd, select_lex->ref_pointer_array, &tables,
107 fields, all_fields, order))
108 {
109 free_underlaid_joins(thd, &thd->lex->select_lex);
110 DBUG_RETURN(TRUE);
111 }
112 }
113
114 #ifdef WITH_PARTITION_STORAGE_ENGINE
115 /*
116 Non delete tables are pruned in JOIN::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 goto exit_all_parts_pruned_away;
123 #endif
124
125 if (lock_tables(thd, table_list, thd->lex->table_count, 0))
126 DBUG_RETURN(true);
127
128 const_cond= (!conds || conds->const_item());
129 safe_update= MY_TEST(thd->variables.option_bits & OPTION_SAFE_UPDATES);
130 if (safe_update && const_cond)
131 {
132 my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
133 ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
134 DBUG_RETURN(TRUE);
135 }
136
137 select_lex->no_error= thd->lex->ignore;
138
139 const_cond_result= const_cond && (!conds || conds->val_int());
140 if (thd->is_error())
141 {
142 /* Error evaluating val_int(). */
143 DBUG_RETURN(TRUE);
144 }
145
146 /*
147 Test if the user wants to delete all rows and deletion doesn't have
148 any side-effects (because of triggers), so we can use optimized
149 handler::delete_all_rows() method.
150
151 We can use delete_all_rows() if and only if:
152 - We allow new functions (not using option --skip-new)
153 - There is no limit clause
154 - The condition is constant
155 - If there is a condition, then it it produces a non-zero value
156 - If the current command is DELETE FROM with no where clause, then:
157 - We should not be binlogging this statement in row-based, and
158 - there should be no delete triggers associated with the table.
159 */
160 if (!using_limit && const_cond_result &&
161 !(specialflag & SPECIAL_NO_NEW_FUNC) &&
162 (!thd->is_current_stmt_binlog_format_row() &&
163 !(table->triggers && table->triggers->has_delete_triggers())))
164 {
165 /* Update the table->file->stats.records number */
166 table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
167 ha_rows const maybe_deleted= table->file->stats.records;
168
169 if (thd->lex->describe)
170 {
171 err= explain_no_table(thd, "Deleting all rows", maybe_deleted);
172 goto exit_without_my_ok;
173 }
174
175 DBUG_PRINT("debug", ("Trying to use delete_all_rows()"));
176 if (!(error=table->file->ha_delete_all_rows()))
177 {
178 /*
179 If delete_all_rows() is used, it is not possible to log the
180 query in row format, so we have to log it in statement format.
181 */
182 query_type= THD::STMT_QUERY_TYPE;
183 error= -1;
184 deleted= maybe_deleted;
185 goto cleanup;
186 }
187 if (error != HA_ERR_WRONG_COMMAND)
188 {
189 table->file->print_error(error,MYF(0));
190 error=0;
191 goto cleanup;
192 }
193 /* Handler didn't support fast delete; Delete rows one by one */
194 }
195
196 if (conds)
197 {
198 COND_EQUAL *cond_equal= NULL;
199 Item::cond_result result;
200
201 conds= optimize_cond(thd, conds, &cond_equal, select_lex->join_list,
202 true, &result);
203 if (result == Item::COND_FALSE) // Impossible where
204 {
205 limit= 0;
206
207 if (thd->lex->describe)
208 {
209 err= explain_no_table(thd, "Impossible WHERE");
210 goto exit_without_my_ok;
211 }
212 }
213 if (conds)
214 {
215 conds= substitute_for_best_equal_field(conds, cond_equal, 0);
216 conds->update_used_tables();
217 }
218 }
219
220 /* Update the table->file->stats.records number */
221 table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
222
223 table->covering_keys.clear_all();
224 table->quick_keys.clear_all(); // Can't use 'only index'
225 table->possible_quick_keys.clear_all();
226
227 #ifdef WITH_PARTITION_STORAGE_ENGINE
228 /* Prune a second time to be able to prune on subqueries in WHERE clause. */
229 if (prune_partitions(thd, table, conds))
230 DBUG_RETURN(true);
231 if (table->all_partitions_pruned_away)
232 goto exit_all_parts_pruned_away;
233 #endif
234
235 select=make_select(table, 0, 0, conds, 0, &error);
236 if (error)
237 DBUG_RETURN(TRUE);
238
239 { // Enter scope for optimizer trace wrapper
240 Opt_trace_object wrapper(&thd->opt_trace);
241 wrapper.add_utf8_table(table);
242
243 if ((select && select->check_quick(thd, safe_update, limit)) || !limit)
244 {
245 if (thd->lex->describe && !error && !thd->is_error())
246 {
247 err= explain_no_table(thd, "Impossible WHERE");
248 goto exit_without_my_ok;
249 }
250 delete select;
251 free_underlaid_joins(thd, select_lex);
252 /*
253 Error was already created by quick select evaluation (check_quick()).
254 TODO: Add error code output parameter to Item::val_xxx() methods.
255 Currently they rely on the user checking DA for
256 errors when unwinding the stack after calling Item::val_xxx().
257 */
258 if (thd->is_error())
259 DBUG_RETURN(true);
260 my_ok(thd, 0);
261 DBUG_RETURN(false); // Nothing to delete
262 }
263 } // Ends scope for optimizer trace wrapper
264
265 /* If running in safe sql mode, don't allow updates without keys */
266 if (table->quick_keys.is_clear_all())
267 {
268 thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
269 if (safe_update && !using_limit)
270 {
271 delete select;
272 free_underlaid_joins(thd, select_lex);
273 my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
274 ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
275 DBUG_RETURN(TRUE);
276 }
277 }
278
279 if (order)
280 {
281 table->update_const_key_parts(conds);
282 order= simple_remove_const(order, conds);
283
284 usable_index= get_index_for_order(order, table, select, limit,
285 &need_sort, &reverse);
286 }
287
288 if (thd->lex->describe)
289 {
290 err= explain_single_table_modification(thd, table, select, usable_index,
291 limit, false, need_sort, false);
292 goto exit_without_my_ok;
293 }
294
295 if (options & OPTION_QUICK)
296 (void) table->file->extra(HA_EXTRA_QUICK);
297
298 if (need_sort)
299 {
300 ha_rows examined_rows;
301 ha_rows found_rows;
302
303 {
304 Filesort fsort(order, HA_POS_ERROR, select);
305 DBUG_ASSERT(usable_index == MAX_KEY);
306 table->sort.io_cache= (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
307 MYF(MY_FAE | MY_ZEROFILL));
308
309 if ((table->sort.found_records= filesort(thd, table, &fsort, true,
310 &examined_rows, &found_rows))
311 == HA_POS_ERROR)
312 {
313 goto exit_without_my_ok;
314 }
315 thd->inc_examined_row_count(examined_rows);
316 /*
317 Filesort has already found and selected the rows we want to delete,
318 so we don't need the where clause
319 */
320 delete select;
321 free_underlaid_joins(thd, select_lex);
322 select= 0;
323 }
324 }
325
326 /* If quick select is used, initialize it before retrieving rows. */
327 if (select && select->quick && (error= select->quick->reset()))
328 {
329 table->file->print_error(error, MYF(0));
330 goto exit_without_my_ok;
331 }
332
333 if (select_lex->has_ft_funcs() && init_ftfuncs(thd, select_lex, 1))
334 goto exit_without_my_ok;
335
336 if (usable_index==MAX_KEY || (select && select->quick))
337 error= init_read_record(&info, thd, table, select, 1, 1, FALSE);
338 else
339 error= init_read_record_idx(&info, thd, table, 1, usable_index, reverse);
340
341 if (error)
342 goto exit_without_my_ok;
343
344 THD_STAGE_INFO(thd, stage_updating);
345
346 if (table->triggers &&
347 table->triggers->has_triggers(TRG_EVENT_DELETE,
348 TRG_ACTION_AFTER))
349 {
350 /*
351 The table has AFTER DELETE triggers that might access to subject table
352 and therefore might need delete to be done immediately. So we turn-off
353 the batching.
354 */
355 (void) table->file->extra(HA_EXTRA_DELETE_CANNOT_BATCH);
356 will_batch= FALSE;
357 }
358 else
359 will_batch= !table->file->start_bulk_delete();
360
361 table->mark_columns_needed_for_delete();
362
363 if ((table->file->ha_table_flags() & HA_READ_BEFORE_WRITE_REMOVAL) &&
364 !using_limit &&
365 !(table->triggers && table->triggers->has_delete_triggers()) &&
366 select && select->quick && select->quick->index != MAX_KEY)
367 read_removal= table->check_read_removal(select->quick->index);
368
369 while (!(error=info.read_record(&info)) && !thd->killed &&
370 ! thd->is_error())
371 {
372 thd->inc_examined_row_count(1);
373 // thd->is_error() is tested to disallow delete row on error
374 if (!select || (!select->skip_record(thd, &skip_record) && !skip_record))
375 {
376
377 if (table->triggers &&
378 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
379 TRG_ACTION_BEFORE, FALSE))
380 {
381 error= 1;
382 break;
383 }
384
385 if (!(error= table->file->ha_delete_row(table->record[0])))
386 {
387 deleted++;
388 if (table->triggers &&
389 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
390 TRG_ACTION_AFTER, FALSE))
391 {
392 error= 1;
393 break;
394 }
395 if (!--limit && using_limit)
396 {
397 error= -1;
398 break;
399 }
400 }
401 else
402 {
403 table->file->print_error(error,MYF(0));
404 /*
405 In < 4.0.14 we set the error number to 0 here, but that
406 was not sensible, because then MySQL would not roll back the
407 failed DELETE, and also wrote it to the binlog. For MyISAM
408 tables a DELETE probably never should fail (?), but for
409 InnoDB it can fail in a FOREIGN KEY error or an
410 out-of-tablespace error.
411 */
412 error= 1;
413 break;
414 }
415 }
416 /*
417 Don't try unlocking the row if skip_record reported an error since in
418 this case the transaction might have been rolled back already.
419 */
420 else if (!thd->is_error())
421 table->file->unlock_row(); // Row failed selection, release lock on it
422 else
423 break;
424 }
425 killed_status= thd->killed;
426 if (killed_status != THD::NOT_KILLED || thd->is_error())
427 error= 1; // Aborted
428 if (will_batch && (loc_error= table->file->end_bulk_delete()))
429 {
430 if (error != 1)
431 table->file->print_error(loc_error,MYF(0));
432 error=1;
433 }
434 if (read_removal)
435 {
436 /* Only handler knows how many records were really written */
437 deleted= table->file->end_read_removal();
438 }
439 THD_STAGE_INFO(thd, stage_end);
440 end_read_record(&info);
441 if (options & OPTION_QUICK)
442 (void) table->file->extra(HA_EXTRA_NORMAL);
443
444 cleanup:
445 DBUG_ASSERT(!thd->lex->describe);
446 /*
447 Invalidate the table in the query cache if something changed. This must
448 be before binlog writing and ha_autocommit_...
449 */
450 if (deleted)
451 {
452 query_cache_invalidate3(thd, table_list, 1);
453 }
454
455 delete select;
456 select= NULL;
457 transactional_table= table->file->has_transactions();
458
459 if (!transactional_table && deleted > 0)
460 thd->transaction.stmt.mark_modified_non_trans_table();
461
462 /* See similar binlogging code in sql_update.cc, for comments */
463 if ((error < 0) || thd->transaction.stmt.cannot_safely_rollback())
464 {
465 if (mysql_bin_log.is_open())
466 {
467 int errcode= 0;
468 if (error < 0)
469 thd->clear_error();
470 else
471 errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
472
473 /*
474 [binlog]: If 'handler::delete_all_rows()' was called and the
475 storage engine does not inject the rows itself, we replicate
476 statement-based; otherwise, 'ha_delete_row()' was used to
477 delete specific rows which we might log row-based.
478 */
479 int log_result= thd->binlog_query(query_type,
480 thd->query(), thd->query_length(),
481 transactional_table, FALSE, FALSE,
482 errcode);
483
484 if (log_result)
485 {
486 error=1;
487 }
488 }
489 }
490 DBUG_ASSERT(transactional_table || !deleted || thd->transaction.stmt.cannot_safely_rollback());
491 free_underlaid_joins(thd, select_lex);
492 if (error < 0 ||
493 (thd->lex->ignore && !thd->is_error() && !thd->is_fatal_error))
494 {
495 my_ok(thd, deleted);
496 DBUG_PRINT("info",("%ld records deleted",(long) deleted));
497 }
498 DBUG_RETURN(thd->is_error() || thd->killed);
499
500 #ifdef WITH_PARTITION_STORAGE_ENGINE
501 exit_all_parts_pruned_away:
502 /* No matching records */
503 if (!thd->lex->describe)
504 {
505 my_ok(thd, 0);
506 DBUG_RETURN(0);
507 }
508 err= explain_no_table(thd, "No matching rows after partition pruning");
509 #endif
510
511 exit_without_my_ok:
512 delete select;
513 free_underlaid_joins(thd, select_lex);
514 table->set_keyread(false);
515 DBUG_RETURN((err || thd->is_error() || thd->killed) ? 1 : 0);
516 }
517
518
519 /*
520 Prepare items in DELETE statement
521
522 SYNOPSIS
523 mysql_prepare_delete()
524 thd - thread handler
525 table_list - global/local table list
526 conds - conditions
527
528 RETURN VALUE
529 FALSE OK
530 TRUE error
531 */
mysql_prepare_delete(THD * thd,TABLE_LIST * table_list,Item ** conds)532 int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
533 {
534 Item *fake_conds= 0;
535 SELECT_LEX *select_lex= &thd->lex->select_lex;
536 DBUG_ENTER("mysql_prepare_delete");
537 List<Item> all_fields;
538
539 thd->lex->allow_sum_func= 0;
540 if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
541 &thd->lex->select_lex.top_join_list,
542 table_list,
543 &select_lex->leaf_tables, FALSE,
544 DELETE_ACL, SELECT_ACL) ||
545 setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
546 setup_ftfuncs(select_lex))
547 DBUG_RETURN(TRUE);
548 if (!table_list->updatable || check_key_in_view(thd, table_list))
549 {
550 my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE");
551 DBUG_RETURN(TRUE);
552 }
553 {
554 TABLE_LIST *duplicate;
555 if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0)))
556 {
557 update_non_unique_table_error(table_list, "DELETE", duplicate);
558 DBUG_RETURN(TRUE);
559 }
560 }
561
562 if (select_lex->inner_refs_list.elements &&
563 fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
564 DBUG_RETURN(TRUE);
565
566 select_lex->fix_prepare_information(thd, conds, &fake_conds);
567 DBUG_RETURN(FALSE);
568 }
569
570
571 /***************************************************************************
572 Delete multiple tables from join
573 ***************************************************************************/
574
575 #define MEM_STRIP_BUF_SIZE current_thd->variables.sortbuff_size
576
refpos_order_cmp(const void * arg,const void * a,const void * b)577 extern "C" int refpos_order_cmp(const void* arg, const void *a,const void *b)
578 {
579 handler *file= (handler*)arg;
580 return file->cmp_ref((const uchar*)a, (const uchar*)b);
581 }
582
583 /**
584 Make delete specific preparation and checks after opening tables.
585
586 @param thd Thread context.
587 @param[out] table_count Number of tables to be deleted from.
588
589 @retval false - success.
590 @retval true - error.
591 */
592
mysql_multi_delete_prepare(THD * thd,uint * table_count)593 int mysql_multi_delete_prepare(THD *thd, uint *table_count)
594 {
595 LEX *lex= thd->lex;
596 TABLE_LIST *aux_tables= lex->auxiliary_table_list.first;
597 TABLE_LIST *target_tbl;
598 DBUG_ENTER("mysql_multi_delete_prepare");
599
600 /*
601 setup_tables() need for VIEWs. JOIN::prepare() will not do it second
602 time.
603
604 lex->query_tables also point on local list of DELETE SELECT_LEX
605 */
606 if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
607 &thd->lex->select_lex.top_join_list,
608 lex->query_tables,
609 &lex->select_lex.leaf_tables, FALSE,
610 DELETE_ACL, SELECT_ACL))
611 DBUG_RETURN(TRUE);
612
613 *table_count= 0;
614
615 /*
616 Multi-delete can't be constructed over-union => we always have
617 single SELECT on top and have to check underlying SELECTs of it
618 */
619 lex->select_lex.exclude_from_table_unique_test= TRUE;
620 /* Fix tables-to-be-deleted-from list to point at opened tables */
621 for (target_tbl= (TABLE_LIST*) aux_tables;
622 target_tbl;
623 target_tbl= target_tbl->next_local)
624 {
625 ++(*table_count);
626
627 if (!(target_tbl->table= target_tbl->correspondent_table->table))
628 {
629 DBUG_ASSERT(target_tbl->correspondent_table->view &&
630 target_tbl->correspondent_table->multitable_view);
631 my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
632 target_tbl->correspondent_table->view_db.str,
633 target_tbl->correspondent_table->view_name.str);
634 DBUG_RETURN(TRUE);
635 }
636
637 if (!target_tbl->correspondent_table->updatable ||
638 check_key_in_view(thd, target_tbl->correspondent_table))
639 {
640 my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
641 target_tbl->table_name, "DELETE");
642 DBUG_RETURN(TRUE);
643 }
644 /*
645 Check that table from which we delete is not used somewhere
646 inside subqueries/view.
647 */
648 {
649 TABLE_LIST *duplicate;
650 if ((duplicate= unique_table(thd, target_tbl->correspondent_table,
651 lex->query_tables, 0)))
652 {
653 update_non_unique_table_error(target_tbl->correspondent_table,
654 "DELETE", duplicate);
655 DBUG_RETURN(TRUE);
656 }
657 }
658 }
659 /*
660 Reset the exclude flag to false so it doesn't interfare
661 with further calls to unique_table
662 */
663 lex->select_lex.exclude_from_table_unique_test= FALSE;
664 DBUG_RETURN(FALSE);
665 }
666
667
multi_delete(TABLE_LIST * dt,uint num_of_tables_arg)668 multi_delete::multi_delete(TABLE_LIST *dt, uint num_of_tables_arg)
669 : delete_tables(dt), deleted(0), found(0),
670 num_of_tables(num_of_tables_arg), error(0),
671 do_delete(0), transactional_tables(0), normal_tables(0), error_handled(0)
672 {
673 tempfiles= (Unique **) sql_calloc(sizeof(Unique *) * num_of_tables);
674 }
675
676
677 int
prepare(List<Item> & values,SELECT_LEX_UNIT * u)678 multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
679 {
680 DBUG_ENTER("multi_delete::prepare");
681 unit= u;
682 do_delete= 1;
683 THD_STAGE_INFO(thd, stage_deleting_from_main_table);
684 DBUG_RETURN(0);
685 }
686
687
688 bool
initialize_tables(JOIN * join)689 multi_delete::initialize_tables(JOIN *join)
690 {
691 TABLE_LIST *walk;
692 Unique **tempfiles_ptr;
693 DBUG_ENTER("initialize_tables");
694
695 if ((thd->variables.option_bits & OPTION_SAFE_UPDATES) && error_if_full_join(join))
696 DBUG_RETURN(1);
697
698 table_map tables_to_delete_from=0;
699 delete_while_scanning= 1;
700 for (walk= delete_tables; walk; walk= walk->next_local)
701 {
702 tables_to_delete_from|= walk->table->map;
703 if (delete_while_scanning &&
704 unique_table(thd, walk, join->tables_list, false))
705 {
706 /*
707 If the table we are going to delete from appears
708 in join, we need to defer delete. So the delete
709 doesn't interfers with the scaning of results.
710 */
711 delete_while_scanning= 0;
712 }
713 }
714
715
716 walk= delete_tables;
717 for (uint i= 0; i < join->primary_tables; i++)
718 {
719 JOIN_TAB *const tab= join->join_tab + i;
720 if (tab->table->map & tables_to_delete_from)
721 {
722 /* We are going to delete from this table */
723 TABLE *tbl=walk->table=tab->table;
724 walk= walk->next_local;
725 /* Don't use KEYREAD optimization on this table */
726 tbl->no_keyread=1;
727 /* Don't use record cache */
728 tbl->no_cache= 1;
729 tbl->covering_keys.clear_all();
730 if (tbl->file->has_transactions())
731 transactional_tables= 1;
732 else
733 normal_tables= 1;
734 if (tbl->triggers &&
735 tbl->triggers->has_triggers(TRG_EVENT_DELETE,
736 TRG_ACTION_AFTER))
737 {
738 /*
739 The table has AFTER DELETE triggers that might access to subject
740 table and therefore might need delete to be done immediately.
741 So we turn-off the batching.
742 */
743 (void) tbl->file->extra(HA_EXTRA_DELETE_CANNOT_BATCH);
744 }
745 tbl->prepare_for_position();
746 tbl->mark_columns_needed_for_delete();
747 }
748 else if ((tab->type != JT_SYSTEM && tab->type != JT_CONST) &&
749 walk == delete_tables)
750 {
751 /*
752 We are not deleting from the table we are scanning. In this
753 case send_data() shouldn't delete any rows a we may touch
754 the rows in the deleted table many times
755 */
756 delete_while_scanning= 0;
757 }
758 }
759 walk= delete_tables;
760 tempfiles_ptr= tempfiles;
761 if (delete_while_scanning)
762 {
763 table_being_deleted= delete_tables;
764 walk= walk->next_local;
765 }
766 for (;walk ;walk= walk->next_local)
767 {
768 TABLE *table=walk->table;
769 *tempfiles_ptr++= new Unique (refpos_order_cmp,
770 (void *) table->file,
771 table->file->ref_length,
772 MEM_STRIP_BUF_SIZE);
773 }
774 if (thd->lex->current_select->has_ft_funcs() &&
775 init_ftfuncs(thd, thd->lex->current_select, 1))
776 DBUG_RETURN(true);
777
778 DBUG_RETURN(thd->is_fatal_error != 0);
779 }
780
781
~multi_delete()782 multi_delete::~multi_delete()
783 {
784 for (table_being_deleted= delete_tables;
785 table_being_deleted;
786 table_being_deleted= table_being_deleted->next_local)
787 {
788 TABLE *table= table_being_deleted->table;
789 table->no_keyread=0;
790 }
791
792 for (uint counter= 0; counter < num_of_tables; counter++)
793 {
794 if (tempfiles[counter])
795 delete tempfiles[counter];
796 }
797 }
798
799
send_data(List<Item> & values)800 bool multi_delete::send_data(List<Item> &values)
801 {
802 int secure_counter= delete_while_scanning ? -1 : 0;
803 TABLE_LIST *del_table;
804 DBUG_ENTER("multi_delete::send_data");
805
806 bool ignore= thd->lex->current_select->no_error;
807
808 for (del_table= delete_tables;
809 del_table;
810 del_table= del_table->next_local, secure_counter++)
811 {
812 TABLE *table= del_table->table;
813
814 /* Check if we are using outer join and we didn't find the row */
815 if (table->status & (STATUS_NULL_ROW | STATUS_DELETED))
816 continue;
817
818 table->file->position(table->record[0]);
819 found++;
820
821 if (secure_counter < 0)
822 {
823 /* We are scanning the current table */
824 DBUG_ASSERT(del_table == table_being_deleted);
825 if (table->triggers &&
826 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
827 TRG_ACTION_BEFORE, FALSE))
828 DBUG_RETURN(1);
829 table->status|= STATUS_DELETED;
830 if (!(error=table->file->ha_delete_row(table->record[0])))
831 {
832 deleted++;
833 if (!table->file->has_transactions())
834 thd->transaction.stmt.mark_modified_non_trans_table();
835 if (table->triggers &&
836 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
837 TRG_ACTION_AFTER, FALSE))
838 DBUG_RETURN(1);
839 }
840 else if (!ignore)
841 {
842 /*
843 If the IGNORE option is used errors caused by ha_delete_row don't
844 have to stop the iteration.
845 */
846 table->file->print_error(error,MYF(0));
847 DBUG_RETURN(1);
848 }
849 }
850 else
851 {
852 error=tempfiles[secure_counter]->unique_add((char*) table->file->ref);
853 if (error)
854 {
855 error= 1; // Fatal error
856 DBUG_RETURN(1);
857 }
858 }
859 }
860 DBUG_RETURN(0);
861 }
862
863
send_error(uint errcode,const char * err)864 void multi_delete::send_error(uint errcode,const char *err)
865 {
866 DBUG_ENTER("multi_delete::send_error");
867
868 /* First send error what ever it is ... */
869 my_message(errcode, err, MYF(0));
870
871 DBUG_VOID_RETURN;
872 }
873
874
abort_result_set()875 void multi_delete::abort_result_set()
876 {
877 DBUG_ENTER("multi_delete::abort_result_set");
878
879 /* the error was handled or nothing deleted and no side effects return */
880 if (error_handled ||
881 (!thd->transaction.stmt.cannot_safely_rollback() && !deleted))
882 DBUG_VOID_RETURN;
883
884 /* Something already deleted so we have to invalidate cache */
885 if (deleted)
886 query_cache_invalidate3(thd, delete_tables, 1);
887
888 /*
889 If rows from the first table only has been deleted and it is
890 transactional, just do rollback.
891 The same if all tables are transactional, regardless of where we are.
892 In all other cases do attempt deletes ...
893 */
894 if (do_delete && normal_tables &&
895 (table_being_deleted != delete_tables ||
896 !table_being_deleted->table->file->has_transactions()))
897 {
898 /*
899 We have to execute the recorded do_deletes() and write info into the
900 error log
901 */
902 error= 1;
903 send_eof();
904 DBUG_ASSERT(error_handled);
905 DBUG_VOID_RETURN;
906 }
907
908 if (thd->transaction.stmt.cannot_safely_rollback())
909 {
910 /*
911 there is only side effects; to binlog with the error
912 */
913 if (mysql_bin_log.is_open())
914 {
915 int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
916 /* possible error of writing binary log is ignored deliberately */
917 (void) thd->binlog_query(THD::ROW_QUERY_TYPE,
918 thd->query(), thd->query_length(),
919 transactional_tables, FALSE, FALSE, errcode);
920 }
921 }
922 DBUG_VOID_RETURN;
923 }
924
925
926
927 /**
928 Do delete from other tables.
929
930 @retval 0 ok
931 @retval 1 error
932
933 @todo Is there any reason not use the normal nested-loops join? If not, and
934 there is no documentation supporting it, this method and callee should be
935 removed and there should be hooks within normal execution.
936 */
937
do_deletes()938 int multi_delete::do_deletes()
939 {
940 DBUG_ENTER("do_deletes");
941 DBUG_ASSERT(do_delete);
942
943 do_delete= 0; // Mark called
944 if (!found)
945 DBUG_RETURN(0);
946
947 table_being_deleted= (delete_while_scanning ? delete_tables->next_local :
948 delete_tables);
949
950 for (uint counter= 0; table_being_deleted;
951 table_being_deleted= table_being_deleted->next_local, counter++)
952 {
953 TABLE *table = table_being_deleted->table;
954 if (tempfiles[counter]->get(table))
955 DBUG_RETURN(1);
956
957 int local_error=
958 do_table_deletes(table, thd->lex->current_select->no_error);
959
960 if (thd->killed && !local_error)
961 DBUG_RETURN(1);
962
963 if (local_error == -1) // End of file
964 local_error = 0;
965
966 if (local_error)
967 DBUG_RETURN(local_error);
968 }
969 DBUG_RETURN(0);
970 }
971
972
973 /**
974 Implements the inner loop of nested-loops join within multi-DELETE
975 execution.
976
977 @param table The table from which to delete.
978
979 @param ignore If used, all non fatal errors will be translated
980 to warnings and we should not break the row-by-row iteration.
981
982 @return Status code
983
984 @retval 0 All ok.
985 @retval 1 Triggers or handler reported error.
986 @retval -1 End of file from handler.
987 */
do_table_deletes(TABLE * table,bool ignore)988 int multi_delete::do_table_deletes(TABLE *table, bool ignore)
989 {
990 int local_error= 0;
991 READ_RECORD info;
992 ha_rows last_deleted= deleted;
993 DBUG_ENTER("do_deletes_for_table");
994 if (init_read_record(&info, thd, table, NULL, 0, 1, FALSE))
995 DBUG_RETURN(1);
996 /*
997 Ignore any rows not found in reference tables as they may already have
998 been deleted by foreign key handling
999 */
1000 info.ignore_not_found_rows= 1;
1001 bool will_batch= !table->file->start_bulk_delete();
1002 while (!(local_error= info.read_record(&info)) && !thd->killed)
1003 {
1004 if (table->triggers &&
1005 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
1006 TRG_ACTION_BEFORE, FALSE))
1007 {
1008 local_error= 1;
1009 break;
1010 }
1011
1012 local_error= table->file->ha_delete_row(table->record[0]);
1013 if (local_error && !ignore)
1014 {
1015 table->file->print_error(local_error, MYF(0));
1016 break;
1017 }
1018
1019 /*
1020 Increase the reported number of deleted rows only if no error occurred
1021 during ha_delete_row.
1022 Also, don't execute the AFTER trigger if the row operation failed.
1023 */
1024 if (!local_error)
1025 {
1026 deleted++;
1027 if (table->triggers &&
1028 table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
1029 TRG_ACTION_AFTER, FALSE))
1030 {
1031 local_error= 1;
1032 break;
1033 }
1034 }
1035 }
1036 if (will_batch)
1037 {
1038 int tmp_error= table->file->end_bulk_delete();
1039 if (tmp_error && !local_error)
1040 {
1041 local_error= tmp_error;
1042 table->file->print_error(local_error, MYF(0));
1043 }
1044 }
1045 if (last_deleted != deleted && !table->file->has_transactions())
1046 thd->transaction.stmt.mark_modified_non_trans_table();
1047
1048 end_read_record(&info);
1049
1050 DBUG_RETURN(local_error);
1051 }
1052
1053 /*
1054 Send ok to the client
1055
1056 return: 0 sucess
1057 1 error
1058 */
1059
send_eof()1060 bool multi_delete::send_eof()
1061 {
1062 THD::killed_state killed_status= THD::NOT_KILLED;
1063 THD_STAGE_INFO(thd, stage_deleting_from_reference_tables);
1064
1065 /* Does deletes for the last n - 1 tables, returns 0 if ok */
1066 int local_error= do_deletes(); // returns 0 if success
1067
1068 /* compute a total error to know if something failed */
1069 local_error= local_error || error;
1070 killed_status= (local_error == 0)? THD::NOT_KILLED : thd->killed;
1071 /* reset used flags */
1072 THD_STAGE_INFO(thd, stage_end);
1073
1074 /*
1075 We must invalidate the query cache before binlog writing and
1076 ha_autocommit_...
1077 */
1078 if (deleted)
1079 {
1080 query_cache_invalidate3(thd, delete_tables, 1);
1081 }
1082 if ((local_error == 0) || thd->transaction.stmt.cannot_safely_rollback())
1083 {
1084 if (mysql_bin_log.is_open())
1085 {
1086 int errcode= 0;
1087 if (local_error == 0)
1088 thd->clear_error();
1089 else
1090 errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
1091 thd->thread_specific_used= TRUE;
1092 if (thd->binlog_query(THD::ROW_QUERY_TYPE,
1093 thd->query(), thd->query_length(),
1094 transactional_tables, FALSE, FALSE, errcode) &&
1095 !normal_tables)
1096 {
1097 local_error=1; // Log write failed: roll back the SQL statement
1098 }
1099 }
1100 }
1101 if (local_error != 0)
1102 error_handled= TRUE; // to force early leave from ::send_error()
1103
1104 if (!local_error)
1105 {
1106 ::my_ok(thd, deleted);
1107 }
1108 return 0;
1109 }
1110
1111