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