~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_delete.cc

  • Committer: Eric Day
  • Date: 2009-08-27 07:26:22 UTC
  • mto: This revision was merged to the branch mainline in revision 1131.
  • Revision ID: eday@oddments.org-20090827072622-72te13ua0wdlc2ky
Reworked listen interface to not require binding of TCP ports.

Show diffs side-by-side

added added

removed removed

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