Bug #99763 error log reports Invalid (old?) table or database name
Submitted: 3 Jun 2020 6:28 Modified: 3 Jun 2020 6:39
Reporter: zhai weixiang (OCA) Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S2 (Serious)
Version:8.0, 8.0.20 OS:Any
Assigned to: CPU Architecture:Any
Tags: regression

[3 Jun 2020 6:28] zhai weixiang
Description:
create a partition table, and using XA trx, after xa prepare and restart, it will reports ' Invalid (old?) table or database name' in error log

How to repeat:
a simple test case, check the error log after running it

call mtr.add_suppression("Found .* prepared XA transactions");
create  table t1(a int primary key, b int) PARTITION BY HASH(a) PARTITIONS 4;
connect (con1,localhost,root);

--connection con1
xa begin '123';
insert into t1 values(1,2);
xa end '123';
xa prepare '123';

--connection default
#restart
--source include/restart_mysqld.inc

disconnect con1;

--connection default
xa recover;
xa commit '123';
drop table t1;

and the error log:

[ERROR] [MY-010520] [Server] Invalid (old?) table or database name 't1#p#p1'

Suggested fix:
get_table_name_info() doesn't handle partition table, should format dbname and tablename.

a simple fix like this:

diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index eb7bf18..f50a5ca 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -2793,15 +2793,14 @@ dberr_t trx_prepare_for_mysql(trx_t *trx) {
 static bool get_table_name_info(st_handler_tablename *table,
                                 const dict_table_t *dd_table,
                                 MEM_ROOT *mem_root) {
-  const char *ptr;
+  std::string db_str;
+  std::string tbl_str;
+  dict_name::get_table(dd_table->name.m_name, db_str, tbl_str);

-  size_t len = dict_get_db_name_len(dd_table->name.m_name);
-  table->db = strmake_root(mem_root, dd_table->name.m_name, len);
+  table->db = strmake_root(mem_root, db_str.c_str(), db_str.size());
   if (table->db == nullptr) return true;
-
-  ptr = dict_remove_db_name(dd_table->name.m_name);
-  len = ut_strlen(ptr);
-  table->tablename = strmake_root(mem_root, ptr, len);
+
+  table->tablename = strmake_root(mem_root, tbl_str.c_str(), tbl_str.size());
   if (table->tablename == nullptr) return true;

   return false;
[3 Jun 2020 6:39] MySQL Verification Team
Hello zhai,

Thank you for the report and feedback.

regards,
Umesh