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 */
17
17
Delete of records and truncate of tables.
19
19
Multi-table deletes were introduced by Monty and Sinisa
21
#include <drizzled/server_includes.h>
22
22
#include <drizzled/sql_select.h>
23
23
#include <drizzled/error.h>
24
24
#include <drizzled/probes.h>
25
25
#include <drizzled/sql_parse.h>
26
26
#include <drizzled/sql_base.h>
27
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>
39
30
Implement DELETE SQL word.
43
34
end of dispatch_command().
46
bool delete_query(Session *session, TableList *table_list, COND *conds,
47
SQL_LIST *order, ha_rows limit, uint64_t,
37
bool mysql_delete(Session *session, TableList *table_list, COND *conds,
38
SQL_LIST *order, ha_rows limit, uint64_t options,
48
39
bool reset_auto_increment)
52
optimizer::SqlSelect *select= NULL;
54
46
bool using_limit=limit != HA_POS_ERROR;
55
bool transactional_table, const_cond;
47
bool transactional_table, safe_update, const_cond;
56
48
bool const_cond_result;
57
49
ha_rows deleted= 0;
58
50
uint32_t usable_index= MAX_KEY;
59
Select_Lex *select_lex= &session->getLex()->select_lex;
60
Session::killed_state_t killed_status= Session::NOT_KILLED;
51
Select_Lex *select_lex= &session->lex->select_lex;
52
Session::killed_state killed_status= Session::NOT_KILLED;
62
55
if (session->openTablesLock(table_list))
64
DRIZZLE_DELETE_DONE(1, 0);
68
58
table= table_list->table;
85
72
List<Item> all_fields;
74
memset(&tables, 0, sizeof(tables));
87
75
tables.table = table;
88
76
tables.alias = table_list->alias;
90
78
if (select_lex->setup_ref_array(session, order->elements) ||
91
79
setup_order(session, select_lex->ref_pointer_array, &tables,
92
fields, all_fields, (Order*) order->first))
95
free_underlaid_joins(session, &session->getLex()->select_lex);
96
DRIZZLE_DELETE_DONE(1, 0);
80
fields, all_fields, (order_st*) order->first))
83
free_underlaid_joins(session, &session->lex->select_lex);
102
88
const_cond= (!conds || conds->const_item());
89
safe_update=test(session->options & OPTION_SAFE_UPDATES);
90
if (safe_update && const_cond)
92
my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
93
ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
104
select_lex->no_error= session->getLex()->ignore;
97
select_lex->no_error= session->lex->ignore;
106
99
const_cond_result= const_cond && (!conds || conds->val_int());
107
100
if (session->is_error())
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);
162
155
table->covering_keys.reset();
163
156
table->quick_keys.reset(); // Can't use 'only index'
164
select= optimizer::make_select(table, 0, 0, conds, 0, &error);
157
select=make_select(table, 0, 0, conds, 0, &error);
167
DRIZZLE_DELETE_DONE(1, 0);
171
if ((select && select->check_quick(session, false, limit)) || !limit)
160
if ((select && select->check_quick(session, safe_update, limit)) || !limit)
174
163
free_underlaid_joins(session, select_lex);
175
164
session->row_count_func= 0;
176
if (session->is_error())
178
DRIZZLE_DELETE_DONE(0, 0);
180
* Resetting the Diagnostic area to prevent
183
session->main_da.reset_diagnostics_area();
184
session->my_ok((ha_rows) session->rowCount());
165
DRIZZLE_DELETE_END();
166
session->my_ok((ha_rows) session->row_count_func);
186
168
We don't need to call reset_auto_increment in this case, because
187
169
mysql_truncate always gives a NULL conds argument, hence we never
190
return 0; // Nothing to delete
172
return(0); // Nothing to delete
193
175
/* If running in safe sql mode, don't allow updates without keys */
194
176
if (table->quick_keys.none())
196
178
session->server_status|=SERVER_QUERY_NO_INDEX_USED;
179
if (safe_update && !using_limit)
182
free_underlaid_joins(session, select_lex);
183
my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
184
ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
188
if (options & OPTION_QUICK)
189
(void) table->file->extra(HA_EXTRA_QUICK);
199
191
if (order && order->elements)
201
193
uint32_t length= 0;
202
SortField *sortorder;
194
SORT_FIELD *sortorder;
203
195
ha_rows examined_rows;
205
197
if ((!select || table->quick_keys.none()) && limit != HA_POS_ERROR)
206
usable_index= optimizer::get_index_for_order(table, (Order*)(order->first), limit);
198
usable_index= get_index_for_order(table, (order_st*)(order->first), limit);
208
200
if (usable_index == MAX_KEY)
210
FileSort filesort(*session);
211
table->sort.io_cache= new internal::IO_CACHE;
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)
202
table->sort.io_cache= new IO_CACHE;
203
memset(table->sort.io_cache, 0, sizeof(IO_CACHE));
206
if (!(sortorder= make_unireg_sortorder((order_st*) order->first,
208
(table->sort.found_records = filesort(session, table, sortorder, length,
209
select, HA_POS_ERROR, 1,
220
free_underlaid_joins(session, &session->getLex()->select_lex);
222
DRIZZLE_DELETE_DONE(1, 0);
214
free_underlaid_joins(session, &session->lex->select_lex);
226
218
Filesort has already found and selected the rows we want to delete,
239
231
free_underlaid_joins(session, select_lex);
240
DRIZZLE_DELETE_DONE(1, 0);
244
234
if (usable_index==MAX_KEY)
246
if ((error= info.init_read_record(session,table,select,1,1)))
248
table->print_error(error, MYF(0));
250
free_underlaid_joins(session, select_lex);
235
init_read_record(&info,session,table,select,1,1);
256
if ((error= info.init_read_record_idx(session, table, 1, usable_index)))
258
table->print_error(error, MYF(0));
260
free_underlaid_joins(session, select_lex);
237
init_read_record_idx(&info, session, table, 1, usable_index);
265
239
session->set_proc_info("updating");
241
will_batch= !table->file->start_bulk_delete();
267
244
table->mark_columns_needed_for_delete();
269
while (!(error=info.read_record(&info)) && !session->getKilled() &&
246
while (!(error=info.read_record(&info)) && !session->killed &&
270
247
! session->is_error())
272
249
// session->is_error() is tested to disallow delete row on error
273
250
if (!(select && select->skip_record())&& ! session->is_error() )
275
if (!(error= table->cursor->deleteRecord(table->getInsertRecord())))
252
if (!(error= table->file->ha_delete_row(table->record[0])))
278
255
if (!--limit && using_limit)
314
296
We're really doing a truncate and need to reset the table's
315
297
auto-increment counter.
317
int error2= table->cursor->ha_reset_auto_increment(0);
299
int error2= table->file->ha_reset_auto_increment(0);
319
301
if (error2 && (error2 != HA_ERR_WRONG_COMMAND))
321
table->print_error(error2, MYF(0));
303
table->file->print_error(error2, MYF(0));
327
transactional_table= table->cursor->has_transactions();
311
transactional_table= table->file->has_transactions();
329
313
if (!transactional_table && deleted > 0)
330
session->transaction.stmt.markModifiedNonTransData();
314
session->transaction.stmt.modified_non_trans_table= true;
332
316
/* See similar binlogging code in sql_update.cc, for comments */
333
if ((error < 0) || session->transaction.stmt.hasModifiedNonTransData())
317
if ((error < 0) || session->transaction.stmt.modified_non_trans_table)
335
if (session->transaction.stmt.hasModifiedNonTransData())
336
session->transaction.all.markModifiedNonTransData();
319
if (session->transaction.stmt.modified_non_trans_table)
320
session->transaction.all.modified_non_trans_table= true;
338
assert(transactional_table || !deleted || session->transaction.stmt.hasModifiedNonTransData());
322
assert(transactional_table || !deleted || session->transaction.stmt.modified_non_trans_table);
339
323
free_underlaid_joins(session, select_lex);
341
DRIZZLE_DELETE_DONE((error >= 0 || session->is_error()), deleted);
342
if (error < 0 || (session->getLex()->ignore && !session->is_fatal_error))
325
DRIZZLE_DELETE_END();
326
if (error < 0 || (session->lex->ignore && !session->is_fatal_error))
344
328
session->row_count_func= deleted;
346
* Resetting the Diagnostic area to prevent
349
session->main_da.reset_diagnostics_area();
350
session->my_ok((ha_rows) session->rowCount());
329
session->my_ok((ha_rows) session->row_count_func);
352
session->status_var.deleted_row_count+= deleted;
331
return(error >= 0 || session->is_error());
354
return (error >= 0 || session->is_error());
334
DRIZZLE_DELETE_END();
371
int prepare_delete(Session *session, TableList *table_list, Item **conds)
352
int mysql_prepare_delete(Session *session, TableList *table_list, Item **conds)
373
Select_Lex *select_lex= &session->getLex()->select_lex;
354
Select_Lex *select_lex= &session->lex->select_lex;
375
356
List<Item> all_fields;
377
session->getLex()->allow_sum_func= 0;
378
if (setup_tables_and_check_access(session, &session->getLex()->select_lex.context,
379
&session->getLex()->select_lex.top_join_list,
358
session->lex->allow_sum_func= 0;
359
if (setup_tables_and_check_access(session, &session->lex->select_lex.context,
360
&session->lex->select_lex.top_join_list,
381
362
&select_lex->leaf_tables, false) ||
382
363
session->setup_conds(table_list, conds))
385
366
TableList *duplicate;
386
if ((duplicate= unique_table(table_list, table_list->next_global)))
367
if ((duplicate= unique_table(session, table_list, table_list->next_global, 0)))
388
369
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->alias);
406
387
Optimize delete of all rows by doing a full generate of the table
407
388
This will work even if the .ISM and .ISD tables are destroyed
390
dont_send_ok should be set if:
391
- We should always wants to generate the table (even if the table type
392
normally can't safely do this.
393
- We don't want an ok to be sent to the end user.
394
- We don't want to log the truncate command
395
- If we want to have a name lock on the table on exit without errors.
410
bool truncate(Session& session, TableList *table_list)
398
bool mysql_truncate(Session *session, TableList *table_list, bool dont_send_ok)
400
HA_CREATE_INFO create_info;
401
char path[FN_REFLEN];
413
TransactionServices &transaction_services= TransactionServices::singleton();
415
uint64_t save_options= session.options;
404
uint32_t path_length;
407
memset(&create_info, 0, sizeof(create_info));
408
/* If it is a temporary table, close and regenerate it */
409
if (!dont_send_ok && (table= session->find_temporary_table(table_list)))
411
StorageEngine *table_type= table->s->db_type();
412
TableShare *share= table->s;
414
if (!table_type->check_flag(HTON_BIT_CAN_RECREATE))
417
table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
419
session->close_temporary_table(table, false, false); // Don't free share
420
ha_create_table(session, share->normalized_path.str,
421
share->db.str, share->table_name.str, &create_info, 1,
423
// We don't need to call invalidate() because this table is not in cache
424
if ((error= (int) !(session->open_temporary_table(share->path.str,
426
share->table_name.str, 1,
428
(void) session->rm_temporary_table(table_type, path);
429
share->free_table_share();
432
If we return here we will not have logged the truncation to the bin log
433
and we will not my_ok() to the client.
438
path_length= build_table_filename(path, sizeof(path), table_list->db,
439
table_list->table_name, 0);
444
pthread_mutex_lock(&LOCK_open); /* Recreate table for truncate */
445
error= ha_create_table(session, path, table_list->db, table_list->table_name,
446
&create_info, 1, NULL);
447
pthread_mutex_unlock(&LOCK_open);
455
TRUNCATE must always be statement-based binlogged (not row-based) so
456
we don't test current_stmt_binlog_row_based.
458
write_bin_log(session, true, session->query, session->query_length);
459
session->my_ok(); // This should return record count
461
pthread_mutex_lock(&LOCK_open); /* For truncate delete from hash when finished */
462
unlock_table_name(table_list);
463
pthread_mutex_unlock(&LOCK_open);
467
pthread_mutex_lock(&LOCK_open); /* For truncate delete from hash when finished */
468
unlock_table_name(table_list);
469
pthread_mutex_unlock(&LOCK_open);
474
/* Probably InnoDB table */
475
uint64_t save_options= session->options;
416
476
table_list->lock_type= TL_WRITE;
417
session.options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
418
init_select(session.getLex());
419
error= delete_query(&session, table_list, (COND*) 0, (SQL_LIST*) 0,
477
session->options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
478
ha_enable_transaction(session, false);
479
mysql_init_select(session->lex);
480
error= mysql_delete(session, table_list, (COND*) 0, (SQL_LIST*) 0,
420
481
HA_POS_ERROR, 0L, true);
482
ha_enable_transaction(session, true);
422
484
Safety, in case the engine ignored ha_enable_transaction(false)
423
485
above. Also clears session->transaction.*.
425
error= transaction_services.autocommitOrRollback(session, error);
426
session.options= save_options;
487
error= ha_autocommit_or_rollback(session, error);
489
session->options= save_options;
431
} /* namespace drizzled */