~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_delete.cc

  • Committer: Jay Pipes
  • Date: 2008-09-11 16:03:22 UTC
  • mto: (383.5.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 386.
  • Revision ID: jay@mysql.com-20080911160322-vrl0k1djo6q6ytv1
Removed SQL_MODE variances from comment_table.test and ensured correct error thrown when a comment that is too long was input.  After moving to proto buffer definition for table, the 2048 length will go away.

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 mysql_delete(Session *session, TableList *table_list, COND *conds,
47
 
                  SQL_LIST *order, ha_rows limit, uint64_t,
 
33
bool mysql_delete(THD *thd, TableList *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;
 
37
  bool          will_batch;
 
38
  int           error, loc_error;
51
39
  Table         *table;
52
 
  optimizer::SqlSelect *select= NULL;
53
 
  ReadRecord    info;
 
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 (mysql_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)
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_st*) 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
      (thd->lex->sql_command == SQLCOM_TRUNCATE ||
 
125
       (!thd->current_stmt_binlog_row_based)))
133
126
  {
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()))
 
127
    /* Update the table->file->stats.records number */
 
128
    table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
 
129
    ha_rows const maybe_deleted= table->file->stats.records;
 
130
    if (!(error=table->file->ha_delete_all_rows()))
138
131
    {
139
132
      error= -1;                                // ok
140
133
      deleted= maybe_deleted;
142
135
    }
143
136
    if (error != HA_ERR_WRONG_COMMAND)
144
137
    {
145
 
      table->print_error(error,MYF(0));
 
138
      table->file->print_error(error,MYF(0));
146
139
      error=0;
147
140
      goto cleanup;
148
141
    }
151
144
  if (conds)
152
145
  {
153
146
    Item::cond_result result;
154
 
    conds= remove_eq_conds(session, conds, &result);
 
147
    conds= remove_eq_conds(thd, conds, &result);
155
148
    if (result == Item::COND_FALSE)             // Impossible where
156
149
      limit= 0;
157
150
  }
158
151
 
159
 
  /* Update the table->cursor->stats.records number */
160
 
  table->cursor->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
 
152
  /* Update the table->file->stats.records number */
 
153
  table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
161
154
 
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);
 
155
  table->covering_keys.clear_all();
 
156
  table->quick_keys.clear_all();                // Can't use 'only index'
 
157
  select=make_select(table, 0, 0, conds, 0, &error);
165
158
  if (error)
166
 
  {
167
 
    DRIZZLE_DELETE_DONE(1, 0);
168
 
    return true;
169
 
  }
170
 
 
171
 
  if ((select && select->check_quick(session, false, limit)) || !limit)
 
159
    goto err;
 
160
  if ((select && select->check_quick(thd, safe_update, limit)) || !limit)
172
161
  {
173
162
    delete select;
174
 
    free_underlaid_joins(session, select_lex);
175
 
    session->row_count_func= 0;
176
 
    DRIZZLE_DELETE_DONE(0, 0);
177
 
    /**
178
 
     * Resetting the Diagnostic area to prevent
179
 
     * lp bug# 439719
180
 
     */
181
 
    session->main_da.reset_diagnostics_area();
182
 
    session->my_ok((ha_rows) session->row_count_func);
 
163
    free_underlaid_joins(thd, select_lex);
 
164
    thd->row_count_func= 0;
 
165
    DRIZZLE_DELETE_END();
 
166
    my_ok(thd, (ha_rows) thd->row_count_func);
183
167
    /*
184
168
      We don't need to call reset_auto_increment in this case, because
185
169
      mysql_truncate always gives a NULL conds argument, hence we never
186
170
      get here.
187
171
    */
188
 
    return 0; // Nothing to delete
 
172
    return(0);                          // Nothing to delete
189
173
  }
190
174
 
191
175
  /* If running in safe sql mode, don't allow updates without keys */
192
 
  if (table->quick_keys.none())
 
176
  if (table->quick_keys.is_clear_all())
193
177
  {
194
 
    session->server_status|=SERVER_QUERY_NO_INDEX_USED;
 
178
    thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
 
179
    if (safe_update && !using_limit)
 
180
    {
 
181
      delete select;
 
182
      free_underlaid_joins(thd, select_lex);
 
183
      my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
 
184
                 ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
 
185
      goto err;
 
186
    }
195
187
  }
 
188
  if (options & OPTION_QUICK)
 
189
    (void) table->file->extra(HA_EXTRA_QUICK);
196
190
 
197
191
  if (order && order->elements)
198
192
  {
199
 
    uint32_t         length= 0;
200
 
    SortField  *sortorder;
 
193
    uint         length= 0;
 
194
    SORT_FIELD  *sortorder;
201
195
    ha_rows examined_rows;
202
 
 
203
 
    if ((!select || table->quick_keys.none()) && limit != HA_POS_ERROR)
204
 
      usable_index= optimizer::get_index_for_order(table, (Order*)(order->first), limit);
 
196
    
 
197
    if ((!select || table->quick_keys.is_clear_all()) && limit != HA_POS_ERROR)
 
198
      usable_index= get_index_for_order(table, (order_st*)(order->first), limit);
205
199
 
206
200
    if (usable_index == MAX_KEY)
207
201
    {
208
 
      FileSort filesort(*session);
209
 
      table->sort.io_cache= new internal::IO_CACHE;
210
 
 
211
 
 
212
 
      if (not (sortorder= make_unireg_sortorder((Order*) order->first, &length, NULL)) ||
213
 
          (table->sort.found_records = filesort.run(table, sortorder, length,
214
 
                                                    select, HA_POS_ERROR, 1,
215
 
                                                    examined_rows)) == HA_POS_ERROR)
 
202
      table->sort.io_cache= (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
 
203
                                                   MYF(MY_FAE | MY_ZEROFILL));
 
204
    
 
205
      if (!(sortorder= make_unireg_sortorder((order_st*) order->first,
 
206
                                             &length, NULL)) ||
 
207
          (table->sort.found_records = filesort(thd, table, sortorder, length,
 
208
                                                select, HA_POS_ERROR, 1,
 
209
                                                &examined_rows))
 
210
          == HA_POS_ERROR)
216
211
      {
217
212
        delete select;
218
 
        free_underlaid_joins(session, &session->lex->select_lex);
219
 
 
220
 
        DRIZZLE_DELETE_DONE(1, 0);
221
 
        return true;
 
213
        free_underlaid_joins(thd, &thd->lex->select_lex);
 
214
        goto err;
222
215
      }
223
216
      /*
224
217
        Filesort has already found and selected the rows we want to delete,
225
218
        so we don't need the where clause
226
219
      */
227
220
      delete select;
228
 
      free_underlaid_joins(session, select_lex);
 
221
      free_underlaid_joins(thd, select_lex);
229
222
      select= 0;
230
223
    }
231
224
  }
234
227
  if (select && select->quick && select->quick->reset())
235
228
  {
236
229
    delete select;
237
 
    free_underlaid_joins(session, select_lex);
238
 
    DRIZZLE_DELETE_DONE(1, 0);
239
 
    return true;
 
230
    free_underlaid_joins(thd, select_lex);
 
231
    goto err;
240
232
  }
241
 
 
242
233
  if (usable_index==MAX_KEY)
243
 
  {
244
 
    info.init_read_record(session,table,select,1,1);
245
 
  }
 
234
    init_read_record(&info,thd,table,select,1,1);
246
235
  else
247
 
  {
248
 
    info.init_read_record_idx(session, table, 1, usable_index);
249
 
  }
250
 
 
251
 
  session->set_proc_info("updating");
 
236
    init_read_record_idx(&info, thd, table, 1, usable_index);
 
237
 
 
238
  thd_proc_info(thd, "updating");
 
239
 
 
240
  will_batch= !table->file->start_bulk_delete();
 
241
 
252
242
 
253
243
  table->mark_columns_needed_for_delete();
254
244
 
255
 
  while (!(error=info.read_record(&info)) && !session->getKilled() &&
256
 
         ! session->is_error())
 
245
  while (!(error=info.read_record(&info)) && !thd->killed &&
 
246
         ! thd->is_error())
257
247
  {
258
 
    // session->is_error() is tested to disallow delete row on error
259
 
    if (!(select && select->skip_record())&& ! session->is_error() )
 
248
    // thd->is_error() is tested to disallow delete row on error
 
249
    if (!(select && select->skip_record())&& ! thd->is_error() )
260
250
    {
261
 
      if (!(error= table->cursor->deleteRecord(table->getInsertRecord())))
 
251
      if (!(error= table->file->ha_delete_row(table->record[0])))
262
252
      {
263
253
        deleted++;
264
254
        if (!--limit && using_limit)
269
259
      }
270
260
      else
271
261
      {
272
 
        table->print_error(error,MYF(0));
 
262
        table->file->print_error(error,MYF(0));
273
263
        /*
274
264
          In < 4.0.14 we set the error number to 0 here, but that
275
265
          was not sensible, because then MySQL would not roll back the
283
273
      }
284
274
    }
285
275
    else
286
 
      table->cursor->unlock_row();  // Row failed selection, release lock on it
 
276
      table->file->unlock_row();  // Row failed selection, release lock on it
287
277
  }
288
 
  killed_status= session->getKilled();
289
 
  if (killed_status != Session::NOT_KILLED || session->is_error())
 
278
  killed_status= thd->killed;
 
279
  if (killed_status != THD::NOT_KILLED || thd->is_error())
290
280
    error= 1;                                   // Aborted
291
 
 
292
 
  session->set_proc_info("end");
293
 
  info.end_read_record();
294
 
 
295
 
cleanup:
 
281
  if (will_batch && (loc_error= table->file->end_bulk_delete()))
 
282
  {
 
283
    if (error != 1)
 
284
      table->file->print_error(loc_error,MYF(0));
 
285
    error=1;
 
286
  }
 
287
  thd_proc_info(thd, "end");
 
288
  end_read_record(&info);
 
289
  if (options & OPTION_QUICK)
 
290
    (void) table->file->extra(HA_EXTRA_NORMAL);
296
291
 
297
292
  if (reset_auto_increment && (error < 0))
298
293
  {
300
295
      We're really doing a truncate and need to reset the table's
301
296
      auto-increment counter.
302
297
    */
303
 
    int error2= table->cursor->ha_reset_auto_increment(0);
 
298
    int error2= table->file->ha_reset_auto_increment(0);
304
299
 
305
300
    if (error2 && (error2 != HA_ERR_WRONG_COMMAND))
306
301
    {
307
 
      table->print_error(error2, MYF(0));
 
302
      table->file->print_error(error2, MYF(0));
308
303
      error= 1;
309
304
    }
310
305
  }
311
306
 
 
307
cleanup:
 
308
 
312
309
  delete select;
313
 
  transactional_table= table->cursor->has_transactions();
 
310
  transactional_table= table->file->has_transactions();
314
311
 
315
312
  if (!transactional_table && deleted > 0)
316
 
    session->transaction.stmt.markModifiedNonTransData();
317
 
 
 
313
    thd->transaction.stmt.modified_non_trans_table= true;
 
314
  
318
315
  /* See similar binlogging code in sql_update.cc, for comments */
319
 
  if ((error < 0) || session->transaction.stmt.hasModifiedNonTransData())
320
 
  {
321
 
    if (session->transaction.stmt.hasModifiedNonTransData())
322
 
      session->transaction.all.markModifiedNonTransData();
323
 
  }
324
 
  assert(transactional_table || !deleted || session->transaction.stmt.hasModifiedNonTransData());
325
 
  free_underlaid_joins(session, select_lex);
326
 
 
327
 
  DRIZZLE_DELETE_DONE((error >= 0 || session->is_error()), deleted);
328
 
  if (error < 0 || (session->lex->ignore && !session->is_fatal_error))
329
 
  {
330
 
    session->row_count_func= deleted;
331
 
    /**
332
 
     * Resetting the Diagnostic area to prevent
333
 
     * lp bug# 439719
334
 
     */
335
 
    session->main_da.reset_diagnostics_area();    
336
 
    session->my_ok((ha_rows) session->row_count_func);
337
 
  }
338
 
  session->status_var.deleted_row_count+= deleted;
339
 
 
340
 
  return (error >= 0 || session->is_error());
 
316
  if ((error < 0) || thd->transaction.stmt.modified_non_trans_table)
 
317
  {
 
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;
 
339
  }
 
340
  assert(transactional_table || !deleted || thd->transaction.stmt.modified_non_trans_table);
 
341
  free_underlaid_joins(thd, select_lex);
 
342
 
 
343
  DRIZZLE_DELETE_END();
 
344
  if (error < 0 || (thd->lex->ignore && !thd->is_fatal_error))
 
345
  {
 
346
    thd->row_count_func= deleted;
 
347
    my_ok(thd, (ha_rows) thd->row_count_func);
 
348
  }
 
349
  return(error >= 0 || thd->is_error());
 
350
 
 
351
err:
 
352
  DRIZZLE_DELETE_END();
 
353
  return(true);
341
354
}
342
355
 
343
356
 
346
359
 
347
360
  SYNOPSIS
348
361
    mysql_prepare_delete()
349
 
    session                     - thread handler
 
362
    thd                 - thread handler
350
363
    table_list          - global/local table list
351
364
    conds               - conditions
352
365
 
354
367
    false OK
355
368
    true  error
356
369
*/
357
 
int mysql_prepare_delete(Session *session, TableList *table_list, Item **conds)
 
370
int mysql_prepare_delete(THD *thd, TableList *table_list, Item **conds)
358
371
{
359
 
  Select_Lex *select_lex= &session->lex->select_lex;
360
 
 
 
372
  SELECT_LEX *select_lex= &thd->lex->select_lex;
 
373
  
361
374
  List<Item> all_fields;
362
375
 
363
 
  session->lex->allow_sum_func= 0;
364
 
  if (setup_tables_and_check_access(session, &session->lex->select_lex.context,
365
 
                                    &session->lex->select_lex.top_join_list,
366
 
                                    table_list,
 
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, 
367
393
                                    &select_lex->leaf_tables, false) ||
368
 
      session->setup_conds(table_list, conds))
 
394
      setup_conds(thd, table_list, select_lex->leaf_tables, conds))
369
395
    return(true);
370
396
  {
371
397
    TableList *duplicate;
372
 
    if ((duplicate= unique_table(table_list, table_list->next_global)))
 
398
    if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0)))
373
399
    {
374
 
      my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->alias);
 
400
      update_non_unique_table_error(table_list, "DELETE", duplicate);
375
401
      return(true);
376
402
    }
377
403
  }
378
404
 
379
405
  if (select_lex->inner_refs_list.elements &&
380
 
    fix_inner_refs(session, all_fields, select_lex, select_lex->ref_pointer_array))
 
406
    fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
381
407
    return(-1);
382
408
 
383
409
  return(false);
385
411
 
386
412
 
387
413
/***************************************************************************
 
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 uchar*)a, (const uchar*)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, uint 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 (uint 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(uint 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
/***************************************************************************
388
829
  TRUNCATE Table
389
830
****************************************************************************/
390
831
 
391
832
/*
392
833
  Optimize delete of all rows by doing a full generate of the table
393
834
  This will work even if the .ISM and .ISD tables are destroyed
 
835
 
 
836
  dont_send_ok should be set if:
 
837
  - We should always wants to generate the table (even if the table type
 
838
    normally can't safely do this.
 
839
  - We don't want an ok to be sent to the end user.
 
840
  - We don't want to log the truncate command
 
841
  - If we want to have a name lock on the table on exit without errors.
394
842
*/
395
843
 
396
 
bool mysql_truncate(Session& session, TableList *table_list)
 
844
bool mysql_truncate(THD *thd, TableList *table_list, bool dont_send_ok)
397
845
{
 
846
  HA_CREATE_INFO create_info;
 
847
  char path[FN_REFLEN];
 
848
  Table *table;
398
849
  bool error;
399
 
  TransactionServices &transaction_services= TransactionServices::singleton();
400
 
 
401
 
  uint64_t save_options= session.options;
 
850
  uint path_length;
 
851
  
 
852
 
 
853
  memset(&create_info, 0, sizeof(create_info));
 
854
  /* If it is a temporary table, close and regenerate it */
 
855
  if (!dont_send_ok && (table= find_temporary_table(thd, table_list)))
 
856
  {
 
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);
 
860
 
 
861
    if (!ha_check_storage_engine_flag(table_type, HTON_CAN_RECREATE))
 
862
      goto trunc_by_del;
 
863
 
 
864
    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);
 
869
    // 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);
 
876
    my_free((char*) table,MYF(0));
 
877
    /*
 
878
      If we return here we will not have logged the truncation to the bin log
 
879
      and we will not my_ok() to the client.
 
880
    */
 
881
    goto end;
 
882
  }
 
883
 
 
884
  path_length= build_table_filename(path, sizeof(path), table_list->db,
 
885
                                    table_list->table_name, reg_ext, 0);
 
886
 
 
887
  if (!dont_send_ok)
 
888
  {
 
889
    enum legacy_db_type table_type;
 
890
    mysql_frm_type(thd, path, &table_type);
 
891
    if (table_type == DB_TYPE_UNKNOWN)
 
892
    {
 
893
      my_error(ER_NO_SUCH_TABLE, MYF(0),
 
894
               table_list->db, table_list->table_name);
 
895
      return(true);
 
896
    }
 
897
 
 
898
    if (!ha_check_storage_engine_flag(ha_resolve_by_legacy_type(thd, table_type),
 
899
                                      HTON_CAN_RECREATE))
 
900
      goto trunc_by_del;
 
901
 
 
902
    if (lock_and_wait_for_table_name(thd, table_list))
 
903
      return(true);
 
904
  }
 
905
 
 
906
  // Remove the .frm extension AIX 5.2 64-bit compiler bug (BUG#16155): this
 
907
  // crashes, replacement works.  *(path + path_length - reg_ext_length)=
 
908
  // '\0';
 
909
  path[path_length - reg_ext_length] = 0;
 
910
  VOID(pthread_mutex_lock(&LOCK_open));
 
911
  error= ha_create_table(thd, path, table_list->db, table_list->table_name,
 
912
                         &create_info, 1);
 
913
  VOID(pthread_mutex_unlock(&LOCK_open));
 
914
 
 
915
end:
 
916
  if (!dont_send_ok)
 
917
  {
 
918
    if (!error)
 
919
    {
 
920
      /*
 
921
        TRUNCATE must always be statement-based binlogged (not row-based) so
 
922
        we don't test current_stmt_binlog_row_based.
 
923
      */
 
924
      write_bin_log(thd, true, thd->query, thd->query_length);
 
925
      my_ok(thd);               // This should return record count
 
926
    }
 
927
    VOID(pthread_mutex_lock(&LOCK_open));
 
928
    unlock_table_name(thd, table_list);
 
929
    VOID(pthread_mutex_unlock(&LOCK_open));
 
930
  }
 
931
  else if (error)
 
932
  {
 
933
    VOID(pthread_mutex_lock(&LOCK_open));
 
934
    unlock_table_name(thd, table_list);
 
935
    VOID(pthread_mutex_unlock(&LOCK_open));
 
936
  }
 
937
  return(error);
 
938
 
 
939
trunc_by_del:
 
940
  /* Probably InnoDB table */
 
941
  uint64_t save_options= thd->options;
402
942
  table_list->lock_type= TL_WRITE;
403
 
  session.options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
404
 
  mysql_init_select(session.lex);
405
 
  error= mysql_delete(&session, table_list, (COND*) 0, (SQL_LIST*) 0,
406
 
                      HA_POS_ERROR, 0L, true);
 
943
  thd->options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
 
944
  ha_enable_transaction(thd, false);
 
945
  mysql_init_select(thd->lex);
 
946
  bool save_binlog_row_based= thd->current_stmt_binlog_row_based;
 
947
  thd->clear_current_stmt_binlog_row_based();
 
948
  error= mysql_delete(thd, table_list, (COND*) 0, (SQL_LIST*) 0,
 
949
                      HA_POS_ERROR, 0LL, true);
 
950
  ha_enable_transaction(thd, true);
407
951
  /*
408
952
    Safety, in case the engine ignored ha_enable_transaction(false)
409
 
    above. Also clears session->transaction.*.
 
953
    above. Also clears thd->transaction.*.
410
954
  */
411
 
  error= transaction_services.autocommitOrRollback(&session, error);
412
 
  session.options= save_options;
413
 
 
414
 
  return error;
 
955
  error= ha_autocommit_or_rollback(thd, error);
 
956
  ha_commit(thd);
 
957
  thd->options= save_options;
 
958
  thd->current_stmt_binlog_row_based= save_binlog_row_based;
 
959
  return(error);
415
960
}
416
 
 
417
 
} /* namespace drizzled */