dbal icon indicating copy to clipboard operation
dbal copied to clipboard

Disable foreign key constraint check/generation

Open quazardous opened this issue 9 years ago • 9 comments
trafficstars

Hi, (I'm coming from doctrine/migrations#43)

I'm working with pretty big innodb tables and I need partitions more than foreign keys. Since they are mutually exclusive in MySQL I nee to disable foreign keys and put a more basic index instead.

So I would love to be able to explicitly disable foreign key check/generation with a cool annotation...

PS : I don't know if it's ORM related ....

quazardous avatar Sep 29 '16 13:09 quazardous

I agree with @quazardous - it would be great to have such functionality.

duzymaju avatar Oct 12 '16 13:10 duzymaju

Is there any work around to remove foreign keys on the partition table?

JordyMoos avatar Feb 06 '17 11:02 JordyMoos

+1

mutale avatar Mar 26 '17 15:03 mutale

+1

KarolyBujtor avatar Oct 10 '19 08:10 KarolyBujtor

If you need to voice your approval, please use the emoji reaction like the 12 other users that already did so. If you feel very strongly that this is needed, consider writing a PR, or drafting a plan to write a PR (look at the code, report here what would need to be done), but be constructive please.

greg0ire avatar Oct 12 '19 13:10 greg0ire

It is possible to use the schema events of dbal to adapt the schema and therefore to remove the foreign keys from tables.

SenseException avatar Oct 16 '19 21:10 SenseException

I had to disable creating foreign keys for certain tables as well. The simplest solution that I could find was overriding 2 methods of the Platform class.

I'm using Symfony, so I have created App\Doctrine\Platform\PostgreSQLPlatform:

<?php

namespace App\Doctrine\Platform;

use Doctrine\DBAL\Platforms\PostgreSQLPlatform as DoctrinePostgreSQLPlatform;
use Doctrine\DBAL\Schema\TableDiff;

class PostgreSQLPlatform extends DoctrinePostgreSQLPlatform
{
    public function getCreateTablesSQL(array $tables): array
    {
        foreach ($tables as $table) {
            if (!str_starts_with($table->getName(), 'log_')) {
                continue;
            }

            $foreignKeys = $table->getForeignKeys();

            foreach ($foreignKeys as $foreignKey) {
                $table->removeForeignKey($foreignKey->getName());
            }
        }

        return parent::getCreateTablesSQL($tables);
    }

    public function getAlterTableSQL(TableDiff $diff): array
    {
        $tableName = $diff->getOldTable()?->getName();

        if (null !== $tableName && str_starts_with($tableName, 'log_')) {
            $diff->addedForeignKeys = [];
            $diff->changedForeignKeys = [];
            $diff->removedForeignKeys = [];
        }

        return parent::getAlterTableSQL($diff);
    }
}

Then you just have to configure the DBAL to use your platform:

doctrine:
    dbal:
        connections:
            default:
                platform_service: App\Doctrine\Platform\PostgreSQLPlatform

fwolfsjaeger avatar May 25 '23 10:05 fwolfsjaeger

@fwolfsjaeger platform_service is deprecatad now :(

platform_service: ~ # Deprecated (Since doctrine/doctrine-bundle 2.9: The "platform_service" configuration key is deprecated since doctrine-bundle 2.9. DBAL 4 will not support setting a custom platform via connection params anymore.)

klobastov avatar Oct 06 '23 04:10 klobastov

Wire a middleware that changes the platform.

derrabus avatar Oct 06 '23 05:10 derrabus