377
422
bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
426
DBUG_ENTER("load_db_opt");
383
memset(create, 0, sizeof(*create));
430
bzero((char*) create,sizeof(*create));
384
431
create->default_table_charset= thd->variables.collation_server;
386
433
/* Check if options for this database are already in the hash */
387
434
if (!get_dbopt(path, create))
390
fstream input(path, ios::in | ios::binary);
393
else if (!db.ParseFromIstream(&input))
396
buffer= db.characterset();
397
if (!(create->default_table_charset= get_charset_by_csname(buffer.c_str(), MY_CS_PRIMARY, MYF(0))))
399
sql_print_error(_("Error while loading database options: '%s':"),path);
400
sql_print_error(ER(ER_UNKNOWN_COLLATION), buffer.c_str());
401
create->default_table_charset= default_charset_info;
404
buffer= db.collation();
405
if (!(create->default_table_charset= get_charset_by_name(buffer.c_str(), MYF(0))))
407
sql_print_error(_("Error while loading database options: '%s':"),path);
408
sql_print_error(ER(ER_UNKNOWN_COLLATION), buffer.c_str());
409
create->default_table_charset= default_charset_info;
437
/* Otherwise, load options from the .opt file */
438
if ((file=my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0)
442
if (init_io_cache(&cache, file, IO_SIZE, READ_CACHE, 0, 0, MYF(0)))
445
while ((int) (nbytes= my_b_gets(&cache, (char*) buf, sizeof(buf))) > 0)
447
char *pos= buf+nbytes-1;
448
/* Remove end space and control characters */
449
while (pos > buf && !my_isgraph(&my_charset_latin1, pos[-1]))
452
if ((pos= strchr(buf, '=')))
454
if (!strncmp(buf,"default-character-set", (pos-buf)))
457
Try character set name, and if it fails
458
try collation name, probably it's an old
459
4.1.0 db.opt file, which didn't have
460
separate default-character-set and
461
default-collation commands.
463
if (!(create->default_table_charset=
464
get_charset_by_csname(pos+1, MY_CS_PRIMARY, MYF(0))) &&
465
!(create->default_table_charset=
466
get_charset_by_name(pos+1, MYF(0))))
468
sql_print_error("Error while loading database options: '%s':",path);
469
sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET),pos+1);
470
create->default_table_charset= default_charset_info;
473
else if (!strncmp(buf,"default-collation", (pos-buf)))
475
if (!(create->default_table_charset= get_charset_by_name(pos+1,
478
sql_print_error("Error while loading database options: '%s':",path);
479
sql_print_error(ER(ER_UNKNOWN_COLLATION),pos+1);
480
create->default_table_charset= default_charset_info;
413
486
Put the loaded value into the hash.
414
487
Note that another thread could've added the same
920
1008
if (thd->db && !strcmp(thd->db, db))
921
1009
mysql_change_db_impl(thd, NULL, thd->variables.collation_server);
922
pthread_mutex_unlock(&LOCK_mysql_create_db);
1010
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
923
1011
start_waiting_global_read_lock(thd);
929
Removes files with known extensions plus.
1017
Removes files with known extensions plus all found subdirectories that
1018
are 2 hex digits (raid directories).
930
1019
thd MUST be set when calling this function!
933
1022
static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
934
const char *org_path, uint32_t level,
935
TableList **dropped_tables)
1023
const char *org_path, uint level,
1024
TABLE_LIST **dropped_tables)
938
uint32_t found_other_files=0;
1027
ulong found_other_files=0;
939
1028
char filePath[FN_REFLEN];
940
TableList *tot_list=0, **tot_list_next;
1029
TABLE_LIST *tot_list=0, **tot_list_next;
1030
List<String> raid_dirs;
1031
DBUG_ENTER("mysql_rm_known_files");
1032
DBUG_PRINT("enter",("path: %s", org_path));
942
1034
tot_list_next= &tot_list;
944
for (uint32_t idx=0 ;
945
1037
idx < (uint) dirp->number_off_files && !thd->killed ;
948
1040
FILEINFO *file=dirp->dir_entry+idx;
949
1041
char *extension;
1042
DBUG_PRINT("info",("Examining: %s", file->name));
951
1044
/* skiping . and .. */
952
1045
if (file->name[0] == '.' && (!file->name[1] ||
953
1046
(file->name[1] == '.' && !file->name[2])))
1049
/* Check if file is a raid directory */
1050
if ((my_isdigit(system_charset_info, file->name[0]) ||
1051
(file->name[0] >= 'a' && file->name[0] <= 'f')) &&
1052
(my_isdigit(system_charset_info, file->name[1]) ||
1053
(file->name[1] >= 'a' && file->name[1] <= 'f')) &&
1054
!file->name[2] && !level)
1056
char newpath[FN_REFLEN], *copy_of_path;
1061
strxmov(newpath,org_path,"/",file->name,NullS);
1062
length= unpack_filename(newpath,newpath);
1063
if ((new_dirp = my_dir(newpath,MYF(MY_DONT_SORT))))
1065
DBUG_PRINT("my",("New subdir found: %s", newpath));
1066
if ((mysql_rm_known_files(thd, new_dirp, NullS, newpath,1,0)) < 0)
1068
if (!(copy_of_path= (char*) thd->memdup(newpath, length+1)) ||
1069
!(dir= new (thd->mem_root) String(copy_of_path, length,
1070
&my_charset_bin)) ||
1071
raid_dirs.push_back(dir))
1075
found_other_files++;
1078
else if (file->name[0] == 'a' && file->name[1] == 'r' &&
1079
file->name[2] == 'c' && file->name[3] == '\0')
1082
char newpath[FN_REFLEN];
1084
strxmov(newpath, org_path, "/", "arc", NullS);
1085
(void) unpack_filename(newpath, newpath);
1086
if ((new_dirp = my_dir(newpath, MYF(MY_DONT_SORT))))
1088
DBUG_PRINT("my",("Archive subdir found: %s", newpath));
1089
if ((mysql_rm_arc_files(thd, new_dirp, newpath)) < 0)
1093
found_other_files++;
956
1096
if (!(extension= strrchr(file->name, '.')))
957
extension= strchr(file->name, '\0');
1097
extension= strend(file->name);
958
1098
if (find_type(extension, &deletable_extentions,1+2) <= 0)
960
1100
if (find_type(extension, ha_known_exts(),1+2) <= 0)
1044
static bool rm_dir_w_symlink(const char *org_path, bool send_error)
1192
static my_bool rm_dir_w_symlink(const char *org_path, my_bool send_error)
1046
1194
char tmp_path[FN_REFLEN], *pos;
1047
1195
char *path= tmp_path;
1196
DBUG_ENTER("rm_dir_w_symlink");
1048
1197
unpack_filename(tmp_path, org_path);
1049
1198
#ifdef HAVE_READLINK
1051
1200
char tmp2_path[FN_REFLEN];
1053
1202
/* Remove end FN_LIBCHAR as this causes problem on Linux in readlink */
1054
pos= strchr(path, '\0');
1055
1204
if (pos > path && pos[-1] == FN_LIBCHAR)
1058
1207
if ((error= my_readlink(tmp2_path, path, MYF(MY_WME))) < 0)
1062
1211
if (my_delete(path, MYF(send_error ? MY_WME : 0)))
1213
DBUG_RETURN(send_error);
1066
1215
/* Delete directory symbolic link pointed at */
1067
1216
path= tmp2_path;
1070
1219
/* Remove last FN_LIBCHAR to not cause a problem on OS/2 */
1071
pos= strchr(path, '\0');
1073
1222
if (pos > path && pos[-1] == FN_LIBCHAR)
1075
1224
if (rmdir(path) < 0 && send_error)
1077
1226
my_error(ER_DB_DROP_RMDIR, MYF(0), path, errno);
1234
Remove .frm archives from directory
1238
dirp list of files in archive directory
1240
org_path path of archive directory
1243
> 0 number of removed files
1246
static long mysql_rm_arc_files(THD *thd, MY_DIR *dirp,
1247
const char *org_path)
1250
ulong found_other_files= 0;
1251
char filePath[FN_REFLEN];
1252
DBUG_ENTER("mysql_rm_arc_files");
1253
DBUG_PRINT("enter", ("path: %s", org_path));
1256
idx < (uint) dirp->number_off_files && !thd->killed ;
1259
FILEINFO *file=dirp->dir_entry+idx;
1260
char *extension, *revision;
1261
DBUG_PRINT("info",("Examining: %s", file->name));
1263
/* skiping . and .. */
1264
if (file->name[0] == '.' && (!file->name[1] ||
1265
(file->name[1] == '.' && !file->name[2])))
1268
extension= fn_ext(file->name);
1269
if (extension[0] != '.' ||
1270
extension[1] != 'f' || extension[2] != 'r' ||
1271
extension[3] != 'm' || extension[4] != '-')
1273
found_other_files++;
1276
revision= extension+5;
1277
while (*revision && my_isdigit(system_charset_info, *revision))
1281
found_other_files++;
1284
strxmov(filePath, org_path, "/", file->name, NullS);
1285
if (my_delete_with_symlink(filePath,MYF(MY_WME)))
1296
If the directory is a symbolic link, remove the link first, then
1297
remove the directory the symbolic link pointed at
1299
if (!found_other_files &&
1300
rm_dir_w_symlink(org_path, 0))
1302
DBUG_RETURN(deleted);
1651
lock_databases(THD *thd, const char *db1, uint length1,
1652
const char *db2, uint length2)
1654
pthread_mutex_lock(&LOCK_lock_db);
1655
while (!thd->killed &&
1656
(hash_search(&lock_db_cache,(uchar*) db1, length1) ||
1657
hash_search(&lock_db_cache,(uchar*) db2, length2)))
1659
wait_for_condition(thd, &LOCK_lock_db, &COND_refresh);
1660
pthread_mutex_lock(&LOCK_lock_db);
1665
pthread_mutex_unlock(&LOCK_lock_db);
1669
lock_db_insert(db1, length1);
1670
lock_db_insert(db2, length2);
1671
creating_database++;
1674
Wait if a concurent thread is creating a table at the same time.
1675
The assumption here is that it will not take too long until
1676
there is a point in time when a table is not created.
1679
while (!thd->killed && creating_table)
1681
wait_for_condition(thd, &LOCK_lock_db, &COND_refresh);
1682
pthread_mutex_lock(&LOCK_lock_db);
1687
lock_db_delete(db1, length1);
1688
lock_db_delete(db2, length2);
1689
creating_database--;
1690
pthread_mutex_unlock(&LOCK_lock_db);
1691
pthread_cond_signal(&COND_refresh);
1696
We can unlock now as the hash will protect against anyone creating a table
1697
in the databases we are using
1699
pthread_mutex_unlock(&LOCK_lock_db);
1705
Upgrade a 5.0 database.
1706
This function is invoked whenever an ALTER DATABASE UPGRADE query is executed:
1707
ALTER DATABASE 'olddb' UPGRADE DATA DIRECTORY NAME.
1709
If we have managed to rename (move) tables to the new database
1710
but something failed on a later step, then we store the
1711
RENAME DATABASE event in the log. mysql_rename_db() is atomic in
1712
the sense that it will rename all or none of the tables.
1714
@param thd Current thread
1715
@param old_db 5.0 database name, in #mysql50#name format
1716
@return 0 on success, 1 on error
1718
bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db)
1720
int error= 0, change_to_newdb= 0;
1721
char path[FN_REFLEN+16];
1723
HA_CREATE_INFO create_info;
1725
TABLE_LIST *table_list;
1726
SELECT_LEX *sl= thd->lex->current_select;
1728
DBUG_ENTER("mysql_upgrade_db");
1730
if ((old_db->length <= MYSQL50_TABLE_NAME_PREFIX_LENGTH) ||
1731
(strncmp(old_db->str,
1732
MYSQL50_TABLE_NAME_PREFIX,
1733
MYSQL50_TABLE_NAME_PREFIX_LENGTH) != 0))
1735
my_error(ER_WRONG_USAGE, MYF(0),
1736
"ALTER DATABASE UPGRADE DATA DIRECTORY NAME",
1741
/* `#mysql50#<name>` converted to encoded `<name>` */
1742
new_db.str= old_db->str + MYSQL50_TABLE_NAME_PREFIX_LENGTH;
1743
new_db.length= old_db->length - MYSQL50_TABLE_NAME_PREFIX_LENGTH;
1745
if (lock_databases(thd, old_db->str, old_db->length,
1746
new_db.str, new_db.length))
1750
Let's remember if we should do "USE newdb" afterwards.
1751
thd->db will be cleared in mysql_rename_db()
1753
if (thd->db && !strcmp(thd->db, old_db->str))
1756
build_table_filename(path, sizeof(path)-1,
1757
old_db->str, "", MY_DB_OPT_FILE, 0);
1758
if ((load_db_opt(thd, path, &create_info)))
1759
create_info.default_table_charset= thd->variables.collation_server;
1761
length= build_table_filename(path, sizeof(path)-1, old_db->str, "", "", 0);
1762
if (length && path[length-1] == FN_LIBCHAR)
1763
path[length-1]=0; // remove ending '\'
1764
if ((error= my_access(path,F_OK)))
1766
my_error(ER_BAD_DB_ERROR, MYF(0), old_db->str);
1770
/* Step1: Create the new database */
1771
if ((error= mysql_create_db(thd, new_db.str, &create_info, 1)))
1774
/* Step2: Move tables to the new database */
1775
if ((dirp = my_dir(path,MYF(MY_DONT_SORT))))
1777
uint nfiles= (uint) dirp->number_off_files;
1778
for (uint idx=0 ; idx < nfiles && !thd->killed ; idx++)
1780
FILEINFO *file= dirp->dir_entry + idx;
1781
char *extension, tname[FN_REFLEN];
1782
LEX_STRING table_str;
1783
DBUG_PRINT("info",("Examining: %s", file->name));
1785
/* skiping non-FRM files */
1786
if (my_strcasecmp(files_charset_info,
1787
(extension= fn_rext(file->name)), reg_ext))
1790
/* A frm file found, add the table info rename list */
1793
table_str.length= filename_to_tablename(file->name,
1794
tname, sizeof(tname)-1);
1795
table_str.str= (char*) sql_memdup(tname, table_str.length + 1);
1796
Table_ident *old_ident= new Table_ident(thd, *old_db, table_str, 0);
1797
Table_ident *new_ident= new Table_ident(thd, new_db, table_str, 0);
1798
if (!old_ident || !new_ident ||
1799
!sl->add_table_to_list(thd, old_ident, NULL,
1800
TL_OPTION_UPDATING, TL_IGNORE) ||
1801
!sl->add_table_to_list(thd, new_ident, NULL,
1802
TL_OPTION_UPDATING, TL_IGNORE))
1812
if ((table_list= thd->lex->query_tables) &&
1813
(error= mysql_rename_tables(thd, table_list, 1)))
1816
Failed to move all tables from the old database to the new one.
1817
In the best case mysql_rename_tables() moved all tables back to the old
1818
database. In the worst case mysql_rename_tables() moved some tables
1819
to the new database, then failed, then started to move the tables back,
1820
and then failed again. In this situation we have some tables in the
1821
old database and some tables in the new database.
1822
Let's delete the option file, and then the new database directory.
1823
If some tables were left in the new directory, rmdir() will fail.
1824
It garantees we never loose any tables.
1826
build_table_filename(path, sizeof(path)-1,
1827
new_db.str,"",MY_DB_OPT_FILE, 0);
1828
my_delete(path, MYF(MY_WME));
1829
length= build_table_filename(path, sizeof(path)-1, new_db.str, "", "", 0);
1830
if (length && path[length-1] == FN_LIBCHAR)
1831
path[length-1]=0; // remove ending '\'
1837
if ((dirp = my_dir(path,MYF(MY_DONT_SORT))))
1839
uint nfiles= (uint) dirp->number_off_files;
1840
for (uint idx=0 ; idx < nfiles ; idx++)
1842
FILEINFO *file= dirp->dir_entry + idx;
1843
char oldname[FN_REFLEN], newname[FN_REFLEN];
1844
DBUG_PRINT("info",("Examining: %s", file->name));
1846
/* skiping . and .. and MY_DB_OPT_FILE */
1847
if ((file->name[0] == '.' &&
1848
(!file->name[1] || (file->name[1] == '.' && !file->name[2]))) ||
1849
!my_strcasecmp(files_charset_info, file->name, MY_DB_OPT_FILE))
1852
/* pass empty file name, and file->name as extension to avoid encoding */
1853
build_table_filename(oldname, sizeof(oldname)-1,
1854
old_db->str, "", file->name, 0);
1855
build_table_filename(newname, sizeof(newname)-1,
1856
new_db.str, "", file->name, 0);
1857
my_rename(oldname, newname, MYF(MY_WME));
1863
Step7: drop the old database.
1864
remove_db_from_cache(olddb) and query_cache_invalidate(olddb)
1865
are done inside mysql_rm_db(), no needs to execute them again.
1866
mysql_rm_db() also "unuses" if we drop the current database.
1868
error= mysql_rm_db(thd, old_db->str, 0, 1);
1870
/* Step8: logging */
1871
if (mysql_bin_log.is_open())
1873
Query_log_event qinfo(thd, thd->query, thd->query_length, 0, TRUE);
1875
mysql_bin_log.write(&qinfo);
1878
/* Step9: Let's do "use newdb" if we renamed the current database */
1879
if (change_to_newdb)
1880
error|= mysql_change_db(thd, & new_db, FALSE);
1883
pthread_mutex_lock(&LOCK_lock_db);
1884
/* Remove the databases from db lock cache */
1885
lock_db_delete(old_db->str, old_db->length);
1886
lock_db_delete(new_db.str, new_db.length);
1887
creating_database--;
1888
/* Signal waiting CREATE TABLE's to continue */
1889
pthread_cond_signal(&COND_refresh);
1890
pthread_mutex_unlock(&LOCK_lock_db);
1420
1898
Check if there is directory for the database name.