Browse Source

Merge pull request #7283 from cakephp/issue-7148

Fix Query::count() failing when fields have expressions.
José Lorenzo Rodríguez 10 years ago
parent
commit
97ad888810
2 changed files with 67 additions and 3 deletions
  1. 16 3
      src/ORM/Query.php
  2. 51 0
      tests/TestCase/ORM/QueryTest.php

+ 16 - 3
src/ORM/Query.php

@@ -15,6 +15,7 @@
 namespace Cake\ORM;
 
 use ArrayObject;
+use Cake\Database\ExpressionInterface;
 use Cake\Database\Query as DatabaseQuery;
 use Cake\Database\ValueBinder;
 use Cake\Datasource\QueryTrait;
@@ -510,15 +511,27 @@ class Query extends DatabaseQuery implements JsonSerializable
     {
         $query = $this->cleanCopy();
         $counter = $this->_counter;
-
         if ($counter) {
             $query->counter(null);
             return (int)$counter($query);
         }
 
+        $complex = (
+            $query->clause('distinct') ||
+            count($query->clause('group')) ||
+            count($query->clause('union'))
+        );
+        if (!$complex) {
+            // Expression fields could have bound parameters.
+            foreach ($query->clause('select') as $field) {
+                if ($field instanceof ExpressionInterface) {
+                    $complex = true;
+                    break;
+                }
+            }
+        }
+
         $count = ['count' => $query->func()->count('*')];
-        $complex = count($query->clause('group')) || $query->clause('distinct');
-        $complex = $complex || count($query->clause('union'));
 
         if (!$complex) {
             $query->eagerLoader()->autoFields(false);

+ 51 - 0
tests/TestCase/ORM/QueryTest.php

@@ -1458,6 +1458,57 @@ class QueryTest extends TestCase
         $this->assertSame(3, $result);
     }
 
+    /**
+     * Test getting counts from queries with contain.
+     *
+     * @return void
+     */
+    public function testCountWithSubselect()
+    {
+        $table = TableRegistry::get('Articles');
+        $table->belongsTo('Authors');
+        $table->hasMany('ArticlesTags');
+
+        $counter = $table->ArticlesTags->find();
+        $counter->select([
+                'total' => $counter->func()->count('*')
+            ])
+            ->where([
+                'ArticlesTags.tag_id' => 1,
+                'ArticlesTags.article_id' => new IdentifierExpression('Articles.id')
+            ]);
+
+        $result = $table->find('all')
+            ->select([
+                'Articles.title',
+                'tag_count' => $counter
+            ])
+            ->matching('Authors', function ($q) {
+                return $q->where(['Authors.id' => 1]);
+            })
+            ->count();
+        $this->assertSame(2, $result);
+    }
+
+    /**
+     * Test getting counts with complex fields.
+     *
+     * @return void
+     */
+    public function testCountWithExpressions()
+    {
+        $table = TableRegistry::get('Articles');
+        $query = $table->find();
+        $query->select([
+            'title' => $query->func()->concat(
+                ['title' => 'literal', 'test'],
+                ['string']
+            ),
+        ]);
+        $query->where(['id' => 1]);
+        $this->assertCount(1, $query->all());
+        $this->assertEquals(1, $query->count());
+    }
 
     /**
      * test count with a beforeFind.