Skip to content

Commit 6f857c7

Browse files
committed
MDEV-34953 followup - allow Innodb to work with old data dictionary without upgrade.
Previously, Innodb used partition separator "#p#" on Windows, and "#P#" elsewhere. Now it uses "#P#" uniformly, Yet, there is no automated upgrade procedure yet in place that would fix old data dictionary. This patch fixed it, by accepting both #P# and #p# as partition separators.
1 parent a8cb429 commit 6f857c7

File tree

5 files changed

+58
-65
lines changed

5 files changed

+58
-65
lines changed

storage/innobase/dict/dict0mem.cc

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,6 @@ static bool dict_mem_table_is_system(const char *name)
7373
return false;
7474
}
7575

76-
/** The start of the table basename suffix for partitioned tables */
77-
const char table_name_t::part_suffix[4]
78-
= "#P#";
79-
8076
/** Display an identifier.
8177
@param[in,out] s output stream
8278
@param[in] id_name SQL identifier (other than table name)
@@ -1372,3 +1368,23 @@ dict_index_t::vers_history_row(
13721368
mtr->rollback_to_savepoint(sp);
13731369
return(error);
13741370
}
1371+
1372+
/** Checks whether the file name belongs to a partition of a table.
1373+
@param file_name file name
1374+
@return pointer to the end of the table name part of the file name
1375+
@retval nullptr if the file name does not belong to a partition. */
1376+
const char *dict_is_partition(const char *file_name)
1377+
{
1378+
/* We look for pattern #P# to see if the table is partitioned
1379+
MariaDB table. We also look for #p# pattern, because it was
1380+
previously used on Windows. */
1381+
for (const char *p= file_name;; p++)
1382+
{
1383+
p= strchr(p, '#');
1384+
if (!p)
1385+
break;
1386+
if ((p[1] == 'P' || p[1] == 'p') && p[2] == '#')
1387+
return p;
1388+
}
1389+
return nullptr;
1390+
}

storage/innobase/handler/ha_innodb.cc

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -259,20 +259,6 @@ void set_my_errno(int err)
259259
errno = err;
260260
}
261261

262-
/** Checks whether the file name belongs to a partition of a table.
263-
@param[in] file_name file name
264-
@return pointer to the end of the table name part of the file name, or NULL */
265-
static
266-
char*
267-
is_partition(
268-
/*=========*/
269-
char* file_name)
270-
{
271-
/* We look for pattern #P# to see if the table is partitioned
272-
MariaDB table. */
273-
return strstr(file_name, table_name_t::part_suffix);
274-
}
275-
276262

277263

278264
/** Return the InnoDB ROW_FORMAT enum value
@@ -5114,15 +5100,9 @@ ha_innobase::table_cache_type()
51145100
/** Normalizes a table name string.
51155101
A normalized name consists of the database name catenated to '/'
51165102
and table name. For example: test/mytable.
5117-
@param[out] norm_name Normalized name, null-terminated.
5118-
@param[in] name Name to normalize */
5119-
void
5120-
normalize_table_name(
5121-
/*=======================*/
5122-
char* norm_name, /* out: normalized name as a
5123-
null-terminated string */
5124-
const char* name /* in: table name string */
5125-
)
5103+
@param norm_name Normalized name, null-terminated.
5104+
@param name Name to normalize */
5105+
void normalize_table_name(char* norm_name, const char* name)
51265106
{
51275107
char* name_ptr;
51285108
ulint name_len;
@@ -5801,8 +5781,8 @@ ha_innobase::open(const char* name, int, uint)
58015781
m_upd_buf_size = 0;
58025782
m_disable_rowid_filter = false;
58035783

5804-
char* is_part = is_partition(norm_name);
5805-
THD* thd = ha_thd();
5784+
const char* is_part = dict_is_partition(norm_name);
5785+
THD* thd = ha_thd();
58065786
dict_table_t* ib_table = open_dict_table(name, norm_name, is_part,
58075787
DICT_ERR_IGNORE_FK_NOKEY);
58085788

@@ -6131,7 +6111,14 @@ ha_innobase::open_dict_table(
61316111
ib_table = dict_table_open_on_name(
61326112
par_case_name, false, ignore_err);
61336113
}
6134-
6114+
#ifdef _WIN32
6115+
/*
6116+
Omit the warning below, we know we used to convert
6117+
#P# to lowercase on Windows (we do not do that anymore).
6118+
Mostly likely, we have a partitioned table from an
6119+
older MariaDB version.
6120+
*/
6121+
#else
61356122
if (ib_table != NULL) {
61366123
sql_print_warning("Partition table %s opened"
61376124
" after converting to lower"
@@ -6142,6 +6129,7 @@ ha_innobase::open_dict_table(
61426129
" the current file system\n",
61436130
norm_name);
61446131
}
6132+
#endif
61456133
}
61466134

61476135
DBUG_RETURN(ib_table);
@@ -13552,7 +13540,7 @@ int ha_innobase::delete_table(const char *name)
1355213540
dict_sys.lock(SRW_LOCK_CALL);
1355313541
table= dict_sys.load_table(n, DICT_ERR_IGNORE_DROP);
1355413542
#ifdef WITH_PARTITION_STORAGE_ENGINE
13555-
if (!table && lower_case_table_names == 1 && is_partition(norm_name))
13543+
if (!table && lower_case_table_names == 1 && dict_is_partition(norm_name))
1355613544
{
1355713545
my_casedn_str(system_charset_info, norm_name);
1355813546
table= dict_sys.load_table(n, DICT_ERR_IGNORE_DROP);
@@ -13825,7 +13813,7 @@ static dberr_t innobase_rename_table(trx_t *trx, const char *from,
1382513813
if (error != DB_SUCCESS) {
1382613814
if (error == DB_TABLE_NOT_FOUND
1382713815
&& lower_case_table_names == 1) {
13828-
char* is_part = is_partition(norm_from);
13816+
const char* is_part = dict_is_partition(norm_from);
1382913817

1383013818
if (is_part) {
1383113819
char par_case_name[FN_REFLEN];
@@ -20247,11 +20235,11 @@ innobase_rename_vc_templ(
2024720235

2024820236
/* For partition table, remove the partition name and use the
2024920237
"main" table name to build the template */
20250-
char* is_part = is_partition(tbname);
20238+
const char* is_part = dict_is_partition(tbname);
2025120239

2025220240
if (is_part != NULL) {
20253-
*is_part = '\0';
2025420241
tbnamelen = ulint(is_part - tbname);
20242+
tbname[tbnamelen]= 0;
2025520243
}
2025620244

2025720245
dbnamelen = filename_to_tablename(dbname, t_dbname,

storage/innobase/include/dict0types.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,13 @@ enum ib_quiesce_t {
9494
/** Prefix for InnoDB internal tables, adopted from sql/table.h */
9595
#define TEMP_FILE_PREFIX_INNODB "#sql-ib"
9696

97+
/** Checks whether the file name belongs to a partition of a table.
98+
@param file_name file name
99+
@return pointer to the end of the table name part of the file name
100+
@retval nullptr if the file name does not belong to a partition. */
101+
const char *dict_is_partition(const char *file_name);
102+
103+
97104
/** Table name wrapper for pretty-printing */
98105
struct table_name_t
99106
{
@@ -128,14 +135,10 @@ struct table_name_t
128135
return UNIV_LIKELY(end != nullptr) ? end + 1 : nullptr;
129136
}
130137

131-
/** The start of the table basename suffix for partitioned tables */
132-
static const char part_suffix[4];
133-
134138
/** Determine the partition or subpartition name suffix.
135139
@return the partition name
136140
@retval NULL if the table is not partitioned */
137-
const char* part() const { return strstr(basename(), part_suffix); }
138-
141+
const char* part() const { return dict_is_partition(basename()); }
139142
/** @return whether this is a temporary or intermediate table name */
140143
inline bool is_temporary() const;
141144
};

storage/innobase/include/ha_prototypes.h

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -376,18 +376,12 @@ ib_foreign_warn(
376376
const char *format,/*!< in: warning message */
377377
...);
378378

379-
/*****************************************************************//**
380-
Normalizes a table name string. A normalized name consists of the
381-
database name catenated to '/' and table name. An example:
382-
test/mytable. On Windows normalization puts both the database name and the
383-
table name always to lower case if "set_lower_case" is set to TRUE. */
384-
void
385-
normalize_table_name(
386-
/*=======================*/
387-
char* norm_name, /*!< out: normalized name as a
388-
null-terminated string */
389-
const char* name /*!< in: table name string */
390-
);
379+
/** Normalizes a table name string.
380+
A normalized name consists of the database name catenated to '/'
381+
and table name. For example: test/mytable.
382+
@param norm_name Normalized name, null-terminated.
383+
@param name Name to normalize */
384+
void normalize_table_name(char* norm_name, const char* name);
391385

392386
/** Create a MYSQL_THD for a background thread and mark it as such.
393387
@param name thread info for SHOW PROCESSLIST

storage/innobase/row/row0mysql.cc

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2568,22 +2568,14 @@ row_rename_table_for_mysql(
25682568

25692569
/* MariaDB partition engine hard codes the file name
25702570
separator as "#P#" and "#SP#". The text case is fixed even if
2571-
lower_case_table_names is set to 1 or 2. InnoDB always
2572-
normalises file names to lower case on Windows, this
2571+
lower_case_table_names is set to 1 or 2. InnoDB used to
2572+
normalize file names to lower case on Windows, this
25732573
can potentially cause problems when copying/moving
2574-
tables between platforms.
2575-
2576-
1) If boot against an installation from Windows
2577-
platform, then its partition table name could
2578-
be all be in lower case in system tables. So we
2579-
will need to check lower case name when load table.
2580-
2581-
2) If we boot an installation from other case
2582-
sensitive platform in Windows, we might need to
2583-
check the existence of table name without lowering
2584-
case them in the system table. */
2574+
tables between platforms, even if lower_case_table_names=1
2575+
was set on both platforms.
2576+
*/
25852577
if (!table && lower_case_table_names == 1
2586-
&& strstr(old_name, table_name_t::part_suffix)) {
2578+
&& dict_is_partition(old_name)) {
25872579
char par_case_name[MAX_FULL_NAME_LEN + 1];
25882580
/* Check for the table using lower
25892581
case name, including the partition

0 commit comments

Comments
 (0)