diff --git a/src/Query/Processor.php b/src/Query/Processor.php index 52cc721..3623f55 100644 --- a/src/Query/Processor.php +++ b/src/Query/Processor.php @@ -123,13 +123,23 @@ public function processIndexes($results) /** * {@inheritDoc} - * @param array{key_name: string}&array $results - * @return array + * @param list> $results + * @return list, foreign_schema: string, foreign_table: string, foreign_columns: list, on_update: string, on_delete: string}> */ public function processForeignKeys($results) { return array_map(function ($result) { - return ((object) $result)->key_name; + $result = (object) $result; + + return [ + 'name' => $result->name, + 'columns' => explode(',', $result->columns), + 'foreign_schema' => $result->foreign_schema, + 'foreign_table' => $result->foreign_table, + 'foreign_columns' => explode(',', $result->foreign_columns), + 'on_update' => strtolower($result->on_update), + 'on_delete' => strtolower($result->on_delete), + ]; }, $results); } } diff --git a/src/Schema/Builder.php b/src/Schema/Builder.php index 292a239..e2e85eb 100644 --- a/src/Schema/Builder.php +++ b/src/Schema/Builder.php @@ -133,7 +133,7 @@ public function dropAllTables() $foreigns = $this->getForeignKeys($tableName); $blueprint = $this->createBlueprint($tableName); foreach ($foreigns as $foreign) { - $blueprint->dropForeign($foreign); + $blueprint->dropForeign($foreign['name']); } array_push($queries, ...$blueprint->toSql($connection, $this->grammar)); } diff --git a/src/Schema/Grammar.php b/src/Schema/Grammar.php index 61de7c4..1822325 100644 --- a/src/Schema/Grammar.php +++ b/src/Schema/Grammar.php @@ -81,10 +81,24 @@ public function compileIndexes($table) */ public function compileForeignKeys($table) { - return sprintf( - 'select constraint_name as `key_name` from information_schema.table_constraints where constraint_type = "FOREIGN KEY" and table_schema = \'\' and table_name = %s', - $this->quoteString($table), - ); + return implode(' ', [ + 'select', + implode(', ', [ + 'kc.constraint_name as `name`', + 'string_agg(kc.column_name) as `columns`', + 'cc.table_schema as `foreign_schema`', + 'cc.table_name as `foreign_table`', + 'string_agg(cc.column_name) as `foreign_columns`', + 'rc.update_rule as `on_update`', + 'rc.delete_rule as `on_delete`', + ]), + 'from information_schema.key_column_usage kc', + 'join information_schema.referential_constraints rc on kc.constraint_name = rc.constraint_name', + 'join information_schema.constraint_column_usage cc on kc.constraint_name = cc.constraint_name', + 'where kc.table_schema = ""', + 'and kc.table_name = ' . $this->quoteString($table), + 'group by kc.constraint_name, cc.table_schema, cc.table_name, rc.update_rule, rc.delete_rule' + ]); } /** diff --git a/tests/Schema/BuilderTestLast.php b/tests/Schema/BuilderTestLast.php index 39328b5..fb6c30f 100644 --- a/tests/Schema/BuilderTestLast.php +++ b/tests/Schema/BuilderTestLast.php @@ -305,6 +305,36 @@ public function test_getIndexListing(): void ], $sb->getIndexListing($table)); } + public function test_getForeignKeys(): void + { + $conn = $this->getDefaultConnection(); + $sb = $conn->getSchemaBuilder(); + $table1 = $this->generateTableName(class_basename(__CLASS__). '_1'); + $sb->create($table1, function (Blueprint $table) { + $table->uuid('id')->primary(); + $table->uuid('something'); + $table->index('something'); + }); + + $table2 = $this->generateTableName(class_basename(__CLASS__). '_2'); + $sb->create($table2, function (Blueprint $table) use ($table1) { + $table->uuid('table2_id')->primary(); + $table->uuid('other_id'); + $table->index('other_id'); + $table->foreign('other_id')->references('id')->on($table1); + }); + + $this->assertSame([[ + 'name' => strtolower($table2) . '_other_id_foreign', + 'columns' => ['other_id'], + 'foreign_schema' => '', + 'foreign_table' => $table1, + 'foreign_columns' => ['id'], + 'on_update' => "no action", + 'on_delete' => "no action", + ]], $sb->getForeignKeys($table2)); + } + public function test_dropAllTables(): void { $conn = $this->getDefaultConnection();