Bug #121674 RENAME INDEX fails when functional-index hidden names collide
Description:
ALTER TABLE ... RENAME INDEX fails for a functional index when the generated hidden-column name, after truncation, collides with the unchanged hidden column of another functional index. The two visible index names are distinct and legal, and the intended final table definition can be created directly.
Actual result:
The RENAME INDEX operation returns:
ERROR 1062 (23000): Duplicate entry for key 'columns.table_id'
The error refers to an internal !hidden! column. After the failed ALTER, the original two functional indexes, their expressions, and all three rows remain intact. CHECK TABLE reports OK.
Expected result:
The rename should succeed because the new index name is distinct and the resulting visible schema is valid. Creating an equivalent table with that final schema directly succeeds.
The recorded source shows that handle_rename_functional_index() calls make_functional_index_column_name() using alter_info->create_list. In this case that list does not account for the unchanged colliding hidden column when selecting the replacement name.
Impact:
Affected functional-index renames fail atomically. Existing data and schema remain intact, and no server restart is required. A shorter noncolliding index name or a different table/index rebuild sequence can avoid the failure.
Tested versions:
MySQL Community Server 9.7.2, source revision 561753af986c3c006c4b6c7caa8359748fb55b22.
Environment and configuration:
Linux/amd64 using the default InnoDB table definition shown in the reproducer, with utf8mb4 and utf8mb4_0900_ai_ci. No relevant non-default server variables were recorded.
Additional information:
This occurs when a functional index is renamed to a long distinct name whose truncated hidden-column prefix collides with another functional index's unchanged hidden column.
How to repeat:
The following uses two 53-byte index names whose first 52 bytes are identical. Save this as setup.sql and run:
mysql < setup.sql
CREATE DATABASE rename_test;
USE rename_test;
CREATE TABLE control_table (
x INT,
KEY functional_index_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxa ((x+1)),
KEY functional_index_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxb ((x+2))
);
INSERT INTO control_table VALUES (1),(2),(3);
SHOW CREATE TABLE control_table;
CREATE TABLE t1 (
x INT,
KEY functional_index_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxa ((x+1)),
KEY short_index ((x+2))
);
INSERT INTO t1 VALUES (1),(2),(3);
SHOW CREATE TABLE t1;
The control table demonstrates that the intended final visible schema can be created directly.
Save the following as rename.sql and run it separately so that the expected error does not prevent later inspection:
mysql < rename.sql
USE rename_test;
ALTER TABLE t1
RENAME INDEX short_index
TO functional_index_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxb;
The ALTER returns ERROR 1062 (23000) for the internal columns.table_id key instead of completing the rename.
Save the following as inspect.sql and run:
mysql < inspect.sql
USE rename_test;
SHOW CREATE TABLE t1;
SELECT INDEX_NAME, EXPRESSION
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = 'rename_test'
AND TABLE_NAME = 't1'
ORDER BY INDEX_NAME;
SELECT * FROM t1 ORDER BY x;
CHECK TABLE t1;
The recorded inspection shows that the failed ALTER leaves short_index on (x+2), leaves the other functional index on (x+1), returns rows 1, 2, and 3, and reports CHECK TABLE status OK.
Optional cleanup:
DROP DATABASE rename_test;
Suggested fix:
When generating the replacement hidden-column name for a functional-index rename, include unchanged hidden columns from the existing table in the collision check rather than checking only alter_info->create_list.
Portions of this website are copyright © 2001, 2002 The PHP Group
Page generated in 0.050 sec. using MySQL 8.4.7-u6-cloud
Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the
respective copyright holders.
It is not reviewed in advance
by Oracle and does not necessarily represent the opinion of
Oracle or any other party.