Browse Source

A symptomatic fix for #2722

When a query is executed twice, for example qhen cloned or when marked
as dirty, it will run the contain process again. This is potentially
dangerous and confusing for some users. The best solution we have for
now is to discourage users from resuing a query that was executed before
until we find a proper way of handling this case.
Jose Lorenzo Rodriguez 12 years ago
parent
commit
851e5910bd

+ 4 - 2
src/Database/Query.php

@@ -659,6 +659,7 @@ class Query implements ExpressionInterface, IteratorAggregate {
 
 		$types += $this->defaultTypes();
 		$joins = [];
+		$i = count($this->_parts['join']);
 		foreach ($tables as $alias => $t) {
 			if (!is_array($t)) {
 				$t = ['table' => $t, 'conditions' => $this->newExpr()];
@@ -666,13 +667,14 @@ class Query implements ExpressionInterface, IteratorAggregate {
 			if (!($t['conditions']) instanceof ExpressionInterface) {
 				$t['conditions'] = $this->newExpr()->add($t['conditions'], $types);
 			}
-			$joins[] = $t + ['type' => 'INNER', 'alias' => is_string($alias) ? $alias : null];
+			$alias = is_string($alias) ? $alias : null;
+			$joins[$alias ?: $i++] = $t + ['type' => 'INNER', 'alias' => $alias];
 		}
 
 		if ($overwrite) {
 			$this->_parts['join'] = $joins;
 		} else {
-			$this->_parts['join'] = array_merge($this->_parts['join'], array_values($joins));
+			$this->_parts['join'] = array_merge($this->_parts['join'], $joins);
 		}
 
 		$this->_dirty();

+ 1 - 1
tests/TestCase/ORM/Association/BelongsToManyTest.php

@@ -703,7 +703,7 @@ class BelongsToManyTest extends TestCase {
 
 		$expected = clone $parent;
 		$joins = $expected->join();
-		unset($joins[1]);
+		unset($joins['bar']);
 		$expected
 			->contain([], true)
 			->select(['Articles__id' => 'Articles.id'], true)

+ 1 - 1
tests/TestCase/ORM/Association/HasManyTest.php

@@ -335,7 +335,7 @@ class HasManyTest extends \Cake\TestSuite\TestCase {
 
 		$expected = clone $parent;
 		$joins = $expected->join();
-		unset($joins[1]);
+		unset($joins['bar']);
 		$expected
 			->contain([], true)
 			->select(['Authors__id' => 'Authors.id'], true)

+ 20 - 1
tests/TestCase/ORM/QueryTest.php

@@ -999,7 +999,7 @@ class QueryTest extends TestCase {
 		$expected = new QueryExpression(['a > b']);
 		$result = $query->clause('join');
 		$this->assertEquals([
-			['alias' => 'table_a', 'type' => 'INNER', 'conditions' => $expected]
+			'table_a' => ['alias' => 'table_a', 'type' => 'INNER', 'conditions' => $expected]
 		], $result);
 
 		$expected = new OrderByExpression(['a' => 'ASC']);
@@ -1818,4 +1818,23 @@ class QueryTest extends TestCase {
 		$this->assertEquals($expected, $query->toArray());
 	}
 
+/**
+ * Tests that getting results from a query having a contained association
+ * will no attach joins twice if count() is called on it afterwards
+ *
+ * @return void
+ */
+	public function testCountWithContainCallingAll() {
+		$table = TableRegistry::get('articles');
+		$table->belongsTo('authors');
+		$query = $table->find()
+			->select(['id', 'title'])
+			->contain('authors')
+			->limit(2);
+
+		$results = $query->all();
+		$this->assertCount(2, $results);
+		$this->assertEquals(3, $query->count());
+	}
+
 }