summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMichael Widenius <monty@mariadb.org>2014-03-23 15:43:57 +0200
committerMichael Widenius <monty@askmonty.org>2014-03-23 15:43:57 +0200
commitb18a1b0e6ccc326ced01620edd842d899139feec (patch)
tree1c2d5fab29f5064c7050861aede99c526cc6dfd2 /sql
parent797a44a9ec5a601a4745b9520c2dea321f96d155 (diff)
downloadmariadb-git-b18a1b0e6ccc326ced01620edd842d899139feec.tar.gz
MDEV-5850: MySQL Bug#21317: SHOW CREATE DATABASE does not obey to lower_case_table_names
Bug #3329 Incomplete lower_case_table_names=2 implementation The problem was that check_db_name() converted database names to lower case also in case of lower_case_table_names=2. Fixed by removing the conversion in check_db_name for lower_case_table_names = 2 and instead converting db name to lower case at same places as table names are converted. Fixed bug that SHOW CREATE DATABASE FOO showed information for database 'foo'. I also removed some checks of lower_case_table_names when it was enough to use table_alias_charset. mysql-test/mysql-test-run.pl: Added --use-copy argument to force mysql-test-run to copy files instead of doing symlinks. This is needed when you run with test directory on another file system mysql-test/r/lowercase_table.result: Updated results mysql-test/r/lowercase_table2.result: Updated results mysql-test/suite/parts/r/partition_mgm_lc2_innodb.result: Updated results mysql-test/suite/parts/r/partition_mgm_lc2_memory.result: Updated results mysql-test/suite/parts/r/partition_mgm_lc2_myisam.result: Updated results mysql-test/t/lowercase_table.test: Added tests with mixed case databases mysql-test/t/lowercase_table2.test: Added tests with mixed case databases sql/log.cc: Don't check lower_case_table_names when we can use table_alias_charset sql/sql_base.cc: Don't check lower_case_table_names when we can use table_alias_charset sql/sql_db.cc: Use cmp_db_names() for checking if current database changed. mysql_rm_db() now converts db to lower case if lower_case_table_names was used. Changed database options cache to use table_alias_charset. This fixed a bug where SHOW CREATE DATABASE showed wrong information. sql/sql_parse.cc: Change also db name to lower case when file names are changed. Don't need to story copy of database name anymore when lower_case_table_names == 2 as check_db_name() don't convert in this case. Updated arguments to mysqld_show_create_db(). When adding table to TABLE_LIST also convert db name to lower case if needed (same way as we do with table names). sql/sql_show.cc: mysqld_show_create_db() now also takes original name as argument for output to user. sql/sql_show.h: Updated prototype for mysqld_show_create_db() sql/sql_table.cc: In mysql_rename_table(), do same conversions to database name as we do for the file name
Diffstat (limited to 'sql')
-rw-r--r--sql/log.cc14
-rw-r--r--sql/sql_base.cc4
-rw-r--r--sql/sql_db.cc60
-rw-r--r--sql/sql_parse.cc32
-rw-r--r--sql/sql_show.cc32
-rw-r--r--sql/sql_show.h4
-rw-r--r--sql/sql_table.cc14
-rw-r--r--sql/table.cc12
8 files changed, 96 insertions, 76 deletions
diff --git a/sql/log.cc b/sql/log.cc
index 1943be2817f..e7a4c82b0b4 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -542,25 +542,19 @@ int check_if_log_table(const TABLE_LIST *table,
{
int result= 0;
if (table->db_length == 5 &&
- !(lower_case_table_names ?
- my_strcasecmp(system_charset_info, table->db, "mysql") :
- strcmp(table->db, "mysql")))
+ !my_strcasecmp(table_alias_charset, table->db, "mysql"))
{
const char *table_name= table->table_name;
if (table->table_name_length == 11 &&
- !(lower_case_table_names ?
- my_strcasecmp(system_charset_info,
- table_name, "general_log") :
- strcmp(table_name, "general_log")))
+ !my_strcasecmp(table_alias_charset, table_name, "general_log"))
{
result= QUERY_LOG_GENERAL;
goto end;
}
- if (table->table_name_length == 8 && !(lower_case_table_names ?
- my_strcasecmp(system_charset_info, table_name, "slow_log") :
- strcmp(table_name, "slow_log")))
+ if (table->table_name_length == 8 &&
+ !my_strcasecmp(table_alias_charset, table_name, "slow_log"))
{
result= QUERY_LOG_SLOW;
goto end;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index fba5708adfe..47db5762cc8 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1372,9 +1372,7 @@ retry:
/* Skip if table alias does not match. */
if (check_alias)
{
- if (lower_case_table_names ?
- my_strcasecmp(files_charset_info, t_alias, res->alias) :
- strcmp(t_alias, res->alias))
+ if (my_strcasecmp(table_alias_charset, t_alias, res->alias))
goto next;
}
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index bf55a20f2d9..6c823e0480c 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -78,6 +78,29 @@ typedef struct my_dbopt_st
} my_dbopt_t;
+/**
+ Return TRUE if db1_name is equal to db2_name, FALSE otherwise.
+
+ The function allows to compare database names according to the MariaDB
+ rules. The database names db1 and db2 are equal if:
+ - db1 is NULL and db2 is NULL;
+ or
+ - db1 is not-NULL, db2 is not-NULL, db1 is equal to db2 in
+ table_alias_charset
+
+ This is the same rules as we use for filenames.
+*/
+
+static inline bool
+cmp_db_names(const char *db1_name,
+ const char *db2_name)
+{
+ return ((!db1_name && !db2_name) ||
+ (db1_name && db2_name &&
+ my_strcasecmp(table_alias_charset, db1_name, db2_name) == 0));
+}
+
+
/*
Function we use in the creation of our hash to get key.
*/
@@ -159,8 +182,7 @@ bool my_dboptions_cache_init(void)
if (!dboptions_init)
{
dboptions_init= 1;
- error= my_hash_init(&dboptions, lower_case_table_names ?
- &my_charset_bin : system_charset_info,
+ error= my_hash_init(&dboptions, table_alias_charset,
32, 0, 0, (my_hash_get_key) dboptions_get_key,
free_dbopt,0);
}
@@ -192,8 +214,7 @@ void my_dbopt_cleanup(void)
{
mysql_rwlock_wrlock(&LOCK_dboptions);
my_hash_free(&dboptions);
- my_hash_init(&dboptions, lower_case_table_names ?
- &my_charset_bin : system_charset_info,
+ my_hash_init(&dboptions, table_alias_charset,
32, 0, 0, (my_hash_get_key) dboptions_get_key,
free_dbopt,0);
mysql_rwlock_unlock(&LOCK_dboptions);
@@ -762,7 +783,6 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
Drop_table_error_handler err_handler;
DBUG_ENTER("mysql_rm_db");
-
if (lock_schema_name(thd, db))
DBUG_RETURN(true);
@@ -966,7 +986,7 @@ exit:
SELECT DATABASE() in the future). For this we free() thd->db and set
it to 0.
*/
- if (thd->db && !strcmp(thd->db, db) && !error)
+ if (thd->db && cmp_db_names(thd->db, db) && !error)
mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server);
my_dirend(dirp);
DBUG_RETURN(error);
@@ -993,6 +1013,13 @@ static bool find_db_tables_and_rm_known_files(THD *thd, MY_DIR *dirp,
/* Now put the tables in the list */
tot_list_next_local= tot_list_next_global= &tot_list;
+ if (lower_case_table_names)
+ {
+ /* Change database name to lower case for comparision */
+ db.str= thd->strmake(db.str, db.length);
+ db.length= my_casedn_str(files_charset_info, db.str);
+ }
+
for (size_t idx=0; idx < files.elements(); idx++)
{
LEX_STRING *table= files.at(idx);
@@ -1300,27 +1327,6 @@ static void backup_current_db_name(THD *thd,
/**
- Return TRUE if db1_name is equal to db2_name, FALSE otherwise.
-
- The function allows to compare database names according to the MySQL
- rules. The database names db1 and db2 are equal if:
- - db1 is NULL and db2 is NULL;
- or
- - db1 is not-NULL, db2 is not-NULL, db1 is equal (ignoring case) to
- db2 in system character set (UTF8).
-*/
-
-static inline bool
-cmp_db_names(const char *db1_name,
- const char *db2_name)
-{
- return ((!db1_name && !db2_name) ||
- (db1_name && db2_name &&
- my_strcasecmp(system_charset_info, db1_name, db2_name) == 0));
-}
-
-
-/**
@brief Change the current database and its attributes unconditionally.
@param thd thread handle
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index f2bbd7462fd..1891aa6147b 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1435,7 +1435,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
lex_start(thd);
/* Must be before we init the table list. */
if (lower_case_table_names)
+ {
table_name.length= my_casedn_str(files_charset_info, table_name.str);
+ db.length= my_casedn_str(files_charset_info, db.str);
+ }
table_list.init_one_table(db.str, db.length, table_name.str,
table_name.length, table_name.str, TL_READ);
/*
@@ -3869,9 +3872,7 @@ end_with_restore_list:
prepared statement- safe.
*/
HA_CREATE_INFO create_info(lex->create_info);
- char *alias;
- if (!(alias=thd->strmake(lex->name.str, lex->name.length)) ||
- check_db_name(&lex->name))
+ if (check_db_name(&lex->name))
{
my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str);
break;
@@ -3894,8 +3895,7 @@ end_with_restore_list:
#endif
if (check_access(thd, CREATE_ACL, lex->name.str, NULL, NULL, 1, 0))
break;
- res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias :
- lex->name.str), &create_info, 0);
+ res= mysql_create_db(thd, lex->name.str, &create_info, 0);
break;
}
case SQLCOM_DROP_DB:
@@ -3988,14 +3988,20 @@ end_with_restore_list:
}
case SQLCOM_SHOW_CREATE_DB:
{
+ char db_name_buff[NAME_LEN+1];
+ LEX_STRING db_name;
DBUG_EXECUTE_IF("4x_server_emul",
my_error(ER_UNKNOWN_ERROR, MYF(0)); goto error;);
- if (check_db_name(&lex->name))
+
+ db_name.str= db_name_buff;
+ db_name.length= lex->name.length;
+ strmov(db_name.str, lex->name.str);
+ if (check_db_name(&db_name))
{
- my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str);
+ my_error(ER_WRONG_DB_NAME, MYF(0), db_name);
break;
}
- res= mysqld_show_create_db(thd, lex->name.str, &lex->create_info);
+ res= mysqld_show_create_db(thd, &db_name, &lex->name, &lex->create_info);
break;
}
case SQLCOM_CREATE_EVENT:
@@ -6748,8 +6754,14 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->alias= alias_str;
ptr->is_alias= alias ? TRUE : FALSE;
- if (lower_case_table_names && table->table.length)
- table->table.length= my_casedn_str(files_charset_info, table->table.str);
+ if (lower_case_table_names)
+ {
+ if (table->table.length)
+ table->table.length= my_casedn_str(files_charset_info, table->table.str);
+ if (ptr->db_length)
+ ptr->db_length= my_casedn_str(files_charset_info, ptr->db);
+ }
+
ptr->table_name=table->table.str;
ptr->table_name_length=table->table.length;
ptr->lock_type= lock_type;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index aa23f01ab7d..43a5d1ffec7 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1009,9 +1009,10 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
{
/*
- Use open_tables() directly rather than open_normal_and_derived_tables().
- This ensures that close_thread_tables() is not called if open tables fails
- and the error is ignored. This allows us to handle broken views nicely.
+ Use open_tables() directly rather than
+ open_normal_and_derived_tables(). This ensures that
+ close_thread_tables() is not called if open tables fails and the
+ error is ignored. This allows us to handle broken views nicely.
*/
uint counter;
Show_create_error_handler view_error_suppressor(thd, table_list);
@@ -1105,7 +1106,8 @@ exit:
DBUG_RETURN(error);
}
-bool mysqld_show_create_db(THD *thd, char *dbname,
+bool mysqld_show_create_db(THD *thd, LEX_STRING *dbname,
+ LEX_STRING *orig_dbname,
HA_CREATE_INFO *create_info)
{
char buff[2048];
@@ -1123,32 +1125,32 @@ bool mysqld_show_create_db(THD *thd, char *dbname,
if (test_all_bits(sctx->master_access, DB_ACLS))
db_access=DB_ACLS;
else
- db_access= (acl_get(sctx->host, sctx->ip, sctx->priv_user, dbname, 0) |
+ db_access= (acl_get(sctx->host, sctx->ip, sctx->priv_user, dbname->str, 0) |
sctx->master_access);
- if (!(db_access & DB_ACLS) && check_grant_db(thd,dbname))
+ if (!(db_access & DB_ACLS) && check_grant_db(thd,dbname->str))
{
status_var_increment(thd->status_var.access_denied_errors);
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
- sctx->priv_user, sctx->host_or_ip, dbname);
+ sctx->priv_user, sctx->host_or_ip, dbname->str);
general_log_print(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
- sctx->priv_user, sctx->host_or_ip, dbname);
+ sctx->priv_user, sctx->host_or_ip, orig_dbname->str);
DBUG_RETURN(TRUE);
}
#endif
- if (is_infoschema_db(dbname))
+ if (is_infoschema_db(dbname->str))
{
- dbname= INFORMATION_SCHEMA_NAME.str;
+ *dbname= INFORMATION_SCHEMA_NAME;
create.default_table_charset= system_charset_info;
}
else
{
- if (check_db_dir_existence(dbname))
+ if (check_db_dir_existence(dbname->str))
{
- my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
+ my_error(ER_BAD_DB_ERROR, MYF(0), dbname->str);
DBUG_RETURN(TRUE);
}
- load_db_opt_by_name(thd, dbname, &create);
+ load_db_opt_by_name(thd, dbname->str, &create);
}
List<Item> field_list;
field_list.push_back(new Item_empty_string("Database",NAME_CHAR_LEN));
@@ -1159,12 +1161,12 @@ bool mysqld_show_create_db(THD *thd, char *dbname,
DBUG_RETURN(TRUE);
protocol->prepare_for_resend();
- protocol->store(dbname, strlen(dbname), system_charset_info);
+ protocol->store(orig_dbname->str, orig_dbname->length, system_charset_info);
buffer.length(0);
buffer.append(STRING_WITH_LEN("CREATE DATABASE "));
if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS)
buffer.append(STRING_WITH_LEN("/*!32312 IF NOT EXISTS*/ "));
- append_identifier(thd, &buffer, dbname, strlen(dbname));
+ append_identifier(thd, &buffer, dbname->str, dbname->length);
if (create.default_table_charset)
{
diff --git a/sql/sql_show.h b/sql/sql_show.h
index 0416f2fdaba..708a77d74cd 100644
--- a/sql/sql_show.h
+++ b/sql/sql_show.h
@@ -86,7 +86,9 @@ bool append_identifier(THD *thd, String *packet, const char *name,
void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild);
int mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd);
bool mysqld_show_create(THD *thd, TABLE_LIST *table_list);
-bool mysqld_show_create_db(THD *thd, char *dbname, HA_CREATE_INFO *create);
+bool mysqld_show_create_db(THD *thd, LEX_STRING *db_name,
+ LEX_STRING *orig_db_name,
+ HA_CREATE_INFO *create);
void mysqld_list_processes(THD *thd,const char *user,bool verbose);
int mysqld_show_status(THD *thd);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index d30eb3169e3..ee3b954168d 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -5132,7 +5132,7 @@ mysql_rename_table(handlerton *base, const char *old_db,
char from[FN_REFLEN + 1], to[FN_REFLEN + 1],
lc_from[FN_REFLEN + 1], lc_to[FN_REFLEN + 1];
char *from_base= from, *to_base= to;
- char tmp_name[SAFE_NAME_LEN+1];
+ char tmp_name[SAFE_NAME_LEN+1], tmp_db_name[SAFE_NAME_LEN+1];
handler *file;
int error=0;
ulonglong save_bits= thd->variables.option_bits;
@@ -5169,13 +5169,19 @@ mysql_rename_table(handlerton *base, const char *old_db,
{
strmov(tmp_name, old_name);
my_casedn_str(files_charset_info, tmp_name);
- build_table_filename(lc_from, sizeof(lc_from) - 1, old_db, tmp_name, "",
- flags & FN_FROM_IS_TMP);
+ strmov(tmp_db_name, old_db);
+ my_casedn_str(files_charset_info, tmp_db_name);
+
+ build_table_filename(lc_from, sizeof(lc_from) - 1, tmp_db_name, tmp_name,
+ "", flags & FN_FROM_IS_TMP);
from_base= lc_from;
strmov(tmp_name, new_name);
my_casedn_str(files_charset_info, tmp_name);
- build_table_filename(lc_to, sizeof(lc_to) - 1, new_db, tmp_name, "",
+ strmov(tmp_db_name, new_db);
+ my_casedn_str(files_charset_info, tmp_db_name);
+
+ build_table_filename(lc_to, sizeof(lc_to) - 1, tmp_db_name, tmp_name, "",
flags & FN_TO_IS_TMP);
to_base= lc_to;
}
diff --git a/sql/table.cc b/sql/table.cc
index 8daf54920cd..268b35c409e 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -3440,10 +3440,11 @@ uint calculate_key_len(TABLE *table, uint key, const uchar *buf,
SYNPOSIS
check_db_name()
- org_name Name of database and length
+ org_name Name of database
NOTES
- If lower_case_table_names is set then database is converted to lower case
+ If lower_case_table_names is set to 1 then database name is converted
+ to lower case
RETURN
0 ok
@@ -3465,13 +3466,12 @@ bool check_db_name(LEX_STRING *org_name)
if (!name_length || name_length > NAME_LEN)
return 1;
- if (lower_case_table_names && name != any_db)
- my_casedn_str(files_charset_info, name);
-
+ if (lower_case_table_names == 1 && name != any_db)
+ org_name->length= my_casedn_str(files_charset_info, name);
if (db_name_is_in_ignore_db_dirs_list(name))
return 1;
- return check_table_name(name, name_length, check_for_path_chars);
+ return check_table_name(name, org_name->length, check_for_path_chars);
}