Skip to content

Commit

Permalink
MDEV-16267 Wrong INFORMATION_SCHEMA.INNODB_BUFFER_PAGE.TABLE_NAME
Browse files Browse the repository at this point in the history
This is the MariaDB 10.2 version of the patch.

field_store_string(): Simplify the code.

field_store_index_name(): Remove, and use field_store_string()
instead. Starting with MariaDB 10.2.2, there is the predicate
dict_index_t::is_committed(), and dict_index_t::name never
contains the magic byte 0xff.

Correct some comments to refer to TEMP_INDEX_PREFIX_STR.

i_s_cmp_per_index_fill_low(): Use the appropriate value NULL to
identify that an index was not found. Check that storing each
column value succeeded.

i_s_innodb_buffer_page_fill(), i_s_innodb_buf_page_lru_fill():
Only invoke Field::set_notnull() if the index was found.
(This fixes the bug.)

i_s_dict_fill_sys_indexes(): Adjust the index->name that was
directly loaded from SYS_INDEXES.NAME (which can start with
the 0xff byte). This was the only function that depended
on the translation in field_store_index_name().
  • Loading branch information
dr-m committed May 24, 2018
1 parent fdb8d01 commit 52df804
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 105 deletions.
5 changes: 3 additions & 2 deletions storage/innobase/dict/dict0load.cc
Expand Up @@ -2477,8 +2477,9 @@ dict_load_indexes(
&& static_cast<char>(*field)
== static_cast<char>(*TEMP_INDEX_PREFIX_STR)) {
/* Skip indexes whose name starts with
TEMP_INDEX_PREFIX, because they will
be dropped during crash recovery. */
TEMP_INDEX_PREFIX_STR, because they will
be dropped by row_merge_drop_temp_indexes()
during crash recovery. */
goto next_rec;
}
}
Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/handler/handler0alter.cc
Expand Up @@ -8169,7 +8169,7 @@ commit_cache_norebuild(
(after renaming the indexes), so that in the
event of a crash, crash recovery will drop the
indexes, because it drops all indexes whose
names start with TEMP_INDEX_PREFIX. Once we
names start with TEMP_INDEX_PREFIX_STR. Once we
have started dropping an index tree, there is
no way to roll it back. */

Expand Down
177 changes: 75 additions & 102 deletions storage/innobase/handler/i_s.cc
Expand Up @@ -261,59 +261,13 @@ field_store_string(
const char* str) /*!< in: NUL-terminated utf-8 string,
or NULL */
{
int ret;

if (str != NULL) {

ret = field->store(str, static_cast<uint>(strlen(str)),
system_charset_info);
field->set_notnull();
} else {

ret = 0; /* success */
if (!str) {
field->set_null();
}

return(ret);
}

/*******************************************************************//**
Store the name of an index in a MYSQL_TYPE_VARCHAR field.
Handles the names of incomplete secondary indexes.
@return 0 on success */
static
int
field_store_index_name(
/*===================*/
Field* field, /*!< in/out: target field for
storage */
const char* index_name) /*!< in: NUL-terminated utf-8
index name, possibly starting with
TEMP_INDEX_PREFIX */
{
int ret;

ut_ad(index_name != NULL);
ut_ad(field->real_type() == MYSQL_TYPE_VARCHAR);

/* Since TEMP_INDEX_PREFIX is not a valid UTF8, we need to convert
it to something else. */
if (*index_name == *TEMP_INDEX_PREFIX_STR) {
char buf[NAME_LEN + 1];
buf[0] = '?';
memcpy(buf + 1, index_name + 1, strlen(index_name));
ret = field->store(
buf, static_cast<uint>(strlen(buf)),
system_charset_info);
} else {
ret = field->store(
index_name, static_cast<uint>(strlen(index_name)),
system_charset_info);
return 0;
}

field->set_notnull();

return(ret);
return field->store(str, uint(strlen(str)), system_charset_info);
}

/*******************************************************************//**
Expand Down Expand Up @@ -952,12 +906,8 @@ fill_innodb_locks_from_cache(
buf, uint(bufend - buf), system_charset_info));

/* lock_index */
if (row->lock_index != NULL) {
OK(field_store_index_name(fields[IDX_LOCK_INDEX],
row->lock_index));
} else {
fields[IDX_LOCK_INDEX]->set_null();
}
OK(field_store_string(fields[IDX_LOCK_INDEX],
row->lock_index));

/* lock_space */
OK(field_store_ulint(fields[IDX_LOCK_SPACE],
Expand Down Expand Up @@ -1731,7 +1681,6 @@ i_s_cmp_per_index_fill_low(

for (iter = snap.begin(), i = 0; iter != snap.end(); iter++, i++) {

char name[192];
dict_index_t* index = dict_index_find_on_id_low(iter->first);

if (index != NULL) {
Expand All @@ -1742,47 +1691,49 @@ i_s_cmp_per_index_fill_low(
db_utf8, sizeof(db_utf8),
table_utf8, sizeof(table_utf8));

field_store_string(fields[IDX_DATABASE_NAME], db_utf8);
field_store_string(fields[IDX_TABLE_NAME], table_utf8);
field_store_index_name(fields[IDX_INDEX_NAME],
index->name);
status = field_store_string(fields[IDX_DATABASE_NAME],
db_utf8)
|| field_store_string(fields[IDX_TABLE_NAME],
table_utf8)
|| field_store_string(fields[IDX_INDEX_NAME],
index->name);
} else {
/* index not found */
snprintf(name, sizeof(name),
"index_id:" IB_ID_FMT, iter->first);
field_store_string(fields[IDX_DATABASE_NAME],
"unknown");
field_store_string(fields[IDX_TABLE_NAME],
"unknown");
field_store_string(fields[IDX_INDEX_NAME],
name);
char name[MY_INT64_NUM_DECIMAL_DIGITS
+ sizeof "index_id: "];
fields[IDX_DATABASE_NAME]->set_null();
fields[IDX_TABLE_NAME]->set_null();
fields[IDX_INDEX_NAME]->set_notnull();
status = fields[IDX_INDEX_NAME]->store(
name,
uint(snprintf(name, sizeof name,
"index_id: " IB_ID_FMT,
iter->first)),
system_charset_info);
}

fields[IDX_COMPRESS_OPS]->store(
iter->second.compressed, true);

fields[IDX_COMPRESS_OPS_OK]->store(
iter->second.compressed_ok, true);

fields[IDX_COMPRESS_TIME]->store(
iter->second.compressed_usec / 1000000, true);

fields[IDX_UNCOMPRESS_OPS]->store(
iter->second.decompressed, true);

fields[IDX_UNCOMPRESS_TIME]->store(
iter->second.decompressed_usec / 1000000, true);

if (schema_table_store_record(thd, table)) {
if (status
|| fields[IDX_COMPRESS_OPS]->store(
iter->second.compressed, true)
|| fields[IDX_COMPRESS_OPS_OK]->store(
iter->second.compressed_ok, true)
|| fields[IDX_COMPRESS_TIME]->store(
iter->second.compressed_usec / 1000000, true)
|| fields[IDX_UNCOMPRESS_OPS]->store(
iter->second.decompressed, true)
|| fields[IDX_UNCOMPRESS_TIME]->store(
iter->second.decompressed_usec / 1000000, true)
|| schema_table_store_record(thd, table)) {
status = 1;
break;
}
/* Release and reacquire the dict mutex to allow other
threads to proceed. This could eventually result in the
contents of INFORMATION_SCHEMA.innodb_cmp_per_index being
inconsistent, but it is an acceptable compromise. */
if (i % 1000 == 0) {
if (i == 1000) {
mutex_exit(&dict_sys->mutex);
i = 0;
mutex_enter(&dict_sys->mutex);
}
}
Expand Down Expand Up @@ -4932,9 +4883,11 @@ i_s_innodb_buffer_page_fill(

mutex_enter(&dict_sys->mutex);

if (const dict_index_t* index =
dict_index_get_if_in_cache_low(
page_info->index_id)) {
const dict_index_t* index =
dict_index_get_if_in_cache_low(
page_info->index_id);

if (index) {
table_name_end = innobase_convert_name(
table_name, sizeof(table_name),
index->table_name,
Expand All @@ -4947,17 +4900,22 @@ i_s_innodb_buffer_page_fill(
table_name_end
- table_name),
system_charset_info)
|| field_store_index_name(
fields
[IDX_BUFFER_PAGE_INDEX_NAME],
index->name);
|| fields[IDX_BUFFER_PAGE_INDEX_NAME]
->store(index->name,
uint(strlen(index->name)),
system_charset_info);
}

mutex_exit(&dict_sys->mutex);

OK(ret);

fields[IDX_BUFFER_PAGE_TABLE_NAME]->set_notnull();
if (index) {
fields[IDX_BUFFER_PAGE_TABLE_NAME]
->set_notnull();
fields[IDX_BUFFER_PAGE_INDEX_NAME]
->set_notnull();
}
}

OK(fields[IDX_BUFFER_PAGE_NUM_RECS]->store(
Expand Down Expand Up @@ -5649,9 +5607,11 @@ i_s_innodb_buf_page_lru_fill(

mutex_enter(&dict_sys->mutex);

if (const dict_index_t* index =
dict_index_get_if_in_cache_low(
page_info->index_id)) {
const dict_index_t* index =
dict_index_get_if_in_cache_low(
page_info->index_id);

if (index) {
table_name_end = innobase_convert_name(
table_name, sizeof(table_name),
index->table_name,
Expand All @@ -5664,17 +5624,22 @@ i_s_innodb_buf_page_lru_fill(
table_name_end
- table_name),
system_charset_info)
|| field_store_index_name(
fields
[IDX_BUF_LRU_PAGE_INDEX_NAME],
index->name);
|| fields[IDX_BUF_LRU_PAGE_INDEX_NAME]
->store(index->name,
uint(strlen(index->name)),
system_charset_info);
}

mutex_exit(&dict_sys->mutex);

OK(ret);

fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->set_notnull();
if (index) {
fields[IDX_BUF_LRU_PAGE_TABLE_NAME]
->set_notnull();
fields[IDX_BUF_LRU_PAGE_INDEX_NAME]
->set_notnull();
}
}

OK(fields[IDX_BUF_LRU_PAGE_NUM_RECS]->store(
Expand Down Expand Up @@ -6647,7 +6612,15 @@ i_s_dict_fill_sys_indexes(

fields = table_to_fill->field;

OK(field_store_index_name(fields[SYS_INDEX_NAME], index->name));
if (*index->name == *TEMP_INDEX_PREFIX_STR) {
/* Since TEMP_INDEX_PREFIX_STR is not valid UTF-8, we
need to convert it to something else. */
*const_cast<char*>(index->name()) = '?';
}

OK(fields[SYS_INDEX_NAME]->store(index->name,
uint(strlen(index->name)),
system_charset_info));

OK(fields[SYS_INDEX_ID]->store(longlong(index->id), true));

Expand Down

0 comments on commit 52df804

Please sign in to comment.