Browse Source

Merge pull request #13245 from Ni-san/13221_limit_offset_expression

Make \yii\db\QueryTrait::limit and \yii\db\QueryTrait::offset methods works with \yii\db\Expression
tags/2.0.12
Dmitry Naumenko 8 years ago committed by GitHub
parent
commit
db4ef8e1f9
  1. 1
      framework/CHANGELOG.md
  2. 5
      framework/db/QueryBuilder.php
  3. 11
      framework/db/QueryTrait.php
  4. 19
      framework/db/mysql/QueryBuilder.php
  5. 16
      tests/framework/db/QueryTest.php
  6. 17
      tests/framework/db/mysql/QueryTest.php

1
framework/CHANGELOG.md

@ -29,6 +29,7 @@ Yii Framework 2 Change Log
- Enh #13577: Implemented `yii\db\mssql\QueryBuilder::resetSequence()` (boboldehampsink)
- Enh #13582: Added tests for all `yii\db\QueryBuilder::resetSequence` implementations, fixed SQLite implementation (boboldehampsink)
- Enh #13407: Added URL-safe base64 encode/decode methods to `StringHelper` (andrewnester)
- Enh #13221: Make `\yii\db\QueryTrait::limit()` and `\yii\db\QueryTrait::offset()` methods work with `\yii\db\Expression` (Ni-san)
- Enh #13144: Refactored `yii\db\Query::queryScalar()` (Alex-Code)

5
framework/db/QueryBuilder.php

@ -964,7 +964,7 @@ class QueryBuilder extends \yii\base\Object
*/
protected function hasLimit($limit)
{
return ctype_digit((string) $limit);
return ($limit instanceof Expression) || ctype_digit((string) $limit);
}
/**
@ -974,8 +974,7 @@ class QueryBuilder extends \yii\base\Object
*/
protected function hasOffset($offset)
{
$offset = (string) $offset;
return ctype_digit($offset) && $offset !== '0';
return ($offset instanceof Expression) || ctype_digit((string) $offset) && (string) $offset !== '0';
}
/**

11
framework/db/QueryTrait.php

@ -27,12 +27,13 @@ trait QueryTrait
*/
public $where;
/**
* @var int maximum number of records to be returned. If not set or less than 0, it means no limit.
* @var int|Expression maximum number of records to be returned. May be an instance of [[Expression]].
* If not set or less than 0, it means no limit.
*/
public $limit;
/**
* @var int zero-based offset from where the records are to be returned. If not set or
* less than 0, it means starting from the beginning.
* @var int|Expression zero-based offset from where the records are to be returned.
* May be an instance of [[Expression]]. If not set or less than 0, it means starting from the beginning.
*/
public $offset;
/**
@ -375,7 +376,7 @@ trait QueryTrait
/**
* Sets the LIMIT part of the query.
* @param int $limit the limit. Use null or negative value to disable limit.
* @param int|Expression $limit the limit. Use null or negative value to disable limit.
* @return $this the query object itself
*/
public function limit($limit)
@ -386,7 +387,7 @@ trait QueryTrait
/**
* Sets the OFFSET part of the query.
* @param int $offset the offset. Use null or negative value to disable offset.
* @param int|Expression $offset the offset. Use null or negative value to disable offset.
* @return $this the query object itself
*/
public function offset($offset)

19
framework/db/mysql/QueryBuilder.php

@ -185,6 +185,25 @@ class QueryBuilder extends \yii\db\QueryBuilder
/**
* @inheritdoc
*/
protected function hasLimit($limit)
{
// In MySQL limit argument must be nonnegative integer constant
return ctype_digit((string) $limit);
}
/**
* @inheritdoc
*/
protected function hasOffset($offset)
{
// In MySQL offset argument must be nonnegative integer constant
$offset = (string) $offset;
return ctype_digit($offset) && $offset !== '0';
}
/**
* @inheritdoc
*/
public function insert($table, $columns, &$params)
{
$schema = $this->db->getSchema();

16
tests/framework/db/QueryTest.php

@ -235,6 +235,22 @@ abstract class QueryTest extends DatabaseTestCase
$this->assertEquals(5, $query->offset);
}
public function testLimitOffsetWithExpression()
{
$query = (new Query())->from('customer')->select('id')->orderBy('id');
$query
->limit(new Expression('1 + 1'))
->offset(new Expression('1 + 0'));
$result = $query->column($this->getConnection());
$this->assertCount(2, $result);
$this->assertNotContains(1, $result);
$this->assertContains(2, $result);
$this->assertContains(3, $result);
}
public function testUnion()
{
$connection = $this->getConnection();

17
tests/framework/db/mysql/QueryTest.php

@ -25,4 +25,21 @@ class QueryTest extends \yiiunit\framework\db\QueryTest
$this->assertArrayHasKey('name', $row);
$this->assertArrayHasKey('email', $row);
}
public function testLimitOffsetWithExpression()
{
$query = (new Query())->from('customer')->select('id')->orderBy('id');
// In MySQL limit and offset arguments must both be nonnegative integer constant
$query
->limit(new Expression('2'))
->offset(new Expression('1'));
$result = $query->column($this->getConnection());
$this->assertCount(2, $result);
$this->assertNotContains(1, $result);
$this->assertContains(2, $result);
$this->assertContains(3, $result);
}
}

Loading…
Cancel
Save