~stewart/drizzle/embedded-innodb-create-select-transaction-arrgh

« back to all changes in this revision

Viewing changes to sql/sql_delete.cc

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

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