~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_delete.cc

  • Committer: Monty Taylor
  • Date: 2009-12-22 20:47:20 UTC
  • mto: This revision was merged to the branch mainline in revision 1253.
  • Revision ID: mordred@inaugust.com-20091222204720-7ynx08xryaihgj8h
Removed one more public IO_CACHE.

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