Skip to content

Commit c8d8a92

Browse files
committed
Merge mysql-5.1 -> mysql-5.5
The actual Bug#11754376 does not exist in MySQL 5.5 because at startup we drop entries for temporary tables from InnoDB dictionary cache (only if ROW_FORMAT is not REDUNDANT). But nevertheless the bug in normalize_table_name_low() is present so we fix it.
2 parents 64c2891 + 17afdb9 commit c8d8a92

File tree

3 files changed

+107
-5
lines changed

3 files changed

+107
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
CREATE TABLE bug11754376 (c INT) ENGINE=INNODB;
2+
SET SESSION DEBUG='+d,test_normalize_table_name_low';
3+
DROP TABLE bug11754376;
4+
SET SESSION DEBUG='-d,test_normalize_table_name_low';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#
2+
# Bug#11754376 45976: INNODB LOST FILES FOR TEMPORARY TABLES ON GRACEFUL SHUTDOWN
3+
#
4+
5+
-- source include/have_debug.inc
6+
-- source include/have_innodb.inc
7+
8+
CREATE TABLE bug11754376 (c INT) ENGINE=INNODB;
9+
10+
# This will invoke test_normalize_table_name_low() in debug builds
11+
12+
SET SESSION DEBUG='+d,test_normalize_table_name_low';
13+
14+
DROP TABLE bug11754376;
15+
16+
SET SESSION DEBUG='-d,test_normalize_table_name_low';

storage/innobase/handler/ha_innodb.cc

+87-5
Original file line numberDiff line numberDiff line change
@@ -3292,37 +3292,114 @@ normalize_table_name_low(
32923292
{
32933293
char* name_ptr;
32943294
char* db_ptr;
3295+
ulint db_len;
32953296
char* ptr;
32963297

32973298
/* Scan name from the end */
32983299

3299-
ptr = strend(name)-1;
3300+
ptr = strend(name) - 1;
33003301

3302+
/* seek to the last path separator */
33013303
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
33023304
ptr--;
33033305
}
33043306

33053307
name_ptr = ptr + 1;
33063308

3307-
DBUG_ASSERT(ptr > name);
3309+
/* skip any number of path separators */
3310+
while (ptr >= name && (*ptr == '\\' || *ptr == '/')) {
3311+
ptr--;
3312+
}
33083313

3309-
ptr--;
3314+
DBUG_ASSERT(ptr >= name);
33103315

3316+
/* seek to the last but one path separator or one char before
3317+
the beginning of name */
3318+
db_len = 0;
33113319
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
33123320
ptr--;
3321+
db_len++;
33133322
}
33143323

33153324
db_ptr = ptr + 1;
33163325

3317-
memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
3326+
memcpy(norm_name, db_ptr, db_len);
3327+
3328+
norm_name[db_len] = '/';
33183329

3319-
norm_name[name_ptr - db_ptr - 1] = '/';
3330+
memcpy(norm_name + db_len + 1, name_ptr, strlen(name_ptr) + 1);
33203331

33213332
if (set_lower_case) {
33223333
innobase_casedn_str(norm_name);
33233334
}
33243335
}
33253336

3337+
#if !defined(DBUG_OFF)
3338+
/*********************************************************************
3339+
Test normalize_table_name_low(). */
3340+
static
3341+
void
3342+
test_normalize_table_name_low()
3343+
/*===========================*/
3344+
{
3345+
char norm_name[128];
3346+
const char* test_data[][2] = {
3347+
/* input, expected result */
3348+
{"./mysqltest/t1", "mysqltest/t1"},
3349+
{"./test/#sql-842b_2", "test/#sql-842b_2"},
3350+
{"./test/#sql-85a3_10", "test/#sql-85a3_10"},
3351+
{"./test/#sql2-842b-2", "test/#sql2-842b-2"},
3352+
{"./test/bug29807", "test/bug29807"},
3353+
{"./test/foo", "test/foo"},
3354+
{"./test/innodb_bug52663", "test/innodb_bug52663"},
3355+
{"./test/t", "test/t"},
3356+
{"./test/t1", "test/t1"},
3357+
{"./test/t10", "test/t10"},
3358+
{"/a/b/db/table", "db/table"},
3359+
{"/a/b/db///////table", "db/table"},
3360+
{"/a/b////db///////table", "db/table"},
3361+
{"/var/tmp/mysqld.1/#sql842b_2_10", "mysqld.1/#sql842b_2_10"},
3362+
{"db/table", "db/table"},
3363+
{"ddd/t", "ddd/t"},
3364+
{"d/ttt", "d/ttt"},
3365+
{"d/t", "d/t"},
3366+
{".\\mysqltest\\t1", "mysqltest/t1"},
3367+
{".\\test\\#sql-842b_2", "test/#sql-842b_2"},
3368+
{".\\test\\#sql-85a3_10", "test/#sql-85a3_10"},
3369+
{".\\test\\#sql2-842b-2", "test/#sql2-842b-2"},
3370+
{".\\test\\bug29807", "test/bug29807"},
3371+
{".\\test\\foo", "test/foo"},
3372+
{".\\test\\innodb_bug52663", "test/innodb_bug52663"},
3373+
{".\\test\\t", "test/t"},
3374+
{".\\test\\t1", "test/t1"},
3375+
{".\\test\\t10", "test/t10"},
3376+
{"C:\\a\\b\\db\\table", "db/table"},
3377+
{"C:\\a\\b\\db\\\\\\\\\\\\\\table", "db/table"},
3378+
{"C:\\a\\b\\\\\\\\db\\\\\\\\\\\\\\table", "db/table"},
3379+
{"C:\\var\\tmp\\mysqld.1\\#sql842b_2_10", "mysqld.1/#sql842b_2_10"},
3380+
{"db\\table", "db/table"},
3381+
{"ddd\\t", "ddd/t"},
3382+
{"d\\ttt", "d/ttt"},
3383+
{"d\\t", "d/t"},
3384+
};
3385+
3386+
for (size_t i = 0; i < UT_ARR_SIZE(test_data); i++) {
3387+
printf("test_normalize_table_name_low(): "
3388+
"testing \"%s\", expected \"%s\"... ",
3389+
test_data[i][0], test_data[i][1]);
3390+
3391+
normalize_table_name_low(norm_name, test_data[i][0], FALSE);
3392+
3393+
if (strcmp(norm_name, test_data[i][1]) == 0) {
3394+
printf("ok\n");
3395+
} else {
3396+
printf("got \"%s\"\n", norm_name);
3397+
ut_error;
3398+
}
3399+
}
3400+
}
3401+
#endif /* !DBUG_OFF */
3402+
33263403
/********************************************************************//**
33273404
Get the upper limit of the MySQL integral and floating-point type.
33283405
@return maximum allowed value for the field */
@@ -7343,6 +7420,11 @@ ha_innobase::delete_table(
73437420

73447421
DBUG_ENTER("ha_innobase::delete_table");
73457422

7423+
DBUG_EXECUTE_IF(
7424+
"test_normalize_table_name_low",
7425+
test_normalize_table_name_low();
7426+
);
7427+
73467428
/* Strangely, MySQL passes the table name without the '.frm'
73477429
extension, in contrast to ::create */
73487430
normalize_table_name(norm_name, name);

0 commit comments

Comments
 (0)