handler.cc
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:17k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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; either version 2 of the License, or
  6.    (at your option) any later version.
  7.    
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  16. /* Handler-calling-functions */
  17. #ifdef __GNUC__
  18. #pragma implementation // gcc: Class implementation
  19. #endif
  20. #include "mysql_priv.h"
  21. #include "ha_heap.h"
  22. #include "ha_myisam.h"
  23. #include "ha_myisammrg.h"
  24. #ifndef NO_ISAM
  25. #include "ha_isam.h"
  26. #include "ha_isammrg.h"
  27. #endif
  28. #ifdef HAVE_BERKELEY_DB
  29. #include "ha_berkeley.h"
  30. #endif
  31. #ifdef HAVE_INNOBASE_DB
  32. #include "ha_innobase.h"
  33. #endif
  34. #include <myisampack.h>
  35. #include <errno.h>
  36. /* static functions defined in this file */
  37. static int NEAR_F delete_file(const char *name,const char *ext,int extflag);
  38. ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count,
  39.       ha_read_key_count, ha_read_next_count, ha_read_prev_count,
  40.       ha_read_first_count, ha_read_last_count,
  41.       ha_read_rnd_count, ha_read_rnd_next_count;
  42. const char *ha_table_type[] = {
  43.   "", "DIAB_ISAM","HASH","MISAM","PISAM","RMS_ISAM","HEAP", "ISAM",
  44.   "MRG_ISAM","MYISAM", "MRG_MYISAM", "BDB", "INNOBASE", "?", "?",NullS
  45. };
  46. const char *ha_row_type[] = {
  47.   "", "FIXED", "DYNAMIC", "COMPRESSED","?","?","?"
  48. };
  49. TYPELIB ha_table_typelib= {array_elements(ha_table_type)-4,"",
  50.    ha_table_type+1};
  51. /* Use other database handler if databasehandler is not incompiled */
  52. enum db_type ha_checktype(enum db_type database_type)
  53. {
  54.   switch (database_type) {
  55. #ifdef HAVE_BERKELEY_DB
  56.   case DB_TYPE_BERKELEY_DB:
  57.     return(berkeley_skip ? DB_TYPE_MYISAM : database_type);
  58. #endif
  59. #ifdef HAVE_INNOBASE_DB
  60.   case DB_TYPE_INNOBASE:
  61.     return(innobase_skip ? DB_TYPE_MYISAM : database_type);
  62. #endif
  63. #ifndef NO_HASH
  64.   case DB_TYPE_HASH:
  65. #endif
  66. #ifndef NO_MERGE
  67.   case DB_TYPE_MRG_ISAM:
  68. #endif
  69. #ifndef NO_ISAM
  70.   case DB_TYPE_ISAM:
  71. #endif
  72.   case DB_TYPE_HEAP:
  73.   case DB_TYPE_MYISAM:
  74.   case DB_TYPE_MRG_MYISAM:
  75.     return (database_type); /* Database exists on system */
  76.   default:
  77.     break;
  78.   }
  79.   return(DB_TYPE_MYISAM); /* Use this as default */
  80. } /* ha_checktype */
  81. handler *get_new_handler(TABLE *table, enum db_type db_type)
  82. {
  83.   switch (db_type) {
  84. #ifndef NO_HASH
  85.   return new ha_hash(table);
  86. #endif
  87. #ifndef NO_MERGE
  88.   case DB_TYPE_MRG_ISAM:
  89.     return new ha_isammrg(table);
  90. #endif
  91. #ifndef NO_ISAM
  92.   case DB_TYPE_ISAM:
  93.     return new ha_isam(table);
  94. #endif
  95. #ifdef HAVE_BERKELEY_DB
  96.   case DB_TYPE_BERKELEY_DB:
  97.     return new ha_berkeley(table);
  98. #endif
  99. #ifdef HAVE_INNOBASE_DB
  100.   case DB_TYPE_INNOBASE:
  101.     return new ha_innobase(table);
  102. #endif
  103.   case DB_TYPE_HEAP:
  104.     return new ha_heap(table);
  105.   case DB_TYPE_MYISAM:
  106.   default: // should never happen
  107.     return new ha_myisam(table);
  108.   case DB_TYPE_MRG_MYISAM:
  109.     return new ha_myisammrg(table);
  110.   }
  111. }
  112. int ha_init()
  113. {
  114. #ifdef HAVE_BERKELEY_DB
  115.   if (!berkeley_skip)
  116.   {
  117.     int error;
  118.     if ((error=berkeley_init()))
  119.       return error;
  120.     if (!berkeley_skip) // If we couldn't use handler
  121.       opt_using_transactions=1;
  122.   }
  123. #endif
  124. #ifdef HAVE_INNOBASE_DB
  125.   if (!innobase_skip)
  126.   {
  127.     if (innobase_init())
  128.       return -1;
  129.     if (!innobase_skip) // If we couldn't use handler
  130.       opt_using_transactions=1;
  131.   }
  132. #endif
  133.   return 0;
  134. }
  135. /* close, flush or restart databases */
  136. /* Ignore this for other databases than ours */
  137. int ha_panic(enum ha_panic_function flag)
  138. {
  139.   int error=0;
  140. #ifndef NO_MERGE
  141.   error|=mrg_panic(flag);
  142. #endif
  143. #ifndef NO_HASH
  144.   error|=h_panic(flag); /* fix hash */
  145. #endif
  146.   error|=heap_panic(flag);
  147.   error|=nisam_panic(flag);
  148.   error|=mi_panic(flag);
  149.   error|=myrg_panic(flag);
  150. #ifdef HAVE_BERKELEY_DB
  151.   if (!berkeley_skip)
  152.     error|=berkeley_end();
  153. #endif
  154. #ifdef HAVE_INNOBASE_DB
  155.   if (!innobase_skip)
  156.     error|=innobase_end();
  157. #endif
  158.   return error;
  159. } /* ha_panic */
  160. void ha_close_connection(THD* thd)
  161. {
  162. #ifdef HAVE_INNOBASE_DB
  163.   if (!innobase_skip)
  164.     innobase_close_connection(thd);
  165. #endif
  166. }
  167. /*
  168.   This is used to commit or rollback a single statement depending
  169.   on the value of error
  170. */
  171. int ha_autocommit_or_rollback(THD *thd, int error)
  172. {
  173.   DBUG_ENTER("ha_autocommit_or_rollback");
  174. #ifdef USING_TRANSACTIONS
  175.   if (opt_using_transactions)
  176.   {
  177.     if (!error)
  178.     {
  179.       if (ha_commit_stmt(thd))
  180. error=1;
  181.     }
  182.     else
  183.       (void) ha_rollback_stmt(thd);
  184.   }
  185. #endif
  186.   DBUG_RETURN(error);
  187. }
  188. int ha_commit_trans(THD *thd, THD_TRANS* trans)
  189. {
  190.   int error=0;
  191.   DBUG_ENTER("ha_commit");
  192. #ifdef USING_TRANSACTIONS
  193.   if (opt_using_transactions)
  194.   {
  195.     /* Update the binary log if we have cached some queries */
  196.     if (trans == &thd->transaction.all && mysql_bin_log.is_open() &&
  197. my_b_tell(&thd->transaction.trans_log))
  198.     {
  199.       mysql_bin_log.write(&thd->transaction.trans_log);
  200.       reinit_io_cache(&thd->transaction.trans_log,
  201.       WRITE_CACHE, (my_off_t) 0, 0, 1);
  202.       thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
  203.     }
  204. #ifdef HAVE_BERKELEY_DB
  205.     if (trans->bdb_tid)
  206.     {
  207.       if ((error=berkeley_commit(thd,trans->bdb_tid)))
  208.       {
  209. my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
  210. error=1;
  211.       }
  212.       trans->bdb_tid=0;
  213.     }
  214. #endif
  215. #ifdef HAVE_INNOBASE_DB
  216.     if (trans->innobase_tid)
  217.     {
  218.       if ((error=innobase_commit(thd,trans->innobase_tid)))
  219.       {
  220. my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
  221. error=1;
  222.       }
  223.     }
  224. #endif
  225.     if (error && trans == &thd->transaction.all && mysql_bin_log.is_open())
  226.       sql_print_error("Error: Got error during commit;  Binlog is not up to date!");
  227.   }
  228. #endif // using transactions
  229.   DBUG_RETURN(error);
  230. }
  231. int ha_rollback_trans(THD *thd, THD_TRANS *trans)
  232. {
  233.   int error=0;
  234.   DBUG_ENTER("ha_rollback");
  235. #ifdef USING_TRANSACTIONS
  236.   if (opt_using_transactions)
  237.   {
  238. #ifdef HAVE_BERKELEY_DB
  239.     if (trans->bdb_tid)
  240.     {
  241.       if ((error=berkeley_rollback(thd, trans->bdb_tid)))
  242.       {
  243. my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error);
  244. error=1;
  245.       }
  246.       trans->bdb_tid=0;
  247.     }
  248. #endif
  249. #ifdef HAVE_INNOBASE_DB
  250.     if (trans->innobase_tid)
  251.     {
  252.       if ((error=innobase_rollback(thd, trans->innobase_tid)))
  253.       {
  254. my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error);
  255. error=1;
  256.       }
  257.     }
  258. #endif
  259.     if (trans == &thd->transaction.all)
  260.       reinit_io_cache(&thd->transaction.trans_log,
  261.       WRITE_CACHE, (my_off_t) 0, 0, 1);
  262.     thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
  263.   }
  264. #endif /* USING_TRANSACTIONS */
  265.   DBUG_RETURN(error);
  266. }
  267. bool ha_flush_logs()
  268. {
  269.   bool result=0;
  270. #ifdef HAVE_BERKELEY_DB
  271.   if (!berkeley_skip && berkeley_flush_logs())
  272.     result=1;
  273. #endif
  274. #ifdef HAVE_INNOBASE_DB
  275.   if (!innobase_skip && innobase_flush_logs())
  276.     result=1;
  277. #endif
  278.   return result;
  279. }
  280. /*
  281.   This should return ENOENT if the file doesn't exists.
  282.   The .frm file will be deleted only if we return 0 or ENOENT
  283. */
  284. int ha_delete_table(enum db_type table_type, const char *path)
  285. {
  286.   handler *file=get_new_handler((TABLE*) 0, table_type);
  287.   if (!file)
  288.     return ENOENT;
  289.   int error=file->delete_table(path);
  290.   delete file;
  291.   return error;
  292. }
  293.     
  294. void ha_store_ptr(byte *buff, uint pack_length, my_off_t pos)
  295. {
  296.   switch (pack_length) {
  297. #if SIZEOF_OFF_T > 4
  298.   case 8: mi_int8store(buff,pos); break;
  299.   case 7: mi_int7store(buff,pos); break;
  300.   case 6: mi_int6store(buff,pos); break;
  301.   case 5: mi_int5store(buff,pos); break;
  302. #endif
  303.   case 4: mi_int4store(buff,pos); break;
  304.   case 3: mi_int3store(buff,pos); break;
  305.   case 2: mi_int2store(buff,(uint) pos); break;
  306.   case 1: buff[0]= (uchar) pos; break;
  307.   }
  308.   return;
  309. }
  310. my_off_t ha_get_ptr(byte *ptr, uint pack_length)
  311. {
  312.   my_off_t pos;
  313.   switch (pack_length) {
  314. #if SIZEOF_OFF_T > 4
  315.   case 8:
  316.     pos= (my_off_t) mi_uint8korr(ptr);
  317.     break;
  318.   case 7:
  319.     pos= (my_off_t) mi_uint7korr(ptr);
  320.     break;
  321.   case 6:
  322.     pos= (my_off_t) mi_uint6korr(ptr);
  323.     break;
  324.   case 5:
  325.     pos= (my_off_t) mi_uint5korr(ptr);
  326.     break;
  327. #endif
  328.   case 4:
  329.     pos= (my_off_t) mi_uint4korr(ptr);
  330.     break;
  331.   case 3:
  332.     pos= (my_off_t) mi_uint3korr(ptr);
  333.     break;
  334.   case 2:
  335.     pos= (my_off_t) mi_uint2korr(ptr);
  336.     break;
  337.   case 1:
  338.     pos= (my_off_t) mi_uint2korr(ptr);
  339.     break;
  340.   default:
  341.     pos=0; // Impossible
  342.     break;
  343.   }
  344.  return pos;
  345. }
  346. /****************************************************************************
  347. ** General handler functions
  348. ****************************************************************************/
  349. /* Open database-handler. Try O_RDONLY if can't open as O_RDWR */
  350. /* Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set */
  351. int handler::ha_open(const char *name, int mode, int test_if_locked)
  352. {
  353.   int error;
  354.   DBUG_ENTER("handler::open");
  355.   DBUG_PRINT("enter",("name: %s  db_type: %d  db_stat: %d  mode: %d  lock_test: %d",
  356.       name, table->db_type, table->db_stat, mode, test_if_locked));
  357.   if ((error=open(name,mode,test_if_locked)))
  358.   {
  359.     if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
  360. (table->db_stat & HA_TRY_READ_ONLY))
  361.     {
  362.       table->db_stat|=HA_READ_ONLY;
  363.       error=open(name,O_RDONLY,test_if_locked);
  364.     }
  365.   }
  366.   if (error)
  367.   {
  368.     my_errno=error; /* Safeguard */
  369.     DBUG_PRINT("error",("error: %d  errno: %d",error,errno));
  370.   }
  371.   else
  372.   {
  373.     if (table->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
  374.       table->db_stat|=HA_READ_ONLY;
  375.   }
  376.   if (!error)
  377.   {
  378.     if (!alloc_root_inited(&table->mem_root)) // If temporary table
  379.       ref=(byte*) sql_alloc(ALIGN_SIZE(ref_length)*2);
  380.     else
  381.       ref=(byte*) alloc_root(&table->mem_root, ALIGN_SIZE(ref_length)*2);
  382.     if (!ref)
  383.     {
  384.       close();
  385.       error=HA_ERR_OUT_OF_MEM;
  386.     }
  387.     else
  388.       dupp_ref=ref+ALIGN_SIZE(ref_length);
  389.   }
  390.   DBUG_RETURN(error);
  391. }
  392. int handler::check(THD* thd, HA_CHECK_OPT* check_opt)
  393. {
  394.   return HA_ADMIN_NOT_IMPLEMENTED;
  395. }
  396. int handler::backup(THD* thd, HA_CHECK_OPT* check_opt)
  397. {
  398.   return HA_ADMIN_NOT_IMPLEMENTED;
  399. }
  400. int handler::restore(THD* thd, HA_CHECK_OPT* check_opt)
  401. {
  402.   return HA_ADMIN_NOT_IMPLEMENTED;
  403. }
  404. int handler::repair(THD* thd, HA_CHECK_OPT* check_opt)
  405. {
  406.   return HA_ADMIN_NOT_IMPLEMENTED;
  407. }
  408. int handler::optimize(THD* thd, HA_CHECK_OPT* check_opt)
  409. {
  410.   return HA_ADMIN_NOT_IMPLEMENTED;
  411. }
  412. int handler::analyze(THD* thd, HA_CHECK_OPT* check_opt)
  413. {
  414.   return HA_ADMIN_NOT_IMPLEMENTED;
  415. }
  416. /* Read first row from a table */
  417. int handler::rnd_first(byte * buf)
  418. {
  419.   register int error;
  420.   DBUG_ENTER("handler::rnd_first");
  421.   statistic_increment(ha_read_first_count,&LOCK_status);
  422.   (void) rnd_init();
  423.   while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
  424.   (void) rnd_end();
  425.   DBUG_RETURN(error);
  426. }
  427. /*
  428.   The following function is only needed for tables that may be temporary tables
  429.   during joins
  430. */
  431. int handler::restart_rnd_next(byte *buf, byte *pos)
  432. {
  433.   return HA_ERR_WRONG_COMMAND;
  434. }
  435. /* Set a timestamp in record */
  436. void handler::update_timestamp(byte *record)
  437. {
  438.   long skr= (long) current_thd->query_start();
  439. #ifdef WORDS_BIGENDIAN
  440.   if (table->db_low_byte_first)
  441.   {
  442.     int4store(record,skr);
  443.   }
  444.   else
  445. #endif
  446.   longstore(record,skr);
  447.   return;
  448. }
  449. /* Updates field with field_type NEXT_NUMBER according to following:
  450. ** if field = 0 change field to the next free key in database.
  451. */
  452. void handler::update_auto_increment()
  453. {
  454.   longlong nr;
  455.   THD *thd;
  456.   DBUG_ENTER("update_auto_increment");
  457.   if (table->next_number_field->val_int() != 0)
  458.   {
  459.     auto_increment_column_changed=0;
  460.     DBUG_VOID_RETURN;
  461.   }
  462.   thd=current_thd;
  463.   if ((nr=thd->next_insert_id))
  464.     thd->next_insert_id=0; // Clear after use
  465.   else
  466.     nr=get_auto_increment();
  467.   thd->insert_id((ulonglong) nr);
  468.   table->next_number_field->store(nr);
  469.   auto_increment_column_changed=1;
  470.   DBUG_VOID_RETURN;
  471. }
  472. longlong handler::get_auto_increment()
  473. {
  474.   longlong nr;
  475.   int error;
  476.   (void) extra(HA_EXTRA_KEYREAD);
  477.   index_init(table->next_number_index);
  478.   error=index_last(table->record[1]);
  479.   if (error)
  480.     nr=1;
  481.   else
  482.     nr=(longlong) table->next_number_field->
  483.       val_int_offset(table->rec_buff_length)+1;
  484.   (void) extra(HA_EXTRA_NO_KEYREAD);
  485.   index_end();
  486.   return nr;
  487. }
  488. /* Print error that we got from handler function */
  489. void handler::print_error(int error, myf errflag)
  490. {
  491.   DBUG_ENTER("print_error");
  492.   DBUG_PRINT("enter",("error: %d",error));
  493.   int textno=ER_GET_ERRNO;
  494.   switch (error) {
  495.   case EAGAIN:
  496.     textno=ER_FILE_USED;
  497.     break;
  498.   case ENOENT:
  499.     textno=ER_FILE_NOT_FOUND;
  500.     break;
  501.   case HA_ERR_KEY_NOT_FOUND:
  502.   case HA_ERR_NO_ACTIVE_RECORD:
  503.   case HA_ERR_END_OF_FILE:
  504.     textno=ER_KEY_NOT_FOUND;
  505.     break;
  506.   case HA_ERR_WRONG_TABLE_DEF:
  507.     textno=ER_WRONG_MRG_TABLE;
  508.     break;
  509.   case HA_ERR_FOUND_DUPP_KEY:
  510.   {
  511.     uint key_nr=get_dup_key(error);
  512.     if ((int) key_nr >= 0)
  513.     {
  514.       /* Write the dupplicated key in the error message */
  515.       char key[MAX_KEY_LENGTH];
  516.       String str(key,sizeof(key));
  517.       key_unpack(&str,table,(uint) key_nr);
  518.       uint max_length=MYSQL_ERRMSG_SIZE-(uint) strlen(ER(ER_DUP_ENTRY));
  519.       if (str.length() >= max_length)
  520.       {
  521. str.length(max_length-4);
  522. str.append("...");
  523.       }
  524.       my_error(ER_DUP_ENTRY,MYF(0),str.c_ptr(),key_nr+1);
  525.       DBUG_VOID_RETURN;
  526.     }
  527.     textno=ER_DUP_KEY;
  528.     break;
  529.   }
  530.   case HA_ERR_FOUND_DUPP_UNIQUE:
  531.     textno=ER_DUP_UNIQUE;
  532.     break;
  533.   case HA_ERR_RECORD_CHANGED:
  534.     textno=ER_CHECKREAD;
  535.     break;
  536.   case HA_ERR_CRASHED:
  537.     textno=ER_NOT_KEYFILE;
  538.     break;
  539.   case HA_ERR_CRASHED_ON_USAGE:
  540.     textno=ER_CRASHED_ON_USAGE;
  541.     break;
  542.   case HA_ERR_CRASHED_ON_REPAIR:
  543.     textno=ER_CRASHED_ON_REPAIR;
  544.     break;
  545.   case HA_ERR_OUT_OF_MEM:
  546.     my_error(ER_OUT_OF_RESOURCES,errflag);
  547.     DBUG_VOID_RETURN;
  548.   case HA_ERR_WRONG_COMMAND:
  549.     textno=ER_ILLEGAL_HA;
  550.     break;
  551.   case HA_ERR_OLD_FILE:
  552.     textno=ER_OLD_KEYFILE;
  553.     break;
  554.   case HA_ERR_UNSUPPORTED:
  555.     textno=ER_UNSUPPORTED_EXTENSION;
  556.     break;
  557.   case HA_ERR_RECORD_FILE_FULL:
  558.     textno=ER_RECORD_FILE_FULL;
  559.     break;
  560.   default:
  561.     {
  562.       my_error(ER_GET_ERRNO,errflag,error);
  563.       DBUG_VOID_RETURN;
  564.     }
  565.   }
  566.   my_error(textno,errflag,table->table_name,error);
  567.   DBUG_VOID_RETURN;
  568. }
  569. /* Return key if error because of duplicated keys */
  570. uint handler::get_dup_key(int error)
  571. {
  572.   DBUG_ENTER("get_dup_key");
  573.   table->file->errkey  = (uint) -1;
  574.   if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOUND_DUPP_UNIQUE)
  575.     info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
  576.   DBUG_RETURN(table->file->errkey);
  577. }
  578. int handler::delete_table(const char *name)
  579. {
  580.   int error=0;
  581.   for (const char **ext=bas_ext(); *ext ; ext++)
  582.   {
  583.     if (delete_file(name,*ext,2))
  584.     {
  585.       if ((error=errno) != ENOENT)
  586. break;
  587.     }
  588.   }
  589.   return error;
  590. }
  591. int handler::rename_table(const char * from, const char * to)
  592. {
  593.   DBUG_ENTER("handler::rename_table");
  594.   for (const char **ext=bas_ext(); *ext ; ext++)
  595.   {
  596.     if (rename_file_ext(from,to,*ext))
  597.       DBUG_RETURN(my_errno);
  598.   }
  599.   DBUG_RETURN(0);
  600. }
  601. int handler::index_next_same(byte *buf, const byte *key, uint keylen)
  602. {
  603.   int error;
  604.   if (!(error=index_next(buf)))
  605.   {
  606.     if (key_cmp(table, key, active_index, keylen))
  607.     {
  608.       table->status=STATUS_NOT_FOUND;
  609.       error=HA_ERR_END_OF_FILE;
  610.     }
  611.   }
  612.   return error;
  613. }
  614. /*
  615.   The following is only needed if we would like to use the database
  616.   for internal temporary tables
  617. */
  618. int handler::delete_all_rows()
  619. {
  620.   return (my_errno=HA_ERR_WRONG_COMMAND);
  621. }
  622. /****************************************************************************
  623. ** Some general functions that isn't in the handler class
  624. ****************************************************************************/
  625. /* Initiates table-file and calls apropriate database-creator */
  626. /* Returns 1 if something got wrong */
  627. int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
  628.     bool update_create_info)
  629. {
  630.   int error;
  631.   TABLE table;
  632.   DBUG_ENTER("ha_create_table");
  633.   if (openfrm(name,"",0,(uint) READ_ALL, 0, &table))
  634.     DBUG_RETURN(1);
  635.   if (update_create_info)
  636.   {
  637.     update_create_info_from_table(create_info, &table);
  638.     if (table.file->option_flag() & HA_DROP_BEFORE_CREATE)
  639.       table.file->delete_table(name); // Needed for BDB tables
  640.   }
  641.   error=table.file->create(name,&table,create_info);
  642.   VOID(closefrm(&table));
  643.   if (error)
  644.     my_error(ER_CANT_CREATE_TABLE,MYF(ME_BELL+ME_WAITTANG),name,my_errno);
  645.   DBUG_RETURN(error != 0);
  646. }
  647. /* Use key cacheing on all databases */
  648. void ha_key_cache(void)
  649. {
  650.   if (keybuff_size)
  651.     (void) init_key_cache(keybuff_size,0);
  652. } /* ha_key_cache */
  653. static int NEAR_F delete_file(const char *name,const char *ext,int extflag)
  654. {
  655.   char buff[FN_REFLEN];
  656.   VOID(fn_format(buff,name,"",ext,extflag | 4));
  657.   return(my_delete(buff,MYF(MY_WME)));
  658. }