Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
367cc4e
Selection: support for generics
dg May 10, 2024
0608c21
PascalCase constants
dg May 10, 2024
90bb859
Reflection::getTable() can access unlisted table
dg May 13, 2024
a96116c
renamed IStructure::FIELD_* to Type::*
dg May 10, 2024
ebbb7cd
Driver::getColumns() added NDB type
dg May 13, 2024
da1b2c8
Column::$nativeType changed to NDB $type
dg May 10, 2024
d43272b
Helpers::detectType() supports 'INT UNSIGNED'
dg May 10, 2024
9e87eda
Reflection: removed $schema
dg May 13, 2024
e11f612
opened 4.0-dev
dg Mar 1, 2021
c4e5746
removed old Driver::SUPPORT constants (BC break)
dg May 10, 2024
57e5fa0
deprecated methods trigger notices
dg Jan 19, 2022
ccd13ce
returns always date-time as immutable Nette\Database\DateTime (BC break)
dg May 10, 2024
b23a3b3
Helpers::normalizeRow() & detection moved to new class RowNormalizer
dg May 13, 2024
3e7168b
RowNormalizer: refactoring
dg Dec 14, 2023
229fec5
RowNormalizer: added configuring methods [Closes #257]
dg Jan 19, 2022
98d167f
introduced PdoDriver, descendant of all PDO-based drivers
dg Sep 20, 2021
1297897
database connection moved to PdoDriver::connect()
dg Dec 3, 2023
38b88d5
drivers uses PDO instead of Connection
dg Nov 30, 2023
ccece35
some others methods moved to PdoDriver
dg Dec 13, 2023
c7c81ee
added ResultDriver
dg May 10, 2024
2cf6efa
exceptions are converted in PdoDriver
dg Sep 20, 2021
071d442
added Nette\Database\QueryException
dg Sep 20, 2021
860a033
drivers: getForeignKeys() works with multi-column foreign keys
dg Jan 19, 2022
c328e2c
readme: added jumbo
dg May 16, 2024
9bf1d51
added CredentialProvider
Jun 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
drivers: getForeignKeys() works with multi-column foreign keys
  • Loading branch information
dg committed May 13, 2024
commit 860a0332c5802bc4c67638ea5b10fd4df39bd73a
9 changes: 5 additions & 4 deletions src/Database/Drivers/MsSqlDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,12 @@ public function getForeignKeys(string $table): array
tab1.name = {$this->pdo->quote($table_name)}
X;

foreach ($this->pdo->query($query) as $id => $row) {
$keys[$id]['name'] = $row['fk_name'];
$keys[$id]['local'] = $row['column'];
foreach ($this->pdo->query($query) as $row) {
$id = $row['fk_name'];
$keys[$id]['name'] = $id;
$keys[$id]['local'][] = $row['column'];
$keys[$id]['table'] = $table_schema . '.' . $row['referenced_table'];
$keys[$id]['foreign'] = $row['referenced_column'];
$keys[$id]['foreign'][] = $row['referenced_column'];
}

return array_values($keys);
Expand Down
9 changes: 5 additions & 4 deletions src/Database/Drivers/MySqlDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,12 @@ public function getForeignKeys(string $table): array
WHERE TABLE_SCHEMA = DATABASE()
AND REFERENCED_TABLE_NAME IS NOT NULL
AND TABLE_NAME = {$this->pdo->quote($table)}
X) as $id => $row) {
$keys[$id]['name'] = $row['CONSTRAINT_NAME'];
$keys[$id]['local'] = $row['COLUMN_NAME'];
X) as $row) {
$id = $row['CONSTRAINT_NAME'];
$keys[$id]['name'] = $id;
$keys[$id]['local'][] = $row['COLUMN_NAME'];
$keys[$id]['table'] = $row['REFERENCED_TABLE_NAME'];
$keys[$id]['foreign'] = $row['REFERENCED_COLUMN_NAME'];
$keys[$id]['foreign'][] = $row['REFERENCED_COLUMN_NAME'];
}

return array_values($keys);
Expand Down
13 changes: 11 additions & 2 deletions src/Database/Drivers/PgSqlDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ public function getIndexes(string $table): array
public function getForeignKeys(string $table): array
{
/* Doesn't work with multi-column foreign keys */
return $this->pdo->query(<<<X
$keys = [];
foreach ($this->pdo->query(<<<X
SELECT
co.conname::varchar AS name,
al.attname::varchar AS local,
Expand All @@ -201,7 +202,15 @@ public function getForeignKeys(string $table): array
co.contype = 'f'
AND cl.oid = {$this->pdo->quote($this->delimiteFQN($table))}::regclass
AND nf.nspname = ANY (pg_catalog.current_schemas(FALSE))
X)->fetchAll(\PDO::FETCH_ASSOC);
X) as $row) {
$id = $row['name'];
$keys[$id]['name'] = $id;
$keys[$id]['local'][] = $row['local'];
$keys[$id]['table'] = $row['table'];
$keys[$id]['foreign'][] = $row['foreign'];
}

return array_values($keys);
}


Expand Down
7 changes: 5 additions & 2 deletions src/Database/Drivers/SqliteDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,12 @@ public function getForeignKeys(string $table): array
foreach ($this->pdo->query("PRAGMA foreign_key_list({$this->delimite($table)})") as $row) {
$id = $row['id'];
$keys[$id]['name'] = $id;
$keys[$id]['local'] = $row['from'];
$keys[$id]['local'][] = $row['from'];
$keys[$id]['table'] = $row['table'];
$keys[$id]['foreign'] = $row['to'];
$keys[$id]['foreign'][] = $row['to'];
if ($keys[$id]['foreign'][0] == null) {
$keys[$id]['foreign'] = [];
}
}

return array_values($keys);
Expand Down
6 changes: 5 additions & 1 deletion src/Database/Drivers/SqlsrvDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,11 @@ public function getForeignKeys(string $table): array
WHERE
tl.name = {$this->pdo->quote($table)}
X, \PDO::FETCH_ASSOC) as $row) {
$keys[$row['name']] = $row;
$id = $row['name'];
$keys[$id]['name'] = $id;
$keys[$id]['local'][] = $row['local'];
$keys[$id]['table'] = $row['table'];
$keys[$id]['foreign'][] = $row['column'];
}

return array_values($keys);
Expand Down
12 changes: 3 additions & 9 deletions src/Database/Structure.php
Original file line number Diff line number Diff line change
Expand Up @@ -235,17 +235,11 @@ protected function analyzeForeignKeys(array &$structure, string $table): void

$foreignKeys = $this->connection->getDriver()->getForeignKeys($table);

$fksColumnsCounts = [];
foreach ($foreignKeys as $foreignKey) {
$tmp = &$fksColumnsCounts[$foreignKey['name']];
$tmp++;
}

usort($foreignKeys, fn($a, $b): int => $fksColumnsCounts[$b['name']] <=> $fksColumnsCounts[$a['name']]);
usort($foreignKeys, fn($a, $b): int => count($b['local']) <=> count($a['local']));

foreach ($foreignKeys as $row) {
$structure['belongsTo'][$lowerTable][$row['local']] = $row['table'];
$structure['hasMany'][strtolower($row['table'])][$table][] = $row['local'];
$structure['belongsTo'][$lowerTable][$row['local'][0]] = $row['table'];
$structure['hasMany'][strtolower($row['table'])][$table][] = $row['local'][0];
}

if (isset($structure['belongsTo'][$lowerTable])) {
Expand Down
4 changes: 2 additions & 2 deletions tests/Database/Reflection.postgre.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ test('Tables in schema', function () use ($connection) {
$foreign = $driver->getForeignKeys('one.slave');
Assert::same([
'name' => 'one_slave_fk',
'local' => 'one_id',
'local' => ['one_id'],
'table' => 'one.master',
'foreign' => 'one_id',
'foreign' => ['one_id'],
], (array) $foreign[0]);


Expand Down
8 changes: 4 additions & 4 deletions tests/Database/Structure.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,13 @@ class StructureTestCase extends TestCase
$this->connection->shouldReceive('getDriver')->times(4)->andReturn($this->driver);
$this->driver->shouldReceive('getForeignKeys')->with('authors')->once()->andReturn([]);
$this->driver->shouldReceive('getForeignKeys')->with('Books')->once()->andReturn([
['local' => 'author_id', 'table' => 'authors', 'foreign' => 'id', 'name' => 'authors_fk1'],
['local' => 'translator_id', 'table' => 'authors', 'foreign' => 'id', 'name' => 'authors_fk2'],
['local' => ['author_id'], 'table' => 'authors', 'foreign' => ['id'], 'name' => 'authors_fk1'],
['local' => ['translator_id'], 'table' => 'authors', 'foreign' => ['id'], 'name' => 'authors_fk2'],
]);
$this->driver->shouldReceive('getForeignKeys')->with('tags')->once()->andReturn([]);
$this->driver->shouldReceive('getForeignKeys')->with('books_x_tags')->once()->andReturn([
['local' => 'book_id', 'table' => 'Books', 'foreign' => 'id', 'name' => 'books_x_tags_fk1'],
['local' => 'tag_id', 'table' => 'tags', 'foreign' => 'id', 'name' => 'books_x_tags_fk2'],
['local' => ['book_id'], 'table' => 'Books', 'foreign' => ['id'], 'name' => 'books_x_tags_fk1'],
['local' => ['tag_id'], 'table' => 'tags', 'foreign' => ['id'], 'name' => 'books_x_tags_fk2'],
]);

$this->structure = new StructureMock($this->connection, $this->storage);
Expand Down
4 changes: 2 additions & 2 deletions tests/Database/Structure.schemas.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ class StructureSchemasTestCase extends TestCase
$this->connection->shouldReceive('getDriver')->times(2)->andReturn($this->driver);
$this->driver->shouldReceive('getForeignKeys')->with('authors.authors')->once()->andReturn([]);
$this->driver->shouldReceive('getForeignKeys')->with('books.books')->once()->andReturn([
['local' => 'author_id', 'table' => 'authors.authors', 'foreign' => 'id', 'name' => 'authors_authors_fk1'],
['local' => 'translator_id', 'table' => 'authors.authors', 'foreign' => 'id', 'name' => 'authors_authors_fk2'],
['local' => ['author_id'], 'table' => 'authors.authors', 'foreign' => ['id'], 'name' => 'authors_authors_fk1'],
['local' => ['translator_id'], 'table' => 'authors.authors', 'foreign' => ['id'], 'name' => 'authors_authors_fk2'],
]);

$this->structure = new StructureMock($this->connection, $this->storage);
Expand Down