~drizzle-trunk/drizzle/development

1 by brian
clean slate
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
}