From 2fe8c4050bab20428d1616594a001ee36a6cf4f1 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 23 Mar 2014 21:09:08 -0400 Subject: [PATCH 1/2] Insert manual joins *after* generated joins. Re-order query joins to make manually added joins be performed after generated joins. This removes the need to workaround the current join order, or redefine all association joins when you want to add an additional join on a leaf table. Refs #2179 Refs #2346 --- lib/Cake/Model/Datasource/DboSource.php | 7 ++++ .../Model/Datasource/Database/MysqlTest.php | 40 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/lib/Cake/Model/Datasource/DboSource.php b/lib/Cake/Model/Datasource/DboSource.php index 3c4153b02..e8342a162 100644 --- a/lib/Cake/Model/Datasource/DboSource.php +++ b/lib/Cake/Model/Datasource/DboSource.php @@ -1067,6 +1067,9 @@ class DboSource extends DataSource { } } + $originalJoins = $queryData['joins']; + $queryData['joins'] = array(); + // Generate hasOne and belongsTo associations inside $queryData $linkedModels = array(); foreach ($associations as $type) { @@ -1093,6 +1096,10 @@ class DboSource extends DataSource { } } + if (!empty($originalJoins)) { + $queryData['joins'] = array_merge($queryData['joins'], $originalJoins); + } + // Build SQL statement with the primary model, plus hasOne and belongsTo associations $query = $this->buildAssociationQuery($Model, $queryData); diff --git a/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php b/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php index a403b97a6..f1e90d9d8 100644 --- a/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php +++ b/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php @@ -1268,6 +1268,46 @@ class MysqlTest extends CakeTestCase { return (array)$data + $base; } +/** + * test that read() places provided joins after the generated ones. + * + * @return void + */ + public function testReadCustomJoinsAfterGeneratedJoins() { + $db = $this->Dbo->config['database']; + $test = $this->getMock('Mysql', array('connect', '_execute', 'execute')); + $test->config['database'] = $db; + + $this->Model = $this->getMock('TestModel9', array('getDataSource')); + $this->Model->expects($this->any()) + ->method('getDataSource') + ->will($this->returnValue($test)); + + $this->Model->TestModel8 = $this->getMock('TestModel8', array('getDataSource')); + $this->Model->TestModel8->expects($this->any()) + ->method('getDataSource') + ->will($this->returnValue($test)); + + $search = "LEFT JOIN `cake_test_db`.`test_model8` AS `TestModel8` ON " . + "(`TestModel8`.`name` != 'larry' AND `TestModel9`.`test_model8_id` = `TestModel8`.`id`) " . + "LEFT JOIN `cake_test_db`.`users` AS `User` ON (`TestModel9`.`id` = `User`.`test_id`)"; + + $test->expects($this->at(0))->method('execute') + ->with($this->stringContains($search)); + + $test->read($this->Model, array( + 'joins' => array( + array( + 'table' => 'users', + 'alias' => 'User', + 'type' => 'LEFT', + 'conditions' => array('TestModel9.id = User.test_id') + ) + ), + 'recursive' => 1 + )); + } + /** * testGenerateInnerJoinAssociationQuery method * From ff73229ab8b3b586d1b5f0ef7689a2beee54abb1 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 24 Mar 2014 10:04:19 -0400 Subject: [PATCH 2/2] Fix failing tests. Not everyone uses the same database names as me. --- lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php b/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php index f1e90d9d8..fd5182cd4 100644 --- a/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php +++ b/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php @@ -1288,9 +1288,12 @@ class MysqlTest extends CakeTestCase { ->method('getDataSource') ->will($this->returnValue($test)); - $search = "LEFT JOIN `cake_test_db`.`test_model8` AS `TestModel8` ON " . + $model8Table = $test->fullTableName($this->Model->TestModel8); + $usersTable = $test->fullTableName('users'); + + $search = "LEFT JOIN $model8Table AS `TestModel8` ON " . "(`TestModel8`.`name` != 'larry' AND `TestModel9`.`test_model8_id` = `TestModel8`.`id`) " . - "LEFT JOIN `cake_test_db`.`users` AS `User` ON (`TestModel9`.`id` = `User`.`test_id`)"; + "LEFT JOIN $usersTable AS `User` ON (`TestModel9`.`id` = `User`.`test_id`)"; $test->expects($this->at(0))->method('execute') ->with($this->stringContains($search));