310
311
transactional_table= table->file->has_transactions();
312
313
if (!transactional_table && deleted > 0)
313
thd->transaction.stmt.modified_non_trans_table= true;
314
session->transaction.stmt.modified_non_trans_table= true;
315
316
/* See similar binlogging code in sql_update.cc, for comments */
316
if ((error < 0) || thd->transaction.stmt.modified_non_trans_table)
317
if ((error < 0) || session->transaction.stmt.modified_non_trans_table)
318
if (mysql_bin_log.is_open())
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.
328
int log_result= thd->binlog_query(THD::ROW_QUERY_TYPE,
329
thd->query, thd->query_length,
330
transactional_table, false, killed_status);
332
if (log_result && transactional_table)
337
if (thd->transaction.stmt.modified_non_trans_table)
338
thd->transaction.all.modified_non_trans_table= true;
319
if (session->transaction.stmt.modified_non_trans_table)
320
session->transaction.all.modified_non_trans_table= true;
340
assert(transactional_table || !deleted || thd->transaction.stmt.modified_non_trans_table);
341
free_underlaid_joins(thd, select_lex);
322
assert(transactional_table || !deleted || session->transaction.stmt.modified_non_trans_table);
323
free_underlaid_joins(session, select_lex);
343
325
DRIZZLE_DELETE_END();
344
if (error < 0 || (thd->lex->ignore && !thd->is_fatal_error))
326
if (error < 0 || (session->lex->ignore && !session->is_fatal_error))
346
thd->row_count_func= deleted;
347
my_ok(thd, (ha_rows) thd->row_count_func);
328
session->row_count_func= deleted;
329
session->my_ok((ha_rows) session->row_count_func);
349
return(error >= 0 || thd->is_error());
331
return(error >= 0 || session->is_error());
352
334
DRIZZLE_DELETE_END();
370
int mysql_prepare_delete(THD *thd, TableList *table_list, Item **conds)
352
int mysql_prepare_delete(Session *session, TableList *table_list, Item **conds)
372
SELECT_LEX *select_lex= &thd->lex->select_lex;
354
Select_Lex *select_lex= &session->lex->select_lex;
374
356
List<Item> all_fields;
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.
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.
384
if (thd->lex->current_select->select_limit)
386
thd->lex->set_stmt_unsafe();
387
thd->set_current_stmt_binlog_row_based_if_mixed();
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,
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,
393
362
&select_lex->leaf_tables, false) ||
394
setup_conds(thd, table_list, select_lex->leaf_tables, conds))
363
session->setup_conds(table_list, conds))
397
366
TableList *duplicate;
398
if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0)))
367
if ((duplicate= unique_table(session, table_list, table_list->next_global, 0)))
400
update_non_unique_table_error(table_list, "DELETE", duplicate);
369
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->alias);
405
374
if (select_lex->inner_refs_list.elements &&
406
fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
375
fix_inner_refs(session, all_fields, select_lex, select_lex->ref_pointer_array))
413
382
/***************************************************************************
414
Delete multiple tables from join
415
***************************************************************************/
417
#define MEM_STRIP_BUF_SIZE current_thd->variables.sortbuff_size
419
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
421
handler *file= (handler*)arg;
422
return file->cmp_ref((const unsigned char*)a, (const unsigned char*)b);
426
make delete specific preparation and checks after opening tables
429
mysql_multi_delete_prepare()
437
int mysql_multi_delete_prepare(THD *thd)
440
TableList *aux_tables= (TableList *)lex->auxiliary_table_list.first;
441
TableList *target_tbl;
445
setup_tables() need for VIEWs. JOIN::prepare() will not do it second
448
lex->query_tables also point on local list of DELETE SELECT_LEX
450
if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
451
&thd->lex->select_lex.top_join_list,
453
&lex->select_lex.leaf_tables, false))
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
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;
465
target_tbl= target_tbl->next_local)
467
if (!(target_tbl->table= target_tbl->correspondent_table->table))
469
assert(target_tbl->correspondent_table->merge_underlying_list &&
470
target_tbl->correspondent_table->merge_underlying_list->
472
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), "", "");
477
Check that table from which we delete is not used somewhere
478
inside subqueries/view.
481
TableList *duplicate;
482
if ((duplicate= unique_table(thd, target_tbl->correspondent_table,
483
lex->query_tables, 0)))
485
update_non_unique_table_error(target_tbl->correspondent_table,
486
"DELETE", duplicate);
495
multi_delete::multi_delete(TableList *dt, uint32_t 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)
500
tempfiles= (Unique **) sql_calloc(sizeof(Unique *) * num_of_tables);
505
multi_delete::prepare(List<Item> &values __attribute__((unused)),
511
thd_proc_info(thd, "deleting from main table");
517
multi_delete::initialize_tables(JOIN *join)
520
Unique **tempfiles_ptr;
523
if ((thd->options & OPTION_SAFE_UPDATES) && error_if_full_join(join))
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;
531
delete_while_scanning= 1;
532
for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
536
if (tab->table->map & tables_to_delete_from)
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 */
543
/* Don't use record cache */
545
tbl->covering_keys.clear_all();
546
if (tbl->file->has_transactions())
547
transactional_tables= 1;
550
tbl->prepare_for_position();
551
tbl->mark_columns_needed_for_delete();
553
else if ((tab->type != JT_SYSTEM && tab->type != JT_CONST) &&
554
walk == delete_tables)
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
561
delete_while_scanning= 0;
565
tempfiles_ptr= tempfiles;
566
if (delete_while_scanning)
568
table_being_deleted= delete_tables;
569
walk= walk->next_local;
571
for (;walk ;walk= walk->next_local)
573
Table *table=walk->table;
574
*tempfiles_ptr++= new Unique (refpos_order_cmp,
575
(void *) table->file,
576
table->file->ref_length,
579
return(thd->is_fatal_error != 0);
583
multi_delete::~multi_delete()
585
for (table_being_deleted= delete_tables;
587
table_being_deleted= table_being_deleted->next_local)
589
Table *table= table_being_deleted->table;
593
for (uint32_t counter= 0; counter < num_of_tables; counter++)
595
if (tempfiles[counter])
596
delete tempfiles[counter];
601
bool multi_delete::send_data(List<Item> &values __attribute__((unused)))
603
int secure_counter= delete_while_scanning ? -1 : 0;
604
TableList *del_table;
607
for (del_table= delete_tables;
609
del_table= del_table->next_local, secure_counter++)
611
Table *table= del_table->table;
613
/* Check if we are using outer join and we didn't find the row */
614
if (table->status & (STATUS_NULL_ROW | STATUS_DELETED))
617
table->file->position(table->record[0]);
620
if (secure_counter < 0)
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])))
628
if (!table->file->has_transactions())
629
thd->transaction.stmt.modified_non_trans_table= true;
633
table->file->print_error(error,MYF(0));
639
error=tempfiles[secure_counter]->unique_add((char*) table->file->ref);
642
error= 1; // Fatal error
651
void multi_delete::send_error(uint32_t errcode,const char *err)
655
/* First send error what ever it is ... */
656
my_message(errcode, err, MYF(0));
662
void multi_delete::abort()
666
/* the error was handled or nothing deleted and no side effects return */
668
(!thd->transaction.stmt.modified_non_trans_table && !deleted))
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 ...
677
if (do_delete && normal_tables &&
678
(table_being_deleted != delete_tables ||
679
!table_being_deleted->table->file->has_transactions()))
682
We have to execute the recorded do_deletes() and write info into the
687
assert(error_handled);
691
if (thd->transaction.stmt.modified_non_trans_table)
694
there is only side effects; to binlog with the error
696
if (mysql_bin_log.is_open())
698
thd->binlog_query(THD::ROW_QUERY_TYPE,
699
thd->query, thd->query_length,
700
transactional_tables, false);
702
thd->transaction.all.modified_non_trans_table= true;
710
Do delete from other tables.
716
int multi_delete::do_deletes()
718
int local_error= 0, counter= 0, tmp_error;
723
do_delete= 0; // Mark called
727
table_being_deleted= (delete_while_scanning ? delete_tables->next_local :
730
for (; table_being_deleted;
731
table_being_deleted= table_being_deleted->next_local, counter++)
733
ha_rows last_deleted= deleted;
734
Table *table = table_being_deleted->table;
735
if (tempfiles[counter]->get(table))
742
init_read_record(&info,thd,table,NULL,0,1);
744
Ignore any rows not found in reference tables as they may already have
745
been deleted by foreign key handling
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)
751
if ((local_error=table->file->ha_delete_row(table->record[0])))
753
table->file->print_error(local_error,MYF(0));
758
if (will_batch && (tmp_error= table->file->end_bulk_delete()))
762
local_error= tmp_error;
763
table->file->print_error(local_error,MYF(0));
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)
771
if (local_error == -1) // End of file
779
Send ok to the client
785
bool multi_delete::send_eof()
787
THD::killed_state killed_status= THD::NOT_KILLED;
788
thd_proc_info(thd, "deleting from reference tables");
790
/* Does deletes for the last n - 1 tables, returns 0 if ok */
791
int local_error= do_deletes(); // returns 0 if success
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");
799
if ((local_error == 0) || thd->transaction.stmt.modified_non_trans_table)
801
if (mysql_bin_log.is_open())
803
if (local_error == 0)
805
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
806
thd->query, thd->query_length,
807
transactional_tables, false, killed_status) &&
810
local_error=1; // Log write failed: roll back the SQL statement
813
if (thd->transaction.stmt.modified_non_trans_table)
814
thd->transaction.all.modified_non_trans_table= true;
816
if (local_error != 0)
817
error_handled= true; // to force early leave from ::send_error()
821
thd->row_count_func= deleted;
822
::my_ok(thd, (ha_rows) thd->row_count_func);
828
/***************************************************************************
830
384
****************************************************************************/
841
395
- If we want to have a name lock on the table on exit without errors.
844
bool mysql_truncate(THD *thd, TableList *table_list, bool dont_send_ok)
398
bool mysql_truncate(Session *session, TableList *table_list, bool dont_send_ok)
846
400
HA_CREATE_INFO create_info;
847
401
char path[FN_REFLEN];
850
404
uint32_t path_length;
853
407
memset(&create_info, 0, sizeof(create_info));
854
408
/* If it is a temporary table, close and regenerate it */
855
if (!dont_send_ok && (table= find_temporary_table(thd, table_list)))
409
if (!dont_send_ok && (table= session->find_temporary_table(table_list)))
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);
411
StorageEngine *table_type= table->s->db_type();
412
TableShare *share= table->s;
861
if (!ha_check_storage_engine_flag(table_type, HTON_CAN_RECREATE))
414
if (!table_type->check_flag(HTON_BIT_CAN_RECREATE))
862
415
goto trunc_by_del;
864
417
table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
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);
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,
869
423
// 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,
872
share->table_name.str, 1,
874
(void) rm_temporary_table(table_type, path, frm_only);
875
free_table_share(share);
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();
876
430
free((char*) table);
878
432
If we return here we will not have logged the truncation to the bin log
905
455
TRUNCATE must always be statement-based binlogged (not row-based) so
906
456
we don't test current_stmt_binlog_row_based.
908
write_bin_log(thd, true, thd->query, thd->query_length);
909
my_ok(thd); // This should return record count
458
write_bin_log(session, true, session->query, session->query_length);
459
session->my_ok(); // This should return record count
911
pthread_mutex_lock(&LOCK_open);
912
unlock_table_name(thd, table_list);
461
pthread_mutex_lock(&LOCK_open); /* For truncate delete from hash when finished */
462
unlock_table_name(table_list);
913
463
pthread_mutex_unlock(&LOCK_open);
917
pthread_mutex_lock(&LOCK_open);
918
unlock_table_name(thd, table_list);
467
pthread_mutex_lock(&LOCK_open); /* For truncate delete from hash when finished */
468
unlock_table_name(table_list);
919
469
pthread_mutex_unlock(&LOCK_open);
924
474
/* Probably InnoDB table */
925
uint64_t save_options= thd->options;
475
uint64_t save_options= session->options;
926
476
table_list->lock_type= TL_WRITE;
927
thd->options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
928
ha_enable_transaction(thd, false);
929
mysql_init_select(thd->lex);
930
bool save_binlog_row_based= thd->current_stmt_binlog_row_based;
931
thd->clear_current_stmt_binlog_row_based();
932
error= mysql_delete(thd, 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,
933
481
HA_POS_ERROR, 0L, true);
934
ha_enable_transaction(thd, true);
482
ha_enable_transaction(session, true);
936
484
Safety, in case the engine ignored ha_enable_transaction(false)
937
above. Also clears thd->transaction.*.
485
above. Also clears session->transaction.*.
939
error= ha_autocommit_or_rollback(thd, error);
941
thd->options= save_options;
942
thd->current_stmt_binlog_row_based= save_binlog_row_based;
487
error= ha_autocommit_or_rollback(session, error);
489
session->options= save_options;