Skip to content

Add conflict resolution for auto-generated FK constraint names#1042

Open
dereuromark wants to merge 5 commits intofix-auto-generate-fk-constraint-namefrom
fix-fk-name-conflict-resolution
Open

Add conflict resolution for auto-generated FK constraint names#1042
dereuromark wants to merge 5 commits intofix-auto-generate-fk-constraint-namefrom
fix-fk-name-conflict-resolution

Conversation

@dereuromark
Copy link
Member

@dereuromark dereuromark commented Mar 9, 2026

Summary

I feel like when we now auto generate them instead of the db, we should do this, as there could be conflict somewhere along the migrations.

  • When auto-generating FK constraint names, check if the name already exists
  • Append counter suffix (_2, _3, etc.) if a conflict is detected
  • Prevents duplicate constraint name errors in edge cases

UPDATE:
Also now respects technical max length limit per constraint using truncate.
We could also add hashing instead of just truncate + counter suffix.

This builds on #1041 which added auto-generation of FK constraint names.

Example

// First FK: generates "articles_user_id"
$table->addForeignKey('user_id', 'users', 'id');

// Second FK on same column (unusual but possible): generates "articles_user_id_2"
$table->addForeignKey('user_id', 'admins', 'id');

Changes

All 4 adapters updated with getUniqueForeignKeyName() method:

  • MysqlAdapter
  • SqliteAdapter
  • PostgresAdapter
  • SqlserverAdapter

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.
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).
- 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
Each adapter now defines its database-specific identifier length limit
as a class constant, making the code more self-documenting.
@dereuromark
Copy link
Member Author

Should the common code by moved to Util class? Regarding the

public static function generateUniqueConstraintName(                                                     
      string $baseName,                                                                                    
      array $existingNames,                                                                                
      int $maxLength                                                                                       
  ): string        

@dereuromark dereuromark requested a review from markstory March 9, 2026 20:33
@dereuromark
Copy link
Member Author

dereuromark commented Mar 9, 2026

@markstory I would squash-merge this first into the open PR, then we can merge the whole thing squashed for easier up/down merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant