MySQL requires auto columns to be the primary key
authorAlexander Ebert <ebert@woltlab.com>
Mon, 9 Dec 2019 00:00:23 +0000 (01:00 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Mon, 9 Dec 2019 00:00:23 +0000 (01:00 +0100)
Adding an auto column to an existing table wasn't possible, because the primary key would be added in a secondary step.

However, MySQL does not permit this to be split into two steps, requiring us to define the key when adding the column.

com.woltlab.wcf/files_pre.tar
wcfsetup/install/files/lib/system/database/table/DatabaseTableChangeProcessor.class.php
wcfsetup/install/files/lib/system/database/table/column/AbstractDatabaseTableColumn.class.php

index acdf4ad3076ba7277abbd516956246a4be13808c..513c0bc6454d9b9f0c41a3a53b01e3a54fdfc84c 100644 (file)
Binary files a/com.woltlab.wcf/files_pre.tar and b/com.woltlab.wcf/files_pre.tar differ
index b0897945cecab5043c559f8520d6640832773a23..261de6ae4795ccdb4f1f383662058d83f0480b7e 100644 (file)
@@ -582,9 +582,15 @@ class DatabaseTableChangeProcessor {
         * @param       DatabaseTable           $table
         */
        protected function createTable(DatabaseTable $table) {
-               $columnData = array_map(function(IDatabaseTableColumn $column) {
+               $hasPrimaryKey = false;
+               $columnData = array_map(function(IDatabaseTableColumn $column) use (&$hasPrimaryKey) {
+                       $data = $column->getData();
+                       if (isset($data['key']) && $data['key'] === 'PRIMARY') {
+                               $hasPrimaryKey = true;
+                       }
+                       
                        return [
-                               'data' => $column->getData(),
+                               'data' => $data,
                                'name' => $column->getName()
                        ];
                }, $table->getColumns());
@@ -595,6 +601,13 @@ class DatabaseTableChangeProcessor {
                        ];
                }, $table->getIndices());
                
+               // Auto columns are implicitly defined as the primary key by MySQL.
+               if ($hasPrimaryKey) {
+                       $indexData = array_filter($indexData, function($key) {
+                               return $key !== 'PRIMARY';
+                       }, ARRAY_FILTER_USE_KEY);
+               }
+               
                $this->dbEditor->createTable($table->getName(), $columnData, $indexData);
                
                foreach ($table->getForeignKeys() as $foreignKey) {
index 3ca213c3cfb168d647bf885e8de43e234c4ac2a6..3c84ac5e7ff0a76f8616e9410dfebd4fa910dded 100644 (file)
@@ -61,6 +61,12 @@ abstract class AbstractDatabaseTableColumn implements IDatabaseTableColumn {
                
                if ($this instanceof IAutoIncrementDatabaseTableColumn) {
                        $data['autoIncrement'] = $this->isAutoIncremented() ? 1 : 0;
+                       
+                       // MySQL requires that there is only a single auto column per table *AND*
+                       // that this column is defined as the primary key.
+                       if ($data['autoIncrement'] === 1) {
+                               $data['key'] = 'PRIMARY';
+                       }
                }
                
                if ($this instanceof IDecimalsDatabaseTableColumn && $this->getDecimals() !== null) {