1
/* Copyright (C) 2000 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
Delete of records and truncate of tables.
19
Multi-table deletes were introduced by Monty and Sinisa
22
#include "mysql_priv.h"
23
#include "sql_select.h"
26
Implement DELETE SQL word.
28
@note Like implementations of other DDL/DML in MySQL, this function
29
relies on the caller to close the thread tables. This is done in the
30
end of dispatch_command().
33
bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
34
SQL_LIST *order, ha_rows limit, ulonglong options,
35
bool reset_auto_increment)
42
bool using_limit=limit != HA_POS_ERROR;
43
bool transactional_table, safe_update, const_cond;
44
bool const_cond_result;
46
uint usable_index= MAX_KEY;
47
SELECT_LEX *select_lex= &thd->lex->select_lex;
48
THD::killed_state killed_status= THD::NOT_KILLED;
49
DBUG_ENTER("mysql_delete");
51
if (open_and_lock_tables(thd, table_list))
53
/* TODO look at this error */
54
if (!(table= table_list->table))
56
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), "", "");
59
thd_proc_info(thd, "init");
62
if (mysql_prepare_delete(thd, table_list, &conds))
65
/* check ORDER BY even if it can be ignored */
66
if (order && order->elements)
70
List<Item> all_fields;
72
bzero((char*) &tables,sizeof(tables));
74
tables.alias = table_list->alias;
76
if (select_lex->setup_ref_array(thd, order->elements) ||
77
setup_order(thd, select_lex->ref_pointer_array, &tables,
78
fields, all_fields, (ORDER*) order->first))
81
free_underlaid_joins(thd, &thd->lex->select_lex);
86
const_cond= (!conds || conds->const_item());
87
safe_update=test(thd->options & OPTION_SAFE_UPDATES);
88
if (safe_update && const_cond)
90
my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
91
ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
95
select_lex->no_error= thd->lex->ignore;
97
const_cond_result= const_cond && (!conds || conds->val_int());
100
/* Error evaluating val_int(). */
105
Test if the user wants to delete all rows and deletion doesn't have
106
any side-effects (because of triggers), so we can use optimized
107
handler::delete_all_rows() method.
109
We implement fast TRUNCATE for InnoDB even if triggers are
110
present. TRUNCATE ignores triggers.
112
We can use delete_all_rows() if and only if:
113
- We allow new functions (not using option --skip-new), and are
114
not in safe mode (not using option --safe-mode)
115
- There is no limit clause
116
- The condition is constant
117
- If there is a condition, then it it produces a non-zero value
118
- If the current command is DELETE FROM with no where clause
119
(i.e., not TRUNCATE) then:
120
- We should not be binlogging this statement row-based, and
121
- there should be no delete triggers associated with the table.
123
if (!using_limit && const_cond_result &&
124
!(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) &&
125
(thd->lex->sql_command == SQLCOM_TRUNCATE ||
126
(!thd->current_stmt_binlog_row_based)))
128
/* Update the table->file->stats.records number */
129
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
130
ha_rows const maybe_deleted= table->file->stats.records;
131
DBUG_PRINT("debug", ("Trying to use delete_all_rows()"));
132
if (!(error=table->file->ha_delete_all_rows()))
135
deleted= maybe_deleted;
138
if (error != HA_ERR_WRONG_COMMAND)
140
table->file->print_error(error,MYF(0));
144
/* Handler didn't support fast delete; Delete rows one by one */
148
Item::cond_result result;
149
conds= remove_eq_conds(thd, conds, &result);
150
if (result == Item::COND_FALSE) // Impossible where
154
/* Update the table->file->stats.records number */
155
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
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);
162
if ((select && select->check_quick(thd, safe_update, limit)) || !limit)
165
free_underlaid_joins(thd, select_lex);
166
thd->row_count_func= 0;
168
my_ok(thd, (ha_rows) thd->row_count_func);
170
We don't need to call reset_auto_increment in this case, because
171
mysql_truncate always gives a NULL conds argument, hence we never
174
DBUG_RETURN(0); // Nothing to delete
177
/* If running in safe sql mode, don't allow updates without keys */
178
if (table->quick_keys.is_clear_all())
180
thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
181
if (safe_update && !using_limit)
184
free_underlaid_joins(thd, 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);
193
if (order && order->elements)
196
SORT_FIELD *sortorder;
197
ha_rows examined_rows;
199
if ((!select || table->quick_keys.is_clear_all()) && limit != HA_POS_ERROR)
200
usable_index= get_index_for_order(table, (ORDER*)(order->first), limit);
202
if (usable_index == MAX_KEY)
204
table->sort.io_cache= (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
205
MYF(MY_FAE | MY_ZEROFILL));
207
if (!(sortorder= make_unireg_sortorder((ORDER*) order->first,
209
(table->sort.found_records = filesort(thd, table, sortorder, length,
210
select, HA_POS_ERROR, 1,
215
free_underlaid_joins(thd, &thd->lex->select_lex);
219
Filesort has already found and selected the rows we want to delete,
220
so we don't need the where clause
223
free_underlaid_joins(thd, select_lex);
228
/* If quick select is used, initialize it before retrieving rows. */
229
if (select && select->quick && select->quick->reset())
232
free_underlaid_joins(thd, select_lex);
235
if (usable_index==MAX_KEY)
236
init_read_record(&info,thd,table,select,1,1);
238
init_read_record_idx(&info, thd, table, 1, usable_index);
240
thd_proc_info(thd, "updating");
242
will_batch= !table->file->start_bulk_delete();
245
table->mark_columns_needed_for_delete();
247
while (!(error=info.read_record(&info)) && !thd->killed &&
250
// thd->is_error() is tested to disallow delete row on error
251
if (!(select && select->skip_record())&& ! thd->is_error() )
253
if (!(error= table->file->ha_delete_row(table->record[0])))
256
if (!--limit && using_limit)
264
table->file->print_error(error,MYF(0));
266
In < 4.0.14 we set the error number to 0 here, but that
267
was not sensible, because then MySQL would not roll back the
268
failed DELETE, and also wrote it to the binlog. For MyISAM
269
tables a DELETE probably never should fail (?), but for
270
InnoDB it can fail in a FOREIGN KEY error or an
271
out-of-tablespace error.
278
table->file->unlock_row(); // Row failed selection, release lock on it
280
killed_status= thd->killed;
281
if (killed_status != THD::NOT_KILLED || thd->is_error())
283
if (will_batch && (loc_error= table->file->end_bulk_delete()))
286
table->file->print_error(loc_error,MYF(0));
289
thd_proc_info(thd, "end");
290
end_read_record(&info);
291
if (options & OPTION_QUICK)
292
(void) table->file->extra(HA_EXTRA_NORMAL);
294
if (reset_auto_increment && (error < 0))
297
We're really doing a truncate and need to reset the table's
298
auto-increment counter.
300
int error2= table->file->ha_reset_auto_increment(0);
302
if (error2 && (error2 != HA_ERR_WRONG_COMMAND))
304
table->file->print_error(error2, MYF(0));
312
transactional_table= table->file->has_transactions();
314
if (!transactional_table && deleted > 0)
315
thd->transaction.stmt.modified_non_trans_table= TRUE;
317
/* See similar binlogging code in sql_update.cc, for comments */
318
if ((error < 0) || thd->transaction.stmt.modified_non_trans_table)
320
if (mysql_bin_log.is_open())
325
[binlog]: If 'handler::delete_all_rows()' was called and the
326
storage engine does not inject the rows itself, we replicate
327
statement-based; otherwise, 'ha_delete_row()' was used to
328
delete specific rows which we might log row-based.
330
int log_result= thd->binlog_query(THD::ROW_QUERY_TYPE,
331
thd->query, thd->query_length,
332
transactional_table, FALSE, killed_status);
334
if (log_result && transactional_table)
339
if (thd->transaction.stmt.modified_non_trans_table)
340
thd->transaction.all.modified_non_trans_table= TRUE;
342
DBUG_ASSERT(transactional_table || !deleted || thd->transaction.stmt.modified_non_trans_table);
343
free_underlaid_joins(thd, select_lex);
346
if (error < 0 || (thd->lex->ignore && !thd->is_fatal_error))
348
thd->row_count_func= deleted;
349
my_ok(thd, (ha_rows) thd->row_count_func);
350
DBUG_PRINT("info",("%ld records deleted",(long) deleted));
352
DBUG_RETURN(error >= 0 || thd->is_error());
361
Prepare items in DELETE statement
364
mysql_prepare_delete()
366
table_list - global/local table list
373
int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
376
SELECT_LEX *select_lex= &thd->lex->select_lex;
377
DBUG_ENTER("mysql_prepare_delete");
378
List<Item> all_fields;
381
Statement-based replication of DELETE ... LIMIT is not safe as order of
382
rows is not defined, so in mixed mode we go to row-based.
384
Note that we may consider a statement as safe if ORDER BY primary_key
385
is present. However it may confuse users to see very similiar statements
386
replicated differently.
388
if (thd->lex->current_select->select_limit)
390
thd->lex->set_stmt_unsafe();
391
thd->set_current_stmt_binlog_row_based_if_mixed();
393
thd->lex->allow_sum_func= 0;
394
if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
395
&thd->lex->select_lex.top_join_list,
397
&select_lex->leaf_tables, false) ||
398
setup_conds(thd, table_list, select_lex->leaf_tables, conds))
401
TABLE_LIST *duplicate;
402
if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0)))
404
update_non_unique_table_error(table_list, "DELETE", duplicate);
409
if (select_lex->inner_refs_list.elements &&
410
fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
413
select_lex->fix_prepare_information(thd, conds, &fake_conds);
418
/***************************************************************************
419
Delete multiple tables from join
420
***************************************************************************/
422
#define MEM_STRIP_BUF_SIZE current_thd->variables.sortbuff_size
424
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
426
handler *file= (handler*)arg;
427
return file->cmp_ref((const uchar*)a, (const uchar*)b);
431
make delete specific preparation and checks after opening tables
434
mysql_multi_delete_prepare()
442
int mysql_multi_delete_prepare(THD *thd)
445
TABLE_LIST *aux_tables= (TABLE_LIST *)lex->auxiliary_table_list.first;
446
TABLE_LIST *target_tbl;
447
DBUG_ENTER("mysql_multi_delete_prepare");
450
setup_tables() need for VIEWs. JOIN::prepare() will not do it second
453
lex->query_tables also point on local list of DELETE SELECT_LEX
455
if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
456
&thd->lex->select_lex.top_join_list,
458
&lex->select_lex.leaf_tables, false))
463
Multi-delete can't be constructed over-union => we always have
464
single SELECT on top and have to check underlying SELECTs of it
466
lex->select_lex.exclude_from_table_unique_test= TRUE;
467
/* Fix tables-to-be-deleted-from list to point at opened tables */
468
for (target_tbl= (TABLE_LIST*) aux_tables;
470
target_tbl= target_tbl->next_local)
472
if (!(target_tbl->table= target_tbl->correspondent_table->table))
474
DBUG_ASSERT(target_tbl->correspondent_table->merge_underlying_list &&
475
target_tbl->correspondent_table->merge_underlying_list->
477
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), "", "");
482
Check that table from which we delete is not used somewhere
483
inside subqueries/view.
486
TABLE_LIST *duplicate;
487
if ((duplicate= unique_table(thd, target_tbl->correspondent_table,
488
lex->query_tables, 0)))
490
update_non_unique_table_error(target_tbl->correspondent_table,
491
"DELETE", duplicate);
500
multi_delete::multi_delete(TABLE_LIST *dt, uint num_of_tables_arg)
501
: delete_tables(dt), deleted(0), found(0),
502
num_of_tables(num_of_tables_arg), error(0),
503
do_delete(0), transactional_tables(0), normal_tables(0), error_handled(0)
505
tempfiles= (Unique **) sql_calloc(sizeof(Unique *) * num_of_tables);
510
multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
512
DBUG_ENTER("multi_delete::prepare");
515
thd_proc_info(thd, "deleting from main table");
521
multi_delete::initialize_tables(JOIN *join)
524
Unique **tempfiles_ptr;
525
DBUG_ENTER("initialize_tables");
527
if ((thd->options & OPTION_SAFE_UPDATES) && error_if_full_join(join))
530
table_map tables_to_delete_from=0;
531
for (walk= delete_tables; walk; walk= walk->next_local)
532
tables_to_delete_from|= walk->table->map;
535
delete_while_scanning= 1;
536
for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
540
if (tab->table->map & tables_to_delete_from)
542
/* We are going to delete from this table */
543
TABLE *tbl=walk->table=tab->table;
544
walk= walk->next_local;
545
/* Don't use KEYREAD optimization on this table */
547
/* Don't use record cache */
549
tbl->covering_keys.clear_all();
550
if (tbl->file->has_transactions())
551
transactional_tables= 1;
554
tbl->prepare_for_position();
555
tbl->mark_columns_needed_for_delete();
557
else if ((tab->type != JT_SYSTEM && tab->type != JT_CONST) &&
558
walk == delete_tables)
561
We are not deleting from the table we are scanning. In this
562
case send_data() shouldn't delete any rows a we may touch
563
the rows in the deleted table many times
565
delete_while_scanning= 0;
569
tempfiles_ptr= tempfiles;
570
if (delete_while_scanning)
572
table_being_deleted= delete_tables;
573
walk= walk->next_local;
575
for (;walk ;walk= walk->next_local)
577
TABLE *table=walk->table;
578
*tempfiles_ptr++= new Unique (refpos_order_cmp,
579
(void *) table->file,
580
table->file->ref_length,
583
DBUG_RETURN(thd->is_fatal_error != 0);
587
multi_delete::~multi_delete()
589
for (table_being_deleted= delete_tables;
591
table_being_deleted= table_being_deleted->next_local)
593
TABLE *table= table_being_deleted->table;
597
for (uint counter= 0; counter < num_of_tables; counter++)
599
if (tempfiles[counter])
600
delete tempfiles[counter];
605
bool multi_delete::send_data(List<Item> &values)
607
int secure_counter= delete_while_scanning ? -1 : 0;
608
TABLE_LIST *del_table;
609
DBUG_ENTER("multi_delete::send_data");
611
for (del_table= delete_tables;
613
del_table= del_table->next_local, secure_counter++)
615
TABLE *table= del_table->table;
617
/* Check if we are using outer join and we didn't find the row */
618
if (table->status & (STATUS_NULL_ROW | STATUS_DELETED))
621
table->file->position(table->record[0]);
624
if (secure_counter < 0)
626
/* We are scanning the current table */
627
DBUG_ASSERT(del_table == table_being_deleted);
628
table->status|= STATUS_DELETED;
629
if (!(error=table->file->ha_delete_row(table->record[0])))
632
if (!table->file->has_transactions())
633
thd->transaction.stmt.modified_non_trans_table= TRUE;
637
table->file->print_error(error,MYF(0));
643
error=tempfiles[secure_counter]->unique_add((char*) table->file->ref);
646
error= 1; // Fatal error
655
void multi_delete::send_error(uint errcode,const char *err)
657
DBUG_ENTER("multi_delete::send_error");
659
/* First send error what ever it is ... */
660
my_message(errcode, err, MYF(0));
666
void multi_delete::abort()
668
DBUG_ENTER("multi_delete::abort");
670
/* the error was handled or nothing deleted and no side effects return */
672
(!thd->transaction.stmt.modified_non_trans_table && !deleted))
676
If rows from the first table only has been deleted and it is
677
transactional, just do rollback.
678
The same if all tables are transactional, regardless of where we are.
679
In all other cases do attempt deletes ...
681
if (do_delete && normal_tables &&
682
(table_being_deleted != delete_tables ||
683
!table_being_deleted->table->file->has_transactions()))
686
We have to execute the recorded do_deletes() and write info into the
691
DBUG_ASSERT(error_handled);
695
if (thd->transaction.stmt.modified_non_trans_table)
698
there is only side effects; to binlog with the error
700
if (mysql_bin_log.is_open())
702
thd->binlog_query(THD::ROW_QUERY_TYPE,
703
thd->query, thd->query_length,
704
transactional_tables, FALSE);
706
thd->transaction.all.modified_non_trans_table= true;
714
Do delete from other tables.
720
int multi_delete::do_deletes()
722
int local_error= 0, counter= 0, tmp_error;
724
DBUG_ENTER("do_deletes");
725
DBUG_ASSERT(do_delete);
727
do_delete= 0; // Mark called
731
table_being_deleted= (delete_while_scanning ? delete_tables->next_local :
734
for (; table_being_deleted;
735
table_being_deleted= table_being_deleted->next_local, counter++)
737
ha_rows last_deleted= deleted;
738
TABLE *table = table_being_deleted->table;
739
if (tempfiles[counter]->get(table))
746
init_read_record(&info,thd,table,NULL,0,1);
748
Ignore any rows not found in reference tables as they may already have
749
been deleted by foreign key handling
751
info.ignore_not_found_rows= 1;
752
will_batch= !table->file->start_bulk_delete();
753
while (!(local_error=info.read_record(&info)) && !thd->killed)
755
if ((local_error=table->file->ha_delete_row(table->record[0])))
757
table->file->print_error(local_error,MYF(0));
762
if (will_batch && (tmp_error= table->file->end_bulk_delete()))
766
local_error= tmp_error;
767
table->file->print_error(local_error,MYF(0));
770
if (last_deleted != deleted && !table->file->has_transactions())
771
thd->transaction.stmt.modified_non_trans_table= TRUE;
772
end_read_record(&info);
773
if (thd->killed && !local_error)
775
if (local_error == -1) // End of file
778
DBUG_RETURN(local_error);
783
Send ok to the client
789
bool multi_delete::send_eof()
791
THD::killed_state killed_status= THD::NOT_KILLED;
792
thd_proc_info(thd, "deleting from reference tables");
794
/* Does deletes for the last n - 1 tables, returns 0 if ok */
795
int local_error= do_deletes(); // returns 0 if success
797
/* compute a total error to know if something failed */
798
local_error= local_error || error;
799
killed_status= (local_error == 0)? THD::NOT_KILLED : thd->killed;
800
/* reset used flags */
801
thd_proc_info(thd, "end");
803
if ((local_error == 0) || thd->transaction.stmt.modified_non_trans_table)
805
if (mysql_bin_log.is_open())
807
if (local_error == 0)
809
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
810
thd->query, thd->query_length,
811
transactional_tables, FALSE, killed_status) &&
814
local_error=1; // Log write failed: roll back the SQL statement
817
if (thd->transaction.stmt.modified_non_trans_table)
818
thd->transaction.all.modified_non_trans_table= TRUE;
820
if (local_error != 0)
821
error_handled= TRUE; // to force early leave from ::send_error()
825
thd->row_count_func= deleted;
826
::my_ok(thd, (ha_rows) thd->row_count_func);
832
/***************************************************************************
834
****************************************************************************/
837
Optimize delete of all rows by doing a full generate of the table
838
This will work even if the .ISM and .ISD tables are destroyed
840
dont_send_ok should be set if:
841
- We should always wants to generate the table (even if the table type
842
normally can't safely do this.
843
- We don't want an ok to be sent to the end user.
844
- We don't want to log the truncate command
845
- If we want to have a name lock on the table on exit without errors.
848
bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
850
HA_CREATE_INFO create_info;
851
char path[FN_REFLEN];
855
DBUG_ENTER("mysql_truncate");
857
bzero((char*) &create_info,sizeof(create_info));
858
/* If it is a temporary table, close and regenerate it */
859
if (!dont_send_ok && (table= find_temporary_table(thd, table_list)))
861
handlerton *table_type= table->s->db_type();
862
TABLE_SHARE *share= table->s;
863
bool frm_only= (share->tmp_table == TMP_TABLE_FRM_FILE_ONLY);
865
if (!ha_check_storage_engine_flag(table_type, HTON_CAN_RECREATE))
868
table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
870
close_temporary_table(thd, table, 0, 0); // Don't free share
871
ha_create_table(thd, share->normalized_path.str,
872
share->db.str, share->table_name.str, &create_info, 1);
873
// We don't need to call invalidate() because this table is not in cache
874
if ((error= (int) !(open_temporary_table(thd, share->path.str,
876
share->table_name.str, 1,
878
(void) rm_temporary_table(table_type, path, frm_only);
879
free_table_share(share);
880
my_free((char*) table,MYF(0));
882
If we return here we will not have logged the truncation to the bin log
883
and we will not my_ok() to the client.
888
path_length= build_table_filename(path, sizeof(path), table_list->db,
889
table_list->table_name, reg_ext, 0);
893
enum legacy_db_type table_type;
894
mysql_frm_type(thd, path, &table_type);
895
if (table_type == DB_TYPE_UNKNOWN)
897
my_error(ER_NO_SUCH_TABLE, MYF(0),
898
table_list->db, table_list->table_name);
902
if (!ha_check_storage_engine_flag(ha_resolve_by_legacy_type(thd, table_type),
906
if (lock_and_wait_for_table_name(thd, table_list))
910
// Remove the .frm extension AIX 5.2 64-bit compiler bug (BUG#16155): this
911
// crashes, replacement works. *(path + path_length - reg_ext_length)=
913
path[path_length - reg_ext_length] = 0;
914
VOID(pthread_mutex_lock(&LOCK_open));
915
error= ha_create_table(thd, path, table_list->db, table_list->table_name,
917
VOID(pthread_mutex_unlock(&LOCK_open));
925
TRUNCATE must always be statement-based binlogged (not row-based) so
926
we don't test current_stmt_binlog_row_based.
928
write_bin_log(thd, TRUE, thd->query, thd->query_length);
929
my_ok(thd); // This should return record count
931
VOID(pthread_mutex_lock(&LOCK_open));
932
unlock_table_name(thd, table_list);
933
VOID(pthread_mutex_unlock(&LOCK_open));
937
VOID(pthread_mutex_lock(&LOCK_open));
938
unlock_table_name(thd, table_list);
939
VOID(pthread_mutex_unlock(&LOCK_open));
944
/* Probably InnoDB table */
945
ulonglong save_options= thd->options;
946
table_list->lock_type= TL_WRITE;
947
thd->options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
948
ha_enable_transaction(thd, FALSE);
949
mysql_init_select(thd->lex);
950
bool save_binlog_row_based= thd->current_stmt_binlog_row_based;
951
thd->clear_current_stmt_binlog_row_based();
952
error= mysql_delete(thd, table_list, (COND*) 0, (SQL_LIST*) 0,
953
HA_POS_ERROR, LL(0), TRUE);
954
ha_enable_transaction(thd, TRUE);
956
Safety, in case the engine ignored ha_enable_transaction(FALSE)
957
above. Also clears thd->transaction.*.
959
error= ha_autocommit_or_rollback(thd, error);
961
thd->options= save_options;
962
thd->current_stmt_binlog_row_based= save_binlog_row_based;