[BUGFIX] Detect TEXT/BLOB changes in schema analyzer 07/51807/10
authorThomas Hohn <thomas@hohn.dk>
Thu, 23 Feb 2017 17:54:21 +0000 (18:54 +0100)
committerChristian Kuhn <lolli@schwarzbu.ch>
Sun, 26 Feb 2017 16:51:29 +0000 (17:51 +0100)
Length changes of TEXT/BLOB type are not analyzed by the Doctrine
schema analyzer as only MySQL has different length version of these
fields. Add a custom column comparator that compares the different
fields length on MySQL to properly detect changes in field type.

Resolves: #79722
Releases: master
Change-Id: I2e448dcde02c3fa370496b4920dfad536fbafcd6
Reviewed-on: https://review.typo3.org/51807
Reviewed-by: Morton Jonuschat <m.jonuschat@mojocode.de>
Tested-by: Morton Jonuschat <m.jonuschat@mojocode.de>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
typo3/sysext/core/Classes/Database/Schema/Comparator.php
typo3/sysext/core/Classes/Database/Schema/ConnectionMigrator.php

index 8a09ef9..f21f255 100644 (file)
@@ -15,7 +15,11 @@ namespace TYPO3\CMS\Core\Database\Schema;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Doctrine\DBAL\Platforms\AbstractPlatform;
+use Doctrine\DBAL\Platforms\MySqlPlatform;
+use Doctrine\DBAL\Schema\Column;
 use Doctrine\DBAL\Schema\Table;
+use Doctrine\DBAL\Types;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -26,6 +30,21 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 class Comparator extends \Doctrine\DBAL\Schema\Comparator
 {
     /**
+     * @var AbstractPlatform
+     */
+    protected $databasePlatform;
+
+    /**
+     * Comparator constructor.
+     *
+     * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
+     */
+    public function __construct(AbstractPlatform $platform = null)
+    {
+        $this->databasePlatform = $platform;
+    }
+
+    /**
      * Returns the difference between the tables $fromTable and $toTable.
      *
      * If there are no differences this method returns the boolean false.
@@ -69,4 +88,38 @@ class Comparator extends \Doctrine\DBAL\Schema\Comparator
 
         return $tableDifferences;
     }
+
+    /**
+     * Returns the difference between the columns $column1 and $column2
+     * by first checking the doctrine diffColumn. Extend the Doctrine
+     * method by taking into account MySQL TINY/MEDIUM/LONG type variants.
+     *
+     * @param \Doctrine\DBAL\Schema\Column $column1
+     * @param \Doctrine\DBAL\Schema\Column $column2
+     * @return array
+     */
+    public function diffColumn(Column $column1, Column $column2)
+    {
+        $changedProperties = parent::diffColumn($column1, $column2);
+
+        // Only MySQL has variable length versions of TEXT/BLOB
+        if (!$this->databasePlatform instanceof MySqlPlatform) {
+            return $changedProperties;
+        }
+
+        $properties1 = $column1->toArray();
+        $properties2 = $column2->toArray();
+
+        if ($properties1['type'] instanceof Types\BlobType || $properties1['type'] instanceof Types\TextType) {
+            // Doctrine does not provide a length for LONGTEXT/LONGBLOB columns
+            $length1 = $properties1['length'] ?: 2147483647;
+            $length2 = $properties2['length'] ?: 2147483647;
+
+            if ($length1 !== $length2) {
+                $changedProperties[] = 'length';
+            }
+        }
+
+        return array_unique($changedProperties);
+    }
 }
index 46f63bc..d2ebdcc 100644 (file)
@@ -224,8 +224,9 @@ class ConnectionMigrator
      * for tables that are in the database but have no direct relation to the TYPO3 instance.
      *
      * @param bool $renameUnused
-     * @return \Doctrine\DBAL\Schema\SchemaDiff
      * @throws \Doctrine\DBAL\DBALException
+     * @return \Doctrine\DBAL\Schema\SchemaDiff
+     * @throws \Doctrine\DBAL\Schema\SchemaException
      * @throws \InvalidArgumentException
      */
     protected function buildSchemaDiff(bool $renameUnused = true): SchemaDiff
@@ -247,7 +248,7 @@ class ConnectionMigrator
         }
 
         // Build SchemaDiff and handle renames of tables and colums
-        $comparator = GeneralUtility::makeInstance(Comparator::class);
+        $comparator = GeneralUtility::makeInstance(Comparator::class, $this->connection->getDatabasePlatform());
         $schemaDiff = $comparator->compare($fromSchema, $toSchema);
         $schemaDiff = $this->migrateColumnRenamesToDistinctActions($schemaDiff);