~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql/sql_delete.cc

  • Committer: Monty Taylor
  • Date: 2008-07-05 11:20:18 UTC
  • mto: This revision was merged to the branch mainline in revision 62.
  • Revision ID: monty@inaugust.com-20080705112018-fr12kkmgphtu7m29
Changes so that removal of duplicate curr_dir from my_sys.h work.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
  Multi-table deletes were introduced by Monty and Sinisa
20
20
*/
21
 
#include <drizzled/server_includes.h>
22
 
#include <drizzled/sql_select.h>
23
 
#include <drizzled/drizzled_error_messages.h>
 
21
 
 
22
#include "mysql_priv.h"
 
23
#include "sql_select.h"
24
24
 
25
25
/**
26
26
  Implement DELETE SQL word.
30
30
  end of dispatch_command().
31
31
*/
32
32
 
33
 
bool mysql_delete(THD *thd, TableList *table_list, COND *conds,
34
 
                  SQL_LIST *order, ha_rows limit, uint64_t options,
 
33
bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
 
34
                  SQL_LIST *order, ha_rows limit, ulonglong options,
35
35
                  bool reset_auto_increment)
36
36
{
37
37
  bool          will_batch;
38
38
  int           error, loc_error;
39
 
  Table         *table;
 
39
  TABLE         *table;
40
40
  SQL_SELECT    *select=0;
41
41
  READ_RECORD   info;
42
42
  bool          using_limit=limit != HA_POS_ERROR;
43
43
  bool          transactional_table, safe_update, const_cond;
44
44
  bool          const_cond_result;
45
45
  ha_rows       deleted= 0;
46
 
  uint32_t usable_index= MAX_KEY;
 
46
  uint usable_index= MAX_KEY;
47
47
  SELECT_LEX   *select_lex= &thd->lex->select_lex;
48
48
  THD::killed_state killed_status= THD::NOT_KILLED;
49
 
  
 
49
  DBUG_ENTER("mysql_delete");
50
50
 
51
51
  if (open_and_lock_tables(thd, table_list))
52
 
    return(true);
 
52
    DBUG_RETURN(TRUE);
53
53
  /* TODO look at this error */
54
54
  if (!(table= table_list->table))
55
55
  {
56
56
    my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), "", "");
57
 
    return(true);
 
57
    DBUG_RETURN(TRUE);
58
58
  }
59
 
  thd->set_proc_info("init");
 
59
  thd_proc_info(thd, "init");
60
60
  table->map=1;
61
61
 
62
62
  if (mysql_prepare_delete(thd, table_list, &conds))
65
65
  /* check ORDER BY even if it can be ignored */
66
66
  if (order && order->elements)
67
67
  {
68
 
    TableList   tables;
 
68
    TABLE_LIST   tables;
69
69
    List<Item>   fields;
70
70
    List<Item>   all_fields;
71
71
 
72
 
    memset(&tables, 0, sizeof(tables));
 
72
    bzero((char*) &tables,sizeof(tables));
73
73
    tables.table = table;
74
74
    tables.alias = table_list->alias;
75
75
 
76
76
      if (select_lex->setup_ref_array(thd, order->elements) ||
77
77
          setup_order(thd, select_lex->ref_pointer_array, &tables,
78
 
                    fields, all_fields, (order_st*) order->first))
 
78
                    fields, all_fields, (ORDER*) order->first))
79
79
    {
80
80
      delete select;
81
81
      free_underlaid_joins(thd, &thd->lex->select_lex);
98
98
  if (thd->is_error())
99
99
  {
100
100
    /* Error evaluating val_int(). */
101
 
    return(true);
 
101
    DBUG_RETURN(TRUE);
102
102
  }
103
103
 
104
104
  /*
121
121
      - there should be no delete triggers associated with the table.
122
122
  */
123
123
  if (!using_limit && const_cond_result &&
 
124
      !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) &&
124
125
      (thd->lex->sql_command == SQLCOM_TRUNCATE ||
125
126
       (!thd->current_stmt_binlog_row_based)))
126
127
  {
127
128
    /* Update the table->file->stats.records number */
128
129
    table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
129
130
    ha_rows const maybe_deleted= table->file->stats.records;
 
131
    DBUG_PRINT("debug", ("Trying to use delete_all_rows()"));
130
132
    if (!(error=table->file->ha_delete_all_rows()))
131
133
    {
132
134
      error= -1;                                // ok
162
164
    delete select;
163
165
    free_underlaid_joins(thd, select_lex);
164
166
    thd->row_count_func= 0;
165
 
    DRIZZLE_DELETE_END();
 
167
    MYSQL_DELETE_END();
166
168
    my_ok(thd, (ha_rows) thd->row_count_func);
167
169
    /*
168
170
      We don't need to call reset_auto_increment in this case, because
169
171
      mysql_truncate always gives a NULL conds argument, hence we never
170
172
      get here.
171
173
    */
172
 
    return(0);                          // Nothing to delete
 
174
    DBUG_RETURN(0);                             // Nothing to delete
173
175
  }
174
176
 
175
177
  /* If running in safe sql mode, don't allow updates without keys */
190
192
 
191
193
  if (order && order->elements)
192
194
  {
193
 
    uint32_t         length= 0;
 
195
    uint         length= 0;
194
196
    SORT_FIELD  *sortorder;
195
197
    ha_rows examined_rows;
196
198
    
197
199
    if ((!select || table->quick_keys.is_clear_all()) && limit != HA_POS_ERROR)
198
 
      usable_index= get_index_for_order(table, (order_st*)(order->first), limit);
 
200
      usable_index= get_index_for_order(table, (ORDER*)(order->first), limit);
199
201
 
200
202
    if (usable_index == MAX_KEY)
201
203
    {
202
204
      table->sort.io_cache= (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
203
205
                                                   MYF(MY_FAE | MY_ZEROFILL));
204
206
    
205
 
      if (!(sortorder= make_unireg_sortorder((order_st*) order->first,
 
207
      if (!(sortorder= make_unireg_sortorder((ORDER*) order->first,
206
208
                                             &length, NULL)) ||
207
209
          (table->sort.found_records = filesort(thd, table, sortorder, length,
208
210
                                                select, HA_POS_ERROR, 1,
235
237
  else
236
238
    init_read_record_idx(&info, thd, table, 1, usable_index);
237
239
 
238
 
  thd->set_proc_info("updating");
 
240
  thd_proc_info(thd, "updating");
239
241
 
240
242
  will_batch= !table->file->start_bulk_delete();
241
243
 
284
286
      table->file->print_error(loc_error,MYF(0));
285
287
    error=1;
286
288
  }
287
 
  thd->set_proc_info("end");
 
289
  thd_proc_info(thd, "end");
288
290
  end_read_record(&info);
289
291
  if (options & OPTION_QUICK)
290
292
    (void) table->file->extra(HA_EXTRA_NORMAL);
310
312
  transactional_table= table->file->has_transactions();
311
313
 
312
314
  if (!transactional_table && deleted > 0)
313
 
    thd->transaction.stmt.modified_non_trans_table= true;
 
315
    thd->transaction.stmt.modified_non_trans_table= TRUE;
314
316
  
315
317
  /* See similar binlogging code in sql_update.cc, for comments */
316
318
  if ((error < 0) || thd->transaction.stmt.modified_non_trans_table)
327
329
      */
328
330
      int log_result= thd->binlog_query(THD::ROW_QUERY_TYPE,
329
331
                                        thd->query, thd->query_length,
330
 
                                        transactional_table, false, killed_status);
 
332
                                        transactional_table, FALSE, killed_status);
331
333
 
332
334
      if (log_result && transactional_table)
333
335
      {
335
337
      }
336
338
    }
337
339
    if (thd->transaction.stmt.modified_non_trans_table)
338
 
      thd->transaction.all.modified_non_trans_table= true;
 
340
      thd->transaction.all.modified_non_trans_table= TRUE;
339
341
  }
340
 
  assert(transactional_table || !deleted || thd->transaction.stmt.modified_non_trans_table);
 
342
  DBUG_ASSERT(transactional_table || !deleted || thd->transaction.stmt.modified_non_trans_table);
341
343
  free_underlaid_joins(thd, select_lex);
342
344
 
343
 
  DRIZZLE_DELETE_END();
 
345
  MYSQL_DELETE_END();
344
346
  if (error < 0 || (thd->lex->ignore && !thd->is_fatal_error))
345
347
  {
346
348
    thd->row_count_func= deleted;
347
349
    my_ok(thd, (ha_rows) thd->row_count_func);
 
350
    DBUG_PRINT("info",("%ld records deleted",(long) deleted));
348
351
  }
349
 
  return(error >= 0 || thd->is_error());
 
352
  DBUG_RETURN(error >= 0 || thd->is_error());
350
353
 
351
354
err:
352
 
  DRIZZLE_DELETE_END();
353
 
  return(true);
 
355
  MYSQL_DELETE_END();
 
356
  DBUG_RETURN(TRUE);
354
357
}
355
358
 
356
359
 
364
367
    conds               - conditions
365
368
 
366
369
  RETURN VALUE
367
 
    false OK
368
 
    true  error
 
370
    FALSE OK
 
371
    TRUE  error
369
372
*/
370
 
int mysql_prepare_delete(THD *thd, TableList *table_list, Item **conds)
 
373
int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
371
374
{
 
375
  Item *fake_conds= 0;
372
376
  SELECT_LEX *select_lex= &thd->lex->select_lex;
373
 
  
 
377
  DBUG_ENTER("mysql_prepare_delete");
374
378
  List<Item> all_fields;
375
379
 
376
380
  /*
392
396
                                    table_list, 
393
397
                                    &select_lex->leaf_tables, false) ||
394
398
      setup_conds(thd, table_list, select_lex->leaf_tables, conds))
395
 
    return(true);
 
399
    DBUG_RETURN(TRUE);
396
400
  {
397
 
    TableList *duplicate;
 
401
    TABLE_LIST *duplicate;
398
402
    if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0)))
399
403
    {
400
404
      update_non_unique_table_error(table_list, "DELETE", duplicate);
401
 
      return(true);
 
405
      DBUG_RETURN(TRUE);
402
406
    }
403
407
  }
404
408
 
405
409
  if (select_lex->inner_refs_list.elements &&
406
410
    fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
407
 
    return(-1);
 
411
    DBUG_RETURN(-1);
408
412
 
409
 
  return(false);
 
413
  select_lex->fix_prepare_information(thd, conds, &fake_conds);
 
414
  DBUG_RETURN(FALSE);
410
415
}
411
416
 
412
417
 
419
424
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
420
425
{
421
426
  handler *file= (handler*)arg;
422
 
  return file->cmp_ref((const unsigned char*)a, (const unsigned char*)b);
 
427
  return file->cmp_ref((const uchar*)a, (const uchar*)b);
423
428
}
424
429
 
425
430
/*
430
435
    thd         thread handler
431
436
 
432
437
  RETURN
433
 
    false OK
434
 
    true  Error
 
438
    FALSE OK
 
439
    TRUE  Error
435
440
*/
436
441
 
437
442
int mysql_multi_delete_prepare(THD *thd)
438
443
{
439
444
  LEX *lex= thd->lex;
440
 
  TableList *aux_tables= (TableList *)lex->auxiliary_table_list.first;
441
 
  TableList *target_tbl;
442
 
  
 
445
  TABLE_LIST *aux_tables= (TABLE_LIST *)lex->auxiliary_table_list.first;
 
446
  TABLE_LIST *target_tbl;
 
447
  DBUG_ENTER("mysql_multi_delete_prepare");
443
448
 
444
449
  /*
445
450
    setup_tables() need for VIEWs. JOIN::prepare() will not do it second
451
456
                                    &thd->lex->select_lex.top_join_list,
452
457
                                    lex->query_tables,
453
458
                                    &lex->select_lex.leaf_tables, false))
454
 
    return(true);
 
459
    DBUG_RETURN(TRUE);
455
460
 
456
461
 
457
462
  /*
458
463
    Multi-delete can't be constructed over-union => we always have
459
464
    single SELECT on top and have to check underlying SELECTs of it
460
465
  */
461
 
  lex->select_lex.exclude_from_table_unique_test= true;
 
466
  lex->select_lex.exclude_from_table_unique_test= TRUE;
462
467
  /* Fix tables-to-be-deleted-from list to point at opened tables */
463
 
  for (target_tbl= (TableList*) aux_tables;
 
468
  for (target_tbl= (TABLE_LIST*) aux_tables;
464
469
       target_tbl;
465
470
       target_tbl= target_tbl->next_local)
466
471
  {
467
472
    if (!(target_tbl->table= target_tbl->correspondent_table->table))
468
473
    {
469
 
      assert(target_tbl->correspondent_table->merge_underlying_list &&
 
474
      DBUG_ASSERT(target_tbl->correspondent_table->merge_underlying_list &&
470
475
                  target_tbl->correspondent_table->merge_underlying_list->
471
476
                  next_local);
472
477
      my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), "", "");
473
 
      return(true);
 
478
      DBUG_RETURN(TRUE);
474
479
    }
475
480
 
476
481
    /*
478
483
      inside subqueries/view.
479
484
    */
480
485
    {
481
 
      TableList *duplicate;
 
486
      TABLE_LIST *duplicate;
482
487
      if ((duplicate= unique_table(thd, target_tbl->correspondent_table,
483
488
                                   lex->query_tables, 0)))
484
489
      {
485
490
        update_non_unique_table_error(target_tbl->correspondent_table,
486
491
                                      "DELETE", duplicate);
487
 
        return(true);
 
492
        DBUG_RETURN(TRUE);
488
493
      }
489
494
    }
490
495
  }
491
 
  return(false);
 
496
  DBUG_RETURN(FALSE);
492
497
}
493
498
 
494
499
 
495
 
multi_delete::multi_delete(TableList *dt, uint32_t num_of_tables_arg)
 
500
multi_delete::multi_delete(TABLE_LIST *dt, uint num_of_tables_arg)
496
501
  : delete_tables(dt), deleted(0), found(0),
497
502
    num_of_tables(num_of_tables_arg), error(0),
498
503
    do_delete(0), transactional_tables(0), normal_tables(0), error_handled(0)
502
507
 
503
508
 
504
509
int
505
 
multi_delete::prepare(List<Item> &values __attribute__((unused)),
506
 
                      SELECT_LEX_UNIT *u)
 
510
multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
507
511
{
508
 
  
 
512
  DBUG_ENTER("multi_delete::prepare");
509
513
  unit= u;
510
514
  do_delete= 1;
511
 
  thd->set_proc_info("deleting from main table");
512
 
  return(0);
 
515
  thd_proc_info(thd, "deleting from main table");
 
516
  DBUG_RETURN(0);
513
517
}
514
518
 
515
519
 
516
520
bool
517
521
multi_delete::initialize_tables(JOIN *join)
518
522
{
519
 
  TableList *walk;
 
523
  TABLE_LIST *walk;
520
524
  Unique **tempfiles_ptr;
521
 
  
 
525
  DBUG_ENTER("initialize_tables");
522
526
 
523
527
  if ((thd->options & OPTION_SAFE_UPDATES) && error_if_full_join(join))
524
 
    return(1);
 
528
    DBUG_RETURN(1);
525
529
 
526
530
  table_map tables_to_delete_from=0;
527
531
  for (walk= delete_tables; walk; walk= walk->next_local)
536
540
    if (tab->table->map & tables_to_delete_from)
537
541
    {
538
542
      /* We are going to delete from this table */
539
 
      Table *tbl=walk->table=tab->table;
 
543
      TABLE *tbl=walk->table=tab->table;
540
544
      walk= walk->next_local;
541
545
      /* Don't use KEYREAD optimization on this table */
542
546
      tbl->no_keyread=1;
570
574
  }
571
575
  for (;walk ;walk= walk->next_local)
572
576
  {
573
 
    Table *table=walk->table;
 
577
    TABLE *table=walk->table;
574
578
    *tempfiles_ptr++= new Unique (refpos_order_cmp,
575
579
                                  (void *) table->file,
576
580
                                  table->file->ref_length,
577
581
                                  MEM_STRIP_BUF_SIZE);
578
582
  }
579
 
  return(thd->is_fatal_error != 0);
 
583
  DBUG_RETURN(thd->is_fatal_error != 0);
580
584
}
581
585
 
582
586
 
586
590
       table_being_deleted;
587
591
       table_being_deleted= table_being_deleted->next_local)
588
592
  {
589
 
    Table *table= table_being_deleted->table;
 
593
    TABLE *table= table_being_deleted->table;
590
594
    table->no_keyread=0;
591
595
  }
592
596
 
593
 
  for (uint32_t counter= 0; counter < num_of_tables; counter++)
 
597
  for (uint counter= 0; counter < num_of_tables; counter++)
594
598
  {
595
599
    if (tempfiles[counter])
596
600
      delete tempfiles[counter];
598
602
}
599
603
 
600
604
 
601
 
bool multi_delete::send_data(List<Item> &values __attribute__((unused)))
 
605
bool multi_delete::send_data(List<Item> &values)
602
606
{
603
607
  int secure_counter= delete_while_scanning ? -1 : 0;
604
 
  TableList *del_table;
605
 
  
 
608
  TABLE_LIST *del_table;
 
609
  DBUG_ENTER("multi_delete::send_data");
606
610
 
607
611
  for (del_table= delete_tables;
608
612
       del_table;
609
613
       del_table= del_table->next_local, secure_counter++)
610
614
  {
611
 
    Table *table= del_table->table;
 
615
    TABLE *table= del_table->table;
612
616
 
613
617
    /* Check if we are using outer join and we didn't find the row */
614
618
    if (table->status & (STATUS_NULL_ROW | STATUS_DELETED))
620
624
    if (secure_counter < 0)
621
625
    {
622
626
      /* We are scanning the current table */
623
 
      assert(del_table == table_being_deleted);
 
627
      DBUG_ASSERT(del_table == table_being_deleted);
624
628
      table->status|= STATUS_DELETED;
625
629
      if (!(error=table->file->ha_delete_row(table->record[0])))
626
630
      {
627
631
        deleted++;
628
632
        if (!table->file->has_transactions())
629
 
          thd->transaction.stmt.modified_non_trans_table= true;
 
633
          thd->transaction.stmt.modified_non_trans_table= TRUE;
630
634
      }
631
635
      else
632
636
      {
633
637
        table->file->print_error(error,MYF(0));
634
 
        return(1);
 
638
        DBUG_RETURN(1);
635
639
      }
636
640
    }
637
641
    else
640
644
      if (error)
641
645
      {
642
646
        error= 1;                               // Fatal error
643
 
        return(1);
 
647
        DBUG_RETURN(1);
644
648
      }
645
649
    }
646
650
  }
647
 
  return(0);
 
651
  DBUG_RETURN(0);
648
652
}
649
653
 
650
654
 
651
 
void multi_delete::send_error(uint32_t errcode,const char *err)
 
655
void multi_delete::send_error(uint errcode,const char *err)
652
656
{
653
 
  
 
657
  DBUG_ENTER("multi_delete::send_error");
654
658
 
655
659
  /* First send error what ever it is ... */
656
660
  my_message(errcode, err, MYF(0));
657
661
 
658
 
  return;
 
662
  DBUG_VOID_RETURN;
659
663
}
660
664
 
661
665
 
662
666
void multi_delete::abort()
663
667
{
664
 
  
 
668
  DBUG_ENTER("multi_delete::abort");
665
669
 
666
670
  /* the error was handled or nothing deleted and no side effects return */
667
671
  if (error_handled ||
668
672
      (!thd->transaction.stmt.modified_non_trans_table && !deleted))
669
 
    return;
 
673
    DBUG_VOID_RETURN;
670
674
 
671
675
  /*
672
676
    If rows from the first table only has been deleted and it is
684
688
    */
685
689
    error= 1;
686
690
    send_eof();
687
 
    assert(error_handled);
688
 
    return;
 
691
    DBUG_ASSERT(error_handled);
 
692
    DBUG_VOID_RETURN;
689
693
  }
690
694
  
691
695
  if (thd->transaction.stmt.modified_non_trans_table)
697
701
    {
698
702
      thd->binlog_query(THD::ROW_QUERY_TYPE,
699
703
                        thd->query, thd->query_length,
700
 
                        transactional_tables, false);
 
704
                        transactional_tables, FALSE);
701
705
    }
702
706
    thd->transaction.all.modified_non_trans_table= true;
703
707
  }
704
 
  return;
 
708
  DBUG_VOID_RETURN;
705
709
}
706
710
 
707
711
 
717
721
{
718
722
  int local_error= 0, counter= 0, tmp_error;
719
723
  bool will_batch;
720
 
  
721
 
  assert(do_delete);
 
724
  DBUG_ENTER("do_deletes");
 
725
  DBUG_ASSERT(do_delete);
722
726
 
723
727
  do_delete= 0;                                 // Mark called
724
728
  if (!found)
725
 
    return(0);
 
729
    DBUG_RETURN(0);
726
730
 
727
731
  table_being_deleted= (delete_while_scanning ? delete_tables->next_local :
728
732
                        delete_tables);
731
735
       table_being_deleted= table_being_deleted->next_local, counter++)
732
736
  { 
733
737
    ha_rows last_deleted= deleted;
734
 
    Table *table = table_being_deleted->table;
 
738
    TABLE *table = table_being_deleted->table;
735
739
    if (tempfiles[counter]->get(table))
736
740
    {
737
741
      local_error=1;
764
768
      }
765
769
    }
766
770
    if (last_deleted != deleted && !table->file->has_transactions())
767
 
      thd->transaction.stmt.modified_non_trans_table= true;
 
771
      thd->transaction.stmt.modified_non_trans_table= TRUE;
768
772
    end_read_record(&info);
769
773
    if (thd->killed && !local_error)
770
774
      local_error= 1;
771
775
    if (local_error == -1)                              // End of file
772
776
      local_error = 0;
773
777
  }
774
 
  return(local_error);
 
778
  DBUG_RETURN(local_error);
775
779
}
776
780
 
777
781
 
785
789
bool multi_delete::send_eof()
786
790
{
787
791
  THD::killed_state killed_status= THD::NOT_KILLED;
788
 
  thd->set_proc_info("deleting from reference tables");
 
792
  thd_proc_info(thd, "deleting from reference tables");
789
793
 
790
794
  /* Does deletes for the last n - 1 tables, returns 0 if ok */
791
795
  int local_error= do_deletes();                // returns 0 if success
794
798
  local_error= local_error || error;
795
799
  killed_status= (local_error == 0)? THD::NOT_KILLED : thd->killed;
796
800
  /* reset used flags */
797
 
  thd->set_proc_info("end");
 
801
  thd_proc_info(thd, "end");
798
802
 
799
803
  if ((local_error == 0) || thd->transaction.stmt.modified_non_trans_table)
800
804
  {
804
808
        thd->clear_error();
805
809
      if (thd->binlog_query(THD::ROW_QUERY_TYPE,
806
810
                            thd->query, thd->query_length,
807
 
                            transactional_tables, false, killed_status) &&
 
811
                            transactional_tables, FALSE, killed_status) &&
808
812
          !normal_tables)
809
813
      {
810
814
        local_error=1;  // Log write failed: roll back the SQL statement
811
815
      }
812
816
    }
813
817
    if (thd->transaction.stmt.modified_non_trans_table)
814
 
      thd->transaction.all.modified_non_trans_table= true;
 
818
      thd->transaction.all.modified_non_trans_table= TRUE;
815
819
  }
816
820
  if (local_error != 0)
817
 
    error_handled= true; // to force early leave from ::send_error()
 
821
    error_handled= TRUE; // to force early leave from ::send_error()
818
822
 
819
823
  if (!local_error)
820
824
  {
826
830
 
827
831
 
828
832
/***************************************************************************
829
 
  TRUNCATE Table
 
833
  TRUNCATE TABLE
830
834
****************************************************************************/
831
835
 
832
836
/*
841
845
  - If we want to have a name lock on the table on exit without errors.
842
846
*/
843
847
 
844
 
bool mysql_truncate(THD *thd, TableList *table_list, bool dont_send_ok)
 
848
bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
845
849
{
846
850
  HA_CREATE_INFO create_info;
847
851
  char path[FN_REFLEN];
848
 
  Table *table;
 
852
  TABLE *table;
849
853
  bool error;
850
 
  uint32_t path_length;
851
 
  
 
854
  uint path_length;
 
855
  DBUG_ENTER("mysql_truncate");
852
856
 
853
 
  memset(&create_info, 0, sizeof(create_info));
 
857
  bzero((char*) &create_info,sizeof(create_info));
854
858
  /* If it is a temporary table, close and regenerate it */
855
859
  if (!dont_send_ok && (table= find_temporary_table(thd, table_list)))
856
860
  {
873
877
                                             OTM_OPEN))))
874
878
      (void) rm_temporary_table(table_type, path, frm_only);
875
879
    free_table_share(share);
876
 
    free((char*) table);
 
880
    my_free((char*) table,MYF(0));
877
881
    /*
878
882
      If we return here we will not have logged the truncation to the bin log
879
883
      and we will not my_ok() to the client.
885
889
                                    table_list->table_name, reg_ext, 0);
886
890
 
887
891
  if (!dont_send_ok)
888
 
    goto trunc_by_del;
 
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
  }
889
909
 
890
910
  // Remove the .frm extension AIX 5.2 64-bit compiler bug (BUG#16155): this
891
911
  // crashes, replacement works.  *(path + path_length - reg_ext_length)=
892
912
  // '\0';
893
913
  path[path_length - reg_ext_length] = 0;
894
 
  pthread_mutex_lock(&LOCK_open);
 
914
  VOID(pthread_mutex_lock(&LOCK_open));
895
915
  error= ha_create_table(thd, path, table_list->db, table_list->table_name,
896
916
                         &create_info, 1);
897
 
  pthread_mutex_unlock(&LOCK_open);
 
917
  VOID(pthread_mutex_unlock(&LOCK_open));
898
918
 
899
919
end:
900
920
  if (!dont_send_ok)
905
925
        TRUNCATE must always be statement-based binlogged (not row-based) so
906
926
        we don't test current_stmt_binlog_row_based.
907
927
      */
908
 
      write_bin_log(thd, true, thd->query, thd->query_length);
 
928
      write_bin_log(thd, TRUE, thd->query, thd->query_length);
909
929
      my_ok(thd);               // This should return record count
910
930
    }
911
 
    pthread_mutex_lock(&LOCK_open);
 
931
    VOID(pthread_mutex_lock(&LOCK_open));
912
932
    unlock_table_name(thd, table_list);
913
 
    pthread_mutex_unlock(&LOCK_open);
 
933
    VOID(pthread_mutex_unlock(&LOCK_open));
914
934
  }
915
935
  else if (error)
916
936
  {
917
 
    pthread_mutex_lock(&LOCK_open);
 
937
    VOID(pthread_mutex_lock(&LOCK_open));
918
938
    unlock_table_name(thd, table_list);
919
 
    pthread_mutex_unlock(&LOCK_open);
 
939
    VOID(pthread_mutex_unlock(&LOCK_open));
920
940
  }
921
 
  return(error);
 
941
  DBUG_RETURN(error);
922
942
 
923
943
trunc_by_del:
924
944
  /* Probably InnoDB table */
925
 
  uint64_t save_options= thd->options;
 
945
  ulonglong save_options= thd->options;
926
946
  table_list->lock_type= TL_WRITE;
927
947
  thd->options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
928
 
  ha_enable_transaction(thd, false);
 
948
  ha_enable_transaction(thd, FALSE);
929
949
  mysql_init_select(thd->lex);
930
950
  bool save_binlog_row_based= thd->current_stmt_binlog_row_based;
931
951
  thd->clear_current_stmt_binlog_row_based();
932
952
  error= mysql_delete(thd, table_list, (COND*) 0, (SQL_LIST*) 0,
933
 
                      HA_POS_ERROR, 0L, true);
934
 
  ha_enable_transaction(thd, true);
 
953
                      HA_POS_ERROR, LL(0), TRUE);
 
954
  ha_enable_transaction(thd, TRUE);
935
955
  /*
936
 
    Safety, in case the engine ignored ha_enable_transaction(false)
 
956
    Safety, in case the engine ignored ha_enable_transaction(FALSE)
937
957
    above. Also clears thd->transaction.*.
938
958
  */
939
959
  error= ha_autocommit_or_rollback(thd, error);
940
960
  ha_commit(thd);
941
961
  thd->options= save_options;
942
962
  thd->current_stmt_binlog_row_based= save_binlog_row_based;
943
 
  return(error);
 
963
  DBUG_RETURN(error);
944
964
}