Skip to content

Commit e6182bd

Browse files
zds-slimingxinleo
andauthored
Added Hyperf\Database\Schema\Schema::getForeignKeys(). (#7059)
Co-authored-by: 李铭昕 <715557344@qq.com>
1 parent f953ae3 commit e6182bd

File tree

4 files changed

+94
-0
lines changed

4 files changed

+94
-0
lines changed

src/Query/Processors/PostgresProcessor.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,38 @@ public function processIndexes(array $results): array
7979
];
8080
}, $results);
8181
}
82+
83+
/**
84+
* Process the results of a foreign keys query.
85+
*/
86+
public function processForeignKeys(array $results): array
87+
{
88+
return array_map(function ($result) {
89+
$result = (object) $result;
90+
91+
return [
92+
'name' => $result->name,
93+
'columns' => explode(',', $result->columns),
94+
'foreign_schema' => $result->foreign_schema,
95+
'foreign_table' => $result->foreign_table,
96+
'foreign_columns' => explode(',', $result->foreign_columns),
97+
'on_update' => match (strtolower($result->on_update)) {
98+
'a' => 'no action',
99+
'r' => 'restrict',
100+
'c' => 'cascade',
101+
'n' => 'set null',
102+
'd' => 'set default',
103+
default => null,
104+
},
105+
'on_delete' => match (strtolower($result->on_delete)) {
106+
'a' => 'no action',
107+
'r' => 'restrict',
108+
'c' => 'cascade',
109+
'n' => 'set null',
110+
'd' => 'set default',
111+
default => null,
112+
},
113+
];
114+
}, $results);
115+
}
82116
}

src/Schema/Grammars/PostgresGrammar.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,32 @@ public function typeMultiLineString(Fluent $column)
509509
return $this->formatPostGisType('multilinestring', $column);
510510
}
511511

512+
/**
513+
* Compile the query to determine the foreign keys.
514+
*/
515+
public function compileForeignKeys(string $schema, string $table): string
516+
{
517+
return sprintf(
518+
'select c.conname as name, '
519+
. "string_agg(la.attname, ',' order by conseq.ord) as columns, "
520+
. 'fn.nspname as foreign_schema, fc.relname as foreign_table, '
521+
. "string_agg(fa.attname, ',' order by conseq.ord) as foreign_columns, "
522+
. 'c.confupdtype as on_update, c.confdeltype as on_delete '
523+
. 'from pg_constraint c '
524+
. 'join pg_class tc on c.conrelid = tc.oid '
525+
. 'join pg_namespace tn on tn.oid = tc.relnamespace '
526+
. 'join pg_class fc on c.confrelid = fc.oid '
527+
. 'join pg_namespace fn on fn.oid = fc.relnamespace '
528+
. 'join lateral unnest(c.conkey) with ordinality as conseq(num, ord) on true '
529+
. 'join pg_attribute la on la.attrelid = c.conrelid and la.attnum = conseq.num '
530+
. 'join pg_attribute fa on fa.attrelid = c.confrelid and fa.attnum = c.confkey[conseq.ord] '
531+
. "where c.contype = 'f' and tc.relname = %s and tn.nspname = %s "
532+
. 'group by c.conname, fn.nspname, fc.relname, c.confupdtype, c.confdeltype',
533+
$this->quoteString($table),
534+
$this->quoteString($schema)
535+
);
536+
}
537+
512538
/**
513539
* Create the column definition for a char type.
514540
*

src/Schema/PostgresBuilder.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,20 @@ public function getColumnListing($table): array
214214
return $this->connection->getPostProcessor()->processColumnListing($results);
215215
}
216216

217+
/**
218+
* Get the foreign keys for a given table.
219+
*/
220+
public function getForeignKeys(string $table): array
221+
{
222+
[$schema, $table] = $this->parseSchemaAndTable($table);
223+
224+
$table = $this->connection->getTablePrefix() . $table;
225+
226+
return $this->connection->getPostProcessor()->processForeignKeys(
227+
$this->connection->selectFromWriteConnection($this->grammar->compileForeignKeys($schema, $table))
228+
);
229+
}
230+
217231
/**
218232
* Get the column type listing for a given table.
219233
*/

tests/Cases/SchemaBuilderTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,4 +217,24 @@ public function index(): void
217217
$this->assertTrue(collect($indexes)->contains(fn ($index) => $index['columns'] === ['id'] && $index['primary']));
218218
$this->assertTrue(collect($indexes)->contains('name', 'articles_body_title_fulltext'));
219219
}
220+
221+
public function testGetForeignKeys()
222+
{
223+
Schema::create('users_copy', function (Blueprint $table) {
224+
$table->id();
225+
});
226+
227+
Schema::create('posts_copy', function (Blueprint $table) {
228+
$table->foreignId('user_id')->nullable()->constrained('users_copy')->cascadeOnUpdate()->nullOnDelete();
229+
});
230+
231+
$foreignKeys = Schema::getForeignKeys('posts_copy');
232+
233+
$this->assertCount(1, $foreignKeys);
234+
$this->assertTrue(collect($foreignKeys)->contains(
235+
fn ($foreign) => $foreign['columns'] === ['user_id']
236+
&& $foreign['foreign_table'] === 'users_copy' && $foreign['foreign_columns'] === ['id']
237+
&& $foreign['on_update'] === 'cascade' && $foreign['on_delete'] === 'set null'
238+
));
239+
}
220240
}

0 commit comments

Comments
 (0)