Auto-generate foreign key constraint names when not provided#1041
Auto-generate foreign key constraint names when not provided#1041dereuromark merged 6 commits into5.xfrom
Conversation
c582b85 to
809abc9
Compare
When a foreign key is added without an explicit name, the MysqlAdapter and SqliteAdapter now generate a name following the pattern 'tablename_columnname' (e.g., 'articles_user_id' for a FK on the user_id column in the articles table). This matches the behavior of PostgresAdapter and SqlserverAdapter, which already auto-generate FK names. This ensures constraint names are always strings and prevents issues with constraint lookup methods that expect string names.
Update the expected FK names in comparison files and schema dumps to match the new auto-generated naming pattern (tablename_columnname).
ed2b2d3 to
629c85e
Compare
The FK constraint name change from auto-generated (ibfk_N) to explicit (table_column) also affects the implicit index MySQL creates for FKs. Update comparison files to reflect the index rename from user_id to articles_user_id.
With the FK naming changes, both the lock file and database have the index named articles_user_id, so no diff is needed for this index. Remove the index rename operations that were incorrectly added.
|
Updated PR #1042 with database-specific limits:
|
markstory
left a comment
There was a problem hiding this comment.
Changing the name of indexes, will change the schema created by a migration history. What used to be automatically named by the database engine will now be given a different name by migrations which could cause index add, index drop/change operations to fail as the name of an index has changed.
I don't think we have a good solution for this, but it should be something we point out in the release notes as a potential upgrade issue.
|
After the merge of this and follow up, maybe I can invest some time into shimming possibilities? // Pseudocode for dropForeignKey fallback
$fk = $this->findForeignKeyByName($name);
if (!$fk) {
$fk = $this->findForeignKeyByColumns($columns);
// Log warning about name mismatch
} But that would only work if we can reverse engineer the columns from the up() statement. |
* Add conflict resolution for auto-generated FK constraint names When auto-generating FK constraint names, check if the name already exists and append a counter suffix (_2, _3, etc.) if needed. This prevents duplicate constraint name errors when multiple FKs are created on the same columns with different references. * Remove unused variable * Truncate FK constraint names to max 128 characters Limit auto-generated foreign key constraint names to 125 characters to ensure the final name (including potential _XX counter suffix) stays within 128 characters. This prevents identifier length errors on databases with strict limits (MySQL: 64, PostgreSQL: 63). * Use database-specific identifier length limits - MySQL: 61 chars (64 limit - 3 for _XX suffix) - PostgreSQL: 60 chars (63 limit - 3 for _XX suffix) - SQL Server: 125 chars (128 limit - 3 for _XX suffix) - SQLite: No limit needed * Use IDENTIFIER_MAX_LENGTH class constant for clarity Each adapter now defines its database-specific identifier length limit as a class constant, making the code more self-documenting.
|
All good? |
jamisonbryant
left a comment
There was a problem hiding this comment.
Looks good, should we update the docs and the migration guide? Changing the conventional format for naming foreign keys feels like something we should warn users about.
Add upgrade documentation explaining the new auto-generated FK constraint naming behavior introduced in #1041 and #1042, including: - New consistent naming pattern across all adapters - Potential impact on existing migrations with rollbacks - Conflict resolution with counter suffixes - Database-specific name length limits
|
https://github.com/cakephp/migrations/pull/1049/changes is the follow up then. |
Summary
addForeignKey(){table}_{columns}(matching PostgresAdapter and SqlserverAdapter behavior)This fixes an issue where unnamed constraints could cause problems with CakePHP's
ConnectionHelper::dropTables()which expects string constraint names. When no name was provided, MySQL would auto-generate one, but the schema reflection could store it with integer array keys, causingTypeErrorinTableSchema::getConstraint().Fixes #1040