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