Bug #92567 | Cannot add foreign key constraint to tables inside a database named `aux` | ||
---|---|---|---|
Submitted: | 25 Sep 2018 21:30 | Modified: | 24 Sep 2019 18:47 |
Reporter: | Dan Gorby | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: DDL | Severity: | S2 (Serious) |
Version: | 5.7.23/5.6 | OS: | Any |
Assigned to: | CPU Architecture: | Any |
[25 Sep 2018 21:30]
Dan Gorby
[25 Sep 2018 23:45]
MySQL Verification Team
Thank you for the bug report. Verified as described with version 5.6 and 5.7. The version 8.0 works.
[30 Apr 2019 11:19]
Dmitry Lenev
Posted by developer: The problem affects special ("AUX","PRN","COM1","LPT1",...) table names as well: CREATE TABLE aux(pk INT PRIMARY KEY); CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES aux (pk)); # The above fails with ERROR HY000: Cannot add foreign key constraint SHOW ENGINE INNODB STATUS; #... #------------------------ #LATEST FOREIGN KEY ERROR #------------------------ #2019-04-30 13:53:27 0x7f1e453a0700 Error in foreign key constraint of table test/child: #FOREIGN KEY (fk) REFERENCES aux (pk)): #Cannot resolve table name close to: # (pk)) #... The problem is that dict_scan_id() which is used to parse referenced table name is not aware of the fact these special names are enconded, and thus doesn't convert them to encoded form as it does for, e.g. non-filename-safe characters. In 8.0 the same works mostly because after failing to lookup table under unencoded name in InnoDB's internal dictionary cache we try to load its definition from the SQL-layer data-dictionary using its API, and this API takes unencoded version of names and is able to find the table. However, the code is still sub-optimal as it doesn't work correctly with InnoDB's internal dictionary cache/causes extra overhead. This code will be eventually removed/changed once InnoDB's code doing FOREIGN KEY definition parsing is changed to use structures passed from SQL-layer.
[17 Sep 2019 7:11]
Dmitry Lenev
Posted by developer: Hello! Since the code has been changed in 8.0 in such a way that problem is no longer repeatable and the sub-optimal handling of 'aux' name has been addressed by the following patch: commit b9cfd9bb493b600637a02bafa2cc824603b4da42 (origin/mysql-8.0, mysql-8.0) Author: Dmitry Lenev <dmitry.lenev@oracle.com> Date: Thu Sep 12 10:42:03 2019 +0300 Bug#30287895 "REMOVE DICT_CREATE_FOREIGN_CONSTRAINTS() AND FRIENDS". After transition to new data-dictionary MySQL 8.0 and subsequent move of DDL checks for foreign keys to SQL-layer InnoDB's function dict_create_foreign_constraints() became redundant. It no longer stores anything in InnoDB data-dictionary (since it was removed). It is not responsible for updating InnoDB's dictionary cache either (instead we rely on later dd_table_load_fk() call to do this). It only does some DDL checks for foreign keys which are duplicated by SQL-layer or elsewhere in InnoDB code. OTOH its code still does parsing of original ALTER or CREATE TABLE statements, which causes a few corner-case bugs. It also creates problems for further improvements in the foreign key area. This patch removes dict_create_foreign_constraints() and associated InnoDB code related to foreign key definitions parsing. The following bugs are fixed as result: - Bug#22364336 "ANOMALY IN ALTER TABLE ADD FOREIGN KEY" - spaces around dot in fully-qualified referenced table name were erroneously not allowed by InnoDB parser. - Bug#28486106 "ALTER TABLE ADD FOREIGN KEY ... REMOVE PARTITIONING FAILS IF SELF-REFENCE" - adding a foreign key and removing partitioning from table was not allowed within same ALTER TABLE, even though theoretically this should have been possible. Again the problem was caused by InnoDB parser not detecting the fact that new table version was not partitioned. Also this removes sub-optimal handling of case when parent table resides in database named "aux" which was mentioned in bug#28703793 "CANNOT ADD FOREIGN KEY CONSTRAINT TO TABLES INSIDE A DATABASE NAMED `AUX`" (which by itself is not repeatable in MySQL 8.0). Finally, to minimize impact of dict_create_foreign_constraints() check was added to SQL-layer to detect situation when user tries to create several foreign keys on the table with the same name at early stage of ALTER TABLE execution. This solves the issue described in bug#16904122 "MULTIPLE FK WITH SAME NAME ALLOWED IN ALTER". I am closing this bug as fixed in 8.0.19. Moving it to Documenting state to let Documentation team to update Release Notes.
[24 Sep 2019 18:47]
Daniel Price
Posted by developer: Fixed as of the upcoming 8.0.19 release. The following changelog entry applies to: Bug #30287895 REMOVE DICT_CREATE_FOREIGN_CONSTRAINTS() AND FRIENDS. Bug #22364336 ANOMALY IN ALTER TABLE ADD FOREIGN KEY Bug #28486106 ALTER TABLE ADD FOREIGN KEY ... REMOVE PARTITIONING FAILS IF SELF-REFERENCE. Bug #28703793 CANNOT ADD FOREIGN KEY CONSTRAINT TO TABLES INSIDE A DATABASE NAMED `AUX` Bug #16904122 MULTIPLE FK WITH SAME NAME ALLOWED IN ALTER. "The internal InnoDB dict_create_foreign_constraints() function that parsed SQL statements and performed foreign key related DDL checks was removed. The function became redundant with introduction of the data dictionary in MySQL 8.0 and the subsequent relocation of foreign key related DDL checks to the SQL layer. Removal of the dict_create_foreign_constraints() function also addressed the following foreign key issues: * Spaces around dots (.) in a fully qualified referenced table name were not permitted by the InnoDB parser. * Adding a foreign key and removing partitioning in the same ALTER TABLE statement was not permitted. The InnoDB parser did not detect that the new table version was no longer partitioned. * A foreign key constraint could not reference a table inside a schema named AUX. The function that parsed referenced table names did not recognize that special names such as AUX are encoded. Additionally, a check was added to the SQL layer to detect attempts to create multiple foreign keys of the same name on a table at an early stage in the execution of ALTER TABLE statement."