diff --git a/redaxo/src/core/lib/sql/table.php b/redaxo/src/core/lib/sql/table.php index 2503926439..6d2aac2df1 100644 --- a/redaxo/src/core/lib/sql/table.php +++ b/redaxo/src/core/lib/sql/table.php @@ -141,12 +141,19 @@ private function __construct(string $name, int $db = 1) $this->indexesExisting[$indexName] = $indexName; } + // KEY_COLUMN_USAGE spans all schemas and also lists unique/primary keys, so the join must be qualified. + // INFORMATION_SCHEMA gives no ordering guarantee, and the column order of a composite key ends up in the DDL. /** @var list $foreignKeyParts */ $foreignKeyParts = $this->sql->getArray(' SELECT c.CONSTRAINT_NAME, c.REFERENCED_TABLE_NAME, c.UPDATE_RULE, c.DELETE_RULE, k.COLUMN_NAME, k.REFERENCED_COLUMN_NAME FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS c - INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE k ON c.CONSTRAINT_NAME = k.CONSTRAINT_NAME - WHERE c.CONSTRAINT_SCHEMA = DATABASE() AND c.TABLE_NAME = ?', [$name]); + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE k + ON c.CONSTRAINT_SCHEMA = k.CONSTRAINT_SCHEMA + AND c.CONSTRAINT_NAME = k.CONSTRAINT_NAME + AND c.TABLE_NAME = k.TABLE_NAME + AND k.POSITION_IN_UNIQUE_CONSTRAINT IS NOT NULL + WHERE c.CONSTRAINT_SCHEMA = DATABASE() AND c.TABLE_NAME = ? + ORDER BY c.CONSTRAINT_NAME, k.ORDINAL_POSITION', [$name]); $foreignKeys = []; foreach ($foreignKeyParts as $part) { $foreignKeys[$part['CONSTRAINT_NAME']][] = $part; diff --git a/redaxo/src/core/tests/sql/sql_table_test.php b/redaxo/src/core/tests/sql/sql_table_test.php index ea6f441cd2..13dd4b92b4 100644 --- a/redaxo/src/core/tests/sql/sql_table_test.php +++ b/redaxo/src/core/tests/sql/sql_table_test.php @@ -516,6 +516,12 @@ public function testAddForeignKey(): void $table = rex_sql_table::get(self::TABLE); self::assertEquals($fk, $table->getForeignKey('test1_fk_config')); + + // assertEquals compares arrays order-insensitively, so the column order needs its own assertion. + self::assertSame( + ['config_namespace' => 'namespace', 'config_key' => 'key'], + $table->getForeignKey('test1_fk_config')?->getColumns(), + ); } public function testEnsureForeignKey(): void