Bug #64347 lower_case_table_names and my_database_names_init
Submitted: 16 Feb 2012 6:01 Modified: 16 Feb 2012 16:35
Reporter: Mark Callaghan Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Options Severity:S3 (Non-critical)
Version:5.1.52, 5.1.62, 5.5.22 OS:Any
Assigned to: CPU Architecture:Any
Triage: Needs Triage: D3 (Medium)

[16 Feb 2012 6:01] Mark Callaghan
Description:
I don't understand what my_database_names_init() does for lower_case_table_names compared to how that variable is handled elsewhere. In one function case matters when lower_case_table_names == 0, in the other function case matters when it is != 0. I think one of these is wrong.

-----

In my_database_names_init, 
* (case sensitive) my_charset_bin is used when lower_case_table_names !=0
* else (case insensitive) system_charset_info is used

bool my_database_names_init(void)
{
…
error= hash_init(&dboptions, lower_case_table_names ?
&my_charset_bin : system_charset_info,
32, 0, 0, (hash_get_key) dboptions_get_key,
free_dbopt,0)

-----------------

From log.cc:303
* (case insensitive) my_strcasecmp is used when lower_case_table_names != 0
* else (case sensitive) strcmp is used

int check_if_log_table(uint db_len, const char *db, uint table_name_len,
const char *table_name, uint check_if_opened)
{
if (db_len == 5 &&
!(lower_case_table_names ?
my_strcasecmp(system_charset_info, db, "mysql") :
strcmp(db, "mysql")))

How to repeat:
read the code

Suggested fix:
Change my_database_names_init
[16 Feb 2012 7:35] Valeriy Kravchuk
Thank you for the problem report. Verified by code review. Same code is still used in current mysql-5.1.
[16 Feb 2012 8:13] Valeriy Kravchuk
Same problem applies to mysql-5.5, but in my_dboptions_cache_init() function...
[16 Feb 2012 15:27] Mark Callaghan
The proposed fix from my co-worker is to add "!" before lower_case_table_names in my_database_names_init and my_dbopt_cleanup:

    error= hash_init(&dboptions, (!lower_case_table_names) ?
           hash_init(&lock_db_cache, (!lower_case_table_names) ?
  hash_init(&dboptions, (!lower_case_table_names) ?
[16 Feb 2012 16:33] Mark Callaghan
repro case

Attachment: cs.result (application/octet-stream, text), 659 bytes.

[16 Feb 2012 16:33] Mark Callaghan
repro case

Attachment: cs.test (application/octet-stream, text), 312 bytes.

[16 Feb 2012 16:35] Mark Callaghan
I added a reproduction case to show how the wrong db options are used when lower_case_table_names=0. See that BaR.f uses the options from Bar.f (utf8_unicode_ci).

show global variables like "lower_case_table_names";
Variable_name	Value
lower_case_table_names	0
create database BaR collate ascii_bin;
create database Bar collate utf8_unicode_ci;
show databases;
Database
information_schema
BaR
Bar
mtr
mysql
test
use BaR;
create table f(i int);
show create table f;
Table	Create Table
f	CREATE TABLE `f` (
  `i` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
use Bar;
create table f(i int);
show create table f;
Table	Create Table
f	CREATE TABLE `f` (
  `i` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
use test;
drop database BaR;
drop database Bar;