Fix int length handling during DB updates for MySQL >= 8.0.19
authorMatthias Schmidt <gravatronics@live.com>
Sat, 22 Feb 2020 16:13:54 +0000 (17:13 +0100)
committerMatthias Schmidt <gravatronics@live.com>
Sat, 22 Feb 2020 16:13:54 +0000 (17:13 +0100)
Close #3160

wcfsetup/install/files/lib/system/database/editor/DatabaseEditor.class.php
wcfsetup/install/files/lib/system/database/table/DatabaseTableChangeProcessor.class.php

index dad7e2b17b3598b97f6cb3c3bcaf2d317eef4e3b..bae400b4bf0e9650892a258d77de6938cd1d3b18 100644 (file)
@@ -7,7 +7,7 @@ use wcf\system\exception\NotImplementedException;
  * Abstract implementation of a database editor.
  * 
  * @author     Marcel Werk
- * @copyright  2001-2019 WoltLab GmbH
+ * @copyright  2001-2020 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    WoltLabSuite\Core\System\Database\Editor
  */
@@ -27,6 +27,16 @@ abstract class DatabaseEditor {
                $this->dbObj = $dbObj;
        }
        
+       /**
+        * Returns the database object the editor works with.
+        * 
+        * @return      Database
+        * @since       5.2.3
+        */
+       public function getDatabase() {
+               return $this->dbObj;
+       }
+       
        /**
         * Returns all existing table names.
         * 
index 9f6fc5484d709a85c50d6355a332851acc375926..28f6f8519b6317e69aeee25f3d7fb7d07957298b 100644 (file)
@@ -2,7 +2,9 @@
 namespace wcf\system\database\table;
 use wcf\data\package\Package;
 use wcf\system\database\editor\DatabaseEditor;
+use wcf\system\database\table\column\AbstractIntDatabaseTableColumn;
 use wcf\system\database\table\column\IDatabaseTableColumn;
+use wcf\system\database\table\column\TinyintDatabaseTableColumn;
 use wcf\system\database\table\index\DatabaseTableForeignKey;
 use wcf\system\database\table\index\DatabaseTableIndex;
 use wcf\system\database\util\PreparedStatementConditionBuilder;
@@ -13,7 +15,7 @@ use wcf\system\WCF;
  * Processes a given set of changes to database tables.
  * 
  * @author     Matthias Schmidt
- * @copyright  2001-2019 WoltLab GmbH
+ * @copyright  2001-2020 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    WoltLabSuite\Core\System\Database\Table
  * @since      5.2
@@ -102,6 +104,14 @@ class DatabaseTableChangeProcessor {
         */
        protected $foreignKeysToDrop = [];
        
+       /**
+        * indicates if lengths of integer columns are ignored when comparing the columns
+        * @var boolean
+        * @see https://github.com/WoltLab/WCF/issues/3160
+        * @since       5.2.3
+        */
+       protected $ignoreIntLengths = false;
+       
        /**
         * package that wants to apply the changes
         * @var Package
@@ -186,6 +196,14 @@ class DatabaseTableChangeProcessor {
                                $this->indexPackageIDs[$row['sqlTable']][$row['sqlIndex']] = $row['packageID'];
                        }
                }
+               
+               $sqlVersion = $dbEditor->getDatabase()->getVersion();
+               $compareSQLVersion = preg_replace('/^(\d+\.\d+\.\d+).*$/', '\\1', $sqlVersion);
+               if (!stripos($sqlVersion, 'MariaDB')) {
+                       if (version_compare($compareSQLVersion, '8.0.19') >= 0) {
+                               $this->ignoreIntLengths = true;
+                       }
+               }
        }
        
        /**
@@ -714,8 +732,23 @@ class DatabaseTableChangeProcessor {
         * @return      bool
         */
        protected function diffColumns(IDatabaseTableColumn $oldColumn, IDatabaseTableColumn $newColumn) {
-               if (!empty(array_diff($oldColumn->getData(), $newColumn->getData()))) {
-                       return true;
+               $diff = array_diff($oldColumn->getData(), $newColumn->getData());
+               if (!empty($diff)) {
+                       if (
+                               $this->ignoreIntLengths
+                               && array_key_exists('length', $diff)
+                               && $oldColumn instanceof AbstractIntDatabaseTableColumn
+                               && (
+                                       !($oldColumn instanceof TinyintDatabaseTableColumn)
+                                       || $oldColumn->getLength() != 1
+                               )
+                       ) {
+                               unset($diff['length']);
+                       }
+                       
+                       if (!empty($diff)) {
+                               return true;
+                       }
                }
                
                // default type has to be checked explicitly for `null` to properly detect changing