handler.cc 16.3 KB
Newer Older
unknown's avatar
unknown committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
   
   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.
   
   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.
   
   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 */


/* Handler-calling-functions */

#ifdef __GNUC__
#pragma implementation				// gcc: Class implementation
#endif

#include "mysql_priv.h"
#include "ha_heap.h"
#include "ha_myisam.h"
#include "ha_myisammrg.h"
#ifndef NO_ISAM
#include "ha_isam.h"
#include "ha_isammrg.h"
#endif
#ifdef HAVE_BERKELEY_DB
#include "ha_berkeley.h"
#endif
35 36 37
#ifdef HAVE_INNOBASE_DB
#include "ha_innobase.h"
#endif
unknown's avatar
unknown committed
38 39 40 41 42 43 44 45 46 47 48 49 50 51
#include <myisampack.h>
#include <errno.h>

	/* static functions defined in this file */

static int NEAR_F delete_file(const char *name,const char *ext,int extflag);

ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count,
      ha_read_key_count, ha_read_next_count, ha_read_prev_count,
      ha_read_first_count, ha_read_last_count,
      ha_read_rnd_count, ha_read_rnd_next_count;

const char *ha_table_type[] = {
  "", "DIAB_ISAM","HASH","MISAM","PISAM","RMS_ISAM","HEAP", "ISAM",
52
  "MRG_ISAM","MYISAM", "MRG_MYISAM", "BDB", "INNOBASE", "?", "?",NullS
unknown's avatar
unknown committed
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
};

const char *ha_row_type[] = {
  "", "FIXED", "DYNAMIC", "COMPRESSED","?","?","?"
};

TYPELIB ha_table_typelib= {array_elements(ha_table_type)-4,"",
			   ha_table_type+1};


	/* Use other database handler if databasehandler is not incompiled */

enum db_type ha_checktype(enum db_type database_type)
{
  switch (database_type) {
#ifdef HAVE_BERKELEY_DB
  case DB_TYPE_BERKELEY_DB:
    return(berkeley_skip ? DB_TYPE_MYISAM : database_type);
#endif
72 73 74 75
#ifdef HAVE_INNOBASE_DB
  case DB_TYPE_INNOBASE:
    return(innobase_skip ? DB_TYPE_MYISAM : database_type);
#endif
unknown's avatar
unknown committed
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
#ifndef NO_HASH
  case DB_TYPE_HASH:
#endif
#ifndef NO_MERGE
  case DB_TYPE_MRG_ISAM:
#endif
#ifndef NO_ISAM
  case DB_TYPE_ISAM:
#endif
  case DB_TYPE_HEAP:
  case DB_TYPE_MYISAM:
  case DB_TYPE_MRG_MYISAM:
    return (database_type);			/* Database exists on system */
  default:
    break;
  }
  return(DB_TYPE_MYISAM);			/* Use this as default */
} /* ha_checktype */


handler *get_new_handler(TABLE *table, enum db_type db_type)
{
  switch (db_type) {
#ifndef NO_HASH
  return new ha_hash(table);
#endif
#ifndef NO_MERGE
  case DB_TYPE_MRG_ISAM:
    return new ha_isammrg(table);
#endif
#ifndef NO_ISAM
  case DB_TYPE_ISAM:
    return new ha_isam(table);
#endif
#ifdef HAVE_BERKELEY_DB
  case DB_TYPE_BERKELEY_DB:
    return new ha_berkeley(table);
113 114 115 116
#endif
#ifdef HAVE_INNOBASE_DB
  case DB_TYPE_INNOBASE_DB:
    return new ha_innobase(table);
unknown's avatar
unknown committed
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
#endif
  case DB_TYPE_HEAP:
    return new ha_heap(table);
  case DB_TYPE_MYISAM:
  default:					// should never happen
    return new ha_myisam(table);
  case DB_TYPE_MRG_MYISAM:
    return new ha_myisammrg(table);
  }
}

int ha_init()
{
#ifdef HAVE_BERKELEY_DB
  if (!berkeley_skip)
  {
    int error;
    if ((error=berkeley_init()))
      return error;
  }
137 138 139 140 141 142 143 144
#endif
#ifdef HAVE_INNOBASE_DB
  if (!innobase_skip)
  {
    int error;
    if ((error=innobase_init()))
      return error;
  }
unknown's avatar
unknown committed
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
#endif
  return 0;
}

	/* close, flush or restart databases */
	/* Ignore this for other databases than ours */

int ha_panic(enum ha_panic_function flag)
{
  int error=0;
#ifndef NO_MERGE
  error|=mrg_panic(flag);
#endif
#ifndef NO_HASH
  error|=h_panic(flag);			/* fix hash */
#endif
  error|=heap_panic(flag);
  error|=nisam_panic(flag);
  error|=mi_panic(flag);
  error|=myrg_panic(flag);
#ifdef HAVE_BERKELEY_DB
  if (!berkeley_skip)
    error|=berkeley_end();
168 169 170 171
#endif
#ifdef HAVE_INNOBASE_DB
  if (!innobase_skip)
    error|=innobase_end();
unknown's avatar
unknown committed
172 173 174 175 176
#endif
  return error;
} /* ha_panic */


177 178 179 180 181 182 183 184
void ha_close_connection(THD* thd)
{
#ifdef HAVE_INNOBASE_DB
  if (!innobase_skip)
    innobase_close_connection(THD* thd);
#endif
}

185 186 187 188 189
/*
  This is used to commit or rollback a single statement depending
  on the value of error
*/

unknown's avatar
unknown committed
190 191 192
int ha_autocommit_or_rollback(THD *thd, int error)
{
  DBUG_ENTER("ha_autocommit_or_rollback");
193
#ifdef USING_TRANSACTIONS
194
  if (!error)
unknown's avatar
unknown committed
195
  {
196 197
    if (ha_commit_stmt(thd))
      error=1;
unknown's avatar
unknown committed
198
  }
199 200
  else
    (void) ha_rollback_stmt(thd);
unknown's avatar
unknown committed
201 202 203 204
#endif
  DBUG_RETURN(error);
}

205 206

int ha_commit_trans(THD *thd, THD_TRANS* trans)
unknown's avatar
unknown committed
207 208
{
  int error=0;
209
  DBUG_ENTER("ha_commit");
210 211 212 213 214 215 216 217 218 219
#ifdef USING_TRANSACTIONS
  /* Update the binary log if we have cached some queries */
  if (trans == &thd->transaction.all && mysql_bin_log.is_open() &&
      my_b_tell(&thd->transaction.trans_log))
  {
    mysql_bin_log.write(&thd->transaction.trans_log);
    reinit_io_cache(&thd->transaction.trans_log,
		    WRITE_CACHE, (my_off_t) 0, 0, 1);
    thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
  }
unknown's avatar
unknown committed
220
#ifdef HAVE_BERKELEY_DB
221
  if (trans->bdb_tid)
unknown's avatar
unknown committed
222
  {
223
    if ((error=berkeley_commit(thd,trans->bdb_tid)))
unknown's avatar
unknown committed
224 225 226 227
    {
      my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
      error=1;
    }
228
    trans->bdb_tid=0;
unknown's avatar
unknown committed
229
  }
230 231
#endif
#ifdef HAVE_INNOBASE_DB
232
  if (trans->innobase_tid)
233
  {
234
    if ((error=innobase_commit(thd,trans->innobase_tid)))
235 236 237 238
    {
      my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
      error=1;
    }
239
    trans->innobase_tid=0;
240
  }
241 242 243
#endif
  if (error && trans == &thd->transaction.all && mysql_bin_log.is_open())
    sql_print_error("Error: Got error during commit;  Binlog is not up to date!");
244
#endif // using transactions
unknown's avatar
unknown committed
245 246 247
  DBUG_RETURN(error);
}

248
int ha_rollback_trans(THD *thd, THD_TRANS *trans)
unknown's avatar
unknown committed
249 250
{
  int error=0;
251
  DBUG_ENTER("ha_rollback");
unknown's avatar
unknown committed
252
#ifdef HAVE_BERKELEY_DB
253
  if (trans->bdb_tid)
unknown's avatar
unknown committed
254
  {
255
    if ((error=berkeley_rollback(thd, trans->bdb_tid)))
unknown's avatar
unknown committed
256 257 258 259
    {
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error);
      error=1;
    }
260
    trans->bdb_tid=0;
unknown's avatar
unknown committed
261
  }
262 263
#endif
#ifdef HAVE_INNOBASE_DB
264
  if (trans->innobase_tid)
265
  {
266
    if ((error=innobase_rollback(thd)))
267 268 269 270
    {
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error);
      error=1;
    }
271
    trans->innobase_tid=0;
272
  }
273 274 275 276 277 278
#endif
#ifdef USING_TRANSACTIONS
  if (trans == &thd->transaction.all)
    reinit_io_cache(&thd->transaction.trans_log,
		    WRITE_CACHE, (my_off_t) 0, 0, 1);
  thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
unknown's avatar
unknown committed
279 280 281 282 283 284 285 286 287 288 289
#endif
  DBUG_RETURN(error);
}


bool ha_flush_logs()
{
  bool result=0;
#ifdef HAVE_BERKELEY_DB
  if (!berkeley_skip && berkeley_flush_logs())
    result=1;
290 291 292 293
#endif
#ifdef HAVE_INNOBASE_DB
  if (!innobase_skip && innobase_flush_logs())
    result=1;
unknown's avatar
unknown committed
294 295 296 297
#endif
  return result;
}

unknown's avatar
unknown committed
298 299 300 301
/*
  This should return ENOENT if the file doesn't exists.
  The .frm file will be deleted only if we return 0 or ENOENT
*/
unknown's avatar
unknown committed
302 303 304 305 306

int ha_delete_table(enum db_type table_type, const char *path)
{
  handler *file=get_new_handler((TABLE*) 0, table_type);
  if (!file)
unknown's avatar
unknown committed
307
    return ENOENT;
unknown's avatar
unknown committed
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
  int error=file->delete_table(path);
  delete file;
  return error;
}
    
void ha_store_ptr(byte *buff, uint pack_length, my_off_t pos)
{
  switch (pack_length) {
#if SIZEOF_OFF_T > 4
  case 8: mi_int8store(buff,pos); break;
  case 7: mi_int7store(buff,pos); break;
  case 6: mi_int6store(buff,pos); break;
  case 5: mi_int5store(buff,pos); break;
#endif
  case 4: mi_int4store(buff,pos); break;
  case 3: mi_int3store(buff,pos); break;
  case 2: mi_int2store(buff,(uint) pos); break;
  case 1: buff[0]= (uchar) pos; break;
  }
  return;
}

my_off_t ha_get_ptr(byte *ptr, uint pack_length)
{
  my_off_t pos;
  switch (pack_length) {
#if SIZEOF_OFF_T > 4
  case 8:
    pos= (my_off_t) mi_uint8korr(ptr);
    break;
  case 7:
    pos= (my_off_t) mi_uint7korr(ptr);
    break;
  case 6:
    pos= (my_off_t) mi_uint6korr(ptr);
    break;
  case 5:
    pos= (my_off_t) mi_uint5korr(ptr);
    break;
#endif
  case 4:
    pos= (my_off_t) mi_uint4korr(ptr);
    break;
  case 3:
    pos= (my_off_t) mi_uint3korr(ptr);
    break;
  case 2:
    pos= (my_off_t) mi_uint2korr(ptr);
    break;
  case 1:
    pos= (my_off_t) mi_uint2korr(ptr);
    break;
  default:
    pos=0;					// Impossible
    break;
  }
 return pos;
}

/****************************************************************************
** General handler functions
****************************************************************************/

	/* Open database-handler. Try O_RDONLY if can't open as O_RDWR */
	/* Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set */

int handler::ha_open(const char *name, int mode, int test_if_locked)
{
  int error;
  DBUG_ENTER("handler::open");
unknown's avatar
unknown committed
378 379
  DBUG_PRINT("enter",("name: %s  db_type: %d  db_stat: %d  mode: %d  lock_test: %d",
		      name, table->db_type, table->db_stat, mode, test_if_locked));
unknown's avatar
unknown committed
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401

  if ((error=open(name,mode,test_if_locked)))
  {
    if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
	(table->db_stat & HA_TRY_READ_ONLY))
    {
      table->db_stat|=HA_READ_ONLY;
      error=open(name,O_RDONLY,test_if_locked);
    }
  }
  if (error)
  {
    my_errno=error;			/* Safeguard */
    DBUG_PRINT("error",("error: %d  errno: %d",error,errno));
  }
  else
  {
    if (table->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
      table->db_stat|=HA_READ_ONLY;
  }
  if (!error)
  {
unknown's avatar
unknown committed
402
    if (!alloc_root_inited(&table->mem_root))	// If temporary table
403
      ref=(byte*) sql_alloc(ALIGN_SIZE(ref_length)*2);
unknown's avatar
unknown committed
404 405 406
    else
      ref=(byte*) alloc_root(&table->mem_root, ALIGN_SIZE(ref_length)*2);
    if (!ref)
unknown's avatar
unknown committed
407 408 409 410 411 412 413 414 415 416 417 418
    {
      close();
      error=HA_ERR_OUT_OF_MEM;
    }
    else
      dupp_ref=ref+ALIGN_SIZE(ref_length);
  }
  DBUG_RETURN(error);
}

int handler::check(THD* thd, HA_CHECK_OPT* check_opt)
{
419
  return HA_ADMIN_NOT_IMPLEMENTED;
unknown's avatar
unknown committed
420 421
}

unknown's avatar
unknown committed
422 423 424 425 426 427 428 429 430 431
int handler::backup(THD* thd, HA_CHECK_OPT* check_opt)
{
  return HA_ADMIN_NOT_IMPLEMENTED;
}

int handler::restore(THD* thd, HA_CHECK_OPT* check_opt)
{
  return HA_ADMIN_NOT_IMPLEMENTED;
}

unknown's avatar
unknown committed
432 433
int handler::repair(THD* thd, HA_CHECK_OPT* check_opt)
{
434
  return HA_ADMIN_NOT_IMPLEMENTED;
unknown's avatar
unknown committed
435 436
}

437
int handler::optimize(THD* thd, HA_CHECK_OPT* check_opt)
unknown's avatar
unknown committed
438
{
439
  return HA_ADMIN_NOT_IMPLEMENTED;
unknown's avatar
unknown committed
440 441
}

442
int handler::analyze(THD* thd, HA_CHECK_OPT* check_opt)
unknown's avatar
unknown committed
443
{
444
  return HA_ADMIN_NOT_IMPLEMENTED;
unknown's avatar
unknown committed
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
}

	/* Read first row from a table */

int handler::rnd_first(byte * buf)
{
  register int error;
  DBUG_ENTER("handler::rnd_first");

  statistic_increment(ha_read_first_count,&LOCK_status);
  (void) rnd_init();
  while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
  (void) rnd_end();
  DBUG_RETURN(error);
}


/*
  The following function is only needed for tables that may be temporary tables
  during joins
*/

int handler::restart_rnd_next(byte *buf, byte *pos)
{
  return HA_ERR_WRONG_COMMAND;
}


	/* Set a timestamp in record */

void handler::update_timestamp(byte *record)
{
  long skr= (long) current_thd->query_start();
#ifdef WORDS_BIGENDIAN
  if (table->db_low_byte_first)
  {
    int4store(record,skr);
  }
  else
#endif
  longstore(record,skr);
  return;
}

	/* Updates field with field_type NEXT_NUMBER according to following:
	** if field = 0 change field to the next free key in database.
	*/

void handler::update_auto_increment()
{
  longlong nr;
  THD *thd;
  DBUG_ENTER("update_auto_increment");
  if (table->next_number_field->val_int() != 0)
    DBUG_VOID_RETURN;
  thd=current_thd;
  if ((nr=thd->next_insert_id))
    thd->next_insert_id=0;			// Clear after use
  else
    nr=get_auto_increment();
  thd->insert_id((ulonglong) nr);
  table->next_number_field->store(nr);
  DBUG_VOID_RETURN;
}


longlong handler::get_auto_increment()
{
  longlong nr;
  int error;
  (void) extra(HA_EXTRA_KEYREAD);
  index_init(table->next_number_index);
  error=index_last(table->record[1]);
  if (error)
    nr=1;
  else
    nr=(longlong) table->next_number_field->
      val_int_offset(table->rec_buff_length)+1;
  (void) extra(HA_EXTRA_NO_KEYREAD);
  index_end();
  return nr;
}

	/* Print error that we got from handler function */

void handler::print_error(int error, myf errflag)
{
  DBUG_ENTER("print_error");
  DBUG_PRINT("enter",("error: %d",error));

  int textno=ER_GET_ERRNO;
  switch (error) {
  case EAGAIN:
    textno=ER_FILE_USED;
    break;
  case ENOENT:
    textno=ER_FILE_NOT_FOUND;
    break;
  case HA_ERR_KEY_NOT_FOUND:
  case HA_ERR_NO_ACTIVE_RECORD:
  case HA_ERR_END_OF_FILE:
    textno=ER_KEY_NOT_FOUND;
    break;
  case HA_ERR_WRONG_TABLE_DEF:
    textno=ER_WRONG_MRG_TABLE;
    break;
  case HA_ERR_FOUND_DUPP_KEY:
  {
    uint key_nr=get_dup_key(error);
    if ((int) key_nr >= 0)
    {
      /* Write the dupplicated key in the error message */
      char key[MAX_KEY_LENGTH];
      String str(key,sizeof(key));
      key_unpack(&str,table,(uint) key_nr);
unknown's avatar
unknown committed
560
      uint max_length=MYSQL_ERRMSG_SIZE-(uint) strlen(ER(ER_DUP_ENTRY));
unknown's avatar
unknown committed
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580
      if (str.length() >= max_length)
      {
	str.length(max_length-4);
	str.append("...");
      }
      my_error(ER_DUP_ENTRY,MYF(0),str.c_ptr(),key_nr+1);
      DBUG_VOID_RETURN;
    }
    textno=ER_DUP_KEY;
    break;
  }
  case HA_ERR_FOUND_DUPP_UNIQUE:
    textno=ER_DUP_UNIQUE;
    break;
  case HA_ERR_RECORD_CHANGED:
    textno=ER_CHECKREAD;
    break;
  case HA_ERR_CRASHED:
    textno=ER_NOT_KEYFILE;
    break;
581 582 583 584 585 586
  case HA_ERR_CRASHED_ON_USAGE:
    textno=ER_CRASHED_ON_USAGE;
    break;
  case HA_ERR_CRASHED_ON_REPAIR:
    textno=ER_CRASHED_ON_REPAIR;
    break;
unknown's avatar
unknown committed
587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615
  case HA_ERR_OUT_OF_MEM:
    my_error(ER_OUT_OF_RESOURCES,errflag);
    DBUG_VOID_RETURN;
  case HA_ERR_WRONG_COMMAND:
    textno=ER_ILLEGAL_HA;
    break;
  case HA_ERR_OLD_FILE:
    textno=ER_OLD_KEYFILE;
    break;
  case HA_ERR_UNSUPPORTED:
    textno=ER_UNSUPPORTED_EXTENSION;
    break;
  case HA_ERR_RECORD_FILE_FULL:
    textno=ER_RECORD_FILE_FULL;
    break;
  default:
    {
      my_error(ER_GET_ERRNO,errflag,error);
      DBUG_VOID_RETURN;
    }
  }
  my_error(textno,errflag,table->table_name,error);
  DBUG_VOID_RETURN;
}

	/* Return key if error because of duplicated keys */

uint handler::get_dup_key(int error)
{
616
  DBUG_ENTER("get_dup_key");
unknown's avatar
unknown committed
617 618 619 620 621 622 623 624
  table->file->errkey  = (uint) -1;
  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOUND_DUPP_UNIQUE)
    info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
  DBUG_RETURN(table->file->errkey);
}

int handler::delete_table(const char *name)
{
unknown's avatar
unknown committed
625
  int error=0;
unknown's avatar
unknown committed
626 627 628
  for (const char **ext=bas_ext(); *ext ; ext++)
  {
    if (delete_file(name,*ext,2))
unknown's avatar
unknown committed
629 630 631 632
    {
      if ((error=errno) != ENOENT)
	break;
    }
unknown's avatar
unknown committed
633
  }
unknown's avatar
unknown committed
634
  return error;
unknown's avatar
unknown committed
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
}


int handler::rename_table(const char * from, const char * to)
{
  DBUG_ENTER("handler::rename_table");
  for (const char **ext=bas_ext(); *ext ; ext++)
  {
    if (rename_file_ext(from,to,*ext))
      DBUG_RETURN(my_errno);
  }
  DBUG_RETURN(0);
}


int handler::index_next_same(byte *buf, const byte *key, uint keylen)
{
  int error;
  if (!(error=index_next(buf)))
  {
    if (key_cmp(table, key, active_index, keylen))
    {
      table->status=STATUS_NOT_FOUND;
      error=HA_ERR_END_OF_FILE;
    }
  }
  return error;
}


/*
  The following is only needed if we would like to use the database
  for internal temporary tables
*/

int handler::delete_all_rows()
{
  return (my_errno=HA_ERR_WRONG_COMMAND);
}

/****************************************************************************
** Some general functions that isn't in the handler class
****************************************************************************/

	/* Initiates table-file and calls apropriate database-creator */
	/* Returns 1 if something got wrong */

int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
		    bool update_create_info)

{
  int error;
  TABLE table;
  DBUG_ENTER("ha_create_table");

690
  if (openfrm(name,"",0,(uint) READ_ALL, 0, &table))
unknown's avatar
unknown committed
691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
    DBUG_RETURN(1);
  if (update_create_info)
  {
    update_create_info_from_table(create_info, &table);
    if (table.file->option_flag() & HA_DROP_BEFORE_CREATE)
      table.file->delete_table(name);		// Needed for BDB tables
  }
  error=table.file->create(name,&table,create_info);
  VOID(closefrm(&table));
  if (error)
    my_error(ER_CANT_CREATE_TABLE,MYF(ME_BELL+ME_WAITTANG),name,my_errno);
  DBUG_RETURN(error != 0);
}

	/* Use key cacheing on all databases */

void ha_key_cache(void)
{
  if (keybuff_size)
    (void) init_key_cache(keybuff_size,0);
} /* ha_key_cache */


static int NEAR_F delete_file(const char *name,const char *ext,int extflag)
{
  char buff[FN_REFLEN];
  VOID(fn_format(buff,name,"",ext,extflag | 4));
  return(my_delete(buff,MYF(MY_WME)));
}