dbal icon indicating copy to clipboard operation
dbal copied to clipboard

Comparator::toSql() creates duplicate DROP commands for foreign keys (MySql)

Open gregor-tb opened this issue 4 years ago • 2 comments

Bug Report

Q A
BC Break no
Version all

Summary

Cannot migrate tables with renamed foreign keys when renaming index at the same time with MySqlPlatform.

How to reproduce

Schema 1 contains e.g. one table

  • fk_foo (foreign_id)
  • index_foo (foreign_id)

Schema 2 for same table

  • fk_bar (foreign_id)
  • index_bar (foreign_id)

The Comparator:.compare works fine, it detects:

  • drop fk_foo
  • add fk_bar
  • rename index index_foo to index_bar

But toSql() produces:

  • sql drop fk_foo
  • sql drop fk_foo (it crashes here because index does not exist)
  • sql add fk_bar (with namespace)
  • sql drop index_foo
  • sql add index_bar
  • sql add fk_foo (recreates the dropped(!) fk here, but without namespace)

MysqlPlatform::getPreAlterTableIndexForeignKeySQL() generates the DROP query twice.

I guess $this->getRemainingForeignKeyConstraintsRequiringRenamedIndexes($diff) in getPreAlterTableRenameIndexForeignKeySQL is not working as expected.

Expected behaviour

Drop Command should not be duplicated.

EDIT: I reported the index is dropped twice, but it is the foreign key itself caused by the index.

gregor-tb avatar Apr 01 '20 16:04 gregor-tb

Hi again,

unfortunately this bug still exists, but we made a workaround by replacing rename with add+drop instructions:

    /** @var SchemaDiff $schemaDiff */
    
    // ....

    if ($platform instanceof MySQLPlatform) {
            foreach ($schemaDiff->changedTables as $tableDiff) {
                if ($tableDiff->renamedIndexes) {
                    foreach ($tableDiff->renamedIndexes as $oldName => $index) {
                        $tableDiff->addedIndexes[$index->getName()] = $index;

                        $removedIndex = new Index($oldName, $index->getColumns(), $index->isUnique(), $index->isPrimary(), $index->getFlags(), $index->getOptions());
                        $tableDiff->removedIndexes[$oldName] = $removedIndex;
                    }

                    $tableDiff->renamedIndexes = [];
                }
            }
        }

But now we updated to 3.7.2, and are dealing with lots of deprecation here. Problem there are only getters, but no setters to fix it.

gregor-tb avatar Jan 22 '24 12:01 gregor-tb

It looks like not many people run into that issue, I'm afraid. I'm happy to review any PR that fixes the issue for you. If you don't fix the bug, chances are that nobody else will. 😕

derrabus avatar Jan 25 '24 21:01 derrabus