sql_db.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:27k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000-2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /* create and drop of databases */
  14. #include "mysql_priv.h"
  15. #include <mysys_err.h>
  16. #include <my_dir.h>
  17. #include <m_ctype.h>
  18. #ifdef __WIN__
  19. #include <direct.h>
  20. #endif
  21. #define MAX_DROP_TABLE_Q_LEN      1024
  22. const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS};
  23. static TYPELIB deletable_extentions=
  24. {array_elements(del_exts)-1,"del_exts", del_exts, NULL};
  25. static long mysql_rm_known_files(THD *thd, MY_DIR *dirp,
  26.  const char *db, const char *path, uint level, 
  27.                                  TABLE_LIST **dropped_tables);
  28.          
  29. /* Database options hash */
  30. static HASH dboptions;
  31. static my_bool dboptions_init= 0;
  32. static rw_lock_t LOCK_dboptions;
  33. /* Structure for database options */
  34. typedef struct my_dbopt_st
  35. {
  36.   char *name; /* Database name                  */
  37.   uint name_length; /* Database length name           */
  38.   CHARSET_INFO *charset; /* Database default character set */
  39. } my_dbopt_t;
  40. /*
  41.   Function we use in the creation of our hash to get key.
  42. */
  43. static byte* dboptions_get_key(my_dbopt_t *opt, uint *length,
  44.                                my_bool not_used __attribute__((unused)))
  45. {
  46.   *length= opt->name_length;
  47.   return (byte*) opt->name;
  48. }
  49. /*
  50.   Helper function to write a query to binlog used by mysql_rm_db()
  51. */
  52. static inline void write_to_binlog(THD *thd, char *query, uint q_len,
  53.                                    char *db, uint db_len)
  54. {
  55.   Query_log_event qinfo(thd, query, q_len, 0, 0);
  56.   qinfo.error_code= 0;
  57.   qinfo.db= db;
  58.   qinfo.db_len= db_len;
  59.   mysql_bin_log.write(&qinfo);
  60. }  
  61. /*
  62.   Function to free dboptions hash element
  63. */
  64. static void free_dbopt(void *dbopt)
  65. {
  66.   my_free((gptr) dbopt, MYF(0));
  67. }
  68. /* 
  69.   Initialize database option hash
  70.   SYNOPSIS
  71.     my_dbopt_init()
  72.   NOTES
  73.     Must be called before any other database function is called.
  74.   RETURN
  75.     0 ok
  76.     1 Fatal error
  77. */
  78. bool my_dbopt_init(void)
  79. {
  80.   bool error= 0;
  81.   (void) my_rwlock_init(&LOCK_dboptions, NULL);
  82.   if (!dboptions_init)
  83.   {
  84.     dboptions_init= 1;
  85.     error= hash_init(&dboptions, lower_case_table_names ? 
  86.                      &my_charset_bin : system_charset_info,
  87.                      32, 0, 0, (hash_get_key) dboptions_get_key,
  88.                      free_dbopt,0);
  89.   }
  90.   return error;
  91. }
  92. /* 
  93.   Free database option hash.
  94. */
  95. void my_dbopt_free(void)
  96. {
  97.   if (dboptions_init)
  98.   {
  99.     dboptions_init= 0;
  100.     hash_free(&dboptions);
  101.     (void) rwlock_destroy(&LOCK_dboptions);
  102.   }
  103. }
  104. void my_dbopt_cleanup(void)
  105. {
  106.   rw_wrlock(&LOCK_dboptions);
  107.   hash_free(&dboptions);
  108.   hash_init(&dboptions, lower_case_table_names ? 
  109.             &my_charset_bin : system_charset_info,
  110.             32, 0, 0, (hash_get_key) dboptions_get_key,
  111.             free_dbopt,0);
  112.   rw_unlock(&LOCK_dboptions);
  113. }
  114. /*
  115.   Find database options in the hash.
  116.   
  117.   DESCRIPTION
  118.     Search a database options in the hash, usings its path.
  119.     Fills "create" on success.
  120.   
  121.   RETURN VALUES
  122.     0 on success.
  123.     1 on error.
  124. */
  125. static my_bool get_dbopt(const char *dbname, HA_CREATE_INFO *create)
  126. {
  127.   my_dbopt_t *opt;
  128.   uint length;
  129.   my_bool error= 1;
  130.   
  131.   length= (uint) strlen(dbname);
  132.   
  133.   rw_rdlock(&LOCK_dboptions);
  134.   if ((opt= (my_dbopt_t*) hash_search(&dboptions, (byte*) dbname, length)))
  135.   {
  136.     create->default_table_charset= opt->charset;
  137.     error= 0;
  138.   }
  139.   rw_unlock(&LOCK_dboptions);
  140.   return error;
  141. }
  142. /*
  143.   Writes database options into the hash.
  144.   
  145.   DESCRIPTION
  146.     Inserts database options into the hash, or updates
  147.     options if they are already in the hash.
  148.   
  149.   RETURN VALUES
  150.     0 on success.
  151.     1 on error.
  152. */
  153. static my_bool put_dbopt(const char *dbname, HA_CREATE_INFO *create)
  154. {
  155.   my_dbopt_t *opt;
  156.   uint length;
  157.   my_bool error= 0;
  158.   DBUG_ENTER("put_dbopt");
  159.   length= (uint) strlen(dbname);
  160.   
  161.   rw_wrlock(&LOCK_dboptions);
  162.   if (!(opt= (my_dbopt_t*) hash_search(&dboptions, (byte*) dbname, length)))
  163.   { 
  164.     /* Options are not in the hash, insert them */
  165.     char *tmp_name;
  166.     if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
  167.                          &opt, (uint) sizeof(*opt), &tmp_name, length+1,
  168.                          NullS))
  169.     {
  170.       error= 1;
  171.       goto end;
  172.     }
  173.     
  174.     opt->name= tmp_name;
  175.     strmov(opt->name, dbname);
  176.     opt->name_length= length;
  177.     
  178.     if ((error= my_hash_insert(&dboptions, (byte*) opt)))
  179.     {
  180.       my_free((gptr) opt, MYF(0));
  181.       goto end;
  182.     }
  183.   }
  184.   /* Update / write options in hash */
  185.   opt->charset= create->default_table_charset;
  186. end:
  187.   rw_unlock(&LOCK_dboptions);  
  188.   DBUG_RETURN(error);
  189. }
  190. /*
  191.   Deletes database options from the hash.
  192. */
  193. void del_dbopt(const char *path)
  194. {
  195.   my_dbopt_t *opt;
  196.   rw_wrlock(&LOCK_dboptions);
  197.   if ((opt= (my_dbopt_t *)hash_search(&dboptions, (const byte*) path,
  198.                                       strlen(path))))
  199.     hash_delete(&dboptions, (byte*) opt);
  200.   rw_unlock(&LOCK_dboptions);
  201. }
  202. /*
  203.   Create database options file:
  204.   DESCRIPTION
  205.     Currently database default charset is only stored there.
  206.   RETURN VALUES
  207.   0 ok
  208.   1 Could not create file or write to it.  Error sent through my_error()
  209. */
  210. static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
  211. {
  212.   register File file;
  213.   char buf[256]; // Should be enough for one option
  214.   bool error=1;
  215.   if (!create->default_table_charset)
  216.     create->default_table_charset= thd->variables.collation_server;
  217.   if (put_dbopt(path, create))
  218.     return 1;
  219.   if ((file=my_create(path, CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0)
  220.   {
  221.     ulong length;
  222.     length= (ulong) (strxnmov(buf, sizeof(buf), "default-character-set=",
  223.                               create->default_table_charset->csname,
  224.                               "ndefault-collation=",
  225.                               create->default_table_charset->name,
  226.                               "n", NullS) - buf);
  227.     /* Error is written by my_write */
  228.     if (!my_write(file,(byte*) buf, length, MYF(MY_NABP+MY_WME)))
  229.       error=0;
  230.     my_close(file,MYF(0));
  231.   }
  232.   return error;
  233. }
  234. /* 
  235.   Load database options file
  236.   load_db_opt()
  237.   path Path for option file
  238.   create Where to store the read options
  239.   DESCRIPTION
  240.     For now, only default-character-set is read.
  241.   RETURN VALUES
  242.   0 File found
  243.   1 No database file or could not open it
  244. */
  245. bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
  246. {
  247.   File file;
  248.   char buf[256];
  249.   DBUG_ENTER("load_db_opt");
  250.   bool error=1;
  251.   uint nbytes;
  252.   bzero((char*) create,sizeof(*create));
  253.   create->default_table_charset= thd->variables.collation_server;
  254.   
  255.   /* Check if options for this database are already in the hash */
  256.   if (!get_dbopt(path, create))
  257.     DBUG_RETURN(0);    
  258.   
  259.   /* Otherwise, load options from the .opt file */
  260.   if ((file=my_open(path, O_RDONLY | O_SHARE, MYF(0))) >= 0)
  261.   {
  262.     IO_CACHE cache;
  263.     init_io_cache(&cache, file, IO_SIZE, READ_CACHE, 0, 0, MYF(0));
  264.     while ((int) (nbytes= my_b_gets(&cache, (char*) buf, sizeof(buf))) > 0)
  265.     {
  266.       char *pos= buf+nbytes-1;
  267.       /* Remove end space and control characters */
  268.       while (pos > buf && !my_isgraph(&my_charset_latin1, pos[-1]))
  269. pos--;
  270.       *pos=0;
  271.       if ((pos= strchr(buf, '=')))
  272.       {
  273. if (!strncmp(buf,"default-character-set", (pos-buf)))
  274. {
  275.           /*
  276.              Try character set name, and if it fails 
  277.              try collation name, probably it's an old
  278.              4.1.0 db.opt file, which didn't have
  279.              separate default-character-set and
  280.              default-collation commands.
  281.           */
  282.   if (!(create->default_table_charset=
  283. get_charset_by_csname(pos+1, MY_CS_PRIMARY, MYF(0))) &&
  284.               !(create->default_table_charset=
  285.                 get_charset_by_name(pos+1, MYF(0))))
  286.   {
  287.     sql_print_error("Error while loading database options: '%s':",path);
  288.     sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET),pos+1);
  289.             create->default_table_charset= default_charset_info;
  290.   }
  291. }
  292. else if (!strncmp(buf,"default-collation", (pos-buf)))
  293. {
  294.   if (!(create->default_table_charset= get_charset_by_name(pos+1,
  295.    MYF(0))))
  296.   {
  297.     sql_print_error("Error while loading database options: '%s':",path);
  298.     sql_print_error(ER(ER_UNKNOWN_COLLATION),pos+1);
  299.             create->default_table_charset= default_charset_info;
  300.   }
  301. }
  302.       }
  303.     }
  304.     end_io_cache(&cache);
  305.     my_close(file,MYF(0));
  306.     /*
  307.       Put the loaded value into the hash.
  308.       Note that another thread could've added the same
  309.       entry to the hash after we called get_dbopt(),
  310.       but it's not an error, as put_dbopt() takes this
  311.       possibility into account.
  312.     */
  313.     error= put_dbopt(path, create);
  314.   }
  315.   DBUG_RETURN(error);
  316. }
  317. /*
  318.   Create a database
  319.   SYNOPSIS
  320.   mysql_create_db()
  321.   thd Thread handler
  322.   db Name of database to create
  323. Function assumes that this is already validated.
  324.   create_info Database create options (like character set)
  325.   silent Used by replication when internally creating a database.
  326. In this case the entry should not be logged.
  327.   RETURN VALUES
  328.   0 ok
  329.   -1 Error
  330. */
  331. int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
  332.     bool silent)
  333. {
  334.   char  path[FN_REFLEN+16];
  335.   long result= 1;
  336.   int error= 0;
  337.   MY_STAT stat_info;
  338.   uint create_options= create_info ? create_info->options : 0;
  339.   uint path_len;
  340.   DBUG_ENTER("mysql_create_db");
  341.   
  342.   VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
  343.   /* do not create database if another thread is holding read lock */
  344.   if (wait_if_global_read_lock(thd, 0, 1))
  345.   {
  346.     error= -1;
  347.     goto exit2;
  348.   }
  349.   /* Check directory */
  350.   strxmov(path, mysql_data_home, "/", db, NullS);
  351.   path_len= unpack_dirname(path,path);    // Convert if not unix
  352.   path[path_len-1]= 0;                    // Remove last '/' from path
  353.   if (my_stat(path,&stat_info,MYF(0)))
  354.   {
  355.    if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS))
  356.     {
  357.       my_error(ER_DB_CREATE_EXISTS,MYF(0),db);
  358.       error= -1;
  359.       goto exit;
  360.     }
  361.     push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
  362.                         ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db);
  363.     error= 0;
  364.     send_ok(thd);
  365.     goto exit;
  366.   }
  367.   else
  368.   {
  369.     if (my_errno != ENOENT)
  370.     {
  371.       my_error(EE_STAT, MYF(0),path,my_errno);
  372.       goto exit;
  373.     }
  374.     if (my_mkdir(path,0777,MYF(0)) < 0)
  375.     {
  376.       my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno);
  377.       error= -1;
  378.       goto exit;
  379.     }
  380.   }
  381.   path[path_len-1]= FN_LIBCHAR;
  382.   strmake(path+path_len, MY_DB_OPT_FILE, sizeof(path)-path_len-1);
  383.   if (write_db_opt(thd, path, create_info))
  384.   {
  385.     /*
  386.       Could not create options file.
  387.       Restore things to beginning.
  388.     */
  389.     path[path_len]= 0;
  390.     if (rmdir(path) >= 0)
  391.     {
  392.       error= -1;
  393.       goto exit;
  394.     }
  395.     /*
  396.       We come here when we managed to create the database, but not the option
  397.       file.  In this case it's best to just continue as if nothing has
  398.       happened.  (This is a very unlikely senario)
  399.     */
  400.   }
  401.   
  402.   if (!silent)
  403.   {
  404.     char *query;
  405.     uint query_length;
  406.     if (!thd->query) // Only in replication
  407.     {
  408.       query=       path;
  409.       query_length= (uint) (strxmov(path,"create database `", db, "`", NullS) -
  410.     path);
  411.     }
  412.     else
  413.     {
  414.       query=      thd->query;
  415.       query_length= thd->query_length;
  416.     }
  417.     mysql_update_log.write(thd, query, query_length);
  418.     if (mysql_bin_log.is_open())
  419.     {
  420.       Query_log_event qinfo(thd, query, query_length, 0, 
  421.     /* suppress_use */ TRUE);
  422.       /*
  423. Write should use the database being created as the "current
  424.         database" and not the threads current database, which is the
  425.         default. If we do not change the "current database" to the
  426.         database being created, the CREATE statement will not be
  427.         replicated when using --binlog-do-db to select databases to be
  428.         replicated. 
  429. An example (--binlog-do-db=sisyfos):
  430.        
  431.           CREATE DATABASE bob;        # Not replicated
  432.           USE bob;                    # 'bob' is the current database
  433.           CREATE DATABASE sisyfos;    # Not replicated since 'bob' is
  434.                                       # current database.
  435.           USE sisyfos;                # Will give error on slave since
  436.                                       # database does not exist.
  437.       */
  438.       qinfo.db     = db;
  439.       qinfo.db_len = strlen(db);
  440.       mysql_bin_log.write(&qinfo);
  441.     }
  442.     send_ok(thd, result);
  443.   }
  444. exit:
  445.   start_waiting_global_read_lock(thd);
  446. exit2:
  447.   VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
  448.   DBUG_RETURN(error);
  449. }
  450. /* db-name is already validated when we come here */
  451. int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
  452. {
  453.   char path[FN_REFLEN+16];
  454.   long result=1;
  455.   int error= 0;
  456.   DBUG_ENTER("mysql_alter_db");
  457.   VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
  458.   /* do not alter database if another thread is holding read lock */
  459.   if ((error=wait_if_global_read_lock(thd,0,1)))
  460.     goto exit2;
  461.   /* Check directory */
  462.   strxmov(path, mysql_data_home, "/", db, "/", MY_DB_OPT_FILE, NullS);
  463.   fn_format(path, path, "", "", MYF(MY_UNPACK_FILENAME));
  464.   if ((error=write_db_opt(thd, path, create_info)))
  465.     goto exit;
  466.   /*
  467.      Change options if current database is being altered
  468.      TODO: Delete this code
  469.   */
  470.   if (thd->db && !strcmp(thd->db,db))
  471.   {
  472.     thd->db_charset= create_info->default_table_charset ?
  473.      create_info->default_table_charset :
  474.      thd->variables.collation_server;
  475.     thd->variables.collation_database= thd->db_charset;
  476.   }
  477.   mysql_update_log.write(thd,thd->query, thd->query_length);
  478.   if (mysql_bin_log.is_open())
  479.   {
  480.     Query_log_event qinfo(thd, thd->query, thd->query_length, 0,
  481.   /* suppress_use */ TRUE);
  482.     /*
  483.       Write should use the database being created as the "current
  484.       database" and not the threads current database, which is the
  485.       default.
  486.     */
  487.     qinfo.db     = db;
  488.     qinfo.db_len = strlen(db);
  489.     thd->clear_error();
  490.     mysql_bin_log.write(&qinfo);
  491.   }
  492.   send_ok(thd, result);
  493. exit:
  494.   start_waiting_global_read_lock(thd);
  495. exit2:
  496.   VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
  497.   DBUG_RETURN(error ? -1 : 0); /* -1 to delegate send_error() */
  498. }
  499. /*
  500.   Drop all tables in a database and the database itself
  501.   SYNOPSIS
  502.     mysql_rm_db()
  503.     thd Thread handle
  504.     db Database name in the case given by user
  505.         It's already validated when we come here
  506.     if_exists Don't give error if database doesn't exists
  507.     silent Don't generate errors
  508.   RETURN
  509.     0   ok (Database dropped)
  510.     -1 Error generated
  511. */
  512. int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
  513. {
  514.   long deleted=0;
  515.   int error= 0;
  516.   char path[FN_REFLEN+16], tmp_db[NAME_LEN+1];
  517.   MY_DIR *dirp;
  518.   uint length;
  519.   TABLE_LIST* dropped_tables= 0;
  520.   DBUG_ENTER("mysql_rm_db");
  521.   VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
  522.   /* do not drop database if another thread is holding read lock */
  523.   if (wait_if_global_read_lock(thd, 0, 1))
  524.   {
  525.     error= -1;
  526.     goto exit2;
  527.   }
  528.   (void) sprintf(path,"%s/%s",mysql_data_home,db);
  529.   length= unpack_dirname(path,path); // Convert if not unix
  530.   strmov(path+length, MY_DB_OPT_FILE); // Append db option file name
  531.   del_dbopt(path); // Remove dboption hash entry
  532.   path[length]= ''; // Remove file name
  533.   /* See if the directory exists */
  534.   if (!(dirp= my_dir(path,MYF(MY_DONT_SORT))))
  535.   {
  536.     if (!if_exists)
  537.     {
  538.       error= -1;
  539.       my_error(ER_DB_DROP_EXISTS,MYF(0),db);
  540.       goto exit;
  541.     }
  542.     else
  543.       push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
  544.   ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS), db);
  545.   }
  546.   else
  547.   {
  548.     pthread_mutex_lock(&LOCK_open);
  549.     remove_db_from_cache(db);
  550.     pthread_mutex_unlock(&LOCK_open);
  551.     
  552.     error= -1;
  553.     if ((deleted= mysql_rm_known_files(thd, dirp, db, path, 0,
  554.                                        &dropped_tables)) >= 0)
  555.     {
  556.       ha_drop_database(path);
  557.       query_cache_invalidate1(db);
  558.       error = 0;
  559.     }
  560.   }
  561.   if (lower_case_table_names)
  562.   {
  563.     /* Convert database to lower case */
  564.     strmov(tmp_db, db);
  565.     my_casedn_str(files_charset_info, tmp_db);
  566.     db= tmp_db;
  567.   }
  568.   if (!silent && deleted>=0)
  569.   {
  570.     const char *query;
  571.     ulong query_length;
  572.     if (!thd->query)
  573.     {
  574.       /* The client used the old obsolete mysql_drop_db() call */
  575.       query= path;
  576.       query_length= (uint) (strxmov(path, "drop database `", db, "`",
  577.                                      NullS) - path);
  578.     }
  579.     else
  580.     {
  581.       query =thd->query;
  582.       query_length= thd->query_length;
  583.     }
  584.     mysql_update_log.write(thd, query, query_length);
  585.     if (mysql_bin_log.is_open())
  586.     {
  587.       Query_log_event qinfo(thd, query, query_length, 0, 
  588.     /* suppress_use */ TRUE);
  589.       /*
  590.         Write should use the database being created as the "current
  591.         database" and not the threads current database, which is the
  592.         default.
  593.       */
  594.       qinfo.db     = db;
  595.       qinfo.db_len = strlen(db);
  596.       thd->clear_error();
  597.       mysql_bin_log.write(&qinfo);
  598.     }
  599.     thd->server_status|= SERVER_STATUS_DB_DROPPED;
  600.     send_ok(thd, (ulong) deleted);
  601.     thd->server_status&= ~SERVER_STATUS_DB_DROPPED;
  602.   }
  603.   else if (mysql_bin_log.is_open())
  604.   {
  605.     char *query, *query_pos, *query_end, *query_data_start;
  606.     TABLE_LIST *tbl;
  607.     uint db_len;
  608.     if (!(query= thd->alloc(MAX_DROP_TABLE_Q_LEN)))
  609.       goto exit; /* not much else we can do */
  610.     query_pos= query_data_start= strmov(query,"drop table ");
  611.     query_end= query + MAX_DROP_TABLE_Q_LEN;
  612.     db_len= strlen(db);
  613.     for (tbl= dropped_tables; tbl; tbl= tbl->next)
  614.     {
  615.       uint tbl_name_len;
  616.       /* 3 for the quotes and the comma*/
  617.       tbl_name_len= strlen(tbl->real_name) + 3;
  618.       if (query_pos + tbl_name_len + 1 >= query_end)
  619.       {
  620.         write_to_binlog(thd, query, query_pos -1 - query, db, db_len);
  621.         query_pos= query_data_start;
  622.       }
  623.       *query_pos++ = '`';
  624.       query_pos= strmov(query_pos,tbl->real_name);
  625.       *query_pos++ = '`';
  626.       *query_pos++ = ',';
  627.     }
  628.     if (query_pos != query_data_start)
  629.     {
  630.       write_to_binlog(thd, query, query_pos -1 - query, db, db_len);
  631.     }
  632.   }
  633. exit:
  634.   start_waiting_global_read_lock(thd);
  635.   /*
  636.     If this database was the client's selected database, we silently change the
  637.     client's selected database to nothing (to have an empty SELECT DATABASE()
  638.     in the future). For this we free() thd->db and set it to 0. But we don't do
  639.     free() for the slave thread. Indeed, doing a x_free() on it leads to nasty
  640.     problems (i.e. long painful debugging) because in this thread, thd->db is
  641.     the same as data_buf and db of the Query_log_event which is dropping the
  642.     database. So if you free() thd->db, you're freeing data_buf. You set
  643.     thd->db to 0 but not data_buf (thd->db and data_buf are two distinct
  644.     pointers which point to the same place). Then in ~Query_log_event(), we
  645.     have 'if (data_buf) free(data_buf)' data_buf is !=0 so this makes a
  646.     DOUBLE free().
  647.     Side effects of this double free() are, randomly (depends on the machine),
  648.     when the slave is replicating a DROP DATABASE:
  649.     - garbage characters in the error message:
  650.     "Error 'Can't drop database 'test2'; database doesn't exist' on query
  651.     'h4zI仼'"
  652.     - segfault
  653.     - hang in "free(vio)" (yes!) in the I/O or SQL slave threads (so slave
  654.     server hangs at shutdown etc).
  655.   */
  656.   if (thd->db && !strcmp(thd->db, db))
  657.   {
  658.     if (!(thd->slave_thread)) /* a slave thread will free it itself */
  659.       x_free(thd->db);
  660.     thd->db= 0;
  661.     thd->db_length= 0;
  662.   }
  663. exit2:
  664.   VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
  665.   DBUG_RETURN(error);
  666. }
  667. /*
  668.   Removes files with known extensions plus all found subdirectories that
  669.   are 2 hex digits (raid directories).
  670.   thd MUST be set when calling this function!
  671. */
  672. static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
  673.  const char *org_path, uint level,
  674.                                  TABLE_LIST **dropped_tables)
  675. {
  676.   long deleted=0;
  677.   ulong found_other_files=0;
  678.   char filePath[FN_REFLEN];
  679.   TABLE_LIST *tot_list=0, **tot_list_next;
  680.   List<String> raid_dirs;
  681.   DBUG_ENTER("mysql_rm_known_files");
  682.   DBUG_PRINT("enter",("path: %s", org_path));
  683.   tot_list_next= &tot_list;
  684.   for (uint idx=0 ;
  685.        idx < (uint) dirp->number_off_files && !thd->killed ;
  686.        idx++)
  687.   {
  688.     FILEINFO *file=dirp->dir_entry+idx;
  689.     char *extension;
  690.     DBUG_PRINT("info",("Examining: %s", file->name));
  691.     /* skiping . and .. */
  692.     if (file->name[0] == '.' && (!file->name[1] ||
  693.        (file->name[1] == '.' &&  !file->name[2])))
  694.       continue;
  695.     /* Check if file is a raid directory */
  696.     if ((my_isdigit(&my_charset_latin1, file->name[0]) ||
  697.  (file->name[0] >= 'a' && file->name[0] <= 'f')) &&
  698. (my_isdigit(&my_charset_latin1, file->name[1]) ||
  699.  (file->name[1] >= 'a' && file->name[1] <= 'f')) &&
  700. !file->name[2] && !level)
  701.     {
  702.       char newpath[FN_REFLEN], *copy_of_path;
  703.       MY_DIR *new_dirp;
  704.       String *dir;
  705.       uint length;
  706.       strxmov(newpath,org_path,"/",file->name,NullS);
  707.       length= unpack_filename(newpath,newpath);
  708.       if ((new_dirp = my_dir(newpath,MYF(MY_DONT_SORT))))
  709.       {
  710. DBUG_PRINT("my",("New subdir found: %s", newpath));
  711. if ((mysql_rm_known_files(thd, new_dirp, NullS, newpath,1,0)) < 0)
  712.   goto err;
  713. if (!(copy_of_path= thd->memdup(newpath, length+1)) ||
  714.     !(dir= new (thd->mem_root) String(copy_of_path, length,
  715.        &my_charset_bin)) ||
  716.     raid_dirs.push_back(dir))
  717.   goto err;
  718. continue;
  719.       }
  720.       found_other_files++;
  721.       continue;
  722.     }
  723.     extension= fn_ext(file->name);
  724.     if (find_type(extension, &deletable_extentions,1+2) <= 0)
  725.     {
  726.       if (find_type(extension, ha_known_exts(),1+2) <= 0)
  727. found_other_files++;
  728.       continue;
  729.     }
  730.     /* just for safety we use files_charset_info */
  731.     if (db && !my_strcasecmp(files_charset_info,
  732.                              extension, reg_ext))
  733.     {
  734.       /* Drop the table nicely */
  735.       *extension= 0; // Remove extension
  736.       TABLE_LIST *table_list=(TABLE_LIST*)
  737. thd->calloc(sizeof(*table_list)+ strlen(db)+strlen(file->name)+2);
  738.       if (!table_list)
  739. goto err;
  740.       table_list->db= (char*) (table_list+1);
  741.       strmov(table_list->real_name= strmov(table_list->db,db)+1, file->name);
  742.       table_list->alias= table_list->real_name; // If lower_case_table_names=2
  743.       /* Link into list */
  744.       (*tot_list_next)= table_list;
  745.       tot_list_next= &table_list->next;
  746.       deleted++;
  747.     }
  748.     else
  749.     {
  750.       strxmov(filePath, org_path, "/", file->name, NullS);
  751.       if (my_delete_with_symlink(filePath,MYF(MY_WME)))
  752.       {
  753. goto err;
  754.       }
  755.     }
  756.   }
  757.   if (thd->killed ||
  758.       (tot_list && mysql_rm_table_part2_with_lock(thd, tot_list, 1, 0, 1)))
  759.     goto err;
  760.   /* Remove RAID directories */
  761.   {
  762.     List_iterator<String> it(raid_dirs);
  763.     String *dir;
  764.     while ((dir= it++))
  765.       if (rmdir(dir->c_ptr()) < 0)
  766. found_other_files++;
  767.   }
  768.   my_dirend(dirp);  
  769.   
  770.   if (dropped_tables)
  771.     *dropped_tables= tot_list;
  772.   
  773.   /*
  774.     If the directory is a symbolic link, remove the link first, then
  775.     remove the directory the symbolic link pointed at
  776.   */
  777.   if (found_other_files)
  778.   {
  779.     my_error(ER_DB_DROP_RMDIR, MYF(0), org_path, EEXIST);
  780.     DBUG_RETURN(-1);
  781.   }
  782.   else
  783.   {
  784.     char tmp_path[FN_REFLEN], *pos;
  785.     char *path= tmp_path;
  786.     unpack_filename(tmp_path,org_path);
  787. #ifdef HAVE_READLINK
  788.     int error;
  789.     
  790.     /* Remove end FN_LIBCHAR as this causes problem on Linux in readlink */
  791.     pos=strend(path);
  792.     if (pos > path && pos[-1] == FN_LIBCHAR)
  793.       *--pos=0;
  794.     if ((error=my_readlink(filePath, path, MYF(MY_WME))) < 0)
  795.       DBUG_RETURN(-1);
  796.     if (!error)
  797.     {
  798.       if (my_delete(path,MYF(!level ? MY_WME : 0)))
  799.       {
  800. /* Don't give errors if we can't delete 'RAID' directory */
  801. if (level)
  802.   DBUG_RETURN(deleted);
  803. DBUG_RETURN(-1);
  804.       }
  805.       /* Delete directory symbolic link pointed at */
  806.       path= filePath;
  807.     }
  808. #endif
  809.     /* Remove last FN_LIBCHAR to not cause a problem on OS/2 */
  810.     pos=strend(path);
  811.     if (pos > path && pos[-1] == FN_LIBCHAR)
  812.       *--pos=0;
  813.     /* Don't give errors if we can't delete 'RAID' directory */
  814.     if (rmdir(path) < 0 && !level)
  815.     {
  816.       my_error(ER_DB_DROP_RMDIR, MYF(0), path, errno);
  817.       DBUG_RETURN(-1);
  818.     }
  819.   }
  820.   DBUG_RETURN(deleted);
  821. err:
  822.   my_dirend(dirp);
  823.   DBUG_RETURN(-1);
  824. }
  825. /*
  826.   Change default database.
  827.   SYNOPSIS
  828.     mysql_change_db()
  829.     thd Thread handler
  830.     name Databasename
  831.   DESCRIPTION
  832.     Becasue the database name may have been given directly from the
  833.     communication packet (in case of 'connect' or 'COM_INIT_DB')
  834.     we have to do end space removal in this function.
  835.   NOTES
  836.     Do as little as possible in this function, as it is not called for the
  837.     replication slave SQL thread (for that thread, setting of thd->db is done
  838.     in ::exec_event() methods of log_event.cc).
  839.   RETURN VALUES
  840.     0 ok
  841.     1 error
  842. */
  843. bool mysql_change_db(THD *thd, const char *name)
  844. {
  845.   int length, db_length;
  846.   char *dbname=my_strdup((char*) name,MYF(MY_WME));
  847.   char path[FN_REFLEN];
  848.   HA_CREATE_INFO create;
  849. #ifndef NO_EMBEDDED_ACCESS_CHECKS
  850.   ulong db_access;
  851. #endif
  852.   DBUG_ENTER("mysql_change_db");
  853.   if (!dbname || !(db_length= strlen(dbname)))
  854.   {
  855.     x_free(dbname); /* purecov: inspected */
  856.     send_error(thd,ER_NO_DB_ERROR);             /* purecov: inspected */
  857.     DBUG_RETURN(1); /* purecov: inspected */
  858.   }
  859.   if (check_db_name(dbname))
  860.   {
  861.     net_printf(thd, ER_WRONG_DB_NAME, dbname);
  862.     x_free(dbname);
  863.     DBUG_RETURN(1);
  864.   }
  865.   DBUG_PRINT("info",("Use database: %s", dbname));
  866. #ifndef NO_EMBEDDED_ACCESS_CHECKS
  867.   if (test_all_bits(thd->master_access,DB_ACLS))
  868.     db_access=DB_ACLS;
  869.   else
  870.     db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) |
  871. thd->master_access);
  872.   if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
  873.   {
  874.     net_printf(thd,ER_DBACCESS_DENIED_ERROR,
  875.        thd->priv_user,
  876.        thd->priv_host,
  877.        dbname);
  878.     mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
  879.     thd->priv_user,
  880.     thd->priv_host,
  881.     dbname);
  882.     my_free(dbname,MYF(0));
  883.     DBUG_RETURN(1);
  884.   }
  885. #endif
  886.   (void) sprintf(path,"%s/%s",mysql_data_home,dbname);
  887.   length=unpack_dirname(path,path); // Convert if not unix
  888.   if (length && path[length-1] == FN_LIBCHAR)
  889.     path[length-1]=0; // remove ending ''
  890.   if (my_access(path,F_OK))
  891.   {
  892.     net_printf(thd,ER_BAD_DB_ERROR,dbname);
  893.     my_free(dbname,MYF(0));
  894.     DBUG_RETURN(1);
  895.   }
  896.   send_ok(thd);
  897.   x_free(thd->db);
  898.   thd->db=dbname; // THD::~THD will free this
  899.   thd->db_length=db_length;
  900. #ifndef NO_EMBEDDED_ACCESS_CHECKS
  901.   thd->db_access=db_access;
  902. #endif
  903.   strmov(path+unpack_dirname(path,path), MY_DB_OPT_FILE);
  904.   load_db_opt(thd, path, &create);
  905.   thd->db_charset= create.default_table_charset ?
  906.    create.default_table_charset :
  907.    thd->variables.collation_server;
  908.   thd->variables.collation_database= thd->db_charset;
  909.   DBUG_RETURN(0);
  910. }