~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_delete.cc

  • Committer: Brian Aker
  • Date: 2009-11-18 22:58:22 UTC
  • mto: (1223.1.1 push) (1226.1.2 push)
  • mto: This revision was merged to the branch mainline in revision 1224.
  • Revision ID: brian@gaz-20091118225822-4ryr9rviir23o0kr
Second pass through bugs related to CREATE TABLE LIKE

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"
 
21
#include <drizzled/server_includes.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"
34
29
 
35
 
namespace drizzled
36
 
{
 
30
using namespace drizzled;
37
31
 
38
32
/**
39
33
  Implement DELETE SQL word.
44
38
*/
45
39
 
46
40
bool mysql_delete(Session *session, TableList *table_list, COND *conds,
47
 
                  SQL_LIST *order, ha_rows limit, uint64_t,
 
41
                  SQL_LIST *order, ha_rows limit, uint64_t options,
48
42
                  bool reset_auto_increment)
49
43
{
50
 
  int           error;
 
44
  bool          will_batch;
 
45
  int           error, loc_error;
51
46
  Table         *table;
52
 
  optimizer::SqlSelect *select= NULL;
53
 
  ReadRecord    info;
 
47
  SQL_SELECT    *select=0;
 
48
  READ_RECORD   info;
54
49
  bool          using_limit=limit != HA_POS_ERROR;
55
 
  bool          transactional_table, const_cond;
 
50
  bool          transactional_table, safe_update, const_cond;
56
51
  bool          const_cond_result;
57
52
  ha_rows       deleted= 0;
58
53
  uint32_t usable_index= MAX_KEY;
59
54
  Select_Lex   *select_lex= &session->lex->select_lex;
60
 
  Session::killed_state_t killed_status= Session::NOT_KILLED;
 
55
  Session::killed_state killed_status= Session::NOT_KILLED;
61
56
 
62
57
  if (session->openTablesLock(table_list))
63
58
  {
72
67
  table->map=1;
73
68
 
74
69
  if (mysql_prepare_delete(session, table_list, &conds))
75
 
  {
76
 
    DRIZZLE_DELETE_DONE(1, 0);
77
 
    return true;
78
 
  }
 
70
    goto err;
79
71
 
80
72
  /* check ORDER BY even if it can be ignored */
81
73
  if (order && order->elements)
84
76
    List<Item>   fields;
85
77
    List<Item>   all_fields;
86
78
 
 
79
    memset(&tables, 0, sizeof(tables));
87
80
    tables.table = table;
88
81
    tables.alias = table_list->alias;
89
82
 
90
83
      if (select_lex->setup_ref_array(session, order->elements) ||
91
84
          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
 
      }
 
85
                    fields, all_fields, (order_st*) order->first))
 
86
    {
 
87
      delete select;
 
88
      free_underlaid_joins(session, &session->lex->select_lex);
 
89
      goto err;
 
90
    }
100
91
  }
101
92
 
102
93
  const_cond= (!conds || conds->const_item());
 
94
  safe_update=test(session->options & OPTION_SAFE_UPDATES);
 
95
  if (safe_update && const_cond)
 
96
  {
 
97
    my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
 
98
               ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
 
99
    goto err;
 
100
  }
103
101
 
104
102
  select_lex->no_error= session->lex->ignore;
105
103
 
161
159
 
162
160
  table->covering_keys.reset();
163
161
  table->quick_keys.reset();            // Can't use 'only index'
164
 
  select= optimizer::make_select(table, 0, 0, conds, 0, &error);
 
162
  select=make_select(table, 0, 0, conds, 0, &error);
165
163
  if (error)
166
 
  {
167
 
    DRIZZLE_DELETE_DONE(1, 0);
168
 
    return true;
169
 
  }
170
 
 
171
 
  if ((select && select->check_quick(session, false, limit)) || !limit)
 
164
    goto err;
 
165
  if ((select && select->check_quick(session, safe_update, limit)) || !limit)
172
166
  {
173
167
    delete select;
174
168
    free_underlaid_joins(session, select_lex);
192
186
  if (table->quick_keys.none())
193
187
  {
194
188
    session->server_status|=SERVER_QUERY_NO_INDEX_USED;
 
189
    if (safe_update && !using_limit)
 
190
    {
 
191
      delete select;
 
192
      free_underlaid_joins(session, select_lex);
 
193
      my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
 
194
                 ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
 
195
      goto err;
 
196
    }
195
197
  }
 
198
  if (options & OPTION_QUICK)
 
199
    (void) table->cursor->extra(HA_EXTRA_QUICK);
196
200
 
197
201
  if (order && order->elements)
198
202
  {
199
203
    uint32_t         length= 0;
200
 
    SortField  *sortorder;
 
204
    SORT_FIELD  *sortorder;
201
205
    ha_rows examined_rows;
202
206
 
203
207
    if ((!select || table->quick_keys.none()) && limit != HA_POS_ERROR)
204
 
      usable_index= optimizer::get_index_for_order(table, (Order*)(order->first), limit);
 
208
      usable_index= get_index_for_order(table, (order_st*)(order->first), limit);
205
209
 
206
210
    if (usable_index == MAX_KEY)
207
211
    {
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)
 
212
      table->sort.io_cache= new IO_CACHE;
 
213
      memset(table->sort.io_cache, 0, sizeof(IO_CACHE));
 
214
 
 
215
 
 
216
      if (!(sortorder= make_unireg_sortorder((order_st*) order->first,
 
217
                                             &length, NULL)) ||
 
218
          (table->sort.found_records = filesort(session, table, sortorder, length,
 
219
                                                select, HA_POS_ERROR, 1,
 
220
                                                &examined_rows))
 
221
          == HA_POS_ERROR)
216
222
      {
217
223
        delete select;
218
224
        free_underlaid_joins(session, &session->lex->select_lex);
219
 
 
220
 
        DRIZZLE_DELETE_DONE(1, 0);
221
 
        return true;
 
225
        goto err;
222
226
      }
223
227
      /*
224
228
        Filesort has already found and selected the rows we want to delete,
235
239
  {
236
240
    delete select;
237
241
    free_underlaid_joins(session, select_lex);
238
 
    DRIZZLE_DELETE_DONE(1, 0);
239
 
    return true;
 
242
    goto err;
240
243
  }
241
 
 
242
244
  if (usable_index==MAX_KEY)
243
 
  {
244
 
    info.init_read_record(session,table,select,1,1);
245
 
  }
 
245
    init_read_record(&info,session,table,select,1,1);
246
246
  else
247
 
  {
248
 
    info.init_read_record_idx(session, table, 1, usable_index);
249
 
  }
 
247
    init_read_record_idx(&info, session, table, 1, usable_index);
250
248
 
251
249
  session->set_proc_info("updating");
252
250
 
 
251
  will_batch= !table->cursor->start_bulk_delete();
 
252
 
 
253
 
253
254
  table->mark_columns_needed_for_delete();
254
255
 
255
 
  while (!(error=info.read_record(&info)) && !session->getKilled() &&
 
256
  while (!(error=info.read_record(&info)) && !session->killed &&
256
257
         ! session->is_error())
257
258
  {
258
259
    // session->is_error() is tested to disallow delete row on error
259
260
    if (!(select && select->skip_record())&& ! session->is_error() )
260
261
    {
261
 
      if (!(error= table->cursor->deleteRecord(table->getInsertRecord())))
 
262
      if (!(error= table->cursor->ha_delete_row(table->record[0])))
262
263
      {
263
264
        deleted++;
264
265
        if (!--limit && using_limit)
285
286
    else
286
287
      table->cursor->unlock_row();  // Row failed selection, release lock on it
287
288
  }
288
 
  killed_status= session->getKilled();
 
289
  killed_status= session->killed;
289
290
  if (killed_status != Session::NOT_KILLED || session->is_error())
290
291
    error= 1;                                   // Aborted
291
 
 
 
292
  if (will_batch && (loc_error= table->cursor->end_bulk_delete()))
 
293
  {
 
294
    if (error != 1)
 
295
      table->print_error(loc_error,MYF(0));
 
296
    error=1;
 
297
  }
292
298
  session->set_proc_info("end");
293
 
  info.end_read_record();
 
299
  end_read_record(&info);
 
300
  if (options & OPTION_QUICK)
 
301
    (void) table->cursor->extra(HA_EXTRA_NORMAL);
294
302
 
295
303
cleanup:
296
304
 
313
321
  transactional_table= table->cursor->has_transactions();
314
322
 
315
323
  if (!transactional_table && deleted > 0)
316
 
    session->transaction.stmt.markModifiedNonTransData();
 
324
    session->transaction.stmt.modified_non_trans_table= true;
317
325
 
318
326
  /* See similar binlogging code in sql_update.cc, for comments */
319
 
  if ((error < 0) || session->transaction.stmt.hasModifiedNonTransData())
 
327
  if ((error < 0) || session->transaction.stmt.modified_non_trans_table)
320
328
  {
321
 
    if (session->transaction.stmt.hasModifiedNonTransData())
322
 
      session->transaction.all.markModifiedNonTransData();
 
329
    if (session->transaction.stmt.modified_non_trans_table)
 
330
      session->transaction.all.modified_non_trans_table= true;
323
331
  }
324
 
  assert(transactional_table || !deleted || session->transaction.stmt.hasModifiedNonTransData());
 
332
  assert(transactional_table || !deleted || session->transaction.stmt.modified_non_trans_table);
325
333
  free_underlaid_joins(session, select_lex);
326
334
 
327
335
  DRIZZLE_DELETE_DONE((error >= 0 || session->is_error()), deleted);
335
343
    session->main_da.reset_diagnostics_area();    
336
344
    session->my_ok((ha_rows) session->row_count_func);
337
345
  }
338
 
  session->status_var.deleted_row_count+= deleted;
339
 
 
340
346
  return (error >= 0 || session->is_error());
 
347
 
 
348
err:
 
349
  DRIZZLE_DELETE_DONE(1, 0);
 
350
  return true;
341
351
}
342
352
 
343
353
 
396
406
bool mysql_truncate(Session& session, TableList *table_list)
397
407
{
398
408
  bool error;
399
 
  TransactionServices &transaction_services= TransactionServices::singleton();
400
409
 
401
410
  uint64_t save_options= session.options;
402
411
  table_list->lock_type= TL_WRITE;
403
412
  session.options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
 
413
  ha_enable_transaction(&session, false);
404
414
  mysql_init_select(session.lex);
405
415
  error= mysql_delete(&session, table_list, (COND*) 0, (SQL_LIST*) 0,
406
416
                      HA_POS_ERROR, 0L, true);
 
417
  ha_enable_transaction(&session, true);
407
418
  /*
408
419
    Safety, in case the engine ignored ha_enable_transaction(false)
409
420
    above. Also clears session->transaction.*.
410
421
  */
411
 
  error= transaction_services.autocommitOrRollback(&session, error);
 
422
  error= ha_autocommit_or_rollback(&session, error);
 
423
  ha_commit(&session);
412
424
  session.options= save_options;
413
425
 
414
426
  return error;
415
427
}
416
 
 
417
 
} /* namespace drizzled */