Browse Source

make count behave like in SQL

also fixed count behavior according to limit and offset.
fixes #1458
tags/2.0.0-beta
Carsten Brandt 11 years ago
parent
commit
b4612637ec
  1. 8
      extensions/yii/elasticsearch/Query.php
  2. 12
      extensions/yii/redis/ActiveQuery.php
  3. 15
      framework/yii/db/Query.php
  4. 8
      tests/unit/extensions/redis/ActiveRecordTest.php
  5. 19
      tests/unit/framework/ar/ActiveRecordTestTrait.php

8
extensions/yii/elasticsearch/Query.php

@ -283,13 +283,7 @@ class Query extends Component implements QueryInterface
$options = []; $options = [];
$options['search_type'] = 'count'; $options['search_type'] = 'count';
$count = $this->createCommand($db)->search($options)['hits']['total']; return $this->createCommand($db)->search($options)['hits']['total'];
if ($this->limit === null && $this->offset === null) {
return $count;
} elseif ($this->offset !== null) {
$count = $this->offset < $count ? $count - $this->offset : 0;
}
return $this->limit === null ? $count : ($this->limit > $count ? $count : $this->limit);
} }
/** /**

12
extensions/yii/redis/ActiveQuery.php

@ -126,7 +126,7 @@ class ActiveQuery extends \yii\base\Component implements ActiveQueryInterface
*/ */
public function count($q = '*', $db = null) public function count($q = '*', $db = null)
{ {
if ($this->offset === null && $this->limit === null && $this->where === null) { if ($this->where === null) {
/** @var ActiveRecord $modelClass */ /** @var ActiveRecord $modelClass */
$modelClass = $this->modelClass; $modelClass = $this->modelClass;
if ($db === null) { if ($db === null) {
@ -291,11 +291,17 @@ class ActiveQuery extends \yii\base\Component implements ActiveQueryInterface
/** @var ActiveRecord $modelClass */ /** @var ActiveRecord $modelClass */
$modelClass = $this->modelClass; $modelClass = $this->modelClass;
$start = $this->offset === null ? 0 : $this->offset; if ($type == 'Count') {
$start = 0;
$limit = null;
} else {
$start = $this->offset === null ? 0 : $this->offset;
$limit = $this->limit;
}
$i = 0; $i = 0;
$data = []; $data = [];
foreach($pks as $pk) { foreach($pks as $pk) {
if (++$i > $start && ($this->limit === null || $i <= $start + $this->limit)) { if (++$i > $start && ($limit === null || $i <= $start + $limit)) {
$key = $modelClass::keyPrefix() . ':a:' . $modelClass::buildKey($pk); $key = $modelClass::keyPrefix() . ':a:' . $modelClass::buildKey($pk);
$result = $db->executeCommand('HGETALL', [$key]); $result = $db->executeCommand('HGETALL', [$key]);
if (!empty($result)) { if (!empty($result)) {

15
framework/yii/db/Query.php

@ -253,7 +253,11 @@ class Query extends Component implements QueryInterface
*/ */
public function exists($db = null) public function exists($db = null)
{ {
return $this->queryScalar(new Expression('1'), $db) !== false; $select = $this->select;
$this->select = [new Expression('1')];
$command = $this->createCommand($db);
$this->select = $select;
return $command->queryScalar() !== false;
} }
/** /**
@ -266,9 +270,18 @@ class Query extends Component implements QueryInterface
private function queryScalar($selectExpression, $db) private function queryScalar($selectExpression, $db)
{ {
$select = $this->select; $select = $this->select;
$limit = $this->limit;
$offset = $this->offset;
$this->select = [$selectExpression]; $this->select = [$selectExpression];
$this->limit = null;
$this->offset = null;
$command = $this->createCommand($db); $command = $this->createCommand($db);
$this->select = $select; $this->select = $select;
$this->limit = $limit;
$this->offset = $offset;
return $command->queryScalar(); return $command->queryScalar();
} }

8
tests/unit/extensions/redis/ActiveRecordTest.php

@ -205,14 +205,6 @@ class ActiveRecordTest extends RedisTestCase
$this->assertEquals(2, $order->items[1]->id); $this->assertEquals(2, $order->items[1]->id);
} }
public function testFindCount()
{
$this->assertEquals(3, Customer::find()->count());
$this->assertEquals(1, Customer::find()->limit(1)->count());
$this->assertEquals(2, Customer::find()->limit(2)->count());
$this->assertEquals(1, Customer::find()->offset(2)->limit(2)->count());
}
public function testFindColumn() public function testFindColumn()
{ {
$this->assertEquals(['user1', 'user2', 'user3'], Customer::find()->column('name')); $this->assertEquals(['user1', 'user2', 'user3'], Customer::find()->column('name'));

19
tests/unit/framework/ar/ActiveRecordTestTrait.php

@ -287,10 +287,17 @@ trait ActiveRecordTestTrait
{ {
/** @var TestCase|ActiveRecordTestTrait $this */ /** @var TestCase|ActiveRecordTestTrait $this */
$this->assertEquals(3, $this->callCustomerFind()->count()); $this->assertEquals(3, $this->callCustomerFind()->count());
// TODO should limit have effect on count()
// $this->assertEquals(1, $this->callCustomerFind()->limit(1)->count()); $this->assertEquals(1, $this->callCustomerFind()->where(['id' => 1])->count());
// $this->assertEquals(2, $this->callCustomerFind()->limit(2)->count()); $this->assertEquals(2, $this->callCustomerFind()->where(['id' => [1, 2]])->count());
// $this->assertEquals(1, $this->callCustomerFind()->offset(2)->limit(2)->count()); $this->assertEquals(2, $this->callCustomerFind()->where(['id' => [1, 2]])->offset(1)->count());
$this->assertEquals(2, $this->callCustomerFind()->where(['id' => [1, 2]])->offset(2)->count());
// limit should have no effect on count()
$this->assertEquals(3, $this->callCustomerFind()->limit(1)->count());
$this->assertEquals(3, $this->callCustomerFind()->limit(2)->count());
$this->assertEquals(3, $this->callCustomerFind()->limit(10)->count());
$this->assertEquals(3, $this->callCustomerFind()->offset(2)->limit(2)->count());
} }
public function testFindLimit() public function testFindLimit()
@ -371,6 +378,10 @@ trait ActiveRecordTestTrait
$this->assertFalse($this->callCustomerFind()->where(['id' => 5])->exists()); $this->assertFalse($this->callCustomerFind()->where(['id' => 5])->exists());
$this->assertTrue($this->callCustomerFind()->where(['name' => 'user1'])->exists()); $this->assertTrue($this->callCustomerFind()->where(['name' => 'user1'])->exists());
$this->assertFalse($this->callCustomerFind()->where(['name' => 'user5'])->exists()); $this->assertFalse($this->callCustomerFind()->where(['name' => 'user5'])->exists());
$this->assertTrue($this->callCustomerFind()->where(['id' => [2,3]])->exists());
$this->assertTrue($this->callCustomerFind()->where(['id' => [2,3]])->offset(1)->exists());
$this->assertFalse($this->callCustomerFind()->where(['id' => [2,3]])->offset(2)->exists());
} }
public function testFindLazy() public function testFindLazy()

Loading…
Cancel
Save