Commit 52df8040 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-16267 Wrong INFORMATION_SCHEMA.INNODB_BUFFER_PAGE.TABLE_NAME

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().
parent fdb8d018
...@@ -2477,8 +2477,9 @@ dict_load_indexes( ...@@ -2477,8 +2477,9 @@ dict_load_indexes(
&& static_cast<char>(*field) && static_cast<char>(*field)
== static_cast<char>(*TEMP_INDEX_PREFIX_STR)) { == static_cast<char>(*TEMP_INDEX_PREFIX_STR)) {
/* Skip indexes whose name starts with /* Skip indexes whose name starts with
TEMP_INDEX_PREFIX, because they will TEMP_INDEX_PREFIX_STR, because they will
be dropped during crash recovery. */ be dropped by row_merge_drop_temp_indexes()
during crash recovery. */
goto next_rec; goto next_rec;
} }
} }
......
...@@ -8169,7 +8169,7 @@ commit_cache_norebuild( ...@@ -8169,7 +8169,7 @@ commit_cache_norebuild(
(after renaming the indexes), so that in the (after renaming the indexes), so that in the
event of a crash, crash recovery will drop the event of a crash, crash recovery will drop the
indexes, because it drops all indexes whose 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 have started dropping an index tree, there is
no way to roll it back. */ no way to roll it back. */
......
...@@ -261,59 +261,13 @@ field_store_string( ...@@ -261,59 +261,13 @@ field_store_string(
const char* str) /*!< in: NUL-terminated utf-8 string, const char* str) /*!< in: NUL-terminated utf-8 string,
or NULL */ or NULL */
{ {
int ret; if (!str) {
if (str != NULL) {
ret = field->store(str, static_cast<uint>(strlen(str)),
system_charset_info);
field->set_notnull();
} else {
ret = 0; /* success */
field->set_null(); field->set_null();
} return 0;
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);
} }
field->set_notnull(); field->set_notnull();
return field->store(str, uint(strlen(str)), system_charset_info);
return(ret);
} }
/*******************************************************************//** /*******************************************************************//**
...@@ -952,12 +906,8 @@ fill_innodb_locks_from_cache( ...@@ -952,12 +906,8 @@ fill_innodb_locks_from_cache(
buf, uint(bufend - buf), system_charset_info)); buf, uint(bufend - buf), system_charset_info));
/* lock_index */ /* lock_index */
if (row->lock_index != NULL) { OK(field_store_string(fields[IDX_LOCK_INDEX],
OK(field_store_index_name(fields[IDX_LOCK_INDEX],
row->lock_index)); row->lock_index));
} else {
fields[IDX_LOCK_INDEX]->set_null();
}
/* lock_space */ /* lock_space */
OK(field_store_ulint(fields[IDX_LOCK_SPACE], OK(field_store_ulint(fields[IDX_LOCK_SPACE],
...@@ -1731,7 +1681,6 @@ i_s_cmp_per_index_fill_low( ...@@ -1731,7 +1681,6 @@ i_s_cmp_per_index_fill_low(
for (iter = snap.begin(), i = 0; iter != snap.end(); iter++, i++) { 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); dict_index_t* index = dict_index_find_on_id_low(iter->first);
if (index != NULL) { if (index != NULL) {
...@@ -1742,38 +1691,39 @@ i_s_cmp_per_index_fill_low( ...@@ -1742,38 +1691,39 @@ i_s_cmp_per_index_fill_low(
db_utf8, sizeof(db_utf8), db_utf8, sizeof(db_utf8),
table_utf8, sizeof(table_utf8)); table_utf8, sizeof(table_utf8));
field_store_string(fields[IDX_DATABASE_NAME], db_utf8); status = field_store_string(fields[IDX_DATABASE_NAME],
field_store_string(fields[IDX_TABLE_NAME], table_utf8); db_utf8)
field_store_index_name(fields[IDX_INDEX_NAME], || field_store_string(fields[IDX_TABLE_NAME],
table_utf8)
|| field_store_string(fields[IDX_INDEX_NAME],
index->name); index->name);
} else { } else {
/* index not found */ /* index not found */
snprintf(name, sizeof(name), char name[MY_INT64_NUM_DECIMAL_DIGITS
"index_id:" IB_ID_FMT, iter->first); + sizeof "index_id: "];
field_store_string(fields[IDX_DATABASE_NAME], fields[IDX_DATABASE_NAME]->set_null();
"unknown"); fields[IDX_TABLE_NAME]->set_null();
field_store_string(fields[IDX_TABLE_NAME], fields[IDX_INDEX_NAME]->set_notnull();
"unknown"); status = fields[IDX_INDEX_NAME]->store(
field_store_string(fields[IDX_INDEX_NAME], name,
name); uint(snprintf(name, sizeof name,
"index_id: " IB_ID_FMT,
iter->first)),
system_charset_info);
} }
fields[IDX_COMPRESS_OPS]->store( if (status
iter->second.compressed, true); || fields[IDX_COMPRESS_OPS]->store(
iter->second.compressed, true)
fields[IDX_COMPRESS_OPS_OK]->store( || fields[IDX_COMPRESS_OPS_OK]->store(
iter->second.compressed_ok, true); iter->second.compressed_ok, true)
|| fields[IDX_COMPRESS_TIME]->store(
fields[IDX_COMPRESS_TIME]->store( iter->second.compressed_usec / 1000000, true)
iter->second.compressed_usec / 1000000, true); || fields[IDX_UNCOMPRESS_OPS]->store(
iter->second.decompressed, true)
fields[IDX_UNCOMPRESS_OPS]->store( || fields[IDX_UNCOMPRESS_TIME]->store(
iter->second.decompressed, true); iter->second.decompressed_usec / 1000000, true)
|| schema_table_store_record(thd, table)) {
fields[IDX_UNCOMPRESS_TIME]->store(
iter->second.decompressed_usec / 1000000, true);
if (schema_table_store_record(thd, table)) {
status = 1; status = 1;
break; break;
} }
...@@ -1781,8 +1731,9 @@ i_s_cmp_per_index_fill_low( ...@@ -1781,8 +1731,9 @@ i_s_cmp_per_index_fill_low(
threads to proceed. This could eventually result in the threads to proceed. This could eventually result in the
contents of INFORMATION_SCHEMA.innodb_cmp_per_index being contents of INFORMATION_SCHEMA.innodb_cmp_per_index being
inconsistent, but it is an acceptable compromise. */ inconsistent, but it is an acceptable compromise. */
if (i % 1000 == 0) { if (i == 1000) {
mutex_exit(&dict_sys->mutex); mutex_exit(&dict_sys->mutex);
i = 0;
mutex_enter(&dict_sys->mutex); mutex_enter(&dict_sys->mutex);
} }
} }
...@@ -4932,9 +4883,11 @@ i_s_innodb_buffer_page_fill( ...@@ -4932,9 +4883,11 @@ i_s_innodb_buffer_page_fill(
mutex_enter(&dict_sys->mutex); mutex_enter(&dict_sys->mutex);
if (const dict_index_t* index = const dict_index_t* index =
dict_index_get_if_in_cache_low( dict_index_get_if_in_cache_low(
page_info->index_id)) { page_info->index_id);
if (index) {
table_name_end = innobase_convert_name( table_name_end = innobase_convert_name(
table_name, sizeof(table_name), table_name, sizeof(table_name),
index->table_name, index->table_name,
...@@ -4947,17 +4900,22 @@ i_s_innodb_buffer_page_fill( ...@@ -4947,17 +4900,22 @@ i_s_innodb_buffer_page_fill(
table_name_end table_name_end
- table_name), - table_name),
system_charset_info) system_charset_info)
|| field_store_index_name( || fields[IDX_BUFFER_PAGE_INDEX_NAME]
fields ->store(index->name,
[IDX_BUFFER_PAGE_INDEX_NAME], uint(strlen(index->name)),
index->name); system_charset_info);
} }
mutex_exit(&dict_sys->mutex); mutex_exit(&dict_sys->mutex);
OK(ret); 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( OK(fields[IDX_BUFFER_PAGE_NUM_RECS]->store(
...@@ -5649,9 +5607,11 @@ i_s_innodb_buf_page_lru_fill( ...@@ -5649,9 +5607,11 @@ i_s_innodb_buf_page_lru_fill(
mutex_enter(&dict_sys->mutex); mutex_enter(&dict_sys->mutex);
if (const dict_index_t* index = const dict_index_t* index =
dict_index_get_if_in_cache_low( dict_index_get_if_in_cache_low(
page_info->index_id)) { page_info->index_id);
if (index) {
table_name_end = innobase_convert_name( table_name_end = innobase_convert_name(
table_name, sizeof(table_name), table_name, sizeof(table_name),
index->table_name, index->table_name,
...@@ -5664,17 +5624,22 @@ i_s_innodb_buf_page_lru_fill( ...@@ -5664,17 +5624,22 @@ i_s_innodb_buf_page_lru_fill(
table_name_end table_name_end
- table_name), - table_name),
system_charset_info) system_charset_info)
|| field_store_index_name( || fields[IDX_BUF_LRU_PAGE_INDEX_NAME]
fields ->store(index->name,
[IDX_BUF_LRU_PAGE_INDEX_NAME], uint(strlen(index->name)),
index->name); system_charset_info);
} }
mutex_exit(&dict_sys->mutex); mutex_exit(&dict_sys->mutex);
OK(ret); 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( OK(fields[IDX_BUF_LRU_PAGE_NUM_RECS]->store(
...@@ -6647,7 +6612,15 @@ i_s_dict_fill_sys_indexes( ...@@ -6647,7 +6612,15 @@ i_s_dict_fill_sys_indexes(
fields = table_to_fill->field; 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)); OK(fields[SYS_INDEX_ID]->store(longlong(index->id), true));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment