Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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
  • Loading branch information
markstory committed Mar 24, 2014
1 parent a89b313 commit 2fe8c40
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 0 deletions.
7 changes: 7 additions & 0 deletions lib/Cake/Model/Datasource/DboSource.php
Expand Up @@ -1067,6 +1067,9 @@ public function read(Model $Model, $queryData = array(), $recursive = null) {
}
}

$originalJoins = $queryData['joins'];
$queryData['joins'] = array();

// Generate hasOne and belongsTo associations inside $queryData
$linkedModels = array();
foreach ($associations as $type) {
Expand All @@ -1093,6 +1096,10 @@ public function read(Model $Model, $queryData = array(), $recursive = null) {
}
}

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);

Expand Down
40 changes: 40 additions & 0 deletions lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php
Expand Up @@ -1268,6 +1268,46 @@ protected function _scrubQueryData($data) {
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
*
Expand Down

0 comments on commit 2fe8c40

Please sign in to comment.