Skip to content

Commit 73d23f8

Browse files
author
Jan Lindström
committed
MDEV-9471: Server crashes or returns an error while trying to alter partitioning on a table moved from Windows to Linux
At alter table when server renames the table to temporal name, old name uses normal partioned table naming rules. However, if tables are created on Windows and then transfered to Linux and lower-case-table-names=1 we should modify the old name on rename to lower case to be able to find it from the InnoDB dictionary.
1 parent 5cf293f commit 73d23f8

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed

storage/innobase/row/row0mysql.cc

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4793,6 +4793,7 @@ row_rename_table_for_mysql(
47934793
pars_info_t* info = NULL;
47944794
int retry;
47954795
bool aux_fts_rename = false;
4796+
char* is_part = NULL;
47964797

47974798
ut_a(old_name != NULL);
47984799
ut_a(new_name != NULL);
@@ -4830,6 +4831,55 @@ row_rename_table_for_mysql(
48304831
table = dict_table_open_on_name(old_name, dict_locked, FALSE,
48314832
DICT_ERR_IGNORE_NONE);
48324833

4834+
/* We look for pattern #P# to see if the table is partitioned
4835+
MySQL table. */
4836+
#ifdef __WIN__
4837+
is_part = strstr((char *)old_name, (char *)"#p#");
4838+
#else
4839+
is_part = strstr((char *)old_name, (char *)"#P#");
4840+
#endif /* __WIN__ */
4841+
4842+
/* MySQL partition engine hard codes the file name
4843+
separator as "#P#". The text case is fixed even if
4844+
lower_case_table_names is set to 1 or 2. This is true
4845+
for sub-partition names as well. InnoDB always
4846+
normalises file names to lower case on Windows, this
4847+
can potentially cause problems when copying/moving
4848+
tables between platforms.
4849+
4850+
1) If boot against an installation from Windows
4851+
platform, then its partition table name could
4852+
be all be in lower case in system tables. So we
4853+
will need to check lower case name when load table.
4854+
4855+
2) If we boot an installation from other case
4856+
sensitive platform in Windows, we might need to
4857+
check the existence of table name without lowering
4858+
case them in the system table. */
4859+
if (!table &&
4860+
is_part &&
4861+
innobase_get_lower_case_table_names() == 1) {
4862+
char par_case_name[MAX_FULL_NAME_LEN + 1];
4863+
#ifndef __WIN__
4864+
/* Check for the table using lower
4865+
case name, including the partition
4866+
separator "P" */
4867+
memcpy(par_case_name, old_name,
4868+
strlen(old_name));
4869+
par_case_name[strlen(old_name)] = 0;
4870+
innobase_casedn_str(par_case_name);
4871+
#else
4872+
/* On Windows platfrom, check
4873+
whether there exists table name in
4874+
system table whose name is
4875+
not being normalized to lower case */
4876+
normalize_table_name_low(
4877+
par_case_name, old_name, FALSE);
4878+
#endif
4879+
table = dict_table_open_on_name(par_case_name, dict_locked, FALSE,
4880+
DICT_ERR_IGNORE_NONE);
4881+
}
4882+
48334883
if (!table) {
48344884
err = DB_TABLE_NOT_FOUND;
48354885
ut_print_timestamp(stderr);

storage/xtradb/row/row0mysql.cc

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4808,6 +4808,7 @@ row_rename_table_for_mysql(
48084808
pars_info_t* info = NULL;
48094809
int retry;
48104810
bool aux_fts_rename = false;
4811+
char* is_part = NULL;
48114812

48124813
ut_a(old_name != NULL);
48134814
ut_a(new_name != NULL);
@@ -4845,6 +4846,55 @@ row_rename_table_for_mysql(
48454846
table = dict_table_open_on_name(old_name, dict_locked, FALSE,
48464847
DICT_ERR_IGNORE_NONE);
48474848

4849+
/* We look for pattern #P# to see if the table is partitioned
4850+
MySQL table. */
4851+
#ifdef __WIN__
4852+
is_part = strstr((char *)old_name, (char *)"#p#");
4853+
#else
4854+
is_part = strstr((char *)old_name, (char *)"#P#");
4855+
#endif /* __WIN__ */
4856+
4857+
/* MySQL partition engine hard codes the file name
4858+
separator as "#P#". The text case is fixed even if
4859+
lower_case_table_names is set to 1 or 2. This is true
4860+
for sub-partition names as well. InnoDB always
4861+
normalises file names to lower case on Windows, this
4862+
can potentially cause problems when copying/moving
4863+
tables between platforms.
4864+
4865+
1) If boot against an installation from Windows
4866+
platform, then its partition table name could
4867+
be all be in lower case in system tables. So we
4868+
will need to check lower case name when load table.
4869+
4870+
2) If we boot an installation from other case
4871+
sensitive platform in Windows, we might need to
4872+
check the existence of table name without lowering
4873+
case them in the system table. */
4874+
if (!table &&
4875+
is_part &&
4876+
innobase_get_lower_case_table_names() == 1) {
4877+
char par_case_name[MAX_FULL_NAME_LEN + 1];
4878+
#ifndef __WIN__
4879+
/* Check for the table using lower
4880+
case name, including the partition
4881+
separator "P" */
4882+
memcpy(par_case_name, old_name,
4883+
strlen(old_name));
4884+
par_case_name[strlen(old_name)] = 0;
4885+
innobase_casedn_str(par_case_name);
4886+
#else
4887+
/* On Windows platfrom, check
4888+
whether there exists table name in
4889+
system table whose name is
4890+
not being normalized to lower case */
4891+
normalize_table_name_low(
4892+
par_case_name, old_name, FALSE);
4893+
#endif
4894+
table = dict_table_open_on_name(par_case_name, dict_locked, FALSE,
4895+
DICT_ERR_IGNORE_NONE);
4896+
}
4897+
48484898
if (!table) {
48494899
err = DB_TABLE_NOT_FOUND;
48504900
ut_print_timestamp(stderr);

0 commit comments

Comments
 (0)