19
19
Multi-table deletes were introduced by Monty and Sinisa
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"
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>
38
30
Implement DELETE SQL word.
45
37
bool mysql_delete(Session *session, TableList *table_list, COND *conds,
46
SQL_LIST *order, ha_rows limit, uint64_t,
38
SQL_LIST *order, ha_rows limit, uint64_t options,
47
39
bool reset_auto_increment)
51
optimizer::SqlSelect *select= NULL;
53
46
bool using_limit=limit != HA_POS_ERROR;
54
bool transactional_table, const_cond;
47
bool transactional_table, safe_update, const_cond;
55
48
bool const_cond_result;
56
49
ha_rows deleted= 0;
57
50
uint32_t usable_index= MAX_KEY;
58
51
Select_Lex *select_lex= &session->lex->select_lex;
59
52
Session::killed_state killed_status= Session::NOT_KILLED;
61
55
if (session->openTablesLock(table_list))
63
57
DRIZZLE_DELETE_DONE(1, 0);
154
/* Update the table->cursor->stats.records number */
155
table->cursor->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
155
/* Update the table->file->stats.records number */
156
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
157
158
table->covering_keys.reset();
158
159
table->quick_keys.reset(); // Can't use 'only index'
159
select= optimizer::make_select(table, 0, 0, conds, 0, &error);
160
select=make_select(table, 0, 0, conds, 0, &error);
162
if ((select && select->check_quick(session, false, limit)) || !limit)
163
if ((select && select->check_quick(session, safe_update, limit)) || !limit)
165
166
free_underlaid_joins(session, select_lex);
166
167
session->row_count_func= 0;
167
DRIZZLE_DELETE_DONE(0, 0);
169
* Resetting the Diagnostic area to prevent
172
session->main_da.reset_diagnostics_area();
168
DRIZZLE_DELETE_END(0, 0);
173
169
session->my_ok((ha_rows) session->row_count_func);
175
171
We don't need to call reset_auto_increment in this case, because
192
198
ha_rows examined_rows;
194
200
if ((!select || table->quick_keys.none()) && limit != HA_POS_ERROR)
195
usable_index= optimizer::get_index_for_order(table, (order_st*)(order->first), limit);
201
usable_index= get_index_for_order(table, (order_st*)(order->first), limit);
197
203
if (usable_index == MAX_KEY)
199
table->sort.io_cache= new internal::IO_CACHE;
200
memset(table->sort.io_cache, 0, sizeof(internal::IO_CACHE));
205
table->sort.io_cache= new IO_CACHE;
206
memset(table->sort.io_cache, 0, sizeof(IO_CACHE));
203
209
if (!(sortorder= make_unireg_sortorder((order_st*) order->first,
286
299
We're really doing a truncate and need to reset the table's
287
300
auto-increment counter.
289
int error2= table->cursor->ha_reset_auto_increment(0);
302
int error2= table->file->ha_reset_auto_increment(0);
291
304
if (error2 && (error2 != HA_ERR_WRONG_COMMAND))
293
table->print_error(error2, MYF(0));
306
table->file->print_error(error2, MYF(0));
299
transactional_table= table->cursor->has_transactions();
314
transactional_table= table->file->has_transactions();
301
316
if (!transactional_table && deleted > 0)
302
session->transaction.stmt.markModifiedNonTransData();
317
session->transaction.stmt.modified_non_trans_table= true;
304
319
/* See similar binlogging code in sql_update.cc, for comments */
305
if ((error < 0) || session->transaction.stmt.hasModifiedNonTransData())
320
if ((error < 0) || session->transaction.stmt.modified_non_trans_table)
307
if (session->transaction.stmt.hasModifiedNonTransData())
308
session->transaction.all.markModifiedNonTransData();
322
if (session->transaction.stmt.modified_non_trans_table)
323
session->transaction.all.modified_non_trans_table= true;
310
assert(transactional_table || !deleted || session->transaction.stmt.hasModifiedNonTransData());
325
assert(transactional_table || !deleted || session->transaction.stmt.modified_non_trans_table);
311
326
free_underlaid_joins(session, select_lex);
313
DRIZZLE_DELETE_DONE((error >= 0 || session->is_error()), deleted);
328
int res= (error >= 0 || session->is_error());
329
DRIZZLE_DELETE_END(res, deleted);
314
330
if (error < 0 || (session->lex->ignore && !session->is_fatal_error))
316
332
session->row_count_func= deleted;
318
* Resetting the Diagnostic area to prevent
321
session->main_da.reset_diagnostics_area();
322
333
session->my_ok((ha_rows) session->row_count_func);
324
335
return (error >= 0 || session->is_error());
327
DRIZZLE_DELETE_DONE(1, 0);
338
DRIZZLE_DELETE_END(1, 0);
380
391
Optimize delete of all rows by doing a full generate of the table
381
392
This will work even if the .ISM and .ISD tables are destroyed
394
dont_send_ok should be set if:
395
- We should always wants to generate the table (even if the table type
396
normally can't safely do this.
397
- We don't want an ok to be sent to the end user.
398
- We don't want to log the truncate command
399
- If we want to have a name lock on the table on exit without errors.
384
bool mysql_truncate(Session& session, TableList *table_list)
402
bool mysql_truncate(Session *session, TableList *table_list, bool dont_send_ok)
404
HA_CREATE_INFO create_info;
405
char path[FN_REFLEN];
387
TransactionServices &transaction_services= TransactionServices::singleton();
389
uint64_t save_options= session.options;
408
uint32_t path_length;
411
memset(&create_info, 0, sizeof(create_info));
412
/* If it is a temporary table, close and regenerate it */
413
if (!dont_send_ok && (table= session->find_temporary_table(table_list)))
415
StorageEngine *table_type= table->s->db_type();
416
TableShare *share= table->s;
418
if (!table_type->check_flag(HTON_BIT_CAN_RECREATE))
421
table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
423
session->close_temporary_table(table, false, false); // Don't free share
424
ha_create_table(session, share->normalized_path.str,
425
share->db.str, share->table_name.str, &create_info, 1,
427
// We don't need to call invalidate() because this table is not in cache
428
if ((error= (int) !(session->open_temporary_table(share->path.str,
430
share->table_name.str, 1,
432
(void) session->rm_temporary_table(table_type, path);
433
share->free_table_share();
436
If we return here we will not have logged the truncation to the bin log
437
and we will not my_ok() to the client.
442
path_length= build_table_filename(path, sizeof(path), table_list->db,
443
table_list->table_name, 0);
448
pthread_mutex_lock(&LOCK_open); /* Recreate table for truncate */
449
error= ha_create_table(session, path, table_list->db, table_list->table_name,
450
&create_info, 1, NULL);
451
pthread_mutex_unlock(&LOCK_open);
459
TRUNCATE must always be statement-based binlogged (not row-based) so
460
we don't test current_stmt_binlog_row_based.
462
write_bin_log(session, true, session->query, session->query_length);
463
session->my_ok(); // This should return record count
465
pthread_mutex_lock(&LOCK_open); /* For truncate delete from hash when finished */
466
unlock_table_name(table_list);
467
pthread_mutex_unlock(&LOCK_open);
471
pthread_mutex_lock(&LOCK_open); /* For truncate delete from hash when finished */
472
unlock_table_name(table_list);
473
pthread_mutex_unlock(&LOCK_open);
478
/* Probably InnoDB table */
479
uint64_t save_options= session->options;
390
480
table_list->lock_type= TL_WRITE;
391
session.options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
392
mysql_init_select(session.lex);
393
error= mysql_delete(&session, table_list, (COND*) 0, (SQL_LIST*) 0,
481
session->options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
482
ha_enable_transaction(session, false);
483
mysql_init_select(session->lex);
484
error= mysql_delete(session, table_list, (COND*) 0, (SQL_LIST*) 0,
394
485
HA_POS_ERROR, 0L, true);
486
ha_enable_transaction(session, true);
396
488
Safety, in case the engine ignored ha_enable_transaction(false)
397
489
above. Also clears session->transaction.*.
399
error= transaction_services.ha_autocommit_or_rollback(&session, error);
400
session.options= save_options;
491
error= ha_autocommit_or_rollback(session, error);
493
session->options= save_options;
405
} /* namespace drizzled */