~vlad-lesin/percona-server/mysql-5.0.33-original

« back to all changes in this revision

Viewing changes to libmysqld/sql_delete.cc

  • Committer: Vlad Lesin
  • Date: 2012-07-31 09:21:34 UTC
  • Revision ID: vladislav.lesin@percona.com-20120731092134-zfodx022b7992wsi
VirginĀ 5.0.33

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000 MySQL AB
 
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 as published by
 
5
   the Free Software Foundation; either version 2 of the License, or
 
6
   (at your option) any later version.
 
7
 
 
8
   This program is distributed in the hope that it will be useful,
 
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
   GNU General Public License for more details.
 
12
 
 
13
   You should have received a copy of the GNU General Public License
 
14
   along with this program; if not, write to the Free Software
 
15
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
16
 
 
17
/*
 
18
  Delete of records and truncate of tables.
 
19
 
 
20
  Multi-table deletes were introduced by Monty and Sinisa
 
21
*/
 
22
 
 
23
#include "mysql_priv.h"
 
24
#include "ha_innodb.h"
 
25
#include "sql_select.h"
 
26
#include "sp_head.h"
 
27
#include "sql_trigger.h"
 
28
 
 
29
bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
 
30
                  SQL_LIST *order, ha_rows limit, ulonglong options,
 
31
                  bool reset_auto_increment)
 
32
{
 
33
  int           error;
 
34
  TABLE         *table;
 
35
  SQL_SELECT    *select=0;
 
36
  READ_RECORD   info;
 
37
  bool          using_limit=limit != HA_POS_ERROR;
 
38
  bool          transactional_table, safe_update, const_cond;
 
39
  ha_rows       deleted;
 
40
  uint usable_index= MAX_KEY;
 
41
  SELECT_LEX   *select_lex= &thd->lex->select_lex;
 
42
  DBUG_ENTER("mysql_delete");
 
43
 
 
44
  if (open_and_lock_tables(thd, table_list))
 
45
    DBUG_RETURN(TRUE);
 
46
  if (!(table= table_list->table))
 
47
  {
 
48
    my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
 
49
             table_list->view_db.str, table_list->view_name.str);
 
50
    DBUG_RETURN(TRUE);
 
51
  }
 
52
  error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
 
53
  if (error)
 
54
  {
 
55
    table->file->print_error(error, MYF(0));
 
56
    DBUG_RETURN(error);
 
57
  }
 
58
  thd->proc_info="init";
 
59
  table->map=1;
 
60
 
 
61
  if (mysql_prepare_delete(thd, table_list, &conds))
 
62
    DBUG_RETURN(TRUE);
 
63
 
 
64
  const_cond= (!conds || conds->const_item());
 
65
  safe_update=test(thd->options & OPTION_SAFE_UPDATES);
 
66
  if (safe_update && const_cond)
 
67
  {
 
68
    my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
 
69
               ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
 
70
    DBUG_RETURN(TRUE);
 
71
  }
 
72
 
 
73
  select_lex->no_error= thd->lex->ignore;
 
74
 
 
75
  /*
 
76
    Test if the user wants to delete all rows and deletion doesn't have
 
77
    any side-effects (because of triggers), so we can use optimized
 
78
    handler::delete_all_rows() method.
 
79
  */
 
80
  if (!using_limit && const_cond && (!conds || conds->val_int()) &&
 
81
      !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) &&
 
82
      !(table->triggers && table->triggers->has_delete_triggers()))
 
83
  {
 
84
    deleted= table->file->records;
 
85
    if (!(error=table->file->delete_all_rows()))
 
86
    {
 
87
      error= -1;                                // ok
 
88
      goto cleanup;
 
89
    }
 
90
    if (error != HA_ERR_WRONG_COMMAND)
 
91
    {
 
92
      table->file->print_error(error,MYF(0));
 
93
      error=0;
 
94
      goto cleanup;
 
95
    }
 
96
    /* Handler didn't support fast delete; Delete rows one by one */
 
97
  }
 
98
 
 
99
  if (conds)
 
100
  {
 
101
    Item::cond_result result;
 
102
    conds= remove_eq_conds(thd, conds, &result);
 
103
    if (result == Item::COND_FALSE)             // Impossible where
 
104
      limit= 0;
 
105
  }
 
106
 
 
107
  table->used_keys.clear_all();
 
108
  table->quick_keys.clear_all();                // Can't use 'only index'
 
109
  select=make_select(table, 0, 0, conds, 0, &error);
 
110
  if (error)
 
111
    DBUG_RETURN(TRUE);
 
112
  if ((select && select->check_quick(thd, safe_update, limit)) || !limit)
 
113
  {
 
114
    delete select;
 
115
    free_underlaid_joins(thd, select_lex);
 
116
    thd->row_count_func= 0;
 
117
    send_ok(thd,0L);
 
118
 
 
119
    /*
 
120
      We don't need to call reset_auto_increment in this case, because
 
121
      mysql_truncate always gives a NULL conds argument, hence we never
 
122
      get here.
 
123
    */
 
124
 
 
125
    DBUG_RETURN(0);                             // Nothing to delete
 
126
  }
 
127
 
 
128
  /* If running in safe sql mode, don't allow updates without keys */
 
129
  if (table->quick_keys.is_clear_all())
 
130
  {
 
131
    thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
 
132
    if (safe_update && !using_limit)
 
133
    {
 
134
      delete select;
 
135
      free_underlaid_joins(thd, select_lex);
 
136
      my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
 
137
                 ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
 
138
      DBUG_RETURN(TRUE);
 
139
    }
 
140
  }
 
141
  if (options & OPTION_QUICK)
 
142
    (void) table->file->extra(HA_EXTRA_QUICK);
 
143
 
 
144
  if (order && order->elements)
 
145
  {
 
146
    uint         length;
 
147
    SORT_FIELD  *sortorder;
 
148
    TABLE_LIST   tables;
 
149
    List<Item>   fields;
 
150
    List<Item>   all_fields;
 
151
    ha_rows examined_rows;
 
152
 
 
153
    bzero((char*) &tables,sizeof(tables));
 
154
    tables.table = table;
 
155
    tables.alias = table_list->alias;
 
156
 
 
157
      if (select_lex->setup_ref_array(thd, order->elements) ||
 
158
          setup_order(thd, select_lex->ref_pointer_array, &tables,
 
159
                    fields, all_fields, (ORDER*) order->first))
 
160
    {
 
161
      delete select;
 
162
      free_underlaid_joins(thd, &thd->lex->select_lex);
 
163
      DBUG_RETURN(TRUE);
 
164
    }
 
165
    
 
166
    if (!select && limit != HA_POS_ERROR)
 
167
      usable_index= get_index_for_order(table, (ORDER*)(order->first), limit);
 
168
 
 
169
    if (usable_index == MAX_KEY)
 
170
    {
 
171
      table->sort.io_cache= (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
 
172
                                                   MYF(MY_FAE | MY_ZEROFILL));
 
173
    
 
174
      if (!(sortorder= make_unireg_sortorder((ORDER*) order->first,
 
175
                                             &length, NULL)) ||
 
176
          (table->sort.found_records = filesort(thd, table, sortorder, length,
 
177
                                                select, HA_POS_ERROR,
 
178
                                                &examined_rows))
 
179
          == HA_POS_ERROR)
 
180
      {
 
181
        delete select;
 
182
        free_underlaid_joins(thd, &thd->lex->select_lex);
 
183
        DBUG_RETURN(TRUE);
 
184
      }
 
185
      /*
 
186
        Filesort has already found and selected the rows we want to delete,
 
187
        so we don't need the where clause
 
188
      */
 
189
      delete select;
 
190
      free_underlaid_joins(thd, select_lex);
 
191
      select= 0;
 
192
    }
 
193
  }
 
194
 
 
195
  /* If quick select is used, initialize it before retrieving rows. */
 
196
  if (select && select->quick && select->quick->reset())
 
197
  {
 
198
    delete select;
 
199
    free_underlaid_joins(thd, select_lex);
 
200
    DBUG_RETURN(TRUE);
 
201
  }
 
202
  if (usable_index==MAX_KEY)
 
203
    init_read_record(&info,thd,table,select,1,1);
 
204
  else
 
205
    init_read_record_idx(&info, thd, table, 1, usable_index);
 
206
 
 
207
  deleted=0L;
 
208
  init_ftfuncs(thd, select_lex, 1);
 
209
  thd->proc_info="updating";
 
210
 
 
211
  if (table->triggers)
 
212
    table->triggers->mark_fields_used(thd, TRG_EVENT_DELETE);
 
213
 
 
214
  while (!(error=info.read_record(&info)) && !thd->killed &&
 
215
         !thd->net.report_error)
 
216
  {
 
217
    // thd->net.report_error is tested to disallow delete row on error
 
218
    if (!(select && select->skip_record())&& !thd->net.report_error )
 
219
    {
 
220
 
 
221
      if (table->triggers &&
 
222
          table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
 
223
                                            TRG_ACTION_BEFORE, FALSE))
 
224
      {
 
225
        error= 1;
 
226
        break;
 
227
      }
 
228
 
 
229
      if (!(error=table->file->delete_row(table->record[0])))
 
230
      {
 
231
        deleted++;
 
232
        if (table->triggers &&
 
233
            table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
 
234
                                              TRG_ACTION_AFTER, FALSE))
 
235
        {
 
236
          error= 1;
 
237
          break;
 
238
        }
 
239
        if (!--limit && using_limit)
 
240
        {
 
241
          error= -1;
 
242
          break;
 
243
        }
 
244
      }
 
245
      else
 
246
      {
 
247
        table->file->print_error(error,MYF(0));
 
248
        /*
 
249
          In < 4.0.14 we set the error number to 0 here, but that
 
250
          was not sensible, because then MySQL would not roll back the
 
251
          failed DELETE, and also wrote it to the binlog. For MyISAM
 
252
          tables a DELETE probably never should fail (?), but for
 
253
          InnoDB it can fail in a FOREIGN KEY error or an
 
254
          out-of-tablespace error.
 
255
        */
 
256
        error= 1;
 
257
        break;
 
258
      }
 
259
    }
 
260
    else
 
261
      table->file->unlock_row();  // Row failed selection, release lock on it
 
262
  }
 
263
  if (thd->killed && !error)
 
264
    error= 1;                                   // Aborted
 
265
  thd->proc_info="end";
 
266
  end_read_record(&info);
 
267
  free_io_cache(table);                         // Will not do any harm
 
268
  if (options & OPTION_QUICK)
 
269
    (void) table->file->extra(HA_EXTRA_NORMAL);
 
270
 
 
271
  if (reset_auto_increment && (error < 0))
 
272
  {
 
273
    /*
 
274
      We're really doing a truncate and need to reset the table's
 
275
      auto-increment counter.
 
276
    */
 
277
    int error2= table->file->reset_auto_increment(0);
 
278
 
 
279
    if (error2 && (error2 != HA_ERR_WRONG_COMMAND))
 
280
    {
 
281
      table->file->print_error(error2, MYF(0));
 
282
      error= 1;
 
283
    }
 
284
  }
 
285
 
 
286
cleanup:
 
287
  /*
 
288
    Invalidate the table in the query cache if something changed. This must
 
289
    be before binlog writing and ha_autocommit_...
 
290
  */
 
291
  if (deleted)
 
292
  {
 
293
    query_cache_invalidate3(thd, table_list, 1);
 
294
  }
 
295
 
 
296
  delete select;
 
297
  transactional_table= table->file->has_transactions();
 
298
  /* See similar binlogging code in sql_update.cc, for comments */
 
299
  if ((error < 0) || (deleted && !transactional_table))
 
300
  {
 
301
    if (mysql_bin_log.is_open())
 
302
    {
 
303
      if (error < 0)
 
304
        thd->clear_error();
 
305
      Query_log_event qinfo(thd, thd->query, thd->query_length,
 
306
                            transactional_table, FALSE);
 
307
      if (mysql_bin_log.write(&qinfo) && transactional_table)
 
308
        error=1;
 
309
    }
 
310
    if (!transactional_table)
 
311
      thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
 
312
  }
 
313
  free_underlaid_joins(thd, select_lex);
 
314
  if (transactional_table)
 
315
  {
 
316
    if (ha_autocommit_or_rollback(thd,error >= 0))
 
317
      error=1;
 
318
  }
 
319
 
 
320
  if (thd->lock)
 
321
  {
 
322
    mysql_unlock_tables(thd, thd->lock);
 
323
    thd->lock=0;
 
324
  }
 
325
  if (error < 0 || (thd->lex->ignore && !thd->is_fatal_error))
 
326
  {
 
327
    thd->row_count_func= deleted;
 
328
    send_ok(thd,deleted);
 
329
    DBUG_PRINT("info",("%ld records deleted",(long) deleted));
 
330
  }
 
331
  DBUG_RETURN(error >= 0 || thd->net.report_error);
 
332
}
 
333
 
 
334
 
 
335
/*
 
336
  Prepare items in DELETE statement
 
337
 
 
338
  SYNOPSIS
 
339
    mysql_prepare_delete()
 
340
    thd                 - thread handler
 
341
    table_list          - global/local table list
 
342
    conds               - conditions
 
343
 
 
344
  RETURN VALUE
 
345
    FALSE OK
 
346
    TRUE  error
 
347
*/
 
348
bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
 
349
{
 
350
  Item *fake_conds= 0;
 
351
  SELECT_LEX *select_lex= &thd->lex->select_lex;
 
352
  DBUG_ENTER("mysql_prepare_delete");
 
353
 
 
354
  thd->lex->allow_sum_func= 0;
 
355
  if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
 
356
                                    &thd->lex->select_lex.top_join_list,
 
357
                                    table_list, conds, 
 
358
                                    &select_lex->leaf_tables, FALSE, 
 
359
                                    DELETE_ACL, SELECT_ACL) ||
 
360
      setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
 
361
      setup_ftfuncs(select_lex))
 
362
    DBUG_RETURN(TRUE);
 
363
  if (!table_list->updatable || check_key_in_view(thd, table_list))
 
364
  {
 
365
    my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE");
 
366
    DBUG_RETURN(TRUE);
 
367
  }
 
368
  {
 
369
    TABLE_LIST *duplicate;
 
370
    if ((duplicate= unique_table(thd, table_list, table_list->next_global)))
 
371
    {
 
372
      update_non_unique_table_error(table_list, "DELETE", duplicate);
 
373
      DBUG_RETURN(TRUE);
 
374
    }
 
375
  }
 
376
  select_lex->fix_prepare_information(thd, conds, &fake_conds);
 
377
  DBUG_RETURN(FALSE);
 
378
}
 
379
 
 
380
 
 
381
/***************************************************************************
 
382
  Delete multiple tables from join 
 
383
***************************************************************************/
 
384
 
 
385
#define MEM_STRIP_BUF_SIZE current_thd->variables.sortbuff_size
 
386
 
 
387
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
 
388
{
 
389
  handler *file= (handler*)arg;
 
390
  return file->cmp_ref((const byte*)a, (const byte*)b);
 
391
}
 
392
 
 
393
/*
 
394
  make delete specific preparation and checks after opening tables
 
395
 
 
396
  SYNOPSIS
 
397
    mysql_multi_delete_prepare()
 
398
    thd         thread handler
 
399
 
 
400
  RETURN
 
401
    FALSE OK
 
402
    TRUE  Error
 
403
*/
 
404
 
 
405
bool mysql_multi_delete_prepare(THD *thd)
 
406
{
 
407
  LEX *lex= thd->lex;
 
408
  TABLE_LIST *aux_tables= (TABLE_LIST *)lex->auxiliary_table_list.first;
 
409
  TABLE_LIST *target_tbl;
 
410
  DBUG_ENTER("mysql_multi_delete_prepare");
 
411
 
 
412
  /*
 
413
    setup_tables() need for VIEWs. JOIN::prepare() will not do it second
 
414
    time.
 
415
 
 
416
    lex->query_tables also point on local list of DELETE SELECT_LEX
 
417
  */
 
418
  if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
 
419
                                    &thd->lex->select_lex.top_join_list,
 
420
                                    lex->query_tables, &lex->select_lex.where,
 
421
                                    &lex->select_lex.leaf_tables, FALSE, 
 
422
                                    DELETE_ACL, SELECT_ACL))
 
423
    DBUG_RETURN(TRUE);
 
424
 
 
425
 
 
426
  /*
 
427
    Multi-delete can't be constructed over-union => we always have
 
428
    single SELECT on top and have to check underlying SELECTs of it
 
429
  */
 
430
  lex->select_lex.exclude_from_table_unique_test= TRUE;
 
431
  /* Fix tables-to-be-deleted-from list to point at opened tables */
 
432
  for (target_tbl= (TABLE_LIST*) aux_tables;
 
433
       target_tbl;
 
434
       target_tbl= target_tbl->next_local)
 
435
  {
 
436
    if (!(target_tbl->table= target_tbl->correspondent_table->table))
 
437
    {
 
438
      DBUG_ASSERT(target_tbl->correspondent_table->view &&
 
439
                  target_tbl->correspondent_table->merge_underlying_list &&
 
440
                  target_tbl->correspondent_table->merge_underlying_list->
 
441
                  next_local);
 
442
      my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
 
443
               target_tbl->correspondent_table->view_db.str,
 
444
               target_tbl->correspondent_table->view_name.str);
 
445
      DBUG_RETURN(TRUE);
 
446
    }
 
447
 
 
448
    if (!target_tbl->correspondent_table->updatable ||
 
449
        check_key_in_view(thd, target_tbl->correspondent_table))
 
450
    {
 
451
      my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
 
452
               target_tbl->table_name, "DELETE");
 
453
      DBUG_RETURN(TRUE);
 
454
    }
 
455
    /*
 
456
      Check that table from which we delete is not used somewhere
 
457
      inside subqueries/view.
 
458
    */
 
459
    {
 
460
      TABLE_LIST *duplicate;
 
461
      if ((duplicate= unique_table(thd, target_tbl->correspondent_table,
 
462
                                   lex->query_tables)))
 
463
      {
 
464
        update_non_unique_table_error(target_tbl->correspondent_table,
 
465
                                      "DELETE", duplicate);
 
466
        DBUG_RETURN(TRUE);
 
467
      }
 
468
    }
 
469
  }
 
470
  DBUG_RETURN(FALSE);
 
471
}
 
472
 
 
473
 
 
474
multi_delete::multi_delete(TABLE_LIST *dt, uint num_of_tables_arg)
 
475
  : delete_tables(dt), deleted(0), found(0),
 
476
    num_of_tables(num_of_tables_arg), error(0),
 
477
    do_delete(0), transactional_tables(0), normal_tables(0)
 
478
{
 
479
  tempfiles= (Unique **) sql_calloc(sizeof(Unique *) * num_of_tables);
 
480
}
 
481
 
 
482
 
 
483
int
 
484
multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
 
485
{
 
486
  DBUG_ENTER("multi_delete::prepare");
 
487
  unit= u;
 
488
  do_delete= 1;
 
489
  thd->proc_info="deleting from main table";
 
490
  DBUG_RETURN(0);
 
491
}
 
492
 
 
493
 
 
494
bool
 
495
multi_delete::initialize_tables(JOIN *join)
 
496
{
 
497
  TABLE_LIST *walk;
 
498
  Unique **tempfiles_ptr;
 
499
  DBUG_ENTER("initialize_tables");
 
500
 
 
501
  if ((thd->options & OPTION_SAFE_UPDATES) && error_if_full_join(join))
 
502
    DBUG_RETURN(1);
 
503
 
 
504
  table_map tables_to_delete_from=0;
 
505
  for (walk= delete_tables; walk; walk= walk->next_local)
 
506
    tables_to_delete_from|= walk->table->map;
 
507
 
 
508
  walk= delete_tables;
 
509
  delete_while_scanning= 1;
 
510
  for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
 
511
       tab < end;
 
512
       tab++)
 
513
  {
 
514
    if (tab->table->map & tables_to_delete_from)
 
515
    {
 
516
      /* We are going to delete from this table */
 
517
      TABLE *tbl=walk->table=tab->table;
 
518
      walk= walk->next_local;
 
519
      /* Don't use KEYREAD optimization on this table */
 
520
      tbl->no_keyread=1;
 
521
      /* Don't use record cache */
 
522
      tbl->no_cache= 1;
 
523
      tbl->used_keys.clear_all();
 
524
      if (tbl->file->has_transactions())
 
525
        transactional_tables= 1;
 
526
      else
 
527
        normal_tables= 1;
 
528
      if (tbl->triggers)
 
529
        tbl->triggers->mark_fields_used(thd, TRG_EVENT_DELETE);
 
530
    }
 
531
    else if ((tab->type != JT_SYSTEM && tab->type != JT_CONST) &&
 
532
             walk == delete_tables)
 
533
    {
 
534
      /*
 
535
        We are not deleting from the table we are scanning. In this
 
536
        case send_data() shouldn't delete any rows a we may touch
 
537
        the rows in the deleted table many times
 
538
      */
 
539
      delete_while_scanning= 0;
 
540
    }
 
541
  }
 
542
  walk= delete_tables;
 
543
  tempfiles_ptr= tempfiles;
 
544
  if (delete_while_scanning)
 
545
  {
 
546
    table_being_deleted= delete_tables;
 
547
    walk= walk->next_local;
 
548
  }
 
549
  for (;walk ;walk= walk->next_local)
 
550
  {
 
551
    TABLE *table=walk->table;
 
552
    *tempfiles_ptr++= new Unique (refpos_order_cmp,
 
553
                                  (void *) table->file,
 
554
                                  table->file->ref_length,
 
555
                                  MEM_STRIP_BUF_SIZE);
 
556
  }
 
557
  init_ftfuncs(thd, thd->lex->current_select, 1);
 
558
  DBUG_RETURN(thd->is_fatal_error != 0);
 
559
}
 
560
 
 
561
 
 
562
multi_delete::~multi_delete()
 
563
{
 
564
  for (table_being_deleted= delete_tables;
 
565
       table_being_deleted;
 
566
       table_being_deleted= table_being_deleted->next_local)
 
567
  {
 
568
    TABLE *table= table_being_deleted->table;
 
569
    free_io_cache(table);                       // Alloced by unique
 
570
    table->no_keyread=0;
 
571
  }
 
572
 
 
573
  for (uint counter= 0; counter < num_of_tables; counter++)
 
574
  {
 
575
    if (tempfiles[counter])
 
576
      delete tempfiles[counter];
 
577
  }
 
578
}
 
579
 
 
580
 
 
581
bool multi_delete::send_data(List<Item> &values)
 
582
{
 
583
  int secure_counter= delete_while_scanning ? -1 : 0;
 
584
  TABLE_LIST *del_table;
 
585
  DBUG_ENTER("multi_delete::send_data");
 
586
 
 
587
  for (del_table= delete_tables;
 
588
       del_table;
 
589
       del_table= del_table->next_local, secure_counter++)
 
590
  {
 
591
    TABLE *table= del_table->table;
 
592
 
 
593
    /* Check if we are using outer join and we didn't find the row */
 
594
    if (table->status & (STATUS_NULL_ROW | STATUS_DELETED))
 
595
      continue;
 
596
 
 
597
    table->file->position(table->record[0]);
 
598
    found++;
 
599
 
 
600
    if (secure_counter < 0)
 
601
    {
 
602
      /* We are scanning the current table */
 
603
      DBUG_ASSERT(del_table == table_being_deleted);
 
604
      if (table->triggers &&
 
605
          table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
 
606
                                            TRG_ACTION_BEFORE, FALSE))
 
607
        DBUG_RETURN(1);
 
608
      table->status|= STATUS_DELETED;
 
609
      if (!(error=table->file->delete_row(table->record[0])))
 
610
      {
 
611
        deleted++;
 
612
        if (table->triggers &&
 
613
            table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
 
614
                                              TRG_ACTION_AFTER, FALSE))
 
615
          DBUG_RETURN(1);
 
616
      }
 
617
      else
 
618
      {
 
619
        table->file->print_error(error,MYF(0));
 
620
        DBUG_RETURN(1);
 
621
      }
 
622
    }
 
623
    else
 
624
    {
 
625
      error=tempfiles[secure_counter]->unique_add((char*) table->file->ref);
 
626
      if (error)
 
627
      {
 
628
        error= 1;                               // Fatal error
 
629
        DBUG_RETURN(1);
 
630
      }
 
631
    }
 
632
  }
 
633
  DBUG_RETURN(0);
 
634
}
 
635
 
 
636
 
 
637
void multi_delete::send_error(uint errcode,const char *err)
 
638
{
 
639
  DBUG_ENTER("multi_delete::send_error");
 
640
 
 
641
  /* First send error what ever it is ... */
 
642
  my_message(errcode, err, MYF(0));
 
643
 
 
644
  /* If nothing deleted return */
 
645
  if (!deleted)
 
646
    DBUG_VOID_RETURN;
 
647
 
 
648
  /* Something already deleted so we have to invalidate cache */
 
649
  query_cache_invalidate3(thd, delete_tables, 1);
 
650
 
 
651
  /*
 
652
    If rows from the first table only has been deleted and it is
 
653
    transactional, just do rollback.
 
654
    The same if all tables are transactional, regardless of where we are.
 
655
    In all other cases do attempt deletes ...
 
656
  */
 
657
  if ((table_being_deleted == delete_tables &&
 
658
       table_being_deleted->table->file->has_transactions()) ||
 
659
      !normal_tables)
 
660
    ha_rollback_stmt(thd);
 
661
  else if (do_delete)
 
662
  {
 
663
    /*
 
664
      We have to execute the recorded do_deletes() and write info into the
 
665
      error log
 
666
    */
 
667
    error= 1;
 
668
    send_eof();
 
669
  }
 
670
  DBUG_VOID_RETURN;
 
671
}
 
672
 
 
673
 
 
674
/*
 
675
  Do delete from other tables.
 
676
  Returns values:
 
677
        0 ok
 
678
        1 error
 
679
*/
 
680
 
 
681
int multi_delete::do_deletes()
 
682
{
 
683
  int local_error= 0, counter= 0;
 
684
  DBUG_ENTER("do_deletes");
 
685
  DBUG_ASSERT(do_delete);
 
686
 
 
687
  do_delete= 0;                                 // Mark called
 
688
  if (!found)
 
689
    DBUG_RETURN(0);
 
690
 
 
691
  table_being_deleted= (delete_while_scanning ? delete_tables->next_local :
 
692
                        delete_tables);
 
693
 
 
694
  for (; table_being_deleted;
 
695
       table_being_deleted= table_being_deleted->next_local, counter++)
 
696
  { 
 
697
    TABLE *table = table_being_deleted->table;
 
698
    if (tempfiles[counter]->get(table))
 
699
    {
 
700
      local_error=1;
 
701
      break;
 
702
    }
 
703
 
 
704
    READ_RECORD info;
 
705
    init_read_record(&info,thd,table,NULL,0,1);
 
706
    /*
 
707
      Ignore any rows not found in reference tables as they may already have
 
708
      been deleted by foreign key handling
 
709
    */
 
710
    info.ignore_not_found_rows= 1;
 
711
    while (!(local_error=info.read_record(&info)) && !thd->killed)
 
712
    {
 
713
      if (table->triggers &&
 
714
          table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
 
715
                                            TRG_ACTION_BEFORE, FALSE))
 
716
      {
 
717
        local_error= 1;
 
718
        break;
 
719
      }
 
720
      if ((local_error=table->file->delete_row(table->record[0])))
 
721
      {
 
722
        table->file->print_error(local_error,MYF(0));
 
723
        break;
 
724
      }
 
725
      deleted++;
 
726
      if (table->triggers &&
 
727
          table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
 
728
                                            TRG_ACTION_AFTER, FALSE))
 
729
      {
 
730
        local_error= 1;
 
731
        break;
 
732
      }
 
733
    }
 
734
    end_read_record(&info);
 
735
    if (thd->killed && !local_error)
 
736
      local_error= 1;
 
737
    if (local_error == -1)                              // End of file
 
738
      local_error = 0;
 
739
  }
 
740
  DBUG_RETURN(local_error);
 
741
}
 
742
 
 
743
 
 
744
/*
 
745
  Send ok to the client
 
746
 
 
747
  return:  0 sucess
 
748
           1 error
 
749
*/
 
750
 
 
751
bool multi_delete::send_eof()
 
752
{
 
753
  thd->proc_info="deleting from reference tables";
 
754
 
 
755
  /* Does deletes for the last n - 1 tables, returns 0 if ok */
 
756
  int local_error= do_deletes();                // returns 0 if success
 
757
 
 
758
  /* compute a total error to know if something failed */
 
759
  local_error= local_error || error;
 
760
 
 
761
  /* reset used flags */
 
762
  thd->proc_info="end";
 
763
 
 
764
  /*
 
765
    We must invalidate the query cache before binlog writing and
 
766
    ha_autocommit_...
 
767
  */
 
768
  if (deleted)
 
769
  {
 
770
    query_cache_invalidate3(thd, delete_tables, 1);
 
771
  }
 
772
 
 
773
  if ((local_error == 0) || (deleted && normal_tables))
 
774
  {
 
775
    if (mysql_bin_log.is_open())
 
776
    {
 
777
      if (local_error == 0)
 
778
        thd->clear_error();
 
779
      Query_log_event qinfo(thd, thd->query, thd->query_length,
 
780
                            transactional_tables, FALSE);
 
781
      if (mysql_bin_log.write(&qinfo) && !normal_tables)
 
782
        local_error=1;  // Log write failed: roll back the SQL statement
 
783
    }
 
784
    if (!transactional_tables)
 
785
      thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
 
786
  }
 
787
  /* Commit or rollback the current SQL statement */
 
788
  if (transactional_tables)
 
789
    if (ha_autocommit_or_rollback(thd,local_error > 0))
 
790
      local_error=1;
 
791
 
 
792
  if (!local_error)
 
793
  {
 
794
    thd->row_count_func= deleted;
 
795
    ::send_ok(thd, deleted);
 
796
  }
 
797
  return 0;
 
798
}
 
799
 
 
800
 
 
801
/***************************************************************************
 
802
  TRUNCATE TABLE
 
803
****************************************************************************/
 
804
 
 
805
/*
 
806
  Optimize delete of all rows by doing a full generate of the table
 
807
  This will work even if the .ISM and .ISD tables are destroyed
 
808
 
 
809
  dont_send_ok should be set if:
 
810
  - We should always wants to generate the table (even if the table type
 
811
    normally can't safely do this.
 
812
  - We don't want an ok to be sent to the end user.
 
813
  - We don't want to log the truncate command
 
814
  - If we want to have a name lock on the table on exit without errors.
 
815
*/
 
816
 
 
817
bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
 
818
{
 
819
  HA_CREATE_INFO create_info;
 
820
  char path[FN_REFLEN];
 
821
  TABLE **table_ptr;
 
822
  bool error;
 
823
  DBUG_ENTER("mysql_truncate");
 
824
 
 
825
  bzero((char*) &create_info,sizeof(create_info));
 
826
  /* If it is a temporary table, close and regenerate it */
 
827
  if (!dont_send_ok && (table_ptr=find_temporary_table(thd,table_list->db,
 
828
                                                       table_list->table_name)))
 
829
  {
 
830
    TABLE *table= *table_ptr;
 
831
    table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
 
832
    db_type table_type= table->s->db_type;
 
833
    if (!ha_check_storage_engine_flag(table_type, HTON_CAN_RECREATE))
 
834
      goto trunc_by_del;
 
835
    strmov(path, table->s->path);
 
836
    *table_ptr= table->next;                    // Unlink table from list
 
837
    close_temporary(table,0);
 
838
    if (thd->slave_thread)
 
839
      --slave_open_temp_tables;
 
840
    *fn_ext(path)=0;                            // Remove the .frm extension
 
841
    ha_create_table(path, &create_info,1);
 
842
    // We don't need to call invalidate() because this table is not in cache
 
843
    if ((error= (int) !(open_temporary_table(thd, path, table_list->db,
 
844
                                             table_list->table_name, 1))))
 
845
      (void) rm_temporary_table(table_type, path);
 
846
    /*
 
847
      If we return here we will not have logged the truncation to the bin log
 
848
      and we will not send_ok() to the client.
 
849
    */
 
850
    goto end;
 
851
  }
 
852
 
 
853
  (void) sprintf(path,"%s/%s/%s%s",mysql_data_home,table_list->db,
 
854
                 table_list->table_name,reg_ext);
 
855
  fn_format(path, path, "", "", MY_UNPACK_FILENAME);
 
856
 
 
857
  if (!dont_send_ok)
 
858
  {
 
859
    db_type table_type;
 
860
    mysql_frm_type(thd, path, &table_type);
 
861
    if (table_type == DB_TYPE_UNKNOWN)
 
862
    {
 
863
      my_error(ER_NO_SUCH_TABLE, MYF(0),
 
864
               table_list->db, table_list->table_name);
 
865
      DBUG_RETURN(TRUE);
 
866
    }
 
867
    if (!ha_check_storage_engine_flag(table_type, HTON_CAN_RECREATE))
 
868
      goto trunc_by_del;
 
869
    if (lock_and_wait_for_table_name(thd, table_list))
 
870
      DBUG_RETURN(TRUE);
 
871
  }
 
872
 
 
873
  *fn_ext(path)=0;                              // Remove the .frm extension
 
874
  error= ha_create_table(path,&create_info,1);
 
875
  query_cache_invalidate3(thd, table_list, 0);
 
876
 
 
877
end:
 
878
  if (!dont_send_ok)
 
879
  {
 
880
    if (!error)
 
881
    {
 
882
      if (mysql_bin_log.is_open())
 
883
      {
 
884
        thd->clear_error();
 
885
        Query_log_event qinfo(thd, thd->query, thd->query_length,
 
886
                              0, FALSE);
 
887
        mysql_bin_log.write(&qinfo);
 
888
      }
 
889
      send_ok(thd);             // This should return record count
 
890
    }
 
891
    VOID(pthread_mutex_lock(&LOCK_open));
 
892
    unlock_table_name(thd, table_list);
 
893
    VOID(pthread_mutex_unlock(&LOCK_open));
 
894
  }
 
895
  else if (error)
 
896
  {
 
897
    VOID(pthread_mutex_lock(&LOCK_open));
 
898
    unlock_table_name(thd, table_list);
 
899
    VOID(pthread_mutex_unlock(&LOCK_open));
 
900
  }
 
901
  DBUG_RETURN(error);
 
902
 
 
903
 trunc_by_del:
 
904
  /* Probably InnoDB table */
 
905
  ulonglong save_options= thd->options;
 
906
  table_list->lock_type= TL_WRITE;
 
907
  thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
 
908
  ha_enable_transaction(thd, FALSE);
 
909
  mysql_init_select(thd->lex);
 
910
  error= mysql_delete(thd, table_list, (COND*) 0, (SQL_LIST*) 0,
 
911
                      HA_POS_ERROR, LL(0), TRUE);
 
912
  ha_enable_transaction(thd, TRUE);
 
913
  thd->options= save_options;
 
914
  DBUG_RETURN(error);
 
915
}