Skip to content

Commit

Permalink
Merge pull request #102 from moufmouf/multi_key_fix
Browse files Browse the repository at this point in the history
Fixing multiple primary key with foreign key issue
  • Loading branch information
moufmouf committed Sep 12, 2018
2 parents 6fae482 + 90f8310 commit 9f0d39c
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/DbRow.php
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ public function _setPrimaryKeys(array $primaryKeys): void
{
$this->primaryKeys = $primaryKeys;
foreach ($this->primaryKeys as $column => $value) {
// Warning: in case of multi-columns with one being a reference, the $dbRow will contain a reference column (which is not the case elsewhere in the application)
$this->dbRow[$column] = $value;
}
}
Expand Down
7 changes: 6 additions & 1 deletion src/QueryFactory/FindObjectsQueryFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace TheCodingMachine\TDBM\QueryFactory;

use Doctrine\DBAL\Platforms\MySqlPlatform;
use Doctrine\DBAL\Schema\Schema;
use TheCodingMachine\TDBM\OrderByAnalyzer;
use TheCodingMachine\TDBM\TDBMService;
Expand Down Expand Up @@ -35,7 +36,11 @@ protected function compute(): void
return $this->tdbmService->getConnection()->quoteIdentifier($this->mainTable).'.'.$this->tdbmService->getConnection()->quoteIdentifier($pkColumn);
}, $pkColumnNames);

$countSql = 'SELECT COUNT(DISTINCT '.implode(', ', $pkColumnNames).') FROM MAGICJOIN('.$this->mainTable.')';
if (count($pkColumnNames) === 1 || $this->tdbmService->getConnection()->getDatabasePlatform() instanceof MySqlPlatform) {
$countSql = 'SELECT COUNT(DISTINCT '.implode(', ', $pkColumnNames).') FROM MAGICJOIN('.$this->mainTable.')';
} else {
$countSql = 'SELECT COUNT(*) FROM (SELECT DISTINCT '.implode(', ', $pkColumnNames).' FROM MAGICJOIN('.$this->mainTable.')) tmp';
}

if (!empty($this->filterString)) {
$sql .= ' WHERE '.$this->filterString;
Expand Down
6 changes: 3 additions & 3 deletions src/TDBMService.php
Original file line number Diff line number Diff line change
Expand Up @@ -886,10 +886,10 @@ public function getPrimaryKeysForObjectFromDbRow(DbRow $dbRow): array

$primaryKeyColumns = $this->getPrimaryKeyColumns($table);
$values = array();
$dbRowValues = $dbRow->_getDbRow();
foreach ($primaryKeyColumns as $column) {
$value = $dbRow->get($column);
if ($value !== null) {
$values[$column] = $value;
if (isset($dbRowValues[$column])) {
$values[$column] = $dbRowValues[$column];
}
}

Expand Down
7 changes: 7 additions & 0 deletions tests/TDBMAbstractServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,13 @@ private static function initSchema(Connection $connection): void

$toSchema->getTable($connection->quoteIdentifier('ref_no_prim_key'))->addForeignKeyConstraint($connection->quoteIdentifier('ref_no_prim_key'), [$connection->quoteIdentifier('from')], [$connection->quoteIdentifier('to')]);

// A table with multiple primary keys.
$db->table('states')
->column('country_id')->references('country')
->column('code')->string(3)
->column('name')->string(50)->then()
->primaryKey(['country_id', 'code']);

$sqlStmts = $toSchema->getMigrateFromSql($fromSchema, $connection->getDatabasePlatform());

foreach ($sqlStmts as $sqlStmt) {
Expand Down
43 changes: 43 additions & 0 deletions tests/TDBMDaoGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
use TheCodingMachine\TDBM\Test\Dao\Bean\PersonBean;
use TheCodingMachine\TDBM\Test\Dao\Bean\RefNoPrimKeyBean;
use TheCodingMachine\TDBM\Test\Dao\Bean\RoleBean;
use TheCodingMachine\TDBM\Test\Dao\Bean\StateBean;
use TheCodingMachine\TDBM\Test\Dao\Bean\UserBean;
use TheCodingMachine\TDBM\Test\Dao\BoatDao;
use TheCodingMachine\TDBM\Test\Dao\CatDao;
Expand All @@ -57,6 +58,7 @@
use TheCodingMachine\TDBM\Test\Dao\Generated\UserBaseDao;
use TheCodingMachine\TDBM\Test\Dao\RefNoPrimKeyDao;
use TheCodingMachine\TDBM\Test\Dao\RoleDao;
use TheCodingMachine\TDBM\Test\Dao\StateDao;
use TheCodingMachine\TDBM\Test\Dao\UserDao;
use TheCodingMachine\TDBM\Utils\PathFinder\NoPathFoundException;
use TheCodingMachine\TDBM\Utils\TDBMDaoGenerator;
Expand Down Expand Up @@ -1720,9 +1722,50 @@ public function testFilterBag()
$this->assertSame('John Doe', $users[0]->getName());
}

/**
* @depends testDaoGeneration
*/
public function testDecimalIsMappedToString()
{
$reflectionClass = new \ReflectionClass(BoatBaseBean::class);
$this->assertSame('string', (string) $reflectionClass->getMethod('getLength')->getReturnType());
}

/**
* @depends testDaoGeneration
*/
public function testNoGetByIdOnMultiPrimaryKeys()
{
$reflectionClass = new \ReflectionClass(StateDao::class);
$this->assertFalse($reflectionClass->hasMethod('getById'));
}

/**
* @depends testDaoGeneration
*/
public function testInsertMultiPrimaryKeysBean()
{
$countryDao = new CountryDao($this->tdbmService);

$country = $countryDao->getById(1);

$stateDao = new StateDao($this->tdbmService);
$state = new StateBean($country, 'IDF', 'Ile de France');
$stateDao->save($state);

$this->assertSame($state, $stateDao->findAll()[0]);
}

/**
* @depends testInsertMultiPrimaryKeysBean
*/
public function testDeleteMultiPrimaryKeysBean()
{
$stateDao = new StateDao($this->tdbmService);

$state = $stateDao->findAll()[0];
$stateDao->delete($state);
$this->assertCount(0, $stateDao->findAll());

}
}
5 changes: 3 additions & 2 deletions tests/TDBMSchemaAnalyzerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,12 @@ public function testGetIncomingForeignKeys3()
$tdbmSchemaAnalyzer = new TDBMSchemaAnalyzer(self::getConnection(), $cache, $schemaAnalyzer);

$fks = $tdbmSchemaAnalyzer->getIncomingForeignKeys('country');
$this->assertCount(4, $fks);
$tables = [$fks[0]->getLocalTableName(), $fks[1]->getLocalTableName(), $fks[2]->getLocalTableName(), $fks[3]->getLocalTableName()];
$this->assertCount(5, $fks);
$tables = [$fks[0]->getLocalTableName(), $fks[1]->getLocalTableName(), $fks[2]->getLocalTableName(), $fks[3]->getLocalTableName(), $fks[4]->getLocalTableName()];
$this->assertContains('users', $tables);
$this->assertContains('all_nullable', $tables);
$this->assertContains('boats', $tables);
$this->assertContains('states', $tables);
}

public function testGetPivotTableLinkedToTable()
Expand Down

0 comments on commit 9f0d39c

Please sign in to comment.