~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_delete.cc

  • Committer: Andy Lester
  • Date: 2008-08-10 02:15:48 UTC
  • mto: (266.1.31 use-replace-funcs)
  • mto: This revision was merged to the branch mainline in revision 295.
  • Revision ID: andy@petdance.com-20080810021548-0zx8nhzva6al10k3
Added a proper const qualifer.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
/*
17
17
  Delete of records and truncate of tables.
18
18
 
19
19
  Multi-table deletes were introduced by Monty and Sinisa
20
20
*/
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
 
#include "drizzled/internal/iocache.h"
32
 
#include "drizzled/transaction_services.h"
33
 
#include "drizzled/filesort.h"
34
 
 
35
 
namespace drizzled
36
 
{
 
21
#include <drizzled/server_includes.h>
 
22
#include <drizzled/sql_select.h>
 
23
#include <drizzled/drizzled_error_messages.h>
37
24
 
38
25
/**
39
26
  Implement DELETE SQL word.
43
30
  end of dispatch_command().
44
31
*/
45
32
 
46
 
bool delete_query(Session *session, TableList *table_list, COND *conds,
47
 
                  SQL_LIST *order, ha_rows limit, uint64_t,
 
33
bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
 
34
                  SQL_LIST *order, ha_rows limit, uint64_t options,
48
35
                  bool reset_auto_increment)
49
36
{
50
 
  int           error;
51
 
  Table         *table;
52
 
  optimizer::SqlSelect *select= NULL;
53
 
  ReadRecord    info;
 
37
  bool          will_batch;
 
38
  int           error, loc_error;
 
39
  TABLE         *table;
 
40
  SQL_SELECT    *select=0;
 
41
  READ_RECORD   info;
54
42
  bool          using_limit=limit != HA_POS_ERROR;
55
 
  bool          transactional_table, const_cond;
 
43
  bool          transactional_table, safe_update, const_cond;
56
44
  bool          const_cond_result;
57
45
  ha_rows       deleted= 0;
58
 
  uint32_t usable_index= MAX_KEY;
59
 
  Select_Lex   *select_lex= &session->lex->select_lex;
60
 
  Session::killed_state_t killed_status= Session::NOT_KILLED;
 
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
  
61
50
 
62
 
  if (session->openTablesLock(table_list))
 
51
  if (open_and_lock_tables(thd, table_list))
 
52
    return(true);
 
53
  /* TODO look at this error */
 
54
  if (!(table= table_list->table))
63
55
  {
64
 
    DRIZZLE_DELETE_DONE(1, 0);
65
 
    return true;
 
56
    my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), "", "");
 
57
    return(true);
66
58
  }
67
 
 
68
 
  table= table_list->table;
69
 
  assert(table);
70
 
 
71
 
  session->set_proc_info("init");
 
59
  thd_proc_info(thd, "init");
72
60
  table->map=1;
73
61
 
74
 
  if (prepare_delete(session, table_list, &conds))
75
 
  {
76
 
    DRIZZLE_DELETE_DONE(1, 0);
77
 
    return true;
78
 
  }
 
62
  if (mysql_prepare_delete(thd, table_list, &conds))
 
63
    goto err;
79
64
 
80
65
  /* check ORDER BY even if it can be ignored */
81
66
  if (order && order->elements)
82
67
  {
83
 
    TableList   tables;
 
68
    TABLE_LIST   tables;
84
69
    List<Item>   fields;
85
70
    List<Item>   all_fields;
86
71
 
 
72
    memset(&tables, 0, sizeof(tables));
87
73
    tables.table = table;
88
74
    tables.alias = table_list->alias;
89
75
 
90
 
      if (select_lex->setup_ref_array(session, order->elements) ||
91
 
          setup_order(session, select_lex->ref_pointer_array, &tables,
92
 
                    fields, all_fields, (Order*) order->first))
93
 
      {
94
 
        delete select;
95
 
        free_underlaid_joins(session, &session->lex->select_lex);
96
 
        DRIZZLE_DELETE_DONE(1, 0);
97
 
 
98
 
        return true;
99
 
      }
 
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))
 
79
    {
 
80
      delete select;
 
81
      free_underlaid_joins(thd, &thd->lex->select_lex);
 
82
      goto err;
 
83
    }
100
84
  }
101
85
 
102
86
  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
  }
103
94
 
104
 
  select_lex->no_error= session->lex->ignore;
 
95
  select_lex->no_error= thd->lex->ignore;
105
96
 
106
97
  const_cond_result= const_cond && (!conds || conds->val_int());
107
 
  if (session->is_error())
 
98
  if (thd->is_error())
108
99
  {
109
100
    /* Error evaluating val_int(). */
110
101
    return(true);
129
120
      - We should not be binlogging this statement row-based, and
130
121
      - there should be no delete triggers associated with the table.
131
122
  */
132
 
  if (!using_limit && const_cond_result)
 
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)))
133
127
  {
134
 
    /* Update the table->cursor->stats.records number */
135
 
    table->cursor->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
136
 
    ha_rows const maybe_deleted= table->cursor->stats.records;
137
 
    if (!(error=table->cursor->ha_delete_all_rows()))
 
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()))
138
132
    {
139
133
      error= -1;                                // ok
140
134
      deleted= maybe_deleted;
142
136
    }
143
137
    if (error != HA_ERR_WRONG_COMMAND)
144
138
    {
145
 
      table->print_error(error,MYF(0));
 
139
      table->file->print_error(error,MYF(0));
146
140
      error=0;
147
141
      goto cleanup;
148
142
    }
151
145
  if (conds)
152
146
  {
153
147
    Item::cond_result result;
154
 
    conds= remove_eq_conds(session, conds, &result);
 
148
    conds= remove_eq_conds(thd, conds, &result);
155
149
    if (result == Item::COND_FALSE)             // Impossible where
156
150
      limit= 0;
157
151
  }
158
152
 
159
 
  /* Update the table->cursor->stats.records number */
160
 
  table->cursor->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
 
153
  /* Update the table->file->stats.records number */
 
154
  table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
161
155
 
162
 
  table->covering_keys.reset();
163
 
  table->quick_keys.reset();            // Can't use 'only index'
164
 
  select= optimizer::make_select(table, 0, 0, conds, 0, &error);
 
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);
165
159
  if (error)
166
 
  {
167
 
    DRIZZLE_DELETE_DONE(1, 0);
168
 
    return true;
169
 
  }
170
 
 
171
 
  if ((select && select->check_quick(session, false, limit)) || !limit)
 
160
    goto err;
 
161
  if ((select && select->check_quick(thd, safe_update, limit)) || !limit)
172
162
  {
173
163
    delete select;
174
 
    free_underlaid_joins(session, select_lex);
175
 
    session->row_count_func= 0;
176
 
    if (session->is_error())
177
 
      return true;
178
 
    DRIZZLE_DELETE_DONE(0, 0);
179
 
    /**
180
 
     * Resetting the Diagnostic area to prevent
181
 
     * lp bug# 439719
182
 
     */
183
 
    session->main_da.reset_diagnostics_area();
184
 
    session->my_ok((ha_rows) session->rowCount());
 
164
    free_underlaid_joins(thd, select_lex);
 
165
    thd->row_count_func= 0;
 
166
    MYSQL_DELETE_END();
 
167
    my_ok(thd, (ha_rows) thd->row_count_func);
185
168
    /*
186
169
      We don't need to call reset_auto_increment in this case, because
187
170
      mysql_truncate always gives a NULL conds argument, hence we never
188
171
      get here.
189
172
    */
190
 
    return 0; // Nothing to delete
 
173
    return(0);                          // Nothing to delete
191
174
  }
192
175
 
193
176
  /* If running in safe sql mode, don't allow updates without keys */
194
 
  if (table->quick_keys.none())
 
177
  if (table->quick_keys.is_clear_all())
195
178
  {
196
 
    session->server_status|=SERVER_QUERY_NO_INDEX_USED;
 
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
    }
197
188
  }
 
189
  if (options & OPTION_QUICK)
 
190
    (void) table->file->extra(HA_EXTRA_QUICK);
198
191
 
199
192
  if (order && order->elements)
200
193
  {
201
 
    uint32_t         length= 0;
202
 
    SortField  *sortorder;
 
194
    uint         length= 0;
 
195
    SORT_FIELD  *sortorder;
203
196
    ha_rows examined_rows;
204
 
 
205
 
    if ((!select || table->quick_keys.none()) && limit != HA_POS_ERROR)
206
 
      usable_index= optimizer::get_index_for_order(table, (Order*)(order->first), limit);
 
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);
207
200
 
208
201
    if (usable_index == MAX_KEY)
209
202
    {
210
 
      FileSort filesort(*session);
211
 
      table->sort.io_cache= new internal::IO_CACHE;
212
 
 
213
 
 
214
 
      if (not (sortorder= make_unireg_sortorder((Order*) order->first, &length, NULL)) ||
215
 
          (table->sort.found_records = filesort.run(table, sortorder, length,
216
 
                                                    select, HA_POS_ERROR, 1,
217
 
                                                    examined_rows)) == HA_POS_ERROR)
 
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,
 
207
                                             &length, NULL)) ||
 
208
          (table->sort.found_records = filesort(thd, table, sortorder, length,
 
209
                                                select, HA_POS_ERROR, 1,
 
210
                                                &examined_rows))
 
211
          == HA_POS_ERROR)
218
212
      {
219
213
        delete select;
220
 
        free_underlaid_joins(session, &session->lex->select_lex);
221
 
 
222
 
        DRIZZLE_DELETE_DONE(1, 0);
223
 
        return true;
 
214
        free_underlaid_joins(thd, &thd->lex->select_lex);
 
215
        goto err;
224
216
      }
225
217
      /*
226
218
        Filesort has already found and selected the rows we want to delete,
227
219
        so we don't need the where clause
228
220
      */
229
221
      delete select;
230
 
      free_underlaid_joins(session, select_lex);
 
222
      free_underlaid_joins(thd, select_lex);
231
223
      select= 0;
232
224
    }
233
225
  }
236
228
  if (select && select->quick && select->quick->reset())
237
229
  {
238
230
    delete select;
239
 
    free_underlaid_joins(session, select_lex);
240
 
    DRIZZLE_DELETE_DONE(1, 0);
241
 
    return true;
 
231
    free_underlaid_joins(thd, select_lex);
 
232
    goto err;
242
233
  }
243
 
 
244
234
  if (usable_index==MAX_KEY)
245
 
  {
246
 
    if ((error= info.init_read_record(session,table,select,1,1)))
247
 
    {
248
 
      table->print_error(error, MYF(0));
249
 
      delete select;
250
 
      free_underlaid_joins(session, select_lex);
251
 
      return true;
252
 
    }
253
 
  }
 
235
    init_read_record(&info,thd,table,select,1,1);
254
236
  else
255
 
  {
256
 
    if ((error= info.init_read_record_idx(session, table, 1, usable_index)))
257
 
    {
258
 
      table->print_error(error, MYF(0));
259
 
      delete select;
260
 
      free_underlaid_joins(session, select_lex);
261
 
      return true;
262
 
    }
263
 
  }
264
 
 
265
 
  session->set_proc_info("updating");
 
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
 
266
243
 
267
244
  table->mark_columns_needed_for_delete();
268
245
 
269
 
  while (!(error=info.read_record(&info)) && !session->getKilled() &&
270
 
         ! session->is_error())
 
246
  while (!(error=info.read_record(&info)) && !thd->killed &&
 
247
         ! thd->is_error())
271
248
  {
272
 
    // session->is_error() is tested to disallow delete row on error
273
 
    if (!(select && select->skip_record())&& ! session->is_error() )
 
249
    // thd->is_error() is tested to disallow delete row on error
 
250
    if (!(select && select->skip_record())&& ! thd->is_error() )
274
251
    {
275
 
      if (!(error= table->cursor->deleteRecord(table->getInsertRecord())))
 
252
      if (!(error= table->file->ha_delete_row(table->record[0])))
276
253
      {
277
254
        deleted++;
278
255
        if (!--limit && using_limit)
283
260
      }
284
261
      else
285
262
      {
286
 
        table->print_error(error,MYF(0));
 
263
        table->file->print_error(error,MYF(0));
287
264
        /*
288
265
          In < 4.0.14 we set the error number to 0 here, but that
289
266
          was not sensible, because then MySQL would not roll back the
297
274
      }
298
275
    }
299
276
    else
300
 
      table->cursor->unlock_row();  // Row failed selection, release lock on it
 
277
      table->file->unlock_row();  // Row failed selection, release lock on it
301
278
  }
302
 
  killed_status= session->getKilled();
303
 
  if (killed_status != Session::NOT_KILLED || session->is_error())
 
279
  killed_status= thd->killed;
 
280
  if (killed_status != THD::NOT_KILLED || thd->is_error())
304
281
    error= 1;                                   // Aborted
305
 
 
306
 
  session->set_proc_info("end");
307
 
  info.end_read_record();
308
 
 
309
 
cleanup:
 
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");
 
289
  end_read_record(&info);
 
290
  if (options & OPTION_QUICK)
 
291
    (void) table->file->extra(HA_EXTRA_NORMAL);
310
292
 
311
293
  if (reset_auto_increment && (error < 0))
312
294
  {
314
296
      We're really doing a truncate and need to reset the table's
315
297
      auto-increment counter.
316
298
    */
317
 
    int error2= table->cursor->ha_reset_auto_increment(0);
 
299
    int error2= table->file->ha_reset_auto_increment(0);
318
300
 
319
301
    if (error2 && (error2 != HA_ERR_WRONG_COMMAND))
320
302
    {
321
 
      table->print_error(error2, MYF(0));
 
303
      table->file->print_error(error2, MYF(0));
322
304
      error= 1;
323
305
    }
324
306
  }
325
307
 
 
308
cleanup:
 
309
 
326
310
  delete select;
327
 
  transactional_table= table->cursor->has_transactions();
 
311
  transactional_table= table->file->has_transactions();
328
312
 
329
313
  if (!transactional_table && deleted > 0)
330
 
    session->transaction.stmt.markModifiedNonTransData();
331
 
 
 
314
    thd->transaction.stmt.modified_non_trans_table= true;
 
315
  
332
316
  /* See similar binlogging code in sql_update.cc, for comments */
333
 
  if ((error < 0) || session->transaction.stmt.hasModifiedNonTransData())
334
 
  {
335
 
    if (session->transaction.stmt.hasModifiedNonTransData())
336
 
      session->transaction.all.markModifiedNonTransData();
337
 
  }
338
 
  assert(transactional_table || !deleted || session->transaction.stmt.hasModifiedNonTransData());
339
 
  free_underlaid_joins(session, select_lex);
340
 
 
341
 
  DRIZZLE_DELETE_DONE((error >= 0 || session->is_error()), deleted);
342
 
  if (error < 0 || (session->lex->ignore && !session->is_fatal_error))
343
 
  {
344
 
    session->row_count_func= deleted;
345
 
    /**
346
 
     * Resetting the Diagnostic area to prevent
347
 
     * lp bug# 439719
348
 
     */
349
 
    session->main_da.reset_diagnostics_area();    
350
 
    session->my_ok((ha_rows) session->rowCount());
351
 
  }
352
 
  session->status_var.deleted_row_count+= deleted;
353
 
 
354
 
  return (error >= 0 || session->is_error());
 
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
  MYSQL_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());
 
351
 
 
352
err:
 
353
  MYSQL_DELETE_END();
 
354
  return(true);
355
355
}
356
356
 
357
357
 
359
359
  Prepare items in DELETE statement
360
360
 
361
361
  SYNOPSIS
362
 
    prepare_delete()
363
 
    session                     - thread handler
 
362
    mysql_prepare_delete()
 
363
    thd                 - thread handler
364
364
    table_list          - global/local table list
365
365
    conds               - conditions
366
366
 
368
368
    false OK
369
369
    true  error
370
370
*/
371
 
int prepare_delete(Session *session, TableList *table_list, Item **conds)
 
371
int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
372
372
{
373
 
  Select_Lex *select_lex= &session->lex->select_lex;
374
 
 
 
373
  SELECT_LEX *select_lex= &thd->lex->select_lex;
 
374
  
375
375
  List<Item> all_fields;
376
376
 
377
 
  session->lex->allow_sum_func= 0;
378
 
  if (setup_tables_and_check_access(session, &session->lex->select_lex.context,
379
 
                                    &session->lex->select_lex.top_join_list,
380
 
                                    table_list,
 
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, 
381
394
                                    &select_lex->leaf_tables, false) ||
382
 
      session->setup_conds(table_list, conds))
 
395
      setup_conds(thd, table_list, select_lex->leaf_tables, conds))
383
396
    return(true);
384
397
  {
385
 
    TableList *duplicate;
386
 
    if ((duplicate= unique_table(table_list, table_list->next_global)))
 
398
    TABLE_LIST *duplicate;
 
399
    if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0)))
387
400
    {
388
 
      my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->alias);
 
401
      update_non_unique_table_error(table_list, "DELETE", duplicate);
389
402
      return(true);
390
403
    }
391
404
  }
392
405
 
393
406
  if (select_lex->inner_refs_list.elements &&
394
 
    fix_inner_refs(session, all_fields, select_lex, select_lex->ref_pointer_array))
 
407
    fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
 
408
    return(-1);
 
409
 
 
410
  return(false);
 
411
}
 
412
 
 
413
 
 
414
/***************************************************************************
 
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))
395
455
    return(true);
396
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
  }
397
492
  return(false);
398
493
}
399
494
 
400
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
 
401
829
/***************************************************************************
402
 
  TRUNCATE Table
 
830
  TRUNCATE TABLE
403
831
****************************************************************************/
404
832
 
405
833
/*
406
834
  Optimize delete of all rows by doing a full generate of the table
407
835
  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.
408
843
*/
409
844
 
410
 
bool truncate(Session& session, TableList *table_list)
 
845
bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
411
846
{
 
847
  HA_CREATE_INFO create_info;
 
848
  char path[FN_REFLEN];
 
849
  TABLE *table;
412
850
  bool error;
413
 
  TransactionServices &transaction_services= TransactionServices::singleton();
414
 
 
415
 
  uint64_t save_options= session.options;
 
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;
416
943
  table_list->lock_type= TL_WRITE;
417
 
  session.options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
418
 
  init_select(session.lex);
419
 
  error= delete_query(&session, table_list, (COND*) 0, (SQL_LIST*) 0,
420
 
                      HA_POS_ERROR, 0L, true);
 
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);
421
952
  /*
422
953
    Safety, in case the engine ignored ha_enable_transaction(false)
423
 
    above. Also clears session->transaction.*.
 
954
    above. Also clears thd->transaction.*.
424
955
  */
425
 
  error= transaction_services.autocommitOrRollback(session, error);
426
 
  session.options= save_options;
427
 
 
428
 
  return error;
 
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);
429
961
}
430
 
 
431
 
} /* namespace drizzled */