From 9288f403dab1973d87be3517bb879b5996693914 Mon Sep 17 00:00:00 2001 From: Dorian Savina Date: Mon, 29 May 2017 12:51:52 +0200 Subject: [PATCH 1/2] [fix] findFromSql: allow ORDER BY on columns out of main table - join inherited tables in one SELECT Signed-off-by: Dorian Savina --- .../FindObjectsFromSqlQueryFactory.php | 59 ++++++------------- 1 file changed, 18 insertions(+), 41 deletions(-) diff --git a/src/Mouf/Database/TDBM/QueryFactory/FindObjectsFromSqlQueryFactory.php b/src/Mouf/Database/TDBM/QueryFactory/FindObjectsFromSqlQueryFactory.php index d0f733d..d975afc 100644 --- a/src/Mouf/Database/TDBM/QueryFactory/FindObjectsFromSqlQueryFactory.php +++ b/src/Mouf/Database/TDBM/QueryFactory/FindObjectsFromSqlQueryFactory.php @@ -40,30 +40,9 @@ protected function compute() $allFetchedTables = $this->tdbmService->_getRelatedTablesByInheritance($this->mainTable); - $columnDescList = []; - - $tableGroupName = $this->getTableGroupName($allFetchedTables); - - foreach ($this->schema->getTable($this->mainTable)->getColumns() as $column) { - $columnName = $column->getName(); - $columnDescList[] = [ - 'as' => $columnName, - 'table' => $this->mainTable, - 'column' => $columnName, - 'type' => $column->getType(), - 'tableGroup' => $tableGroupName, - ]; - } - - $sql = 'SELECT DISTINCT '.implode(', ', array_map(function ($columnDesc) { - return $this->tdbmService->getConnection()->quoteIdentifier($this->mainTable).'.'.$this->tdbmService->getConnection()->quoteIdentifier($columnDesc['column']); - }, $columnDescList)).' FROM '.$this->from; + list($columnDescList, $columnsList, $orderString) = $this->getColumnsList($this->mainTable, [], $this->orderBy); - if (count($allFetchedTables) > 1) { - list($columnDescList, $columnsList, $orderString) = $this->getColumnsList($this->mainTable, [], $this->orderBy); - } elseif ($this->orderBy) { - list(, , $orderString) = $this->getColumnsList($this->mainTable, [], $this->orderBy); - } + $sql = 'SELECT DISTINCT '.implode(', ', $columnsList).' FROM '.$this->from; // Let's compute the COUNT. $pkColumnNames = $this->schema->getTable($this->mainTable)->getPrimaryKeyColumns(); @@ -73,20 +52,8 @@ protected function compute() $countSql = 'SELECT COUNT(DISTINCT '.implode(', ', $pkColumnNames).') FROM '.$this->from; - if (!empty($this->filterString)) { - $sql .= ' WHERE '.$this->filterString; - $countSql .= ' WHERE '.$this->filterString; - } - - if (!empty($orderString)) { - $sql .= ' ORDER BY '.$orderString; - } - - if (stripos($countSql, 'GROUP BY') !== false) { - throw new TDBMException('Unsupported use of GROUP BY in SQL request.'); - } - - if ($columnsList !== null) { + // Add joins on inherited tables if necessary + if (count($allFetchedTables) > 1) { $joinSql = ''; $parentFks = $this->getParentRelationshipForeignKeys($this->mainTable); foreach ($parentFks as $fk) { @@ -110,10 +77,20 @@ protected function compute() ); } - $sql = 'SELECT '.implode(', ', $columnsList).' FROM ('.$sql.') AS '.$this->mainTable.' '.$joinSql; - if (!empty($orderString)) { - $sql .= ' ORDER BY '.$orderString; - } + $sql .= $joinSql; + } + + if (!empty($this->filterString)) { + $sql .= ' WHERE '.$this->filterString; + $countSql .= ' WHERE '.$this->filterString; + } + + if (!empty($orderString)) { + $sql .= ' ORDER BY '.$orderString; + } + + if (stripos($countSql, 'GROUP BY') !== false) { + throw new TDBMException('Unsupported use of GROUP BY in SQL request.'); } $this->magicSql = $sql; From 7a9be360bc88cf9be457bc9a53738a154131abb7 Mon Sep 17 00:00:00 2001 From: Dorian Savina Date: Mon, 29 May 2017 12:53:17 +0200 Subject: [PATCH 2/2] [unit test] added test methods TestUserDao::getUsersByCountryOrder and TestUserDao::getUsersFromSqlByCountryOrder Signed-off-by: Dorian Savina --- tests/Mouf/Database/TDBM/Dao/TestUserDao.php | 21 +++++++++++++++++++ .../Database/TDBM/TDBMDaoGeneratorTest.php | 18 ++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/tests/Mouf/Database/TDBM/Dao/TestUserDao.php b/tests/Mouf/Database/TDBM/Dao/TestUserDao.php index cab81d4..52812c3 100644 --- a/tests/Mouf/Database/TDBM/Dao/TestUserDao.php +++ b/tests/Mouf/Database/TDBM/Dao/TestUserDao.php @@ -31,6 +31,27 @@ public function getUsersFromSqlByAlphabeticalOrder() return $this->findFromSql('users', null, [], 'login ASC'); } + /** + * Returns the list of users by alphabetical order. + * + * @return UserBean[] + */ + public function getUsersByCountryOrder() + { + // The third parameter will be used in the "ORDER BY" clause of the SQL query. + return $this->find(null, [], 'country.label ASC', ['country']); + } + /** + * Returns the list of users by alphabetical order. + * + * @return UserBean[] + */ + public function getUsersFromSqlByCountryOrder() + { + // The third parameter will be used in the "ORDER BY" clause of the SQL query. + return $this->findFromSql('users JOIN country ON country.id = users.country_id', null, [], 'country.label ASC'); + } + /** * Returns the list of users whose login starts with $login. * diff --git a/tests/Mouf/Database/TDBM/TDBMDaoGeneratorTest.php b/tests/Mouf/Database/TDBM/TDBMDaoGeneratorTest.php index 5253fa0..f282370 100644 --- a/tests/Mouf/Database/TDBM/TDBMDaoGeneratorTest.php +++ b/tests/Mouf/Database/TDBM/TDBMDaoGeneratorTest.php @@ -601,6 +601,15 @@ public function testFindOrderBy() $this->assertCount(6, $users); $this->assertEquals('bill.shakespeare', $users[0]->getLogin()); $this->assertEquals('jean.dupont', $users[1]->getLogin()); + + $users = $userDao->getUsersByCountryOrder(); + $this->assertCount(6, $users); + $countryName1 = $users[0]->getCountry()->getLabel(); + for ($i = 1; $i < 6; $i++) { + $countryName2 = $users[$i]->getCountry()->getLabel(); + $this->assertLessThanOrEqual(0, strcmp($countryName1, $countryName2)); + $countryName1 = $countryName2; + } } /** @@ -614,6 +623,15 @@ public function testFindFromSqlOrderBy() $this->assertCount(6, $users); $this->assertEquals('bill.shakespeare', $users[0]->getLogin()); $this->assertEquals('jean.dupont', $users[1]->getLogin()); + + $users = $userDao->getUsersFromSqlByCountryOrder(); + $this->assertCount(6, $users); + $countryName1 = $users[0]->getCountry()->getLabel(); + for ($i = 1; $i < 6; $i++) { + $countryName2 = $users[$i]->getCountry()->getLabel(); + $this->assertLessThanOrEqual(0, strcmp($countryName1, $countryName2)); + $countryName1 = $countryName2; + } } /**