allow passing a single Expression object to select() and addSelect()

fixes #9883
This commit is contained in:
Carsten Brandt
2015-10-11 09:58:09 +02:00
parent 8d2af0d2d9
commit decd45201c
3 changed files with 33 additions and 5 deletions

View File

@ -22,6 +22,7 @@ Yii Framework 2 Change Log
- Bug #9754: Fixed `yii\web\Request` error when path info is empty (dynasource) - Bug #9754: Fixed `yii\web\Request` error when path info is empty (dynasource)
- Bug #9791: Fixed endless loop on file creation for non-existing device letters on windows (lukos, cebe) - Bug #9791: Fixed endless loop on file creation for non-existing device letters on windows (lukos, cebe)
- Bug #9874: Fixed outputting exception stacktrace in non-debug mode when `Response::FORMAT_RAW` is used (nainoon) - Bug #9874: Fixed outputting exception stacktrace in non-debug mode when `Response::FORMAT_RAW` is used (nainoon)
- Bug #9883: Passing a single `yii\db\Expression` to `Query::select()` or `::addSelect()` was not handled correctly in all cases (cebe)
- Bug: Fixed generation of canonical URLs for `ViewAction` pages (samdark) - Bug: Fixed generation of canonical URLs for `ViewAction` pages (samdark)
- Enh #7581: Added ability to specify range using anonymous function in `RangeValidator` (RomeroMsk) - Enh #7581: Added ability to specify range using anonymous function in `RangeValidator` (RomeroMsk)
- Enh #8613: `yii\widgets\FragmentCache` will not store empty content anymore which fixes some problems related to `yii\filters\PageCache` (kidol) - Enh #8613: `yii\widgets\FragmentCache` will not store empty content anymore which fixes some problems related to `yii\filters\PageCache` (kidol)

View File

@ -397,11 +397,12 @@ class Query extends Component implements QueryInterface
/** /**
* Sets the SELECT part of the query. * Sets the SELECT part of the query.
* @param string|array $columns the columns to be selected. * @param string|array|Expression $columns the columns to be selected.
* Columns can be specified in either a string (e.g. "id, name") or an array (e.g. ['id', 'name']). * Columns can be specified in either a string (e.g. "id, name") or an array (e.g. ['id', 'name']).
* Columns can be prefixed with table names (e.g. "user.id") and/or contain column aliases (e.g. "user.id AS user_id"). * Columns can be prefixed with table names (e.g. "user.id") and/or contain column aliases (e.g. "user.id AS user_id").
* The method will automatically quote the column names unless a column contains some parenthesis * The method will automatically quote the column names unless a column contains some parenthesis
* (which means the column contains a DB expression). * (which means the column contains a DB expression). A DB expression may also be passed in form of
* an [[Expression]] object.
* *
* Note that if you are selecting an expression like `CONCAT(first_name, ' ', last_name)`, you should * Note that if you are selecting an expression like `CONCAT(first_name, ' ', last_name)`, you should
* use an array to specify the columns. Otherwise, the expression may be incorrectly split into several parts. * use an array to specify the columns. Otherwise, the expression may be incorrectly split into several parts.
@ -418,7 +419,9 @@ class Query extends Component implements QueryInterface
*/ */
public function select($columns, $option = null) public function select($columns, $option = null)
{ {
if (!is_array($columns)) { if ($columns instanceof Expression) {
$columns = [$columns];
} elseif (!is_array($columns)) {
$columns = preg_split('/\s*,\s*/', trim($columns), -1, PREG_SPLIT_NO_EMPTY); $columns = preg_split('/\s*,\s*/', trim($columns), -1, PREG_SPLIT_NO_EMPTY);
} }
$this->select = $columns; $this->select = $columns;
@ -436,13 +439,16 @@ class Query extends Component implements QueryInterface
* $query->addSelect(["*", "CONCAT(first_name, ' ', last_name) AS full_name"])->one(); * $query->addSelect(["*", "CONCAT(first_name, ' ', last_name) AS full_name"])->one();
* ``` * ```
* *
* @param string|array $columns the columns to add to the select. * @param string|array|Expression $columns the columns to add to the select. See [[select()]] for more
* details about the format of this parameter.
* @return $this the query object itself * @return $this the query object itself
* @see select() * @see select()
*/ */
public function addSelect($columns) public function addSelect($columns)
{ {
if (!is_array($columns)) { if ($columns instanceof Expression) {
$columns = [$columns];
} elseif (!is_array($columns)) {
$columns = preg_split('/\s*,\s*/', trim($columns), -1, PREG_SPLIT_NO_EMPTY); $columns = preg_split('/\s*,\s*/', trim($columns), -1, PREG_SPLIT_NO_EMPTY);
} }
if ($this->select === null) { if ($this->select === null) {

View File

@ -505,6 +505,27 @@ class QueryBuilderTest extends DatabaseTestCase
$this->assertEmpty($params); $this->assertEmpty($params);
} }
public function testSelectExpression()
{
$query = (new Query())
->select(new Expression("1 AS ab"))
->from('tablename');
list ($sql, $params) = $this->getQueryBuilder()->build($query);
$expected = $this->replaceQuotes("SELECT 1 AS ab FROM `tablename`");
$this->assertEquals($expected, $sql);
$this->assertEmpty($params);
$query = (new Query())
->select(new Expression("1 AS ab"))
->addSelect(new Expression("2 AS cd"))
->addSelect(['ef' => new Expression("3")])
->from('tablename');
list ($sql, $params) = $this->getQueryBuilder()->build($query);
$expected = $this->replaceQuotes("SELECT 1 AS ab, 2 AS cd, 3 AS `ef` FROM `tablename`");
$this->assertEquals($expected, $sql);
$this->assertEmpty($params);
}
public function testCompositeInCondition() public function testCompositeInCondition()
{ {
$condition = [ $condition = [