Skip to content
Permalink
Browse files

Fix Query::count() failing when fields have expressions.

Because we can't easily introspect and remove any bound parameters that
will be unused, we must use a subselect query instead.

Also include additional test coverage for count() with subqueries, and
matching().

Refs #7148
Refs #7272
  • Loading branch information...
markstory committed Aug 22, 2015
1 parent 5ff3f8d commit c61c40878fb589f3d4da5da3b1cb19b1d7ee1d2f
Showing with 65 additions and 3 deletions.
  1. +16 −3 src/ORM/Query.php
  2. +49 −0 tests/TestCase/ORM/QueryTest.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 @@ public function count()
{
$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);
@@ -1458,6 +1458,55 @@ public function testCountWithContain()
$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])
->where(['ArticlesTags.article_id = 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([
'admin' => $query->func()->concat(
['Articles.title' => 'literal', 'test'],
['string']
),
]);
$query->where(['Articles.id' => 1]);
$this->assertCount(1, $query->all());
$this->assertEquals(1, $query->count());
}
/**
* test count with a beforeFind.

0 comments on commit c61c408

Please sign in to comment.
You can’t perform that action at this time.