~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_delete.cc

Small fixes

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
#include <drizzled/sql_parse.h>
26
26
#include <drizzled/sql_base.h>
27
27
#include <drizzled/lock.h>
 
28
#include "drizzled/probes.h"
 
29
 
 
30
using namespace drizzled;
28
31
 
29
32
/**
30
33
  Implement DELETE SQL word.
48
51
  bool          const_cond_result;
49
52
  ha_rows       deleted= 0;
50
53
  uint32_t usable_index= MAX_KEY;
51
 
  SELECT_LEX   *select_lex= &session->lex->select_lex;
 
54
  Select_Lex   *select_lex= &session->lex->select_lex;
52
55
  Session::killed_state killed_status= Session::NOT_KILLED;
53
56
 
54
 
 
55
 
  if (open_and_lock_tables(session, table_list))
56
 
    return(true);
 
57
  if (session->openTablesLock(table_list))
 
58
  {
 
59
    DRIZZLE_DELETE_DONE(1, 0);
 
60
    return true;
 
61
  }
57
62
 
58
63
  table= table_list->table;
59
64
  assert(table);
152
157
  /* Update the table->file->stats.records number */
153
158
  table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
154
159
 
155
 
  table->covering_keys.clear_all();
156
 
  table->quick_keys.clear_all();                // Can't use 'only index'
 
160
  table->covering_keys.reset();
 
161
  table->quick_keys.reset();            // Can't use 'only index'
157
162
  select=make_select(table, 0, 0, conds, 0, &error);
158
163
  if (error)
159
164
    goto err;
162
167
    delete select;
163
168
    free_underlaid_joins(session, select_lex);
164
169
    session->row_count_func= 0;
165
 
    DRIZZLE_DELETE_END();
166
 
    my_ok(session, (ha_rows) session->row_count_func);
 
170
    DRIZZLE_DELETE_DONE(0, 0);
 
171
    /**
 
172
     * Resetting the Diagnostic area to prevent
 
173
     * lp bug# 439719
 
174
     */
 
175
    session->main_da.reset_diagnostics_area();
 
176
    session->my_ok((ha_rows) session->row_count_func);
167
177
    /*
168
178
      We don't need to call reset_auto_increment in this case, because
169
179
      mysql_truncate always gives a NULL conds argument, hence we never
170
180
      get here.
171
181
    */
172
 
    return(0);                          // Nothing to delete
 
182
    return 0; // Nothing to delete
173
183
  }
174
184
 
175
185
  /* If running in safe sql mode, don't allow updates without keys */
176
 
  if (table->quick_keys.is_clear_all())
 
186
  if (table->quick_keys.none())
177
187
  {
178
188
    session->server_status|=SERVER_QUERY_NO_INDEX_USED;
179
189
    if (safe_update && !using_limit)
194
204
    SORT_FIELD  *sortorder;
195
205
    ha_rows examined_rows;
196
206
 
197
 
    if ((!select || table->quick_keys.is_clear_all()) && limit != HA_POS_ERROR)
 
207
    if ((!select || table->quick_keys.none()) && limit != HA_POS_ERROR)
198
208
      usable_index= get_index_for_order(table, (order_st*)(order->first), limit);
199
209
 
200
210
    if (usable_index == MAX_KEY)
322
332
  assert(transactional_table || !deleted || session->transaction.stmt.modified_non_trans_table);
323
333
  free_underlaid_joins(session, select_lex);
324
334
 
325
 
  DRIZZLE_DELETE_END();
 
335
  DRIZZLE_DELETE_DONE((error >= 0 || session->is_error()), deleted);
326
336
  if (error < 0 || (session->lex->ignore && !session->is_fatal_error))
327
337
  {
328
338
    session->row_count_func= deleted;
329
 
    my_ok(session, (ha_rows) session->row_count_func);
 
339
    /**
 
340
     * Resetting the Diagnostic area to prevent
 
341
     * lp bug# 439719
 
342
     */
 
343
    session->main_da.reset_diagnostics_area();    
 
344
    session->my_ok((ha_rows) session->row_count_func);
330
345
  }
331
 
  return(error >= 0 || session->is_error());
 
346
  return (error >= 0 || session->is_error());
332
347
 
333
348
err:
334
 
  DRIZZLE_DELETE_END();
335
 
  return(true);
 
349
  DRIZZLE_DELETE_DONE(1, 0);
 
350
  return true;
336
351
}
337
352
 
338
353
 
351
366
*/
352
367
int mysql_prepare_delete(Session *session, TableList *table_list, Item **conds)
353
368
{
354
 
  SELECT_LEX *select_lex= &session->lex->select_lex;
 
369
  Select_Lex *select_lex= &session->lex->select_lex;
355
370
 
356
371
  List<Item> all_fields;
357
372
 
360
375
                                    &session->lex->select_lex.top_join_list,
361
376
                                    table_list,
362
377
                                    &select_lex->leaf_tables, false) ||
363
 
      setup_conds(session, table_list, select_lex->leaf_tables, conds))
 
378
      session->setup_conds(table_list, conds))
364
379
    return(true);
365
380
  {
366
381
    TableList *duplicate;
367
382
    if ((duplicate= unique_table(session, table_list, table_list->next_global, 0)))
368
383
    {
369
 
      update_non_unique_table_error(table_list, "DELETE", duplicate);
 
384
      my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->alias);
370
385
      return(true);
371
386
    }
372
387
  }
380
395
 
381
396
 
382
397
/***************************************************************************
383
 
  Delete multiple tables from join
384
 
***************************************************************************/
385
 
 
386
 
#define MEM_STRIP_BUF_SIZE current_session->variables.sortbuff_size
387
 
 
388
 
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
389
 
{
390
 
  handler *file= (handler*)arg;
391
 
  return file->cmp_ref((const unsigned char*)a, (const unsigned char*)b);
392
 
}
393
 
 
394
 
/*
395
 
  make delete specific preparation and checks after opening tables
396
 
 
397
 
  SYNOPSIS
398
 
    mysql_multi_delete_prepare()
399
 
    session         thread handler
400
 
 
401
 
  RETURN
402
 
    false OK
403
 
    true  Error
404
 
*/
405
 
 
406
 
int mysql_multi_delete_prepare(Session *session)
407
 
{
408
 
  LEX *lex= session->lex;
409
 
  TableList *aux_tables= (TableList *)lex->auxiliary_table_list.first;
410
 
  TableList *target_tbl;
411
 
 
412
 
 
413
 
  /*
414
 
    setup_tables() need for VIEWs. JOIN::prepare() will not do it second
415
 
    time.
416
 
 
417
 
    lex->query_tables also point on local list of DELETE SELECT_LEX
418
 
  */
419
 
  if (setup_tables_and_check_access(session, &session->lex->select_lex.context,
420
 
                                    &session->lex->select_lex.top_join_list,
421
 
                                    lex->query_tables,
422
 
                                    &lex->select_lex.leaf_tables, false))
423
 
    return(true);
424
 
 
425
 
 
426
 
  /*
427
 
    Multi-delete can't be constructed over-union => we always have
428
 
    single SELECT on top and have to check underlying SELECTs of it
429
 
  */
430
 
  lex->select_lex.exclude_from_table_unique_test= true;
431
 
  /* Fix tables-to-be-deleted-from list to point at opened tables */
432
 
  for (target_tbl= (TableList*) aux_tables;
433
 
       target_tbl;
434
 
       target_tbl= target_tbl->next_local)
435
 
  {
436
 
    target_tbl->table= target_tbl->correspondent_table->table;
437
 
    assert(target_tbl->table);
438
 
 
439
 
    /*
440
 
      Check that table from which we delete is not used somewhere
441
 
      inside subqueries/view.
442
 
    */
443
 
    {
444
 
      TableList *duplicate;
445
 
      if ((duplicate= unique_table(session, target_tbl->correspondent_table,
446
 
                                   lex->query_tables, 0)))
447
 
      {
448
 
        update_non_unique_table_error(target_tbl->correspondent_table,
449
 
                                      "DELETE", duplicate);
450
 
        return(true);
451
 
      }
452
 
    }
453
 
  }
454
 
  return(false);
455
 
}
456
 
 
457
 
 
458
 
multi_delete::multi_delete(TableList *dt, uint32_t num_of_tables_arg)
459
 
  : delete_tables(dt), deleted(0), found(0),
460
 
    num_of_tables(num_of_tables_arg), error(0),
461
 
    do_delete(0), transactional_tables(0), normal_tables(0), error_handled(0)
462
 
{
463
 
  tempfiles= (Unique **) sql_calloc(sizeof(Unique *) * num_of_tables);
464
 
}
465
 
 
466
 
 
467
 
int
468
 
multi_delete::prepare(List<Item> &, SELECT_LEX_UNIT *u)
469
 
{
470
 
 
471
 
  unit= u;
472
 
  do_delete= 1;
473
 
  session->set_proc_info("deleting from main table");
474
 
  return(0);
475
 
}
476
 
 
477
 
 
478
 
bool
479
 
multi_delete::initialize_tables(JOIN *join)
480
 
{
481
 
  TableList *walk;
482
 
  Unique **tempfiles_ptr;
483
 
 
484
 
 
485
 
  if ((session->options & OPTION_SAFE_UPDATES) && error_if_full_join(join))
486
 
    return(1);
487
 
 
488
 
  table_map tables_to_delete_from=0;
489
 
  for (walk= delete_tables; walk; walk= walk->next_local)
490
 
    tables_to_delete_from|= walk->table->map;
491
 
 
492
 
  walk= delete_tables;
493
 
  delete_while_scanning= 1;
494
 
  for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
495
 
       tab < end;
496
 
       tab++)
497
 
  {
498
 
    if (tab->table->map & tables_to_delete_from)
499
 
    {
500
 
      /* We are going to delete from this table */
501
 
      Table *tbl=walk->table=tab->table;
502
 
      walk= walk->next_local;
503
 
      /* Don't use KEYREAD optimization on this table */
504
 
      tbl->no_keyread=1;
505
 
      /* Don't use record cache */
506
 
      tbl->no_cache= 1;
507
 
      tbl->covering_keys.clear_all();
508
 
      if (tbl->file->has_transactions())
509
 
        transactional_tables= 1;
510
 
      else
511
 
        normal_tables= 1;
512
 
      tbl->prepare_for_position();
513
 
      tbl->mark_columns_needed_for_delete();
514
 
    }
515
 
    else if ((tab->type != JT_SYSTEM && tab->type != JT_CONST) &&
516
 
             walk == delete_tables)
517
 
    {
518
 
      /*
519
 
        We are not deleting from the table we are scanning. In this
520
 
        case send_data() shouldn't delete any rows a we may touch
521
 
        the rows in the deleted table many times
522
 
      */
523
 
      delete_while_scanning= 0;
524
 
    }
525
 
  }
526
 
  walk= delete_tables;
527
 
  tempfiles_ptr= tempfiles;
528
 
  if (delete_while_scanning)
529
 
  {
530
 
    table_being_deleted= delete_tables;
531
 
    walk= walk->next_local;
532
 
  }
533
 
  for (;walk ;walk= walk->next_local)
534
 
  {
535
 
    Table *table=walk->table;
536
 
    *tempfiles_ptr++= new Unique (refpos_order_cmp,
537
 
                                  (void *) table->file,
538
 
                                  table->file->ref_length,
539
 
                                  MEM_STRIP_BUF_SIZE);
540
 
  }
541
 
  return(session->is_fatal_error != 0);
542
 
}
543
 
 
544
 
 
545
 
multi_delete::~multi_delete()
546
 
{
547
 
  for (table_being_deleted= delete_tables;
548
 
       table_being_deleted;
549
 
       table_being_deleted= table_being_deleted->next_local)
550
 
  {
551
 
    Table *table= table_being_deleted->table;
552
 
    table->no_keyread=0;
553
 
  }
554
 
 
555
 
  for (uint32_t counter= 0; counter < num_of_tables; counter++)
556
 
  {
557
 
    if (tempfiles[counter])
558
 
      delete tempfiles[counter];
559
 
  }
560
 
}
561
 
 
562
 
 
563
 
bool multi_delete::send_data(List<Item> &)
564
 
{
565
 
  int secure_counter= delete_while_scanning ? -1 : 0;
566
 
  TableList *del_table;
567
 
 
568
 
 
569
 
  for (del_table= delete_tables;
570
 
       del_table;
571
 
       del_table= del_table->next_local, secure_counter++)
572
 
  {
573
 
    Table *table= del_table->table;
574
 
 
575
 
    /* Check if we are using outer join and we didn't find the row */
576
 
    if (table->status & (STATUS_NULL_ROW | STATUS_DELETED))
577
 
      continue;
578
 
 
579
 
    table->file->position(table->record[0]);
580
 
    found++;
581
 
 
582
 
    if (secure_counter < 0)
583
 
    {
584
 
      /* We are scanning the current table */
585
 
      assert(del_table == table_being_deleted);
586
 
      table->status|= STATUS_DELETED;
587
 
      if (!(error=table->file->ha_delete_row(table->record[0])))
588
 
      {
589
 
        deleted++;
590
 
        if (!table->file->has_transactions())
591
 
          session->transaction.stmt.modified_non_trans_table= true;
592
 
      }
593
 
      else
594
 
      {
595
 
        table->file->print_error(error,MYF(0));
596
 
        return(1);
597
 
      }
598
 
    }
599
 
    else
600
 
    {
601
 
      error=tempfiles[secure_counter]->unique_add((char*) table->file->ref);
602
 
      if (error)
603
 
      {
604
 
        error= 1;                               // Fatal error
605
 
        return(1);
606
 
      }
607
 
    }
608
 
  }
609
 
  return(0);
610
 
}
611
 
 
612
 
 
613
 
void multi_delete::send_error(uint32_t errcode,const char *err)
614
 
{
615
 
 
616
 
 
617
 
  /* First send error what ever it is ... */
618
 
  my_message(errcode, err, MYF(0));
619
 
 
620
 
  return;
621
 
}
622
 
 
623
 
 
624
 
void multi_delete::abort()
625
 
{
626
 
 
627
 
 
628
 
  /* the error was handled or nothing deleted and no side effects return */
629
 
  if (error_handled ||
630
 
      (!session->transaction.stmt.modified_non_trans_table && !deleted))
631
 
    return;
632
 
 
633
 
  /*
634
 
    If rows from the first table only has been deleted and it is
635
 
    transactional, just do rollback.
636
 
    The same if all tables are transactional, regardless of where we are.
637
 
    In all other cases do attempt deletes ...
638
 
  */
639
 
  if (do_delete && normal_tables &&
640
 
      (table_being_deleted != delete_tables ||
641
 
       !table_being_deleted->table->file->has_transactions()))
642
 
  {
643
 
    /*
644
 
      We have to execute the recorded do_deletes() and write info into the
645
 
      error log
646
 
    */
647
 
    error= 1;
648
 
    send_eof();
649
 
    assert(error_handled);
650
 
    return;
651
 
  }
652
 
 
653
 
  if (session->transaction.stmt.modified_non_trans_table)
654
 
  {
655
 
    session->transaction.all.modified_non_trans_table= true;
656
 
  }
657
 
  return;
658
 
}
659
 
 
660
 
 
661
 
 
662
 
/*
663
 
  Do delete from other tables.
664
 
  Returns values:
665
 
        0 ok
666
 
        1 error
667
 
*/
668
 
 
669
 
int multi_delete::do_deletes()
670
 
{
671
 
  int local_error= 0, counter= 0, tmp_error;
672
 
  bool will_batch;
673
 
 
674
 
  assert(do_delete);
675
 
 
676
 
  do_delete= 0;                                 // Mark called
677
 
  if (!found)
678
 
    return(0);
679
 
 
680
 
  table_being_deleted= (delete_while_scanning ? delete_tables->next_local :
681
 
                        delete_tables);
682
 
 
683
 
  for (; table_being_deleted;
684
 
       table_being_deleted= table_being_deleted->next_local, counter++)
685
 
  {
686
 
    ha_rows last_deleted= deleted;
687
 
    Table *table = table_being_deleted->table;
688
 
    if (tempfiles[counter]->get(table))
689
 
    {
690
 
      local_error=1;
691
 
      break;
692
 
    }
693
 
 
694
 
    READ_RECORD info;
695
 
    init_read_record(&info,session,table,NULL,0,1);
696
 
    /*
697
 
      Ignore any rows not found in reference tables as they may already have
698
 
      been deleted by foreign key handling
699
 
    */
700
 
    info.ignore_not_found_rows= 1;
701
 
    will_batch= !table->file->start_bulk_delete();
702
 
    while (!(local_error=info.read_record(&info)) && !session->killed)
703
 
    {
704
 
      if ((local_error=table->file->ha_delete_row(table->record[0])))
705
 
      {
706
 
        table->file->print_error(local_error,MYF(0));
707
 
        break;
708
 
      }
709
 
      deleted++;
710
 
    }
711
 
    if (will_batch && (tmp_error= table->file->end_bulk_delete()))
712
 
    {
713
 
      if (!local_error)
714
 
      {
715
 
        local_error= tmp_error;
716
 
        table->file->print_error(local_error,MYF(0));
717
 
      }
718
 
    }
719
 
    if (last_deleted != deleted && !table->file->has_transactions())
720
 
      session->transaction.stmt.modified_non_trans_table= true;
721
 
    end_read_record(&info);
722
 
    if (session->killed && !local_error)
723
 
      local_error= 1;
724
 
    if (local_error == -1)                              // End of file
725
 
      local_error = 0;
726
 
  }
727
 
  return(local_error);
728
 
}
729
 
 
730
 
 
731
 
/*
732
 
  Send ok to the client
733
 
 
734
 
  return:  0 sucess
735
 
           1 error
736
 
*/
737
 
 
738
 
bool multi_delete::send_eof()
739
 
{
740
 
  Session::killed_state killed_status= Session::NOT_KILLED;
741
 
  session->set_proc_info("deleting from reference tables");
742
 
 
743
 
  /* Does deletes for the last n - 1 tables, returns 0 if ok */
744
 
  int local_error= do_deletes();                // returns 0 if success
745
 
 
746
 
  /* compute a total error to know if something failed */
747
 
  local_error= local_error || error;
748
 
  killed_status= (local_error == 0)? Session::NOT_KILLED : session->killed;
749
 
  /* reset used flags */
750
 
  session->set_proc_info("end");
751
 
 
752
 
  if ((local_error == 0) || session->transaction.stmt.modified_non_trans_table)
753
 
  {
754
 
    if (session->transaction.stmt.modified_non_trans_table)
755
 
      session->transaction.all.modified_non_trans_table= true;
756
 
  }
757
 
  if (local_error != 0)
758
 
    error_handled= true; // to force early leave from ::send_error()
759
 
 
760
 
  if (!local_error)
761
 
  {
762
 
    session->row_count_func= deleted;
763
 
    ::my_ok(session, (ha_rows) session->row_count_func);
764
 
  }
765
 
  return 0;
766
 
}
767
 
 
768
 
 
769
 
/***************************************************************************
770
398
  TRUNCATE Table
771
399
****************************************************************************/
772
400
 
793
421
 
794
422
  memset(&create_info, 0, sizeof(create_info));
795
423
  /* If it is a temporary table, close and regenerate it */
796
 
  if (!dont_send_ok && (table= find_temporary_table(session, table_list)))
 
424
  if (!dont_send_ok && (table= session->find_temporary_table(table_list)))
797
425
  {
798
 
    handlerton *table_type= table->s->db_type();
799
 
    TABLE_SHARE *share= table->s;
 
426
    plugin::StorageEngine *table_type= table->s->db_type();
 
427
    TableShare *share= table->s;
800
428
 
801
 
    if (!ha_check_storage_engine_flag(table_type, HTON_BIT_CAN_RECREATE))
 
429
    if (!table_type->check_flag(HTON_BIT_CAN_RECREATE))
802
430
      goto trunc_by_del;
803
431
 
804
432
    table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
805
433
 
806
 
    close_temporary_table(session, table, 0, 0);    // Don't free share
807
 
    ha_create_table(session, share->normalized_path.str,
808
 
                    share->db.str, share->table_name.str, &create_info, 1);
 
434
    session->close_temporary_table(table, false, false);    // Don't free share
 
435
    plugin::StorageEngine::createTable(session, share->normalized_path.str,
 
436
                                       share->db.str, share->table_name.str,
 
437
                                       &create_info, true, NULL);
809
438
    // We don't need to call invalidate() because this table is not in cache
810
 
    if ((error= (int) !(open_temporary_table(session, share->path.str,
811
 
                                             share->db.str,
812
 
                                             share->table_name.str, 1,
813
 
                                             OTM_OPEN))))
814
 
      (void) rm_temporary_table(table_type, path);
815
 
    free_table_share(share);
 
439
    if ((error= (int) !(session->open_temporary_table(share->path.str,
 
440
                                                      share->db.str,
 
441
                                                      share->table_name.str, 1,
 
442
                                                      OTM_OPEN))))
 
443
      (void) session->rm_temporary_table(table_type, path);
 
444
    share->free_table_share();
816
445
    free((char*) table);
817
446
    /*
818
447
      If we return here we will not have logged the truncation to the bin log
822
451
  }
823
452
 
824
453
  path_length= build_table_filename(path, sizeof(path), table_list->db,
825
 
                                    table_list->table_name, reg_ext, 0);
 
454
                                    table_list->table_name, 0);
826
455
 
827
456
  if (!dont_send_ok)
828
457
    goto trunc_by_del;
829
458
 
830
 
  // Remove the .frm extension AIX 5.2 64-bit compiler bug (BUG#16155): this
831
 
  // crashes, replacement works.  *(path + path_length - reg_ext_length)=
832
 
  // '\0';
833
 
  path[path_length - reg_ext_length] = 0;
834
 
  pthread_mutex_lock(&LOCK_open);
835
 
  error= ha_create_table(session, path, table_list->db, table_list->table_name,
836
 
                         &create_info, 1);
 
459
  pthread_mutex_lock(&LOCK_open); /* Recreate table for truncate */
 
460
  error= plugin::StorageEngine::createTable(session, path, table_list->db,
 
461
                                            table_list->table_name,
 
462
                                            &create_info, true, NULL);
837
463
  pthread_mutex_unlock(&LOCK_open);
838
464
 
839
465
end:
845
471
        TRUNCATE must always be statement-based binlogged (not row-based) so
846
472
        we don't test current_stmt_binlog_row_based.
847
473
      */
848
 
      write_bin_log(session, true, session->query, session->query_length);
849
 
      my_ok(session);           // This should return record count
 
474
      write_bin_log(session, session->query, session->query_length);
 
475
      session->my_ok();         // This should return record count
850
476
    }
851
 
    pthread_mutex_lock(&LOCK_open);
852
 
    unlock_table_name(session, table_list);
 
477
    pthread_mutex_lock(&LOCK_open); /* For truncate delete from hash when finished */
 
478
    unlock_table_name(table_list);
853
479
    pthread_mutex_unlock(&LOCK_open);
854
480
  }
855
481
  else if (error)
856
482
  {
857
 
    pthread_mutex_lock(&LOCK_open);
858
 
    unlock_table_name(session, table_list);
 
483
    pthread_mutex_lock(&LOCK_open); /* For truncate delete from hash when finished */
 
484
    unlock_table_name(table_list);
859
485
    pthread_mutex_unlock(&LOCK_open);
860
486
  }
861
487
  return(error);