sql_delete.cc 16.1 KB
Newer Older
1
/* Copyright (C) 2000 MySQL AB
unknown's avatar
unknown committed
2

unknown's avatar
unknown committed
3 4 5 6
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
unknown's avatar
unknown committed
7

unknown's avatar
unknown committed
8 9 10 11
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
unknown's avatar
unknown committed
12

unknown's avatar
unknown committed
13 14 15 16
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

17

unknown's avatar
unknown committed
18
/*
19
  Delete of records and truncate of tables.
20

21
  Multi-table deletes were introduced by Monty and Sinisa
unknown's avatar
unknown committed
22 23
*/

24 25


26
#include "mysql_priv.h"
27
#include "ha_innodb.h"
28
#include "sql_select.h"
unknown's avatar
unknown committed
29

30
int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
unknown's avatar
unknown committed
31
                 ha_rows limit, ulong options)
unknown's avatar
unknown committed
32 33 34
{
  int		error;
  TABLE		*table;
35
  SQL_SELECT	*select=0;
unknown's avatar
unknown committed
36 37
  READ_RECORD	info;
  bool 		using_limit=limit != HA_POS_ERROR;
unknown's avatar
unknown committed
38
  bool		transactional_table, log_delayed, safe_update, const_cond; 
39
  ha_rows	deleted;
unknown's avatar
unknown committed
40 41
  DBUG_ENTER("mysql_delete");

unknown's avatar
unknown committed
42
  if (!(table = open_ltable(thd, table_list, table_list->lock_type)))
unknown's avatar
unknown committed
43
    DBUG_RETURN(-1);
44
  table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
unknown's avatar
unknown committed
45 46
  thd->proc_info="init";
  table->map=1;
47 48
  if (setup_conds(thd,table_list,&conds) || 
      setup_ftfuncs(&thd->lex.select_lex))
unknown's avatar
unknown committed
49 50
    DBUG_RETURN(-1);

51 52 53 54 55 56 57 58
  const_cond= (!conds || conds->const_item());
  safe_update=test(thd->options & OPTION_SAFE_UPDATES);
  if (safe_update && const_cond)
  {
    send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
    DBUG_RETURN(1);
  }

59
  /* Test if the user wants to delete all rows */
60 61
  if (!using_limit && const_cond &&
      !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)))
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
  {
    deleted= table->file->records;
    if (!(error=table->file->delete_all_rows()))
    {
      error= -1;				// ok
      goto cleanup;
    }
    if (error != HA_ERR_WRONG_COMMAND)
    {
      table->file->print_error(error,MYF(0));
      error=0;
      goto cleanup;
    }
    /* Handler didn't support fast delete; Delete rows one by one */
  }

unknown's avatar
unknown committed
78 79 80 81
  table->used_keys=table->quick_keys=0;		// Can't use 'only index'
  select=make_select(table,0,0,conds,&error);
  if (error)
    DBUG_RETURN(-1);
82
  if ((select && select->check_quick(safe_update, limit)) || !limit)
unknown's avatar
unknown committed
83 84
  {
    delete select;
85
    send_ok(thd,0L);
unknown's avatar
unknown committed
86
    DBUG_RETURN(0);				// Nothing to delete
unknown's avatar
unknown committed
87 88 89
  }

  /* If running in safe sql mode, don't allow updates without keys */
90
  if (!table->quick_keys)
unknown's avatar
unknown committed
91
  {
92
    thd->lex.select_lex.options|=QUERY_NO_INDEX_USED;
unknown's avatar
unknown committed
93
    if (safe_update && !using_limit)
94 95
    {
      delete select;
96
      send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
97 98
      DBUG_RETURN(1);
    }
unknown's avatar
unknown committed
99
  }
100
  if (options & OPTION_QUICK)
101 102 103 104 105 106 107 108 109
    (void) table->file->extra(HA_EXTRA_QUICK);

  if (order)
  {
    uint         length;
    SORT_FIELD  *sortorder;
    TABLE_LIST   tables;
    List<Item>   fields;
    List<Item>   all_fields;
110
    ha_rows examined_rows;
111 112 113 114 115 116 117 118

    bzero((char*) &tables,sizeof(tables));
    tables.table = table;

    table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
                                             MYF(MY_FAE | MY_ZEROFILL));
    if (setup_order(thd, &tables, fields, all_fields, order) ||
        !(sortorder=make_unireg_sortorder(order, &length)) ||
119 120
        (table->found_records = filesort(thd, table, sortorder, length,
                                        (SQL_SELECT *) 0, HA_POS_ERROR,
121
					 &examined_rows))
122 123 124 125 126 127 128 129
        == HA_POS_ERROR)
    {
      delete select;
      DBUG_RETURN(-1);		// This will force out message
    }
  }

  init_read_record(&info,thd,table,select,1,1);
130
  deleted=0L;
131
  init_ftfuncs(thd, &thd->lex.select_lex, 1);
unknown's avatar
unknown committed
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
  thd->proc_info="updating";
  while (!(error=info.read_record(&info)) && !thd->killed)
  {
    if (!(select && select->skipp_record()))
    {
      if (!(error=table->file->delete_row(table->record[0])))
      {
	deleted++;
	if (!--limit && using_limit)
	{
	  error= -1;
	  break;
	}
      }
      else
      {
	table->file->print_error(error,MYF(0));
	error=0;
	break;
      }
    }
unknown's avatar
unknown committed
153 154
    else
      table->file->unlock_row();  // Row failed selection, release lock on it
unknown's avatar
unknown committed
155 156 157
  }
  thd->proc_info="end";
  end_read_record(&info);
158
  free_io_cache(table);				// Will not do any harm
159
  if (options & OPTION_QUICK)
160
    (void) table->file->extra(HA_EXTRA_NORMAL);
161 162

cleanup:
163 164 165
  transactional_table= table->file->has_transactions();
  log_delayed= (transactional_table || table->tmp_table);
  if (deleted && (error <= 0 || !transactional_table))
unknown's avatar
unknown committed
166
  {
167 168 169
    mysql_update_log.write(thd,thd->query, thd->query_length);
    if (mysql_bin_log.is_open())
    {
170
      Query_log_event qinfo(thd, thd->query, thd->query_length, 
171 172
			    log_delayed);
      if (mysql_bin_log.write(&qinfo) && transactional_table)
173
	error=1;
174
    }
175
    if (!log_delayed)
176
      thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
unknown's avatar
unknown committed
177
  }
unknown's avatar
unknown committed
178 179 180 181 182
  if (transactional_table)
  {
    if (ha_autocommit_or_rollback(thd,error >= 0))
      error=1;
  }
unknown's avatar
unknown committed
183

unknown's avatar
unknown committed
184
  /*
unknown's avatar
unknown committed
185 186
    Store table for future invalidation  or invalidate it in
    the query cache if something changed
unknown's avatar
unknown committed
187
  */
unknown's avatar
unknown committed
188
  if (deleted)
unknown's avatar
merge  
unknown committed
189
  {
190
    query_cache_invalidate3(thd, table_list, 1);
unknown's avatar
merge  
unknown committed
191
  }
unknown's avatar
unknown committed
192 193 194 195 196 197 198
  if (thd->lock)
  {
    mysql_unlock_tables(thd, thd->lock);
    thd->lock=0;
  }
  delete select;
  if (error >= 0)				// Fatal error
199
    send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN: 0);
unknown's avatar
unknown committed
200 201
  else
  {
202
    send_ok(thd,deleted);
unknown's avatar
unknown committed
203 204 205 206 207 208
    DBUG_PRINT("info",("%d records deleted",deleted));
  }
  DBUG_RETURN(0);
}


209
/***************************************************************************
210
  Delete multiple tables from join 
211 212
***************************************************************************/

213
#define MEM_STRIP_BUF_SIZE current_thd->variables.sortbuff_size
unknown's avatar
unknown committed
214

215
extern "C" int refposcmp2(void* arg, const void *a,const void *b)
216
{
217
  return memcmp(a,b, *(int*) arg);
218
}
219

unknown's avatar
unknown committed
220 221 222
multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
			   uint num_of_tables_arg)
  : delete_tables (dt), thd(thd_arg), deleted(0),
unknown's avatar
unknown committed
223
    num_of_tables(num_of_tables_arg), error(0),
224
    do_delete(0), transactional_tables(0), log_delayed(0), normal_tables(0)
225
{
unknown's avatar
unknown committed
226 227 228 229 230
  tempfiles = (Unique **) sql_calloc(sizeof(Unique *) * (num_of_tables-1));
}


int
231
multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
unknown's avatar
unknown committed
232 233
{
  DBUG_ENTER("multi_delete::prepare");
234
  unit= u;
unknown's avatar
unknown committed
235 236 237 238 239 240 241
  do_delete = true;   
  thd->proc_info="deleting from main table";

  if (thd->options & OPTION_SAFE_UPDATES)
  {
    TABLE_LIST *table_ref;
    for (table_ref=delete_tables;  table_ref; table_ref=table_ref->next)
242
    {
unknown's avatar
unknown committed
243 244
      TABLE *table=table_ref->table;
      if ((thd->options & OPTION_SAFE_UPDATES) && !table->quick_keys)
245
      {
unknown's avatar
unknown committed
246
	my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,MYF(0));
247 248 249 250 251 252 253
	DBUG_RETURN(1);
      }
    }
  }
  DBUG_RETURN(0);
}

unknown's avatar
unknown committed
254 255 256 257

void
multi_delete::initialize_tables(JOIN *join)
{
258
  int counter=0;
259 260 261 262
  TABLE_LIST *walk;
  table_map tables_to_delete_from=0;
  for (walk= delete_tables ; walk ; walk=walk->next)
    tables_to_delete_from|= walk->table->map;
unknown's avatar
unknown committed
263

264
  walk= delete_tables;
unknown's avatar
unknown committed
265 266 267 268
  for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
       tab < end;
       tab++)
  {
269
    if (tab->table->map & tables_to_delete_from)
unknown's avatar
unknown committed
270
    {
271
      /* We are going to delete from this table */
272
      TABLE *tbl=walk->table=tab->table;
unknown's avatar
unknown committed
273
      /* Don't use KEYREAD optimization on this table */
274
      tbl->no_keyread=1;
275
      walk=walk->next;
276 277 278 279 280 281
      if (tbl->file->has_transactions())
	log_delayed= transactional_tables= 1;
      else if (tbl->tmp_table != NO_TMP_TABLE)
	log_delayed= 1;
      else
	normal_tables= 1;
unknown's avatar
unknown committed
282 283
    }
  }
284 285 286 287 288 289 290 291 292 293 294 295 296
  walk= delete_tables;
  walk->table->used_keys=0;
  for (walk=walk->next ; walk ; walk=walk->next, counter++)
  {
    tables_to_delete_from|= walk->table->map;
    TABLE *table=walk->table;
  /* Don't use key read with MULTI-TABLE-DELETE */
    table->used_keys=0;
    tempfiles[counter] = new Unique (refposcmp2,
				     (void *) &table->file->ref_length,
				     table->file->ref_length,
				     MEM_STRIP_BUF_SIZE);
  }
unknown's avatar
unknown committed
297
  init_ftfuncs(thd, thd->lex.current_select->select_lex(), 1);
unknown's avatar
unknown committed
298
}
unknown's avatar
unknown committed
299

300

301 302
multi_delete::~multi_delete()
{
unknown's avatar
unknown committed
303 304 305
  for (table_being_deleted=delete_tables ;
       table_being_deleted ;
       table_being_deleted=table_being_deleted->next)
306 307
  {
    TABLE *t=table_being_deleted->table;
308
    free_io_cache(t);				// Alloced by unique
309 310
    t->no_keyread=0;
  }
311

unknown's avatar
unknown committed
312 313
  for (uint counter = 0; counter < num_of_tables-1; counter++)
  {
314
    if (tempfiles[counter])
unknown's avatar
unknown committed
315 316
      delete tempfiles[counter];
  }
317 318
}

unknown's avatar
unknown committed
319

320 321
bool multi_delete::send_data(List<Item> &values)
{
unknown's avatar
unknown committed
322
  int secure_counter= -1;
unknown's avatar
unknown committed
323 324
  DBUG_ENTER("multi_delete::send_data");

unknown's avatar
unknown committed
325 326 327
  for (table_being_deleted=delete_tables ;
       table_being_deleted ;
       table_being_deleted=table_being_deleted->next, secure_counter++)
328 329
  {
    TABLE *table=table_being_deleted->table;
unknown's avatar
unknown committed
330 331 332 333 334 335

    /* Check if we are using outer join and we didn't find the row */
    if (table->status & (STATUS_NULL_ROW | STATUS_DELETED))
      continue;

    table->file->position(table->record[0]);
unknown's avatar
unknown committed
336

unknown's avatar
unknown committed
337
    if (secure_counter < 0)
338
    {
unknown's avatar
unknown committed
339
      /* If this is the table we are scanning */
unknown's avatar
unknown committed
340 341 342
      table->status|= STATUS_DELETED;
      if (!(error=table->file->delete_row(table->record[0])))
	deleted++;
unknown's avatar
unknown committed
343
      else if (!table_being_deleted->next)
344
      {
unknown's avatar
unknown committed
345
	table->file->print_error(error,MYF(0));
unknown's avatar
unknown committed
346
	DBUG_RETURN(1);
unknown's avatar
unknown committed
347 348 349 350
      }
    }
    else
    {
unknown's avatar
unknown committed
351
      error=tempfiles[secure_counter]->unique_add((char*) table->file->ref);
unknown's avatar
unknown committed
352 353 354
      if (error)
      {
	error=-1;
unknown's avatar
unknown committed
355
	DBUG_RETURN(1);
unknown's avatar
unknown committed
356
      }
357 358
    }
  }
unknown's avatar
unknown committed
359
  DBUG_RETURN(0);
360 361 362 363
}

void multi_delete::send_error(uint errcode,const char *err)
{
unknown's avatar
unknown committed
364 365
  DBUG_ENTER("multi_delete::send_error");

unknown's avatar
unknown committed
366
  /* First send error what ever it is ... */
367
  ::send_error(thd,errcode,err);
unknown's avatar
unknown committed
368

unknown's avatar
unknown committed
369 370
  /* If nothing deleted return */
  if (!deleted)
unknown's avatar
unknown committed
371
    DBUG_VOID_RETURN;
372

373
  /* Something already deleted so we have to invalidate cache */
374 375
  query_cache_invalidate3(thd, delete_tables, 1);

unknown's avatar
unknown committed
376 377 378 379 380
  /* Below can happen when thread is killed early ... */
  if (!table_being_deleted)
    table_being_deleted=delete_tables;

  /*
381 382
    If rows from the first table only has been deleted and it is
    transactional, just do rollback.
unknown's avatar
unknown committed
383 384 385 386
    The same if all tables are transactional, regardless of where we are.
    In all other cases do attempt deletes ...
  */
  if ((table_being_deleted->table->file->has_transactions() &&
387
       table_being_deleted == delete_tables) || !normal_tables)
388
    ha_rollback_stmt(thd);
389
  else if (do_delete)
unknown's avatar
unknown committed
390 391 392 393
  {
    VOID(do_deletes(1));
  }
  DBUG_VOID_RETURN;
394 395
}

unknown's avatar
unknown committed
396

unknown's avatar
unknown committed
397 398 399 400 401 402 403
/*
  Do delete from other tables.
  Returns values:
	0 ok
	1 error
*/

unknown's avatar
unknown committed
404
int multi_delete::do_deletes(bool from_send_error)
405
{
406
  int local_error= 0, counter= 0;
unknown's avatar
unknown committed
407

408 409
  if (from_send_error)
  {
unknown's avatar
unknown committed
410 411 412 413
    /* Found out table number for 'table_being_deleted' */
    for (TABLE_LIST *aux=delete_tables;
	 aux != table_being_deleted;
	 aux=aux->next)
414 415 416 417
      counter++;
  }
  else
    table_being_deleted = delete_tables;
unknown's avatar
unknown committed
418

419
  do_delete = false;
unknown's avatar
unknown committed
420 421 422
  for (table_being_deleted=table_being_deleted->next;
       table_being_deleted ;
       table_being_deleted=table_being_deleted->next, counter++)
423
  { 
unknown's avatar
unknown committed
424 425 426
    TABLE *table = table_being_deleted->table;
    if (tempfiles[counter]->get(table))
    {
427
      local_error=1;
unknown's avatar
unknown committed
428 429 430 431 432
      break;
    }

    READ_RECORD	info;
    init_read_record(&info,thd,table,NULL,0,0);
unknown's avatar
merge  
unknown committed
433
    while (!(local_error=info.read_record(&info)) && !thd->killed)
unknown's avatar
unknown committed
434
    {
435
      if ((local_error=table->file->delete_row(table->record[0])))
436
      {
437
	table->file->print_error(local_error,MYF(0));
unknown's avatar
unknown committed
438
	break;
439
      }
unknown's avatar
unknown committed
440
      deleted++;
441
    }
unknown's avatar
unknown committed
442
    end_read_record(&info);
443 444
    if (local_error == -1)				// End of file
      local_error = 0;
445
  }
446
  return local_error;
447 448
}

unknown's avatar
unknown committed
449

450
/*
451 452
  Send ok to the client

453 454 455 456
  return:  0 sucess
	   1 error
*/

457 458
bool multi_delete::send_eof()
{
459
  thd->proc_info="deleting from reference tables";
460 461

  /* Does deletes for the last n - 1 tables, returns 0 if ok */
462
  int local_error= do_deletes(0);		// returns 0 if success
unknown's avatar
unknown committed
463

unknown's avatar
unknown committed
464
  /* reset used flags */
465
  thd->proc_info="end";
unknown's avatar
unknown committed
466 467


468 469 470 471 472 473
  /*
    Write the SQL statement to the binlog if we deleted
    rows and we succeeded, or also in an error case when there
    was a non-transaction-safe table involved, since
    modifications in it cannot be rolled back.
  */
474
  if (deleted)
475 476
  {
    mysql_update_log.write(thd,thd->query,thd->query_length);
unknown's avatar
unknown committed
477 478
    if (mysql_bin_log.is_open())
    {
479 480 481
      Query_log_event qinfo(thd, thd->query, thd->query_length,
			    log_delayed);
      if (mysql_bin_log.write(&qinfo) && !normal_tables)
482
	local_error=1;  // Log write failed: roll back the SQL statement
unknown's avatar
unknown committed
483
    }
484
    /* Commit or rollback the current SQL statement */ 
485
    VOID(ha_autocommit_or_rollback(thd,local_error > 0));
486

unknown's avatar
unknown committed
487
    query_cache_invalidate3(thd, delete_tables, 1);
488
  }
unknown's avatar
merge  
unknown committed
489
  if (local_error)
unknown's avatar
unknown committed
490
    ::send_error(thd);
491
  else
unknown's avatar
unknown committed
492
    ::send_ok(thd, deleted);
493 494
  return 0;
}
495 496 497


/***************************************************************************
498
  TRUNCATE TABLE
499 500 501 502 503 504 505 506 507 508 509
****************************************************************************/

/*
  Optimize delete of all rows by doing a full generate of the table
  This will work even if the .ISM and .ISD tables are destroyed

  dont_send_ok should be set if:
  - We should always wants to generate the table (even if the table type
    normally can't safely do this.
  - We don't want an ok to be sent to the end user.
  - We don't want to log the truncate command
unknown's avatar
unknown committed
510
  - If we want to have a name lock on the table on exit without errors.
511 512 513 514 515 516 517 518 519 520 521
*/

int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
{
  HA_CREATE_INFO create_info;
  char path[FN_REFLEN];
  TABLE **table_ptr;
  int error;
  DBUG_ENTER("mysql_truncate");

  /* If it is a temporary table, close and regenerate it */
unknown's avatar
unknown committed
522 523
  if (!dont_send_ok && (table_ptr=find_temporary_table(thd,table_list->db,
						       table_list->real_name)))
524 525 526 527 528 529
  {
    TABLE *table= *table_ptr;
    HA_CREATE_INFO create_info;
    table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
    bzero((char*) &create_info,sizeof(create_info));
    create_info.auto_increment_value= table->file->auto_increment_value;
unknown's avatar
unknown committed
530
    create_info.table_charset=default_charset_info;
531

unknown's avatar
unknown committed
532
    db_type table_type=table->db_type;
533 534 535 536 537
    strmov(path,table->path);
    *table_ptr= table->next;			// Unlink table from list
    close_temporary(table,0);
    *fn_ext(path)=0;				// Remove the .frm extension
    ha_create_table(path, &create_info,1);
unknown's avatar
unknown committed
538
    // We don't need to call invalidate() because this table is not in cache
539 540 541
    if ((error= (int) !(open_temporary_table(thd, path, table_list->db,
					     table_list->real_name, 1))))
      (void) rm_temporary_table(table_type, path);
542
    /*
unknown's avatar
unknown committed
543 544
      If we return here we will not have logged the truncation to the bin log
      and we will not send_ok() to the client.
545 546
    */
    goto end; 
547 548 549 550 551 552 553 554 555 556 557
  }

  (void) sprintf(path,"%s/%s/%s%s",mysql_data_home,table_list->db,
		 table_list->real_name,reg_ext);
  fn_format(path,path,"","",4);

  if (!dont_send_ok)
  {
    db_type table_type;
    if ((table_type=get_table_type(path)) == DB_TYPE_UNKNOWN)
    {
558 559
      my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db,
	       table_list->real_name);
560 561 562 563 564
      DBUG_RETURN(-1);
    }
    if (!ha_supports_generate(table_type))
    {
      /* Probably InnoDB table */
unknown's avatar
unknown committed
565 566 567
      table_list->lock_type= TL_WRITE;
      DBUG_RETURN(mysql_delete(thd, table_list, (COND*) 0, (ORDER*) 0,
			       HA_POS_ERROR, 0));
568 569 570 571 572 573
    }
    if (lock_and_wait_for_table_name(thd, table_list))
      DBUG_RETURN(-1);
  }

  bzero((char*) &create_info,sizeof(create_info));
unknown's avatar
unknown committed
574 575
  create_info.table_charset=default_charset_info;

576 577
  *fn_ext(path)=0;				// Remove the .frm extension
  error= ha_create_table(path,&create_info,1) ? -1 : 0;
unknown's avatar
unknown committed
578
  query_cache_invalidate3(thd, table_list, 0); 
579

580
end:
unknown's avatar
unknown committed
581
  if (!dont_send_ok)
582
  {
unknown's avatar
unknown committed
583
    if (!error)
584
    {
unknown's avatar
unknown committed
585 586 587
      mysql_update_log.write(thd,thd->query,thd->query_length);
      if (mysql_bin_log.is_open())
      {
588 589
	Query_log_event qinfo(thd, thd->query, thd->query_length,
			      thd->tmp_table);
unknown's avatar
unknown committed
590 591
	mysql_bin_log.write(&qinfo);
      }
592
      send_ok(thd);		// This should return record count
593
    }
594
    VOID(pthread_mutex_lock(&LOCK_open));
unknown's avatar
unknown committed
595
    unlock_table_name(thd, table_list);
596
    VOID(pthread_mutex_unlock(&LOCK_open));
597
  }
unknown's avatar
unknown committed
598
  else if (error)
599 600
  {
    VOID(pthread_mutex_lock(&LOCK_open));
unknown's avatar
unknown committed
601
    unlock_table_name(thd, table_list);
602 603
    VOID(pthread_mutex_unlock(&LOCK_open));
  }
604 605
  DBUG_RETURN(error ? -1 : 0);
}