~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql/sql_delete.cc

Removed DBUG symbols and fixed TRUE/FALSE

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
  
50
50
 
51
51
  if (open_and_lock_tables(thd, table_list))
52
 
    return(true);
 
52
    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
    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
    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
  {
162
163
    delete select;
163
164
    free_underlaid_joins(thd, select_lex);
164
165
    thd->row_count_func= 0;
165
 
    DRIZZLE_DELETE_END();
 
166
    MYSQL_DELETE_END();
166
167
    my_ok(thd, (ha_rows) thd->row_count_func);
167
168
    /*
168
169
      We don't need to call reset_auto_increment in this case, because
190
191
 
191
192
  if (order && order->elements)
192
193
  {
193
 
    uint32_t         length= 0;
 
194
    uint         length= 0;
194
195
    SORT_FIELD  *sortorder;
195
196
    ha_rows examined_rows;
196
197
    
197
198
    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);
 
199
      usable_index= get_index_for_order(table, (ORDER*)(order->first), limit);
199
200
 
200
201
    if (usable_index == MAX_KEY)
201
202
    {
202
203
      table->sort.io_cache= (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
203
204
                                                   MYF(MY_FAE | MY_ZEROFILL));
204
205
    
205
 
      if (!(sortorder= make_unireg_sortorder((order_st*) order->first,
 
206
      if (!(sortorder= make_unireg_sortorder((ORDER*) order->first,
206
207
                                             &length, NULL)) ||
207
208
          (table->sort.found_records = filesort(thd, table, sortorder, length,
208
209
                                                select, HA_POS_ERROR, 1,
235
236
  else
236
237
    init_read_record_idx(&info, thd, table, 1, usable_index);
237
238
 
238
 
  thd->set_proc_info("updating");
 
239
  thd_proc_info(thd, "updating");
239
240
 
240
241
  will_batch= !table->file->start_bulk_delete();
241
242
 
284
285
      table->file->print_error(loc_error,MYF(0));
285
286
    error=1;
286
287
  }
287
 
  thd->set_proc_info("end");
 
288
  thd_proc_info(thd, "end");
288
289
  end_read_record(&info);
289
290
  if (options & OPTION_QUICK)
290
291
    (void) table->file->extra(HA_EXTRA_NORMAL);
310
311
  transactional_table= table->file->has_transactions();
311
312
 
312
313
  if (!transactional_table && deleted > 0)
313
 
    thd->transaction.stmt.modified_non_trans_table= true;
 
314
    thd->transaction.stmt.modified_non_trans_table= TRUE;
314
315
  
315
316
  /* See similar binlogging code in sql_update.cc, for comments */
316
317
  if ((error < 0) || thd->transaction.stmt.modified_non_trans_table)
327
328
      */
328
329
      int log_result= thd->binlog_query(THD::ROW_QUERY_TYPE,
329
330
                                        thd->query, thd->query_length,
330
 
                                        transactional_table, false, killed_status);
 
331
                                        transactional_table, FALSE, killed_status);
331
332
 
332
333
      if (log_result && transactional_table)
333
334
      {
335
336
      }
336
337
    }
337
338
    if (thd->transaction.stmt.modified_non_trans_table)
338
 
      thd->transaction.all.modified_non_trans_table= true;
 
339
      thd->transaction.all.modified_non_trans_table= TRUE;
339
340
  }
340
341
  assert(transactional_table || !deleted || thd->transaction.stmt.modified_non_trans_table);
341
342
  free_underlaid_joins(thd, select_lex);
342
343
 
343
 
  DRIZZLE_DELETE_END();
 
344
  MYSQL_DELETE_END();
344
345
  if (error < 0 || (thd->lex->ignore && !thd->is_fatal_error))
345
346
  {
346
347
    thd->row_count_func= deleted;
349
350
  return(error >= 0 || thd->is_error());
350
351
 
351
352
err:
352
 
  DRIZZLE_DELETE_END();
353
 
  return(true);
 
353
  MYSQL_DELETE_END();
 
354
  return(TRUE);
354
355
}
355
356
 
356
357
 
364
365
    conds               - conditions
365
366
 
366
367
  RETURN VALUE
367
 
    false OK
368
 
    true  error
 
368
    FALSE OK
 
369
    TRUE  error
369
370
*/
370
 
int mysql_prepare_delete(THD *thd, TableList *table_list, Item **conds)
 
371
int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
371
372
{
 
373
  Item *fake_conds= 0;
372
374
  SELECT_LEX *select_lex= &thd->lex->select_lex;
373
375
  
374
376
  List<Item> all_fields;
392
394
                                    table_list, 
393
395
                                    &select_lex->leaf_tables, false) ||
394
396
      setup_conds(thd, table_list, select_lex->leaf_tables, conds))
395
 
    return(true);
 
397
    return(TRUE);
396
398
  {
397
 
    TableList *duplicate;
 
399
    TABLE_LIST *duplicate;
398
400
    if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0)))
399
401
    {
400
402
      update_non_unique_table_error(table_list, "DELETE", duplicate);
401
 
      return(true);
 
403
      return(TRUE);
402
404
    }
403
405
  }
404
406
 
406
408
    fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
407
409
    return(-1);
408
410
 
409
 
  return(false);
 
411
  select_lex->fix_prepare_information(thd, conds, &fake_conds);
 
412
  return(FALSE);
410
413
}
411
414
 
412
415
 
419
422
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
420
423
{
421
424
  handler *file= (handler*)arg;
422
 
  return file->cmp_ref((const unsigned char*)a, (const unsigned char*)b);
 
425
  return file->cmp_ref((const uchar*)a, (const uchar*)b);
423
426
}
424
427
 
425
428
/*
430
433
    thd         thread handler
431
434
 
432
435
  RETURN
433
 
    false OK
434
 
    true  Error
 
436
    FALSE OK
 
437
    TRUE  Error
435
438
*/
436
439
 
437
440
int mysql_multi_delete_prepare(THD *thd)
438
441
{
439
442
  LEX *lex= thd->lex;
440
 
  TableList *aux_tables= (TableList *)lex->auxiliary_table_list.first;
441
 
  TableList *target_tbl;
 
443
  TABLE_LIST *aux_tables= (TABLE_LIST *)lex->auxiliary_table_list.first;
 
444
  TABLE_LIST *target_tbl;
442
445
  
443
446
 
444
447
  /*
451
454
                                    &thd->lex->select_lex.top_join_list,
452
455
                                    lex->query_tables,
453
456
                                    &lex->select_lex.leaf_tables, false))
454
 
    return(true);
 
457
    return(TRUE);
455
458
 
456
459
 
457
460
  /*
458
461
    Multi-delete can't be constructed over-union => we always have
459
462
    single SELECT on top and have to check underlying SELECTs of it
460
463
  */
461
 
  lex->select_lex.exclude_from_table_unique_test= true;
 
464
  lex->select_lex.exclude_from_table_unique_test= TRUE;
462
465
  /* Fix tables-to-be-deleted-from list to point at opened tables */
463
 
  for (target_tbl= (TableList*) aux_tables;
 
466
  for (target_tbl= (TABLE_LIST*) aux_tables;
464
467
       target_tbl;
465
468
       target_tbl= target_tbl->next_local)
466
469
  {
470
473
                  target_tbl->correspondent_table->merge_underlying_list->
471
474
                  next_local);
472
475
      my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), "", "");
473
 
      return(true);
 
476
      return(TRUE);
474
477
    }
475
478
 
476
479
    /*
478
481
      inside subqueries/view.
479
482
    */
480
483
    {
481
 
      TableList *duplicate;
 
484
      TABLE_LIST *duplicate;
482
485
      if ((duplicate= unique_table(thd, target_tbl->correspondent_table,
483
486
                                   lex->query_tables, 0)))
484
487
      {
485
488
        update_non_unique_table_error(target_tbl->correspondent_table,
486
489
                                      "DELETE", duplicate);
487
 
        return(true);
 
490
        return(TRUE);
488
491
      }
489
492
    }
490
493
  }
491
 
  return(false);
 
494
  return(FALSE);
492
495
}
493
496
 
494
497
 
495
 
multi_delete::multi_delete(TableList *dt, uint32_t num_of_tables_arg)
 
498
multi_delete::multi_delete(TABLE_LIST *dt, uint num_of_tables_arg)
496
499
  : delete_tables(dt), deleted(0), found(0),
497
500
    num_of_tables(num_of_tables_arg), error(0),
498
501
    do_delete(0), transactional_tables(0), normal_tables(0), error_handled(0)
502
505
 
503
506
 
504
507
int
505
 
multi_delete::prepare(List<Item> &values __attribute__((unused)),
506
 
                      SELECT_LEX_UNIT *u)
 
508
multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
507
509
{
508
510
  
509
511
  unit= u;
510
512
  do_delete= 1;
511
 
  thd->set_proc_info("deleting from main table");
 
513
  thd_proc_info(thd, "deleting from main table");
512
514
  return(0);
513
515
}
514
516
 
516
518
bool
517
519
multi_delete::initialize_tables(JOIN *join)
518
520
{
519
 
  TableList *walk;
 
521
  TABLE_LIST *walk;
520
522
  Unique **tempfiles_ptr;
521
523
  
522
524
 
536
538
    if (tab->table->map & tables_to_delete_from)
537
539
    {
538
540
      /* We are going to delete from this table */
539
 
      Table *tbl=walk->table=tab->table;
 
541
      TABLE *tbl=walk->table=tab->table;
540
542
      walk= walk->next_local;
541
543
      /* Don't use KEYREAD optimization on this table */
542
544
      tbl->no_keyread=1;
570
572
  }
571
573
  for (;walk ;walk= walk->next_local)
572
574
  {
573
 
    Table *table=walk->table;
 
575
    TABLE *table=walk->table;
574
576
    *tempfiles_ptr++= new Unique (refpos_order_cmp,
575
577
                                  (void *) table->file,
576
578
                                  table->file->ref_length,
586
588
       table_being_deleted;
587
589
       table_being_deleted= table_being_deleted->next_local)
588
590
  {
589
 
    Table *table= table_being_deleted->table;
 
591
    TABLE *table= table_being_deleted->table;
590
592
    table->no_keyread=0;
591
593
  }
592
594
 
593
 
  for (uint32_t counter= 0; counter < num_of_tables; counter++)
 
595
  for (uint counter= 0; counter < num_of_tables; counter++)
594
596
  {
595
597
    if (tempfiles[counter])
596
598
      delete tempfiles[counter];
598
600
}
599
601
 
600
602
 
601
 
bool multi_delete::send_data(List<Item> &values __attribute__((unused)))
 
603
bool multi_delete::send_data(List<Item> &values)
602
604
{
603
605
  int secure_counter= delete_while_scanning ? -1 : 0;
604
 
  TableList *del_table;
 
606
  TABLE_LIST *del_table;
605
607
  
606
608
 
607
609
  for (del_table= delete_tables;
608
610
       del_table;
609
611
       del_table= del_table->next_local, secure_counter++)
610
612
  {
611
 
    Table *table= del_table->table;
 
613
    TABLE *table= del_table->table;
612
614
 
613
615
    /* Check if we are using outer join and we didn't find the row */
614
616
    if (table->status & (STATUS_NULL_ROW | STATUS_DELETED))
626
628
      {
627
629
        deleted++;
628
630
        if (!table->file->has_transactions())
629
 
          thd->transaction.stmt.modified_non_trans_table= true;
 
631
          thd->transaction.stmt.modified_non_trans_table= TRUE;
630
632
      }
631
633
      else
632
634
      {
648
650
}
649
651
 
650
652
 
651
 
void multi_delete::send_error(uint32_t errcode,const char *err)
 
653
void multi_delete::send_error(uint errcode,const char *err)
652
654
{
653
655
  
654
656
 
697
699
    {
698
700
      thd->binlog_query(THD::ROW_QUERY_TYPE,
699
701
                        thd->query, thd->query_length,
700
 
                        transactional_tables, false);
 
702
                        transactional_tables, FALSE);
701
703
    }
702
704
    thd->transaction.all.modified_non_trans_table= true;
703
705
  }
731
733
       table_being_deleted= table_being_deleted->next_local, counter++)
732
734
  { 
733
735
    ha_rows last_deleted= deleted;
734
 
    Table *table = table_being_deleted->table;
 
736
    TABLE *table = table_being_deleted->table;
735
737
    if (tempfiles[counter]->get(table))
736
738
    {
737
739
      local_error=1;
764
766
      }
765
767
    }
766
768
    if (last_deleted != deleted && !table->file->has_transactions())
767
 
      thd->transaction.stmt.modified_non_trans_table= true;
 
769
      thd->transaction.stmt.modified_non_trans_table= TRUE;
768
770
    end_read_record(&info);
769
771
    if (thd->killed && !local_error)
770
772
      local_error= 1;
785
787
bool multi_delete::send_eof()
786
788
{
787
789
  THD::killed_state killed_status= THD::NOT_KILLED;
788
 
  thd->set_proc_info("deleting from reference tables");
 
790
  thd_proc_info(thd, "deleting from reference tables");
789
791
 
790
792
  /* Does deletes for the last n - 1 tables, returns 0 if ok */
791
793
  int local_error= do_deletes();                // returns 0 if success
794
796
  local_error= local_error || error;
795
797
  killed_status= (local_error == 0)? THD::NOT_KILLED : thd->killed;
796
798
  /* reset used flags */
797
 
  thd->set_proc_info("end");
 
799
  thd_proc_info(thd, "end");
798
800
 
799
801
  if ((local_error == 0) || thd->transaction.stmt.modified_non_trans_table)
800
802
  {
804
806
        thd->clear_error();
805
807
      if (thd->binlog_query(THD::ROW_QUERY_TYPE,
806
808
                            thd->query, thd->query_length,
807
 
                            transactional_tables, false, killed_status) &&
 
809
                            transactional_tables, FALSE, killed_status) &&
808
810
          !normal_tables)
809
811
      {
810
812
        local_error=1;  // Log write failed: roll back the SQL statement
811
813
      }
812
814
    }
813
815
    if (thd->transaction.stmt.modified_non_trans_table)
814
 
      thd->transaction.all.modified_non_trans_table= true;
 
816
      thd->transaction.all.modified_non_trans_table= TRUE;
815
817
  }
816
818
  if (local_error != 0)
817
 
    error_handled= true; // to force early leave from ::send_error()
 
819
    error_handled= TRUE; // to force early leave from ::send_error()
818
820
 
819
821
  if (!local_error)
820
822
  {
826
828
 
827
829
 
828
830
/***************************************************************************
829
 
  TRUNCATE Table
 
831
  TRUNCATE TABLE
830
832
****************************************************************************/
831
833
 
832
834
/*
841
843
  - If we want to have a name lock on the table on exit without errors.
842
844
*/
843
845
 
844
 
bool mysql_truncate(THD *thd, TableList *table_list, bool dont_send_ok)
 
846
bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
845
847
{
846
848
  HA_CREATE_INFO create_info;
847
849
  char path[FN_REFLEN];
848
 
  Table *table;
 
850
  TABLE *table;
849
851
  bool error;
850
 
  uint32_t path_length;
 
852
  uint path_length;
851
853
  
852
854
 
853
 
  memset(&create_info, 0, sizeof(create_info));
 
855
  bzero((char*) &create_info,sizeof(create_info));
854
856
  /* If it is a temporary table, close and regenerate it */
855
857
  if (!dont_send_ok && (table= find_temporary_table(thd, table_list)))
856
858
  {
873
875
                                             OTM_OPEN))))
874
876
      (void) rm_temporary_table(table_type, path, frm_only);
875
877
    free_table_share(share);
876
 
    free((char*) table);
 
878
    my_free((char*) table,MYF(0));
877
879
    /*
878
880
      If we return here we will not have logged the truncation to the bin log
879
881
      and we will not my_ok() to the client.
885
887
                                    table_list->table_name, reg_ext, 0);
886
888
 
887
889
  if (!dont_send_ok)
888
 
    goto trunc_by_del;
 
890
  {
 
891
    enum legacy_db_type table_type;
 
892
    mysql_frm_type(thd, path, &table_type);
 
893
    if (table_type == DB_TYPE_UNKNOWN)
 
894
    {
 
895
      my_error(ER_NO_SUCH_TABLE, MYF(0),
 
896
               table_list->db, table_list->table_name);
 
897
      return(TRUE);
 
898
    }
 
899
 
 
900
    if (!ha_check_storage_engine_flag(ha_resolve_by_legacy_type(thd, table_type),
 
901
                                      HTON_CAN_RECREATE))
 
902
      goto trunc_by_del;
 
903
 
 
904
    if (lock_and_wait_for_table_name(thd, table_list))
 
905
      return(TRUE);
 
906
  }
889
907
 
890
908
  // Remove the .frm extension AIX 5.2 64-bit compiler bug (BUG#16155): this
891
909
  // crashes, replacement works.  *(path + path_length - reg_ext_length)=
892
910
  // '\0';
893
911
  path[path_length - reg_ext_length] = 0;
894
 
  pthread_mutex_lock(&LOCK_open);
 
912
  VOID(pthread_mutex_lock(&LOCK_open));
895
913
  error= ha_create_table(thd, path, table_list->db, table_list->table_name,
896
914
                         &create_info, 1);
897
 
  pthread_mutex_unlock(&LOCK_open);
 
915
  VOID(pthread_mutex_unlock(&LOCK_open));
898
916
 
899
917
end:
900
918
  if (!dont_send_ok)
905
923
        TRUNCATE must always be statement-based binlogged (not row-based) so
906
924
        we don't test current_stmt_binlog_row_based.
907
925
      */
908
 
      write_bin_log(thd, true, thd->query, thd->query_length);
 
926
      write_bin_log(thd, TRUE, thd->query, thd->query_length);
909
927
      my_ok(thd);               // This should return record count
910
928
    }
911
 
    pthread_mutex_lock(&LOCK_open);
 
929
    VOID(pthread_mutex_lock(&LOCK_open));
912
930
    unlock_table_name(thd, table_list);
913
 
    pthread_mutex_unlock(&LOCK_open);
 
931
    VOID(pthread_mutex_unlock(&LOCK_open));
914
932
  }
915
933
  else if (error)
916
934
  {
917
 
    pthread_mutex_lock(&LOCK_open);
 
935
    VOID(pthread_mutex_lock(&LOCK_open));
918
936
    unlock_table_name(thd, table_list);
919
 
    pthread_mutex_unlock(&LOCK_open);
 
937
    VOID(pthread_mutex_unlock(&LOCK_open));
920
938
  }
921
939
  return(error);
922
940
 
923
941
trunc_by_del:
924
942
  /* Probably InnoDB table */
925
 
  uint64_t save_options= thd->options;
 
943
  ulonglong save_options= thd->options;
926
944
  table_list->lock_type= TL_WRITE;
927
945
  thd->options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
928
 
  ha_enable_transaction(thd, false);
 
946
  ha_enable_transaction(thd, FALSE);
929
947
  mysql_init_select(thd->lex);
930
948
  bool save_binlog_row_based= thd->current_stmt_binlog_row_based;
931
949
  thd->clear_current_stmt_binlog_row_based();
932
950
  error= mysql_delete(thd, table_list, (COND*) 0, (SQL_LIST*) 0,
933
 
                      HA_POS_ERROR, 0L, true);
934
 
  ha_enable_transaction(thd, true);
 
951
                      HA_POS_ERROR, 0LL, TRUE);
 
952
  ha_enable_transaction(thd, TRUE);
935
953
  /*
936
 
    Safety, in case the engine ignored ha_enable_transaction(false)
 
954
    Safety, in case the engine ignored ha_enable_transaction(FALSE)
937
955
    above. Also clears thd->transaction.*.
938
956
  */
939
957
  error= ha_autocommit_or_rollback(thd, error);