Browse Source

Fix MySQL schema reflection when columns have expressions

Skip over empty columns when reflecting schema. Currently schema
reflection doesn't support expressions for indexes. This isn't ideal but
we are also missing schema generation and migration support for index
expressions.

Fixes #16727
Mark Story 3 years ago
parent
commit
2333442fac

+ 3 - 1
src/Database/Schema/MysqlSchemaDialect.php

@@ -238,7 +238,9 @@ class MysqlSchemaDialect extends SchemaDialect
             $name = $type = TableSchema::CONSTRAINT_PRIMARY;
         }
 
-        $columns[] = $row['Column_name'];
+        if (strlen($row['Column_name'] ?? '')) {
+            $columns[] = $row['Column_name'];
+        }
 
         if ($row['Index_type'] === 'FULLTEXT') {
             $type = TableSchema::INDEX_FULLTEXT;

+ 33 - 0
tests/TestCase/Database/Schema/MysqlSchemaTest.php

@@ -24,6 +24,7 @@ use Cake\Database\Schema\MysqlSchemaDialect;
 use Cake\Database\Schema\TableSchema;
 use Cake\Datasource\ConnectionManager;
 use Cake\TestSuite\TestCase;
+use Exception;
 use PDO;
 
 /**
@@ -487,6 +488,38 @@ SQL;
     }
 
     /**
+     * Test describing a table with conditional constraints
+     */
+    public function testDescribeTableConditionalConstraint(): void
+    {
+        $connection = ConnectionManager::get('test');
+        $connection->execute('DROP TABLE IF EXISTS conditional_constraint');
+        $table = <<<SQL
+CREATE TABLE conditional_constraint (
+    id INT AUTO_INCREMENT PRIMARY KEY,
+    config_id INT UNSIGNED NOT NULL,
+    status ENUM ('new', 'processing', 'completed', 'failed') DEFAULT 'new' NOT NULL,
+    CONSTRAINT unique_index UNIQUE (config_id, (
+        (CASE WHEN ((`status` = "new") OR (`status` = "processing")) THEN `status` END)
+    ))
+);
+SQL;
+        try {
+            $connection->execute($table);
+        } catch (Exception $e) {
+            $this->markTestSkipped('Could not create table with conditional constraint');
+        }
+        $schema = new SchemaCollection($connection);
+        $result = $schema->describe('conditional_constraint');
+        $connection->execute('DROP TABLE IF EXISTS conditional_constraint');
+
+        $constraint = $result->getConstraint('unique_index');
+        $this->assertNotEmpty($constraint);
+        $this->assertEquals('unique', $constraint['type']);
+        $this->assertEquals(['config_id'], $constraint['columns']);
+    }
+
+    /**
      * Test describing a table creates options
      */
     public function testDescribeTableOptions(): void