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->lex->select_lex;
60
Session::killed_state_t killed_status= Session::NOT_KILLED;
62
if (session->openTablesLock(table_list))
51
SELECT_LEX *select_lex= &session->lex->select_lex;
52
Session::killed_state killed_status= Session::NOT_KILLED;
55
if (open_and_lock_tables(session, table_list))
57
/* TODO look at this error */
58
if (!(table= table_list->table))
64
DRIZZLE_DELETE_DONE(1, 0);
60
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), "", "");
68
table= table_list->table;
71
63
session->set_proc_info("init");
74
if (prepare_delete(session, table_list, &conds))
76
DRIZZLE_DELETE_DONE(1, 0);
66
if (mysql_prepare_delete(session, table_list, &conds))
80
69
/* check ORDER BY even if it can be ignored */
81
70
if (order && order->elements)
159
/* Update the table->cursor->stats.records number */
160
table->cursor->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
154
/* Update the table->file->stats.records number */
155
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
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);
157
table->covering_keys.clear_all();
158
table->quick_keys.clear_all(); // Can't use 'only index'
159
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)
162
if ((select && select->check_quick(session, safe_update, limit)) || !limit)
174
165
free_underlaid_joins(session, select_lex);
175
166
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());
167
DRIZZLE_DELETE_END();
168
my_ok(session, (ha_rows) session->row_count_func);
186
170
We don't need to call reset_auto_increment in this case, because
187
171
mysql_truncate always gives a NULL conds argument, hence we never
190
return 0; // Nothing to delete
174
return(0); // Nothing to delete
193
177
/* If running in safe sql mode, don't allow updates without keys */
194
if (table->quick_keys.none())
178
if (table->quick_keys.is_clear_all())
196
180
session->server_status|=SERVER_QUERY_NO_INDEX_USED;
181
if (safe_update && !using_limit)
184
free_underlaid_joins(session, select_lex);
185
my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
186
ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
190
if (options & OPTION_QUICK)
191
(void) table->file->extra(HA_EXTRA_QUICK);
199
193
if (order && order->elements)
201
195
uint32_t length= 0;
202
SortField *sortorder;
196
SORT_FIELD *sortorder;
203
197
ha_rows examined_rows;
205
if ((!select || table->quick_keys.none()) && limit != HA_POS_ERROR)
206
usable_index= optimizer::get_index_for_order(table, (Order*)(order->first), limit);
199
if ((!select || table->quick_keys.is_clear_all()) && limit != HA_POS_ERROR)
200
usable_index= get_index_for_order(table, (order_st*)(order->first), limit);
208
202
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)
204
table->sort.io_cache= new IO_CACHE;
205
memset(table->sort.io_cache, 0, sizeof(IO_CACHE));
208
if (!(sortorder= make_unireg_sortorder((order_st*) order->first,
210
(table->sort.found_records = filesort(session, table, sortorder, length,
211
select, HA_POS_ERROR, 1,
220
216
free_underlaid_joins(session, &session->lex->select_lex);
222
DRIZZLE_DELETE_DONE(1, 0);
226
220
Filesort has already found and selected the rows we want to delete,
314
298
We're really doing a truncate and need to reset the table's
315
299
auto-increment counter.
317
int error2= table->cursor->ha_reset_auto_increment(0);
301
int error2= table->file->ha_reset_auto_increment(0);
319
303
if (error2 && (error2 != HA_ERR_WRONG_COMMAND))
321
table->print_error(error2, MYF(0));
305
table->file->print_error(error2, MYF(0));
327
transactional_table= table->cursor->has_transactions();
313
transactional_table= table->file->has_transactions();
329
315
if (!transactional_table && deleted > 0)
330
session->transaction.stmt.markModifiedNonTransData();
316
session->transaction.stmt.modified_non_trans_table= true;
332
318
/* See similar binlogging code in sql_update.cc, for comments */
333
if ((error < 0) || session->transaction.stmt.hasModifiedNonTransData())
319
if ((error < 0) || session->transaction.stmt.modified_non_trans_table)
335
if (session->transaction.stmt.hasModifiedNonTransData())
336
session->transaction.all.markModifiedNonTransData();
321
if (session->transaction.stmt.modified_non_trans_table)
322
session->transaction.all.modified_non_trans_table= true;
338
assert(transactional_table || !deleted || session->transaction.stmt.hasModifiedNonTransData());
324
assert(transactional_table || !deleted || session->transaction.stmt.modified_non_trans_table);
339
325
free_underlaid_joins(session, select_lex);
341
DRIZZLE_DELETE_DONE((error >= 0 || session->is_error()), deleted);
327
DRIZZLE_DELETE_END();
342
328
if (error < 0 || (session->lex->ignore && !session->is_fatal_error))
344
330
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());
331
my_ok(session, (ha_rows) session->row_count_func);
352
session->status_var.deleted_row_count+= deleted;
333
return(error >= 0 || session->is_error());
354
return (error >= 0 || session->is_error());
336
DRIZZLE_DELETE_END();
379
362
&session->lex->select_lex.top_join_list,
381
364
&select_lex->leaf_tables, false) ||
382
session->setup_conds(table_list, conds))
365
setup_conds(session, table_list, select_lex->leaf_tables, conds))
385
368
TableList *duplicate;
386
if ((duplicate= unique_table(table_list, table_list->next_global)))
369
if ((duplicate= unique_table(session, table_list, table_list->next_global, 0)))
388
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->alias);
371
update_non_unique_table_error(table_list, "DELETE", duplicate);
393
376
if (select_lex->inner_refs_list.elements &&
394
377
fix_inner_refs(session, all_fields, select_lex, select_lex->ref_pointer_array))
384
/***************************************************************************
385
Delete multiple tables from join
386
***************************************************************************/
388
#define MEM_STRIP_BUF_SIZE current_session->variables.sortbuff_size
390
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
392
handler *file= (handler*)arg;
393
return file->cmp_ref((const unsigned char*)a, (const unsigned char*)b);
397
make delete specific preparation and checks after opening tables
400
mysql_multi_delete_prepare()
401
session thread handler
408
int mysql_multi_delete_prepare(Session *session)
410
LEX *lex= session->lex;
411
TableList *aux_tables= (TableList *)lex->auxiliary_table_list.first;
412
TableList *target_tbl;
416
setup_tables() need for VIEWs. JOIN::prepare() will not do it second
419
lex->query_tables also point on local list of DELETE SELECT_LEX
421
if (setup_tables_and_check_access(session, &session->lex->select_lex.context,
422
&session->lex->select_lex.top_join_list,
424
&lex->select_lex.leaf_tables, false))
429
Multi-delete can't be constructed over-union => we always have
430
single SELECT on top and have to check underlying SELECTs of it
432
lex->select_lex.exclude_from_table_unique_test= true;
433
/* Fix tables-to-be-deleted-from list to point at opened tables */
434
for (target_tbl= (TableList*) aux_tables;
436
target_tbl= target_tbl->next_local)
438
if (!(target_tbl->table= target_tbl->correspondent_table->table))
440
assert(target_tbl->correspondent_table->merge_underlying_list &&
441
target_tbl->correspondent_table->merge_underlying_list->
443
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), "", "");
448
Check that table from which we delete is not used somewhere
449
inside subqueries/view.
452
TableList *duplicate;
453
if ((duplicate= unique_table(session, target_tbl->correspondent_table,
454
lex->query_tables, 0)))
456
update_non_unique_table_error(target_tbl->correspondent_table,
457
"DELETE", duplicate);
466
multi_delete::multi_delete(TableList *dt, uint32_t num_of_tables_arg)
467
: delete_tables(dt), deleted(0), found(0),
468
num_of_tables(num_of_tables_arg), error(0),
469
do_delete(0), transactional_tables(0), normal_tables(0), error_handled(0)
471
tempfiles= (Unique **) sql_calloc(sizeof(Unique *) * num_of_tables);
476
multi_delete::prepare(List<Item> &, SELECT_LEX_UNIT *u)
481
session->set_proc_info("deleting from main table");
487
multi_delete::initialize_tables(JOIN *join)
490
Unique **tempfiles_ptr;
493
if ((session->options & OPTION_SAFE_UPDATES) && error_if_full_join(join))
496
table_map tables_to_delete_from=0;
497
for (walk= delete_tables; walk; walk= walk->next_local)
498
tables_to_delete_from|= walk->table->map;
501
delete_while_scanning= 1;
502
for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
506
if (tab->table->map & tables_to_delete_from)
508
/* We are going to delete from this table */
509
Table *tbl=walk->table=tab->table;
510
walk= walk->next_local;
511
/* Don't use KEYREAD optimization on this table */
513
/* Don't use record cache */
515
tbl->covering_keys.clear_all();
516
if (tbl->file->has_transactions())
517
transactional_tables= 1;
520
tbl->prepare_for_position();
521
tbl->mark_columns_needed_for_delete();
523
else if ((tab->type != JT_SYSTEM && tab->type != JT_CONST) &&
524
walk == delete_tables)
527
We are not deleting from the table we are scanning. In this
528
case send_data() shouldn't delete any rows a we may touch
529
the rows in the deleted table many times
531
delete_while_scanning= 0;
535
tempfiles_ptr= tempfiles;
536
if (delete_while_scanning)
538
table_being_deleted= delete_tables;
539
walk= walk->next_local;
541
for (;walk ;walk= walk->next_local)
543
Table *table=walk->table;
544
*tempfiles_ptr++= new Unique (refpos_order_cmp,
545
(void *) table->file,
546
table->file->ref_length,
549
return(session->is_fatal_error != 0);
553
multi_delete::~multi_delete()
555
for (table_being_deleted= delete_tables;
557
table_being_deleted= table_being_deleted->next_local)
559
Table *table= table_being_deleted->table;
563
for (uint32_t counter= 0; counter < num_of_tables; counter++)
565
if (tempfiles[counter])
566
delete tempfiles[counter];
571
bool multi_delete::send_data(List<Item> &)
573
int secure_counter= delete_while_scanning ? -1 : 0;
574
TableList *del_table;
577
for (del_table= delete_tables;
579
del_table= del_table->next_local, secure_counter++)
581
Table *table= del_table->table;
583
/* Check if we are using outer join and we didn't find the row */
584
if (table->status & (STATUS_NULL_ROW | STATUS_DELETED))
587
table->file->position(table->record[0]);
590
if (secure_counter < 0)
592
/* We are scanning the current table */
593
assert(del_table == table_being_deleted);
594
table->status|= STATUS_DELETED;
595
if (!(error=table->file->ha_delete_row(table->record[0])))
598
if (!table->file->has_transactions())
599
session->transaction.stmt.modified_non_trans_table= true;
603
table->file->print_error(error,MYF(0));
609
error=tempfiles[secure_counter]->unique_add((char*) table->file->ref);
612
error= 1; // Fatal error
621
void multi_delete::send_error(uint32_t errcode,const char *err)
625
/* First send error what ever it is ... */
626
my_message(errcode, err, MYF(0));
632
void multi_delete::abort()
636
/* the error was handled or nothing deleted and no side effects return */
638
(!session->transaction.stmt.modified_non_trans_table && !deleted))
642
If rows from the first table only has been deleted and it is
643
transactional, just do rollback.
644
The same if all tables are transactional, regardless of where we are.
645
In all other cases do attempt deletes ...
647
if (do_delete && normal_tables &&
648
(table_being_deleted != delete_tables ||
649
!table_being_deleted->table->file->has_transactions()))
652
We have to execute the recorded do_deletes() and write info into the
657
assert(error_handled);
661
if (session->transaction.stmt.modified_non_trans_table)
663
session->transaction.all.modified_non_trans_table= true;
671
Do delete from other tables.
677
int multi_delete::do_deletes()
679
int local_error= 0, counter= 0, tmp_error;
684
do_delete= 0; // Mark called
688
table_being_deleted= (delete_while_scanning ? delete_tables->next_local :
691
for (; table_being_deleted;
692
table_being_deleted= table_being_deleted->next_local, counter++)
694
ha_rows last_deleted= deleted;
695
Table *table = table_being_deleted->table;
696
if (tempfiles[counter]->get(table))
703
init_read_record(&info,session,table,NULL,0,1);
705
Ignore any rows not found in reference tables as they may already have
706
been deleted by foreign key handling
708
info.ignore_not_found_rows= 1;
709
will_batch= !table->file->start_bulk_delete();
710
while (!(local_error=info.read_record(&info)) && !session->killed)
712
if ((local_error=table->file->ha_delete_row(table->record[0])))
714
table->file->print_error(local_error,MYF(0));
719
if (will_batch && (tmp_error= table->file->end_bulk_delete()))
723
local_error= tmp_error;
724
table->file->print_error(local_error,MYF(0));
727
if (last_deleted != deleted && !table->file->has_transactions())
728
session->transaction.stmt.modified_non_trans_table= true;
729
end_read_record(&info);
730
if (session->killed && !local_error)
732
if (local_error == -1) // End of file
740
Send ok to the client
746
bool multi_delete::send_eof()
748
Session::killed_state killed_status= Session::NOT_KILLED;
749
session->set_proc_info("deleting from reference tables");
751
/* Does deletes for the last n - 1 tables, returns 0 if ok */
752
int local_error= do_deletes(); // returns 0 if success
754
/* compute a total error to know if something failed */
755
local_error= local_error || error;
756
killed_status= (local_error == 0)? Session::NOT_KILLED : session->killed;
757
/* reset used flags */
758
session->set_proc_info("end");
760
if ((local_error == 0) || session->transaction.stmt.modified_non_trans_table)
762
if (session->transaction.stmt.modified_non_trans_table)
763
session->transaction.all.modified_non_trans_table= true;
765
if (local_error != 0)
766
error_handled= true; // to force early leave from ::send_error()
770
session->row_count_func= deleted;
771
::my_ok(session, (ha_rows) session->row_count_func);
401
777
/***************************************************************************
403
779
****************************************************************************/
406
782
Optimize delete of all rows by doing a full generate of the table
407
783
This will work even if the .ISM and .ISD tables are destroyed
785
dont_send_ok should be set if:
786
- We should always wants to generate the table (even if the table type
787
normally can't safely do this.
788
- We don't want an ok to be sent to the end user.
789
- We don't want to log the truncate command
790
- If we want to have a name lock on the table on exit without errors.
410
bool truncate(Session& session, TableList *table_list)
793
bool mysql_truncate(Session *session, TableList *table_list, bool dont_send_ok)
795
HA_CREATE_INFO create_info;
796
char path[FN_REFLEN];
413
TransactionServices &transaction_services= TransactionServices::singleton();
415
uint64_t save_options= session.options;
799
uint32_t path_length;
802
memset(&create_info, 0, sizeof(create_info));
803
/* If it is a temporary table, close and regenerate it */
804
if (!dont_send_ok && (table= find_temporary_table(session, table_list)))
806
handlerton *table_type= table->s->db_type();
807
TABLE_SHARE *share= table->s;
809
if (!ha_check_storage_engine_flag(table_type, HTON_BIT_CAN_RECREATE))
812
table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
814
close_temporary_table(session, table, 0, 0); // Don't free share
815
ha_create_table(session, share->normalized_path.str,
816
share->db.str, share->table_name.str, &create_info, 1);
817
// We don't need to call invalidate() because this table is not in cache
818
if ((error= (int) !(open_temporary_table(session, share->path.str,
820
share->table_name.str, 1,
822
(void) rm_temporary_table(table_type, path);
823
free_table_share(share);
826
If we return here we will not have logged the truncation to the bin log
827
and we will not my_ok() to the client.
832
path_length= build_table_filename(path, sizeof(path), table_list->db,
833
table_list->table_name, reg_ext, 0);
838
// Remove the .frm extension AIX 5.2 64-bit compiler bug (BUG#16155): this
839
// crashes, replacement works. *(path + path_length - reg_ext_length)=
841
path[path_length - reg_ext_length] = 0;
842
pthread_mutex_lock(&LOCK_open);
843
error= ha_create_table(session, path, table_list->db, table_list->table_name,
845
pthread_mutex_unlock(&LOCK_open);
853
TRUNCATE must always be statement-based binlogged (not row-based) so
854
we don't test current_stmt_binlog_row_based.
856
write_bin_log(session, true, session->query, session->query_length);
857
my_ok(session); // This should return record count
859
pthread_mutex_lock(&LOCK_open);
860
unlock_table_name(session, table_list);
861
pthread_mutex_unlock(&LOCK_open);
865
pthread_mutex_lock(&LOCK_open);
866
unlock_table_name(session, table_list);
867
pthread_mutex_unlock(&LOCK_open);
872
/* Probably InnoDB table */
873
uint64_t save_options= session->options;
416
874
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,
875
session->options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
876
ha_enable_transaction(session, false);
877
mysql_init_select(session->lex);
878
error= mysql_delete(session, table_list, (COND*) 0, (SQL_LIST*) 0,
420
879
HA_POS_ERROR, 0L, true);
880
ha_enable_transaction(session, true);
422
882
Safety, in case the engine ignored ha_enable_transaction(false)
423
883
above. Also clears session->transaction.*.
425
error= transaction_services.autocommitOrRollback(session, error);
426
session.options= save_options;
885
error= ha_autocommit_or_rollback(session, error);
887
session->options= save_options;
431
} /* namespace drizzled */