Browse Source

Merge pull request #16037 from cakephp/db-features

Add driver supports check for disabling constraints outside transactions
Mark Story 4 years ago
parent
commit
a8e6aedefe

+ 1 - 0
src/Database/Driver.php

@@ -449,6 +449,7 @@ abstract class Driver implements DriverInterface
     public function supports(string $feature): bool
     {
         switch ($feature) {
+            case static::FEATURE_DISABLE_CONSTRAINT_WITHOUT_TRANSACTION:
             case static::FEATURE_QUOTE:
             case static::FEATURE_SAVEPOINT:
                 return true;

+ 3 - 0
src/Database/Driver/Postgres.php

@@ -195,6 +195,9 @@ class Postgres extends Driver
             case static::FEATURE_JSON:
             case static::FEATURE_WINDOW:
                 return true;
+
+            case static::FEATURE_DISABLE_CONSTRAINT_WITHOUT_TRANSACTION:
+                return false;
         }
 
         return parent::supports($feature);

+ 7 - 0
src/Database/DriverInterface.php

@@ -38,6 +38,13 @@ interface DriverInterface
     public const FEATURE_CTE = 'cte';
 
     /**
+     * Disabling constraints without being in transaction support.
+     *
+     * @var string
+     */
+    public const FEATURE_DISABLE_CONSTRAINT_WITHOUT_TRANSACTION = 'disable-constraint-without-transaction';
+
+    /**
      * Native JSON data type support.
      *
      * @var string

+ 7 - 7
src/TestSuite/ConnectionHelper.php

@@ -16,7 +16,7 @@ declare(strict_types=1);
 namespace Cake\TestSuite;
 
 use Cake\Database\Connection;
-use Cake\Database\Driver\Postgres;
+use Cake\Database\DriverInterface;
 use Cake\Datasource\ConnectionManager;
 use Closure;
 
@@ -144,18 +144,18 @@ class ConnectionHelper
      * @param \Closure $callback callback
      * @return void
      */
-    protected function runWithoutConstraints(Connection $connection, Closure $callback): void
+    public function runWithoutConstraints(Connection $connection, Closure $callback): void
     {
-        if ($connection->getDriver() instanceof Postgres) {
+        if ($connection->getDriver()->supports(DriverInterface::FEATURE_DISABLE_CONSTRAINT_WITHOUT_TRANSACTION)) {
+            $connection->disableConstraints(function (Connection $connection) use ($callback) {
+                $callback($connection);
+            });
+        } else {
             $connection->transactional(function (Connection $connection) use ($callback) {
                 $connection->disableConstraints(function (Connection $connection) use ($callback) {
                     $callback($connection);
                 });
             });
-        } else {
-            $connection->disableConstraints(function (Connection $connection) use ($callback) {
-                $callback($connection);
-            });
         }
     }
 }

+ 12 - 16
src/TestSuite/Fixture/FixtureHelper.php

@@ -25,6 +25,7 @@ use Cake\Database\Schema\TableSchema;
 use Cake\Datasource\ConnectionInterface;
 use Cake\Datasource\ConnectionManager;
 use Cake\Datasource\FixtureInterface;
+use Cake\TestSuite\ConnectionHelper;
 use Closure;
 use UnexpectedValueException;
 
@@ -135,27 +136,22 @@ class FixtureHelper
         $this->runPerConnection(function (ConnectionInterface $connection, array $groupFixtures) {
             if ($connection instanceof Connection) {
                 $sortedFixtures = $this->sortByConstraint($connection, $groupFixtures);
-            }
-
-            if (isset($sortedFixtures)) {
-                foreach ($sortedFixtures as $fixture) {
-                    $fixture->insert($connection);
-                }
-            } elseif ($connection->getDriver() instanceof Postgres) {
-                // disabling foreign key constraints is only valid in a transaction
-                $connection->transactional(function () use ($connection, $groupFixtures) {
-                    $connection->disableConstraints(function () use ($connection, $groupFixtures) {
+                if ($sortedFixtures) {
+                    foreach ($sortedFixtures as $fixture) {
+                        $fixture->insert($connection);
+                    }
+                } else {
+                    $helper = new ConnectionHelper();
+                    $helper->runWithoutConstraints($connection, function (Connection $connection) use ($groupFixtures) {
                         foreach ($groupFixtures as $fixture) {
                             $fixture->insert($connection);
                         }
                     });
-                });
+                }
             } else {
-                $connection->disableConstraints(function () use ($connection, $groupFixtures) {
-                    foreach ($groupFixtures as $fixture) {
-                        $fixture->insert($connection);
-                    }
-                });
+                foreach ($groupFixtures as $fixture) {
+                    $fixture->insert($connection);
+                }
             }
         }, $fixtures);
     }