~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000 MySQL AB
2
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.
6
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.
11
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 */
15
16
/*
17
  Delete of records and truncate of tables.
18
19
  Multi-table deletes were introduced by Monty and Sinisa
20
*/
243.1.17 by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.)
21
#include <drizzled/server_includes.h>
22
#include <drizzled/sql_select.h>
549 by Monty Taylor
Took gettext.h out of header files.
23
#include <drizzled/error.h>
520.7.1 by Monty Taylor
Moved hash.c to drizzled.
24
#include <drizzled/probes.h>
575.4.7 by Monty Taylor
More header cleanup.
25
#include <drizzled/sql_parse.h>
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
26
#include <drizzled/sql_base.h>
670.2.4 by Monty Taylor
Removed more stuff from the headers.
27
#include <drizzled/lock.h>
1 by brian
clean slate
28
29
/**
30
  Implement DELETE SQL word.
31
32
  @note Like implementations of other DDL/DML in MySQL, this function
33
  relies on the caller to close the thread tables. This is done in the
34
  end of dispatch_command().
35
*/
36
520.1.22 by Brian Aker
Second pass of thd cleanup
37
bool mysql_delete(Session *session, TableList *table_list, COND *conds,
151 by Brian Aker
Ulonglong to uint64_t
38
                  SQL_LIST *order, ha_rows limit, uint64_t options,
1 by brian
clean slate
39
                  bool reset_auto_increment)
40
{
41
  bool          will_batch;
42
  int		error, loc_error;
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
43
  Table		*table;
1 by brian
clean slate
44
  SQL_SELECT	*select=0;
45
  READ_RECORD	info;
46
  bool          using_limit=limit != HA_POS_ERROR;
47
  bool		transactional_table, safe_update, const_cond;
48
  bool          const_cond_result;
49
  ha_rows	deleted= 0;
482 by Brian Aker
Remove uint.
50
  uint32_t usable_index= MAX_KEY;
846 by Brian Aker
Removing on typedeffed class.
51
  Select_Lex   *select_lex= &session->lex->select_lex;
520.1.21 by Brian Aker
THD -> Session rename
52
  Session::killed_state killed_status= Session::NOT_KILLED;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
53
1 by brian
clean slate
54
520.1.22 by Brian Aker
Second pass of thd cleanup
55
  if (open_and_lock_tables(session, table_list))
163 by Brian Aker
Merge Monty's code.
56
    return(true);
737 by Brian Aker
Updates for dead code removal (and forced assert() in delete).
57
58
  table= table_list->table;
59
  assert(table);
60
520.1.22 by Brian Aker
Second pass of thd cleanup
61
  session->set_proc_info("init");
1 by brian
clean slate
62
  table->map=1;
63
520.1.22 by Brian Aker
Second pass of thd cleanup
64
  if (mysql_prepare_delete(session, table_list, &conds))
1 by brian
clean slate
65
    goto err;
66
67
  /* check ORDER BY even if it can be ignored */
68
  if (order && order->elements)
69
  {
327.2.4 by Brian Aker
Refactoring table.h
70
    TableList   tables;
1 by brian
clean slate
71
    List<Item>   fields;
72
    List<Item>   all_fields;
73
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
74
    memset(&tables, 0, sizeof(tables));
1 by brian
clean slate
75
    tables.table = table;
76
    tables.alias = table_list->alias;
77
520.1.22 by Brian Aker
Second pass of thd cleanup
78
      if (select_lex->setup_ref_array(session, order->elements) ||
79
	  setup_order(session, select_lex->ref_pointer_array, &tables,
327.2.3 by Brian Aker
Refactoring of class Table
80
                    fields, all_fields, (order_st*) order->first))
1 by brian
clean slate
81
    {
82
      delete select;
520.1.22 by Brian Aker
Second pass of thd cleanup
83
      free_underlaid_joins(session, &session->lex->select_lex);
1 by brian
clean slate
84
      goto err;
85
    }
86
  }
87
88
  const_cond= (!conds || conds->const_item());
520.1.22 by Brian Aker
Second pass of thd cleanup
89
  safe_update=test(session->options & OPTION_SAFE_UPDATES);
1 by brian
clean slate
90
  if (safe_update && const_cond)
91
  {
92
    my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
93
               ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
94
    goto err;
95
  }
96
520.1.22 by Brian Aker
Second pass of thd cleanup
97
  select_lex->no_error= session->lex->ignore;
1 by brian
clean slate
98
99
  const_cond_result= const_cond && (!conds || conds->val_int());
520.1.22 by Brian Aker
Second pass of thd cleanup
100
  if (session->is_error())
1 by brian
clean slate
101
  {
102
    /* Error evaluating val_int(). */
163 by Brian Aker
Merge Monty's code.
103
    return(true);
1 by brian
clean slate
104
  }
105
106
  /*
107
    Test if the user wants to delete all rows and deletion doesn't have
108
    any side-effects (because of triggers), so we can use optimized
109
    handler::delete_all_rows() method.
110
111
    We implement fast TRUNCATE for InnoDB even if triggers are
112
    present.  TRUNCATE ignores triggers.
113
114
    We can use delete_all_rows() if and only if:
115
    - We allow new functions (not using option --skip-new), and are
116
      not in safe mode (not using option --safe-mode)
117
    - There is no limit clause
118
    - The condition is constant
119
    - If there is a condition, then it it produces a non-zero value
120
    - If the current command is DELETE FROM with no where clause
121
      (i.e., not TRUNCATE) then:
122
      - We should not be binlogging this statement row-based, and
123
      - there should be no delete triggers associated with the table.
124
  */
581 by Brian Aker
Second pass through on replication row patch
125
  if (!using_limit && const_cond_result)
1 by brian
clean slate
126
  {
127
    /* Update the table->file->stats.records number */
128
    table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
129
    ha_rows const maybe_deleted= table->file->stats.records;
130
    if (!(error=table->file->ha_delete_all_rows()))
131
    {
132
      error= -1;				// ok
133
      deleted= maybe_deleted;
134
      goto cleanup;
135
    }
136
    if (error != HA_ERR_WRONG_COMMAND)
137
    {
138
      table->file->print_error(error,MYF(0));
139
      error=0;
140
      goto cleanup;
141
    }
142
    /* Handler didn't support fast delete; Delete rows one by one */
143
  }
144
  if (conds)
145
  {
146
    Item::cond_result result;
520.1.22 by Brian Aker
Second pass of thd cleanup
147
    conds= remove_eq_conds(session, conds, &result);
1 by brian
clean slate
148
    if (result == Item::COND_FALSE)             // Impossible where
149
      limit= 0;
150
  }
151
152
  /* Update the table->file->stats.records number */
153
  table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
154
1005.2.6 by Monty Taylor
Re-added bitset<> as a replacement for Bitmap<>
155
  table->covering_keys.reset();
156
  table->quick_keys.reset();		// Can't use 'only index'
1 by brian
clean slate
157
  select=make_select(table, 0, 0, conds, 0, &error);
158
  if (error)
159
    goto err;
520.1.22 by Brian Aker
Second pass of thd cleanup
160
  if ((select && select->check_quick(session, safe_update, limit)) || !limit)
1 by brian
clean slate
161
  {
162
    delete select;
520.1.22 by Brian Aker
Second pass of thd cleanup
163
    free_underlaid_joins(session, select_lex);
164
    session->row_count_func= 0;
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
165
    DRIZZLE_DELETE_END();
836 by Brian Aker
Fixed session call from function to method.
166
    session->my_ok((ha_rows) session->row_count_func);
1 by brian
clean slate
167
    /*
168
      We don't need to call reset_auto_increment in this case, because
169
      mysql_truncate always gives a NULL conds argument, hence we never
170
      get here.
171
    */
51.2.2 by Patrick Galbraith
Removed DBUGs from
172
    return(0);				// Nothing to delete
1 by brian
clean slate
173
  }
174
175
  /* If running in safe sql mode, don't allow updates without keys */
1005.2.6 by Monty Taylor
Re-added bitset<> as a replacement for Bitmap<>
176
  if (table->quick_keys.none())
1 by brian
clean slate
177
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
178
    session->server_status|=SERVER_QUERY_NO_INDEX_USED;
1 by brian
clean slate
179
    if (safe_update && !using_limit)
180
    {
181
      delete select;
520.1.22 by Brian Aker
Second pass of thd cleanup
182
      free_underlaid_joins(session, select_lex);
1 by brian
clean slate
183
      my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
184
                 ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
185
      goto err;
186
    }
187
  }
188
  if (options & OPTION_QUICK)
189
    (void) table->file->extra(HA_EXTRA_QUICK);
190
191
  if (order && order->elements)
192
  {
482 by Brian Aker
Remove uint.
193
    uint32_t         length= 0;
1 by brian
clean slate
194
    SORT_FIELD  *sortorder;
195
    ha_rows examined_rows;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
196
1005.2.6 by Monty Taylor
Re-added bitset<> as a replacement for Bitmap<>
197
    if ((!select || table->quick_keys.none()) && limit != HA_POS_ERROR)
327.2.3 by Brian Aker
Refactoring of class Table
198
      usable_index= get_index_for_order(table, (order_st*)(order->first), limit);
1 by brian
clean slate
199
200
    if (usable_index == MAX_KEY)
201
    {
684 by Brian Aker
Mass cleanup for casting.
202
      table->sort.io_cache= new IO_CACHE;
641.3.9 by Monty Taylor
More removal of my_malloc.
203
      memset(table->sort.io_cache, 0, sizeof(IO_CACHE));
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
204
205
327.2.3 by Brian Aker
Refactoring of class Table
206
      if (!(sortorder= make_unireg_sortorder((order_st*) order->first,
1 by brian
clean slate
207
                                             &length, NULL)) ||
520.1.22 by Brian Aker
Second pass of thd cleanup
208
	  (table->sort.found_records = filesort(session, table, sortorder, length,
1 by brian
clean slate
209
                                                select, HA_POS_ERROR, 1,
210
                                                &examined_rows))
211
	  == HA_POS_ERROR)
212
      {
213
        delete select;
520.1.22 by Brian Aker
Second pass of thd cleanup
214
        free_underlaid_joins(session, &session->lex->select_lex);
1 by brian
clean slate
215
        goto err;
216
      }
217
      /*
218
        Filesort has already found and selected the rows we want to delete,
219
        so we don't need the where clause
220
      */
221
      delete select;
520.1.22 by Brian Aker
Second pass of thd cleanup
222
      free_underlaid_joins(session, select_lex);
1 by brian
clean slate
223
      select= 0;
224
    }
225
  }
226
227
  /* If quick select is used, initialize it before retrieving rows. */
228
  if (select && select->quick && select->quick->reset())
229
  {
230
    delete select;
520.1.22 by Brian Aker
Second pass of thd cleanup
231
    free_underlaid_joins(session, select_lex);
1 by brian
clean slate
232
    goto err;
233
  }
234
  if (usable_index==MAX_KEY)
520.1.22 by Brian Aker
Second pass of thd cleanup
235
    init_read_record(&info,session,table,select,1,1);
1 by brian
clean slate
236
  else
520.1.22 by Brian Aker
Second pass of thd cleanup
237
    init_read_record_idx(&info, session, table, 1, usable_index);
1 by brian
clean slate
238
520.1.22 by Brian Aker
Second pass of thd cleanup
239
  session->set_proc_info("updating");
1 by brian
clean slate
240
241
  will_batch= !table->file->start_bulk_delete();
242
243
244
  table->mark_columns_needed_for_delete();
245
520.1.22 by Brian Aker
Second pass of thd cleanup
246
  while (!(error=info.read_record(&info)) && !session->killed &&
247
	 ! session->is_error())
1 by brian
clean slate
248
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
249
    // session->is_error() is tested to disallow delete row on error
250
    if (!(select && select->skip_record())&& ! session->is_error() )
1 by brian
clean slate
251
    {
252
      if (!(error= table->file->ha_delete_row(table->record[0])))
253
      {
254
	deleted++;
255
	if (!--limit && using_limit)
256
	{
257
	  error= -1;
258
	  break;
259
	}
260
      }
261
      else
262
      {
263
	table->file->print_error(error,MYF(0));
264
	/*
265
	  In < 4.0.14 we set the error number to 0 here, but that
266
	  was not sensible, because then MySQL would not roll back the
267
	  failed DELETE, and also wrote it to the binlog. For MyISAM
268
	  tables a DELETE probably never should fail (?), but for
269
	  InnoDB it can fail in a FOREIGN KEY error or an
270
	  out-of-tablespace error.
271
	*/
272
 	error= 1;
273
	break;
274
      }
275
    }
276
    else
277
      table->file->unlock_row();  // Row failed selection, release lock on it
278
  }
520.1.22 by Brian Aker
Second pass of thd cleanup
279
  killed_status= session->killed;
280
  if (killed_status != Session::NOT_KILLED || session->is_error())
1 by brian
clean slate
281
    error= 1;					// Aborted
282
  if (will_batch && (loc_error= table->file->end_bulk_delete()))
283
  {
284
    if (error != 1)
285
      table->file->print_error(loc_error,MYF(0));
286
    error=1;
287
  }
520.1.22 by Brian Aker
Second pass of thd cleanup
288
  session->set_proc_info("end");
1 by brian
clean slate
289
  end_read_record(&info);
290
  if (options & OPTION_QUICK)
291
    (void) table->file->extra(HA_EXTRA_NORMAL);
292
293
  if (reset_auto_increment && (error < 0))
294
  {
295
    /*
296
      We're really doing a truncate and need to reset the table's
297
      auto-increment counter.
298
    */
299
    int error2= table->file->ha_reset_auto_increment(0);
300
301
    if (error2 && (error2 != HA_ERR_WRONG_COMMAND))
302
    {
303
      table->file->print_error(error2, MYF(0));
304
      error= 1;
305
    }
306
  }
307
308
cleanup:
309
310
  delete select;
311
  transactional_table= table->file->has_transactions();
312
313
  if (!transactional_table && deleted > 0)
520.1.22 by Brian Aker
Second pass of thd cleanup
314
    session->transaction.stmt.modified_non_trans_table= true;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
315
1 by brian
clean slate
316
  /* See similar binlogging code in sql_update.cc, for comments */
520.1.22 by Brian Aker
Second pass of thd cleanup
317
  if ((error < 0) || session->transaction.stmt.modified_non_trans_table)
1 by brian
clean slate
318
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
319
    if (session->transaction.stmt.modified_non_trans_table)
320
      session->transaction.all.modified_non_trans_table= true;
1 by brian
clean slate
321
  }
520.1.22 by Brian Aker
Second pass of thd cleanup
322
  assert(transactional_table || !deleted || session->transaction.stmt.modified_non_trans_table);
323
  free_underlaid_joins(session, select_lex);
1 by brian
clean slate
324
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
325
  DRIZZLE_DELETE_END();
520.1.22 by Brian Aker
Second pass of thd cleanup
326
  if (error < 0 || (session->lex->ignore && !session->is_fatal_error))
1 by brian
clean slate
327
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
328
    session->row_count_func= deleted;
836 by Brian Aker
Fixed session call from function to method.
329
    session->my_ok((ha_rows) session->row_count_func);
1 by brian
clean slate
330
  }
520.1.22 by Brian Aker
Second pass of thd cleanup
331
  return(error >= 0 || session->is_error());
1 by brian
clean slate
332
333
err:
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
334
  DRIZZLE_DELETE_END();
163 by Brian Aker
Merge Monty's code.
335
  return(true);
1 by brian
clean slate
336
}
337
338
339
/*
340
  Prepare items in DELETE statement
341
342
  SYNOPSIS
343
    mysql_prepare_delete()
520.1.22 by Brian Aker
Second pass of thd cleanup
344
    session			- thread handler
1 by brian
clean slate
345
    table_list		- global/local table list
346
    conds		- conditions
347
348
  RETURN VALUE
163 by Brian Aker
Merge Monty's code.
349
    false OK
350
    true  error
1 by brian
clean slate
351
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
352
int mysql_prepare_delete(Session *session, TableList *table_list, Item **conds)
1 by brian
clean slate
353
{
846 by Brian Aker
Removing on typedeffed class.
354
  Select_Lex *select_lex= &session->lex->select_lex;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
355
1 by brian
clean slate
356
  List<Item> all_fields;
357
520.1.22 by Brian Aker
Second pass of thd cleanup
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,
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
361
                                    table_list,
1 by brian
clean slate
362
                                    &select_lex->leaf_tables, false) ||
1034.1.7 by Brian Aker
Remove dead bits to the end of functions.
363
      setup_conds(session, table_list, conds))
163 by Brian Aker
Merge Monty's code.
364
    return(true);
1 by brian
clean slate
365
  {
327.2.4 by Brian Aker
Refactoring table.h
366
    TableList *duplicate;
520.1.22 by Brian Aker
Second pass of thd cleanup
367
    if ((duplicate= unique_table(session, table_list, table_list->next_global, 0)))
1 by brian
clean slate
368
    {
369
      update_non_unique_table_error(table_list, "DELETE", duplicate);
163 by Brian Aker
Merge Monty's code.
370
      return(true);
1 by brian
clean slate
371
    }
372
  }
373
374
  if (select_lex->inner_refs_list.elements &&
520.1.22 by Brian Aker
Second pass of thd cleanup
375
    fix_inner_refs(session, all_fields, select_lex, select_lex->ref_pointer_array))
51.2.2 by Patrick Galbraith
Removed DBUGs from
376
    return(-1);
1 by brian
clean slate
377
163 by Brian Aker
Merge Monty's code.
378
  return(false);
1 by brian
clean slate
379
}
380
381
382
/***************************************************************************
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
383
  Delete multiple tables from join
1 by brian
clean slate
384
***************************************************************************/
385
386
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
387
{
388
  handler *file= (handler*)arg;
481 by Brian Aker
Remove all of uchar.
389
  return file->cmp_ref((const unsigned char*)a, (const unsigned char*)b);
1 by brian
clean slate
390
}
391
392
/*
393
  make delete specific preparation and checks after opening tables
394
395
  SYNOPSIS
396
    mysql_multi_delete_prepare()
520.1.22 by Brian Aker
Second pass of thd cleanup
397
    session         thread handler
1 by brian
clean slate
398
399
  RETURN
163 by Brian Aker
Merge Monty's code.
400
    false OK
401
    true  Error
1 by brian
clean slate
402
*/
403
520.1.22 by Brian Aker
Second pass of thd cleanup
404
int mysql_multi_delete_prepare(Session *session)
1 by brian
clean slate
405
{
520.1.22 by Brian Aker
Second pass of thd cleanup
406
  LEX *lex= session->lex;
327.2.4 by Brian Aker
Refactoring table.h
407
  TableList *aux_tables= (TableList *)lex->auxiliary_table_list.first;
408
  TableList *target_tbl;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
409
1 by brian
clean slate
410
411
  /*
412
    setup_tables() need for VIEWs. JOIN::prepare() will not do it second
413
    time.
414
846 by Brian Aker
Removing on typedeffed class.
415
    lex->query_tables also point on local list of DELETE Select_Lex
1 by brian
clean slate
416
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
417
  if (setup_tables_and_check_access(session, &session->lex->select_lex.context,
418
                                    &session->lex->select_lex.top_join_list,
1 by brian
clean slate
419
                                    lex->query_tables,
420
                                    &lex->select_lex.leaf_tables, false))
163 by Brian Aker
Merge Monty's code.
421
    return(true);
1 by brian
clean slate
422
423
424
  /*
425
    Multi-delete can't be constructed over-union => we always have
426
    single SELECT on top and have to check underlying SELECTs of it
427
  */
163 by Brian Aker
Merge Monty's code.
428
  lex->select_lex.exclude_from_table_unique_test= true;
1 by brian
clean slate
429
  /* Fix tables-to-be-deleted-from list to point at opened tables */
327.2.4 by Brian Aker
Refactoring table.h
430
  for (target_tbl= (TableList*) aux_tables;
1 by brian
clean slate
431
       target_tbl;
432
       target_tbl= target_tbl->next_local)
433
  {
737 by Brian Aker
Updates for dead code removal (and forced assert() in delete).
434
    target_tbl->table= target_tbl->correspondent_table->table;
435
    assert(target_tbl->table);
1 by brian
clean slate
436
437
    /*
438
      Check that table from which we delete is not used somewhere
439
      inside subqueries/view.
440
    */
441
    {
327.2.4 by Brian Aker
Refactoring table.h
442
      TableList *duplicate;
520.1.22 by Brian Aker
Second pass of thd cleanup
443
      if ((duplicate= unique_table(session, target_tbl->correspondent_table,
1 by brian
clean slate
444
                                   lex->query_tables, 0)))
445
      {
446
        update_non_unique_table_error(target_tbl->correspondent_table,
447
                                      "DELETE", duplicate);
163 by Brian Aker
Merge Monty's code.
448
        return(true);
1 by brian
clean slate
449
      }
450
    }
451
  }
163 by Brian Aker
Merge Monty's code.
452
  return(false);
1 by brian
clean slate
453
}
454
455
482 by Brian Aker
Remove uint.
456
multi_delete::multi_delete(TableList *dt, uint32_t num_of_tables_arg)
1 by brian
clean slate
457
  : delete_tables(dt), deleted(0), found(0),
458
    num_of_tables(num_of_tables_arg), error(0),
459
    do_delete(0), transactional_tables(0), normal_tables(0), error_handled(0)
460
{
461
  tempfiles= (Unique **) sql_calloc(sizeof(Unique *) * num_of_tables);
462
}
463
464
465
int
848 by Brian Aker
typdef class removal (just... use the name of the class).
466
multi_delete::prepare(List<Item> &, Select_Lex_Unit *u)
1 by brian
clean slate
467
{
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
468
1 by brian
clean slate
469
  unit= u;
470
  do_delete= 1;
520.1.22 by Brian Aker
Second pass of thd cleanup
471
  session->set_proc_info("deleting from main table");
51.2.2 by Patrick Galbraith
Removed DBUGs from
472
  return(0);
1 by brian
clean slate
473
}
474
475
476
bool
477
multi_delete::initialize_tables(JOIN *join)
478
{
327.2.4 by Brian Aker
Refactoring table.h
479
  TableList *walk;
1 by brian
clean slate
480
  Unique **tempfiles_ptr;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
481
1 by brian
clean slate
482
520.1.22 by Brian Aker
Second pass of thd cleanup
483
  if ((session->options & OPTION_SAFE_UPDATES) && error_if_full_join(join))
51.2.2 by Patrick Galbraith
Removed DBUGs from
484
    return(1);
1 by brian
clean slate
485
486
  table_map tables_to_delete_from=0;
487
  for (walk= delete_tables; walk; walk= walk->next_local)
488
    tables_to_delete_from|= walk->table->map;
489
490
  walk= delete_tables;
491
  delete_while_scanning= 1;
492
  for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
493
       tab < end;
494
       tab++)
495
  {
496
    if (tab->table->map & tables_to_delete_from)
497
    {
498
      /* We are going to delete from this table */
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
499
      Table *tbl=walk->table=tab->table;
1 by brian
clean slate
500
      walk= walk->next_local;
501
      /* Don't use KEYREAD optimization on this table */
502
      tbl->no_keyread=1;
503
      /* Don't use record cache */
504
      tbl->no_cache= 1;
1005.2.6 by Monty Taylor
Re-added bitset<> as a replacement for Bitmap<>
505
      tbl->covering_keys.reset();
1 by brian
clean slate
506
      if (tbl->file->has_transactions())
507
	transactional_tables= 1;
508
      else
509
	normal_tables= 1;
510
      tbl->prepare_for_position();
511
      tbl->mark_columns_needed_for_delete();
512
    }
513
    else if ((tab->type != JT_SYSTEM && tab->type != JT_CONST) &&
514
             walk == delete_tables)
515
    {
516
      /*
517
        We are not deleting from the table we are scanning. In this
518
        case send_data() shouldn't delete any rows a we may touch
519
        the rows in the deleted table many times
520
      */
521
      delete_while_scanning= 0;
522
    }
523
  }
524
  walk= delete_tables;
525
  tempfiles_ptr= tempfiles;
526
  if (delete_while_scanning)
527
  {
528
    table_being_deleted= delete_tables;
529
    walk= walk->next_local;
530
  }
531
  for (;walk ;walk= walk->next_local)
532
  {
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
533
    Table *table=walk->table;
1 by brian
clean slate
534
    *tempfiles_ptr++= new Unique (refpos_order_cmp,
535
				  (void *) table->file,
536
				  table->file->ref_length,
1034.1.6 by Brian Aker
Increase the default sort buffer size.
537
				  current_session->variables.sortbuff_size);
1 by brian
clean slate
538
  }
520.1.22 by Brian Aker
Second pass of thd cleanup
539
  return(session->is_fatal_error != 0);
1 by brian
clean slate
540
}
541
542
543
multi_delete::~multi_delete()
544
{
545
  for (table_being_deleted= delete_tables;
546
       table_being_deleted;
547
       table_being_deleted= table_being_deleted->next_local)
548
  {
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
549
    Table *table= table_being_deleted->table;
1 by brian
clean slate
550
    table->no_keyread=0;
551
  }
552
482 by Brian Aker
Remove uint.
553
  for (uint32_t counter= 0; counter < num_of_tables; counter++)
1 by brian
clean slate
554
  {
555
    if (tempfiles[counter])
556
      delete tempfiles[counter];
557
  }
558
}
559
560
575.1.2 by Monty Taylor
Changed a bunch of __attribute__((unused)) to removing the parameter name instead.
561
bool multi_delete::send_data(List<Item> &)
1 by brian
clean slate
562
{
563
  int secure_counter= delete_while_scanning ? -1 : 0;
327.2.4 by Brian Aker
Refactoring table.h
564
  TableList *del_table;
575.1.2 by Monty Taylor
Changed a bunch of __attribute__((unused)) to removing the parameter name instead.
565
1 by brian
clean slate
566
567
  for (del_table= delete_tables;
568
       del_table;
569
       del_table= del_table->next_local, secure_counter++)
570
  {
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
571
    Table *table= del_table->table;
1 by brian
clean slate
572
573
    /* Check if we are using outer join and we didn't find the row */
574
    if (table->status & (STATUS_NULL_ROW | STATUS_DELETED))
575
      continue;
576
577
    table->file->position(table->record[0]);
578
    found++;
579
580
    if (secure_counter < 0)
581
    {
582
      /* We are scanning the current table */
51.2.2 by Patrick Galbraith
Removed DBUGs from
583
      assert(del_table == table_being_deleted);
1 by brian
clean slate
584
      table->status|= STATUS_DELETED;
585
      if (!(error=table->file->ha_delete_row(table->record[0])))
586
      {
587
        deleted++;
588
        if (!table->file->has_transactions())
520.1.22 by Brian Aker
Second pass of thd cleanup
589
          session->transaction.stmt.modified_non_trans_table= true;
1 by brian
clean slate
590
      }
591
      else
592
      {
593
        table->file->print_error(error,MYF(0));
51.2.2 by Patrick Galbraith
Removed DBUGs from
594
        return(1);
1 by brian
clean slate
595
      }
596
    }
597
    else
598
    {
599
      error=tempfiles[secure_counter]->unique_add((char*) table->file->ref);
600
      if (error)
601
      {
602
	error= 1;                               // Fatal error
51.2.2 by Patrick Galbraith
Removed DBUGs from
603
	return(1);
1 by brian
clean slate
604
      }
605
    }
606
  }
51.2.2 by Patrick Galbraith
Removed DBUGs from
607
  return(0);
1 by brian
clean slate
608
}
609
610
482 by Brian Aker
Remove uint.
611
void multi_delete::send_error(uint32_t errcode,const char *err)
1 by brian
clean slate
612
{
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
613
1 by brian
clean slate
614
615
  /* First send error what ever it is ... */
616
  my_message(errcode, err, MYF(0));
617
51.2.2 by Patrick Galbraith
Removed DBUGs from
618
  return;
1 by brian
clean slate
619
}
620
621
622
void multi_delete::abort()
623
{
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
624
1 by brian
clean slate
625
626
  /* the error was handled or nothing deleted and no side effects return */
627
  if (error_handled ||
520.1.22 by Brian Aker
Second pass of thd cleanup
628
      (!session->transaction.stmt.modified_non_trans_table && !deleted))
51.2.2 by Patrick Galbraith
Removed DBUGs from
629
    return;
1 by brian
clean slate
630
631
  /*
632
    If rows from the first table only has been deleted and it is
633
    transactional, just do rollback.
634
    The same if all tables are transactional, regardless of where we are.
635
    In all other cases do attempt deletes ...
636
  */
637
  if (do_delete && normal_tables &&
638
      (table_being_deleted != delete_tables ||
639
       !table_being_deleted->table->file->has_transactions()))
640
  {
641
    /*
642
      We have to execute the recorded do_deletes() and write info into the
643
      error log
644
    */
645
    error= 1;
646
    send_eof();
51.2.2 by Patrick Galbraith
Removed DBUGs from
647
    assert(error_handled);
648
    return;
1 by brian
clean slate
649
  }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
650
520.1.22 by Brian Aker
Second pass of thd cleanup
651
  if (session->transaction.stmt.modified_non_trans_table)
1 by brian
clean slate
652
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
653
    session->transaction.all.modified_non_trans_table= true;
1 by brian
clean slate
654
  }
51.2.2 by Patrick Galbraith
Removed DBUGs from
655
  return;
1 by brian
clean slate
656
}
657
658
659
660
/*
661
  Do delete from other tables.
662
  Returns values:
663
	0 ok
664
	1 error
665
*/
666
667
int multi_delete::do_deletes()
668
{
669
  int local_error= 0, counter= 0, tmp_error;
670
  bool will_batch;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
671
51.2.2 by Patrick Galbraith
Removed DBUGs from
672
  assert(do_delete);
1 by brian
clean slate
673
674
  do_delete= 0;                                 // Mark called
675
  if (!found)
51.2.2 by Patrick Galbraith
Removed DBUGs from
676
    return(0);
1 by brian
clean slate
677
678
  table_being_deleted= (delete_while_scanning ? delete_tables->next_local :
679
                        delete_tables);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
680
1 by brian
clean slate
681
  for (; table_being_deleted;
682
       table_being_deleted= table_being_deleted->next_local, counter++)
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
683
  {
1 by brian
clean slate
684
    ha_rows last_deleted= deleted;
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
685
    Table *table = table_being_deleted->table;
1 by brian
clean slate
686
    if (tempfiles[counter]->get(table))
687
    {
688
      local_error=1;
689
      break;
690
    }
691
692
    READ_RECORD	info;
520.1.22 by Brian Aker
Second pass of thd cleanup
693
    init_read_record(&info,session,table,NULL,0,1);
1 by brian
clean slate
694
    /*
695
      Ignore any rows not found in reference tables as they may already have
696
      been deleted by foreign key handling
697
    */
698
    info.ignore_not_found_rows= 1;
699
    will_batch= !table->file->start_bulk_delete();
520.1.22 by Brian Aker
Second pass of thd cleanup
700
    while (!(local_error=info.read_record(&info)) && !session->killed)
1 by brian
clean slate
701
    {
702
      if ((local_error=table->file->ha_delete_row(table->record[0])))
703
      {
704
	table->file->print_error(local_error,MYF(0));
705
	break;
706
      }
707
      deleted++;
708
    }
709
    if (will_batch && (tmp_error= table->file->end_bulk_delete()))
710
    {
711
      if (!local_error)
712
      {
713
        local_error= tmp_error;
714
        table->file->print_error(local_error,MYF(0));
715
      }
716
    }
717
    if (last_deleted != deleted && !table->file->has_transactions())
520.1.22 by Brian Aker
Second pass of thd cleanup
718
      session->transaction.stmt.modified_non_trans_table= true;
1 by brian
clean slate
719
    end_read_record(&info);
520.1.22 by Brian Aker
Second pass of thd cleanup
720
    if (session->killed && !local_error)
1 by brian
clean slate
721
      local_error= 1;
722
    if (local_error == -1)				// End of file
723
      local_error = 0;
724
  }
51.2.2 by Patrick Galbraith
Removed DBUGs from
725
  return(local_error);
1 by brian
clean slate
726
}
727
728
729
/*
730
  Send ok to the client
731
732
  return:  0 sucess
733
	   1 error
734
*/
735
736
bool multi_delete::send_eof()
737
{
520.1.21 by Brian Aker
THD -> Session rename
738
  Session::killed_state killed_status= Session::NOT_KILLED;
520.1.22 by Brian Aker
Second pass of thd cleanup
739
  session->set_proc_info("deleting from reference tables");
1 by brian
clean slate
740
741
  /* Does deletes for the last n - 1 tables, returns 0 if ok */
742
  int local_error= do_deletes();		// returns 0 if success
743
744
  /* compute a total error to know if something failed */
745
  local_error= local_error || error;
520.1.22 by Brian Aker
Second pass of thd cleanup
746
  killed_status= (local_error == 0)? Session::NOT_KILLED : session->killed;
1 by brian
clean slate
747
  /* reset used flags */
520.1.22 by Brian Aker
Second pass of thd cleanup
748
  session->set_proc_info("end");
1 by brian
clean slate
749
520.1.22 by Brian Aker
Second pass of thd cleanup
750
  if ((local_error == 0) || session->transaction.stmt.modified_non_trans_table)
1 by brian
clean slate
751
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
752
    if (session->transaction.stmt.modified_non_trans_table)
753
      session->transaction.all.modified_non_trans_table= true;
1 by brian
clean slate
754
  }
755
  if (local_error != 0)
163 by Brian Aker
Merge Monty's code.
756
    error_handled= true; // to force early leave from ::send_error()
1 by brian
clean slate
757
758
  if (!local_error)
759
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
760
    session->row_count_func= deleted;
836 by Brian Aker
Fixed session call from function to method.
761
    session->my_ok((ha_rows) session->row_count_func);
1 by brian
clean slate
762
  }
763
  return 0;
764
}
765
766
767
/***************************************************************************
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
768
  TRUNCATE Table
1 by brian
clean slate
769
****************************************************************************/
770
771
/*
772
  Optimize delete of all rows by doing a full generate of the table
773
  This will work even if the .ISM and .ISD tables are destroyed
774
775
  dont_send_ok should be set if:
776
  - We should always wants to generate the table (even if the table type
777
    normally can't safely do this.
778
  - We don't want an ok to be sent to the end user.
779
  - We don't want to log the truncate command
780
  - If we want to have a name lock on the table on exit without errors.
781
*/
782
520.1.22 by Brian Aker
Second pass of thd cleanup
783
bool mysql_truncate(Session *session, TableList *table_list, bool dont_send_ok)
1 by brian
clean slate
784
{
785
  HA_CREATE_INFO create_info;
786
  char path[FN_REFLEN];
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
787
  Table *table;
1 by brian
clean slate
788
  bool error;
482 by Brian Aker
Remove uint.
789
  uint32_t path_length;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
790
1 by brian
clean slate
791
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
792
  memset(&create_info, 0, sizeof(create_info));
1 by brian
clean slate
793
  /* If it is a temporary table, close and regenerate it */
520.1.22 by Brian Aker
Second pass of thd cleanup
794
  if (!dont_send_ok && (table= find_temporary_table(session, table_list)))
1 by brian
clean slate
795
  {
960.2.24 by Monty Taylor
Changed handlerton to StorageEngine.
796
    StorageEngine *table_type= table->s->db_type();
1000.1.3 by Brian Aker
Renamed TABLE_SHARE to TableShare
797
    TableShare *share= table->s;
1 by brian
clean slate
798
964.1.4 by Monty Taylor
Moved flags into private area.
799
    if (!table_type->check_flag(HTON_BIT_CAN_RECREATE))
1 by brian
clean slate
800
      goto trunc_by_del;
801
802
    table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
803
520.1.22 by Brian Aker
Second pass of thd cleanup
804
    close_temporary_table(session, table, 0, 0);    // Don't free share
805
    ha_create_table(session, share->normalized_path.str,
1 by brian
clean slate
806
                    share->db.str, share->table_name.str, &create_info, 1);
807
    // We don't need to call invalidate() because this table is not in cache
520.1.22 by Brian Aker
Second pass of thd cleanup
808
    if ((error= (int) !(open_temporary_table(session, share->path.str,
1 by brian
clean slate
809
                                             share->db.str,
810
					     share->table_name.str, 1,
811
                                             OTM_OPEN))))
590.1.3 by Stewart Smith
remove frm_only create_info option
812
      (void) rm_temporary_table(table_type, path);
1000.1.5 by Brian Aker
More refactoring back to TableShare object.
813
    share->free_table_share();
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
814
    free((char*) table);
1 by brian
clean slate
815
    /*
816
      If we return here we will not have logged the truncation to the bin log
817
      and we will not my_ok() to the client.
818
    */
819
    goto end;
820
  }
821
822
  path_length= build_table_filename(path, sizeof(path), table_list->db,
1039.1.6 by Brian Aker
Refactor for build_table_filename()
823
                                    table_list->table_name, 0);
1 by brian
clean slate
824
825
  if (!dont_send_ok)
410 by Brian Aker
Removed legacy type, but truncate is no longer doing recreate. This should
826
    goto trunc_by_del;
1 by brian
clean slate
827
1046.1.2 by Brian Aker
Comments on LOCK_open
828
  pthread_mutex_lock(&LOCK_open); /* Recreate table for truncate */
520.1.22 by Brian Aker
Second pass of thd cleanup
829
  error= ha_create_table(session, path, table_list->db, table_list->table_name,
1 by brian
clean slate
830
                         &create_info, 1);
398.1.10 by Monty Taylor
Actually removed VOID() this time.
831
  pthread_mutex_unlock(&LOCK_open);
1 by brian
clean slate
832
833
end:
834
  if (!dont_send_ok)
835
  {
836
    if (!error)
837
    {
838
      /*
839
        TRUNCATE must always be statement-based binlogged (not row-based) so
840
        we don't test current_stmt_binlog_row_based.
841
      */
520.1.22 by Brian Aker
Second pass of thd cleanup
842
      write_bin_log(session, true, session->query, session->query_length);
836 by Brian Aker
Fixed session call from function to method.
843
      session->my_ok();		// This should return record count
1 by brian
clean slate
844
    }
1046.1.2 by Brian Aker
Comments on LOCK_open
845
    pthread_mutex_lock(&LOCK_open); /* For truncate delete from hash when finished */
1017 by Brian Aker
Drop dead session pass
846
    unlock_table_name(table_list);
398.1.10 by Monty Taylor
Actually removed VOID() this time.
847
    pthread_mutex_unlock(&LOCK_open);
1 by brian
clean slate
848
  }
849
  else if (error)
850
  {
1046.1.2 by Brian Aker
Comments on LOCK_open
851
    pthread_mutex_lock(&LOCK_open); /* For truncate delete from hash when finished */
1017 by Brian Aker
Drop dead session pass
852
    unlock_table_name(table_list);
398.1.10 by Monty Taylor
Actually removed VOID() this time.
853
    pthread_mutex_unlock(&LOCK_open);
1 by brian
clean slate
854
  }
51.2.2 by Patrick Galbraith
Removed DBUGs from
855
  return(error);
1 by brian
clean slate
856
857
trunc_by_del:
858
  /* Probably InnoDB table */
520.1.22 by Brian Aker
Second pass of thd cleanup
859
  uint64_t save_options= session->options;
1 by brian
clean slate
860
  table_list->lock_type= TL_WRITE;
520.1.22 by Brian Aker
Second pass of thd cleanup
861
  session->options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
862
  ha_enable_transaction(session, false);
863
  mysql_init_select(session->lex);
864
  error= mysql_delete(session, table_list, (COND*) 0, (SQL_LIST*) 0,
398.1.8 by Monty Taylor
Enabled -Wlong-long.
865
                      HA_POS_ERROR, 0L, true);
520.1.22 by Brian Aker
Second pass of thd cleanup
866
  ha_enable_transaction(session, true);
1 by brian
clean slate
867
  /*
163 by Brian Aker
Merge Monty's code.
868
    Safety, in case the engine ignored ha_enable_transaction(false)
520.1.22 by Brian Aker
Second pass of thd cleanup
869
    above. Also clears session->transaction.*.
1 by brian
clean slate
870
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
871
  error= ha_autocommit_or_rollback(session, error);
872
  ha_commit(session);
873
  session->options= save_options;
51.2.2 by Patrick Galbraith
Removed DBUGs from
874
  return(error);
1 by brian
clean slate
875
}