Browse Source

renamed groupBy and orderBy to be group and order.

tags/2.0.0-beta
Qiang Xue 13 years ago
parent
commit
769a114d39
  1. 48
      framework/db/ar/ActiveFinder.php
  2. 8
      framework/db/ar/ActiveRecord.php
  3. 9
      framework/db/ar/ActiveRelation.php
  4. 12
      framework/db/ar/JoinElement.php
  5. 54
      framework/db/dao/BaseQuery.php
  6. 8
      framework/db/dao/QueryBuilder.php
  7. 2
      tests/unit/data/ar/Customer.php
  8. 14
      tests/unit/framework/db/ar/ActiveRecordTest.php
  9. 13
      tests/unit/framework/db/dao/CommandTest.php
  10. 30
      tests/unit/framework/db/dao/QueryTest.php

48
framework/db/ar/ActiveFinder.php

@ -103,6 +103,7 @@ class ActiveFinder extends \yii\base\Object
private $_joinCount; private $_joinCount;
private $_tableAliases; private $_tableAliases;
private $_hasMany;
/** /**
* @param ActiveQuery $query * @param ActiveQuery $query
@ -112,6 +113,7 @@ class ActiveFinder extends \yii\base\Object
{ {
$this->_joinCount = 0; $this->_joinCount = 0;
$this->_tableAliases = array(); $this->_tableAliases = array();
$this->_hasMany = false;
$joinTree = new JoinElement($this->_joinCount++, $query, null, null); $joinTree = new JoinElement($this->_joinCount++, $query, null, null);
$this->buildJoinTree($joinTree, $query->with); $this->buildJoinTree($joinTree, $query->with);
$this->initJoinTree($joinTree); $this->initJoinTree($joinTree);
@ -123,7 +125,15 @@ class ActiveFinder extends \yii\base\Object
$joinTree->createRecord($row); $joinTree->createRecord($row);
} }
return $query->indexBy !== null ? $joinTree->records : array_values($joinTree->records); if ($query->indexBy !== null) {
$records = array();
foreach ($joinTree->records as $record) {
$records[$record[$query->indexBy]] = $record;
}
return $records;
} else {
return array_values($joinTree->records);
}
} }
protected function applyScopes($query) protected function applyScopes($query)
@ -182,7 +192,8 @@ class ActiveFinder extends \yii\base\Object
throw new Exception("$modelClass has no relation named '$with'."); throw new Exception("$modelClass has no relation named '$with'.");
} }
$relation = clone $relations[$with]; $relation = clone $relations[$with];
if ($relation->via !== null && isset($relations[$relation->via])) { if (is_string($relation->via) && isset($relations[$relation->via])) {
// join via an existing relation
$parent2 = $this->buildJoinTree($parent, $relation->via); $parent2 = $this->buildJoinTree($parent, $relation->via);
$relation->via = null; $relation->via = null;
if ($parent2->joinOnly === null) { if ($parent2->joinOnly === null) {
@ -213,6 +224,14 @@ class ActiveFinder extends \yii\base\Object
} else { } else {
$alias = 't'; $alias = 't';
} }
if ($element->query instanceof ActiveRelation) {
if ($element->query->hasMany) {
$this->_hasMany = true;
}
if ($element->parent->query->asArray !== null && $element->query->asArray === null) {
$element->query->asArray = $element->parent->query->asArray;
}
}
$count = 0; $count = 0;
while (isset($this->_tableAliases[$alias])) { while (isset($this->_tableAliases[$alias])) {
$alias = 't' . $count++; $alias = 't' . $count++;
@ -279,8 +298,9 @@ class ActiveFinder extends \yii\base\Object
} }
if ($element->query instanceof ActiveRelation) { if ($element->query instanceof ActiveRelation) {
if ($element->query->via !== null) { if (is_array($element->query->via)) {
$query->join[] = strtr($element->query->via, $quotedPrefixes); // todo: join via a pivot table
// $query->join[] = strtr($element->query->via, $quotedPrefixes);
} }
if ($element->query->joinType === null) { if ($element->query->joinType === null) {
@ -311,21 +331,21 @@ class ActiveFinder extends \yii\base\Object
} }
} }
if ($element->query->orderBy !== null) { if ($element->query->order !== null) {
if (!is_array($element->query->orderBy)) { if (!is_array($element->query->order)) {
$element->query->orderBy = preg_split('/\s*,\s*/', trim($element->query->orderBy), -1, PREG_SPLIT_NO_EMPTY); $element->query->order = preg_split('/\s*,\s*/', trim($element->query->order), -1, PREG_SPLIT_NO_EMPTY);
} }
foreach ($element->query->orderBy as $orderBy) { foreach ($element->query->order as $order) {
$query->orderBy[] = strtr($orderBy, $prefixes); $query->order[] = strtr($order, $prefixes);
} }
} }
if ($element->query->groupBy !== null) { if ($element->query->group !== null) {
if (!is_array($element->query->groupBy)) { if (!is_array($element->query->group)) {
$element->query->groupBy = preg_split('/\s*,\s*/', trim($element->query->groupBy), -1, PREG_SPLIT_NO_EMPTY); $element->query->group = preg_split('/\s*,\s*/', trim($element->query->group), -1, PREG_SPLIT_NO_EMPTY);
} }
foreach ($element->query->groupBy as $groupBy) { foreach ($element->query->group as $group) {
$query->groupBy[] = strtr($groupBy, $prefixes); $query->group[] = strtr($group, $prefixes);
} }
} }

8
framework/db/ar/ActiveRecord.php

@ -80,12 +80,12 @@ abstract class ActiveRecord extends Model
* // find all active customers and order them by their age: * // find all active customers and order them by their age:
* $customers = Customer::find() * $customers = Customer::find()
* ->where(array('status' => 1)) * ->where(array('status' => 1))
* ->orderBy('age') * ->order('age')
* ->all(); * ->all();
* // or alternatively: * // or alternatively:
* $customers = Customer::find(array( * $customers = Customer::find(array(
* 'where' => array('status' => 1), * 'where' => array('status' => 1),
* 'orderBy' => 'age', * 'order' => 'age',
* ))->all(); * ))->all();
* ~~~ * ~~~
* *
@ -114,7 +114,7 @@ abstract class ActiveRecord extends Model
/** /**
* Creates an [[ActiveQuery]] instance and query by a given SQL statement. * Creates an [[ActiveQuery]] instance and query by a given SQL statement.
* Note that because the SQL statement is already specified, calling further * Note that because the SQL statement is already specified, calling further
* query methods (such as `where()`, `orderBy()`) on [[ActiveQuery]] will have no effect. * query methods (such as `where()`, `order()`) on [[ActiveQuery]] will have no effect.
* Methods such as `with()`, `asArray()` can still be called though. * Methods such as `with()`, `asArray()` can still be called though.
* @param string $sql the SQL statement to be executed * @param string $sql the SQL statement to be executed
* @param array $params parameters to be bound to the SQL statement during execution. * @param array $params parameters to be bound to the SQL statement during execution.
@ -267,7 +267,7 @@ abstract class ActiveRecord extends Model
* 'manager:Manager' => '@.id = ?.manager_id', * 'manager:Manager' => '@.id = ?.manager_id',
* 'assignments:Assignment[]' => array( * 'assignments:Assignment[]' => array(
* 'on' => '@.owner_id = ?.id AND @.status = 1', * 'on' => '@.owner_id = ?.id AND @.status = 1',
* 'orderBy' => '@.create_time DESC', * 'order' => '@.create_time DESC',
* ), * ),
* 'projects:Project[]' => array( * 'projects:Project[]' => array(
* 'via' => 'assignments', * 'via' => 'assignments',

9
framework/db/ar/ActiveRelation.php

@ -23,6 +23,13 @@ class ActiveRelation extends BaseActiveQuery
*/ */
public $name; public $name;
/** /**
* @var array the columns of the primary and foreign tables that establish the relation.
* The array keys must be columns of the table for this relation, and the array values
* must be the corresponding columns from the primary table. Do not prefix or quote the column names.
* They will be done automatically by Yii.
*/
public $link;
/**
* @var boolean whether this relation is a one-many relation * @var boolean whether this relation is a one-many relation
*/ */
public $hasMany; public $hasMany;
@ -36,7 +43,7 @@ class ActiveRelation extends BaseActiveQuery
*/ */
public $on; public $on;
/** /**
* @var string * @var string|array
*/ */
public $via; public $via;
} }

12
framework/db/ar/JoinElement.php

@ -71,7 +71,6 @@ class JoinElement extends \yii\base\Object
*/ */
public function createRecord($row) public function createRecord($row)
{ {
if ($this->query->indexBy === null) {
$pk = array(); $pk = array();
foreach ($this->pkAlias as $alias) { foreach ($this->pkAlias as $alias) {
if (isset($row[$alias])) { if (isset($row[$alias])) {
@ -81,16 +80,9 @@ class JoinElement extends \yii\base\Object
} }
} }
$pk = count($pk) === 1 ? $pk[0] : serialize($pk); $pk = count($pk) === 1 ? $pk[0] : serialize($pk);
} else {
$pk = array_search($this->query->indexBy, $this->columnAliases);
if ($pk !== false) {
$pk = $row[$pk];
} else {
throw new Exception("Invalid indexBy: {$this->query->modelClass} has no attribute named '{$this->query->indexBy}'.");
}
}
// create record // create record
// todo: asArray
if (isset($this->records[$pk])) { if (isset($this->records[$pk])) {
$record = $this->records[$pk]; $record = $this->records[$pk];
} else { } else {
@ -120,7 +112,7 @@ class JoinElement extends \yii\base\Object
} }
if ($child->query->hasMany) { if ($child->query->hasMany) {
if ($child->query->indexBy !== null) { if ($child->query->indexBy !== null) {
$hash = $childRecord->{$child->query->indexBy}; $hash = $childRecord[$child->query->indexBy];
} else { } else {
$hash = serialize($childRecord->getPrimaryKey()); $hash = serialize($childRecord->getPrimaryKey());
} }

54
framework/db/dao/BaseQuery.php

@ -60,12 +60,12 @@ class BaseQuery extends \yii\base\Object
* @var string|array how to sort the query results. This refers to the ORDER BY clause in a SQL statement. * @var string|array how to sort the query results. This refers to the ORDER BY clause in a SQL statement.
* It can be either a string (e.g. `'id ASC, name DESC'`) or an array (e.g. `array('id ASC', 'name DESC')`). * It can be either a string (e.g. `'id ASC, name DESC'`) or an array (e.g. `array('id ASC', 'name DESC')`).
*/ */
public $orderBy; public $order;
/** /**
* @var string|array how to group the query results. This refers to the GROUP BY clause in a SQL statement. * @var string|array how to group the query results. This refers to the GROUP BY clause in a SQL statement.
* It can be either a string (e.g. `'company, department'`) or an array (e.g. `array('company', 'department')`). * It can be either a string (e.g. `'company, department'`) or an array (e.g. `array('company', 'department')`).
*/ */
public $groupBy; public $group;
/** /**
* @var string|array how to join with other tables. This refers to the JOIN clause in a SQL statement. * @var string|array how to join with other tables. This refers to the JOIN clause in a SQL statement.
* It can either a string (e.g. `'LEFT JOIN tbl_user ON tbl_user.id=author_id'`) or an array (e.g. * It can either a string (e.g. `'LEFT JOIN tbl_user ON tbl_user.id=author_id'`) or an array (e.g.
@ -329,11 +329,11 @@ class BaseQuery extends \yii\base\Object
* 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).
* @return BaseQuery the query object itself * @return BaseQuery the query object itself
* @see addGroupBy() * @see addGroup()
*/ */
public function groupBy($columns) public function group($columns)
{ {
$this->groupBy = $columns; $this->group = $columns;
return $this; return $this;
} }
@ -344,20 +344,20 @@ class BaseQuery extends \yii\base\Object
* 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).
* @return BaseQuery the query object itself * @return BaseQuery the query object itself
* @see groupBy() * @see group()
*/ */
public function addGroupBy($columns) public function addGroup($columns)
{ {
if (empty($this->groupBy)) { if (empty($this->group)) {
$this->groupBy = $columns; $this->group = $columns;
} else { } else {
if (!is_array($this->groupBy)) { if (!is_array($this->group)) {
$this->groupBy = preg_split('/\s*,\s*/', trim($this->groupBy), -1, PREG_SPLIT_NO_EMPTY); $this->group = preg_split('/\s*,\s*/', trim($this->group), -1, PREG_SPLIT_NO_EMPTY);
} }
if (!is_array($columns)) { if (!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->groupBy = array_merge($this->groupBy, $columns); $this->group = array_merge($this->group, $columns);
} }
return $this; return $this;
} }
@ -427,11 +427,11 @@ class BaseQuery extends \yii\base\Object
* 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).
* @return BaseQuery the query object itself * @return BaseQuery the query object itself
* @see addOrderBy() * @see addOrder()
*/ */
public function orderBy($columns) public function order($columns)
{ {
$this->orderBy = $columns; $this->order = $columns;
return $this; return $this;
} }
@ -442,20 +442,20 @@ class BaseQuery extends \yii\base\Object
* 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).
* @return BaseQuery the query object itself * @return BaseQuery the query object itself
* @see orderBy() * @see order()
*/ */
public function addOrderBy($columns) public function addOrder($columns)
{ {
if (empty($this->orderBy)) { if (empty($this->order)) {
$this->orderBy = $columns; $this->order = $columns;
} else { } else {
if (!is_array($this->orderBy)) { if (!is_array($this->order)) {
$this->orderBy = preg_split('/\s*,\s*/', trim($this->orderBy), -1, PREG_SPLIT_NO_EMPTY); $this->order = preg_split('/\s*,\s*/', trim($this->order), -1, PREG_SPLIT_NO_EMPTY);
} }
if (!is_array($columns)) { if (!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->orderBy = array_merge($this->orderBy, $columns); $this->order = array_merge($this->order, $columns);
} }
return $this; return $this;
} }
@ -541,7 +541,7 @@ class BaseQuery extends \yii\base\Object
* takes precedence over this query. * takes precedence over this query.
* - [[where]], [[having]]: the new query's corresponding property value * - [[where]], [[having]]: the new query's corresponding property value
* will be 'AND' together with the existing one. * will be 'AND' together with the existing one.
* - [[params]], [[orderBy]], [[groupBy]], [[join]], [[union]]: the new query's * - [[params]], [[order]], [[group]], [[join]], [[union]]: the new query's
* corresponding property value will be appended to the existing one. * corresponding property value will be appended to the existing one.
* *
* In general, the merging makes the resulting query more restrictive and specific. * In general, the merging makes the resulting query more restrictive and specific.
@ -592,12 +592,12 @@ class BaseQuery extends \yii\base\Object
$this->addParams($query->params); $this->addParams($query->params);
} }
if ($query->orderBy !== null) { if ($query->order !== null) {
$this->addOrderBy($query->orderBy); $this->addOrder($query->order);
} }
if ($query->groupBy !== null) { if ($query->group !== null) {
$this->addGroupBy($query->groupBy); $this->addGroup($query->group);
} }
if ($query->join !== null) { if ($query->join !== null) {

8
framework/db/dao/QueryBuilder.php

@ -68,10 +68,10 @@ class QueryBuilder extends \yii\base\Object
$this->buildFrom($query->from), $this->buildFrom($query->from),
$this->buildJoin($query->join), $this->buildJoin($query->join),
$this->buildWhere($query->where), $this->buildWhere($query->where),
$this->buildGroupBy($query->groupBy), $this->buildGroup($query->group),
$this->buildHaving($query->having), $this->buildHaving($query->having),
$this->buildUnion($query->union), $this->buildUnion($query->union),
$this->buildOrderBy($query->orderBy), $this->buildOrder($query->order),
$this->buildLimit($query->limit, $query->offset), $this->buildLimit($query->limit, $query->offset),
); );
return implode($this->separator, array_filter($clauses)); return implode($this->separator, array_filter($clauses));
@ -756,7 +756,7 @@ class QueryBuilder extends \yii\base\Object
* @param string|array $columns * @param string|array $columns
* @return string the GROUP BY clause * @return string the GROUP BY clause
*/ */
public function buildGroupBy($columns) public function buildGroup($columns)
{ {
if (empty($columns)) { if (empty($columns)) {
return ''; return '';
@ -779,7 +779,7 @@ class QueryBuilder extends \yii\base\Object
* @param string|array $columns * @param string|array $columns
* @return string the ORDER BY clause built from [[query]]. * @return string the ORDER BY clause built from [[query]].
*/ */
public function buildOrderBy($columns) public function buildOrder($columns)
{ {
if (empty($columns)) { if (empty($columns)) {
return ''; return '';

2
tests/unit/data/ar/Customer.php

@ -25,7 +25,7 @@ class Customer extends ActiveRecord
{ {
return array( return array(
'active' => function($q) { 'active' => function($q) {
return $q->andWhere('@.status = 1'); return $q->andWhere('@.status = ' . self::STATUS_ACTIVE);
}, },
); );
} }

14
tests/unit/framework/db/ar/ActiveRecordTest.php

@ -200,7 +200,7 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
$this->assertTrue($customer instanceof Customer); $this->assertTrue($customer instanceof Customer);
$this->assertEquals('user3', $customer->name); $this->assertEquals('user3', $customer->name);
$customer = Customer::find()->select('id')->orderBy('id DESC')->one(); $customer = Customer::find()->select('id')->order('id DESC')->one();
$this->assertTrue($customer instanceof Customer); $this->assertTrue($customer instanceof Customer);
$this->assertEquals(3, $customer->id); $this->assertEquals(3, $customer->id);
$this->assertEquals(null, $customer->name); $this->assertEquals(null, $customer->name);
@ -214,23 +214,27 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
$this->assertEquals(2, count($customers)); $this->assertEquals(2, count($customers));
// asArray // asArray
$customers = Customer::find()->orderBy('id')->asArray()->all(); $customers = Customer::find()->order('id')->asArray()->all();
$this->assertEquals('user2', $customers[1]['name']); $this->assertEquals('user2', $customers[1]['name']);
// indexBy // indexBy
$customers = Customer::find()->orderBy('id')->indexBy('name')->all(); $customers = Customer::find()->order('id')->indexBy('name')->all();
$this->assertEquals(2, $customers['user2']['id']); $this->assertEquals(2, $customers['user2']['id']);
} }
public function testEagerLoading() public function testEagerLoading()
{ {
$customers = Customer::find()->with('orders')->orderBy('@.id')->all(); $customers = Customer::find()->with('orders')->order('@.id')->all();
$this->assertEquals(3, count($customers)); $this->assertEquals(3, count($customers));
$this->assertEquals(1, count($customers[0]->orders)); $this->assertEquals(1, count($customers[0]->orders));
$this->assertEquals(2, count($customers[1]->orders)); $this->assertEquals(2, count($customers[1]->orders));
$this->assertEquals(0, count($customers[2]->orders)); $this->assertEquals(0, count($customers[2]->orders));
$customers = Customer::find()->with('orders.customer')->orderBy('@.id')->all(); $customers = Customer::find()->with('orders.customer')->order('@.id')->all();
$this->assertEquals(3, count($customers));
$this->assertEquals(1, $customers[0]->orders[0]->customer->id);
$this->assertEquals(2, $customers[1]->orders[0]->customer->id);
$this->assertEquals(2, $customers[1]->orders[1]->customer->id);
} }
/* /*

13
tests/unit/framework/db/dao/CommandTest.php

@ -21,19 +21,6 @@ class CommandTest extends \yiiunit\MysqlTestCase
$sql = 'SELECT * FROM tbl_customer'; $sql = 'SELECT * FROM tbl_customer';
$command = $db->createCommand($sql); $command = $db->createCommand($sql);
$this->assertEquals($sql, $command->sql); $this->assertEquals($sql, $command->sql);
// Query object
$query = new Query;
$query->select('id')->from('tbl_customer');
$command = $db->createCommand($query);
$this->assertEquals("SELECT `id` FROM `tbl_customer`", $command->sql);
// array
$command = $db->createCommand(array(
'select' => 'name',
'from' => 'tbl_customer',
));
$this->assertEquals("SELECT `name` FROM `tbl_customer`", $command->sql);
} }
function testGetSetSql() function testGetSetSql()

30
tests/unit/framework/db/dao/QueryTest.php

@ -13,7 +13,7 @@ class QueryTest extends \yiiunit\MysqlTestCase
{ {
// default // default
$query = new Query; $query = new Query;
$query->select(); $query->select('*');
$this->assertEquals('*', $query->select); $this->assertEquals('*', $query->select);
$this->assertNull($query->distinct); $this->assertNull($query->distinct);
$this->assertEquals(null, $query->selectOption); $this->assertEquals(null, $query->selectOption);
@ -53,17 +53,17 @@ class QueryTest extends \yiiunit\MysqlTestCase
} }
function testGroupBy() function testGroup()
{ {
$query = new Query; $query = new Query;
$query->groupBy('team'); $query->group('team');
$this->assertEquals('team', $query->groupBy); $this->assertEquals('team', $query->group);
$query->addGroupBy('company'); $query->addGroup('company');
$this->assertEquals(array('team', 'company'), $query->groupBy); $this->assertEquals(array('team', 'company'), $query->group);
$query->addGroupBy('age'); $query->addGroup('age');
$this->assertEquals(array('team', 'company', 'age'), $query->groupBy); $this->assertEquals(array('team', 'company', 'age'), $query->group);
} }
function testHaving() function testHaving()
@ -82,17 +82,17 @@ class QueryTest extends \yiiunit\MysqlTestCase
$this->assertEquals(array(':id' => 1, ':name' => 'something', ':age' => '30'), $query->params); $this->assertEquals(array(':id' => 1, ':name' => 'something', ':age' => '30'), $query->params);
} }
function testOrderBy() function testOrder()
{ {
$query = new Query; $query = new Query;
$query->orderBy('team'); $query->order('team');
$this->assertEquals('team', $query->orderBy); $this->assertEquals('team', $query->order);
$query->addOrderBy('company'); $query->addOrder('company');
$this->assertEquals(array('team', 'company'), $query->orderBy); $this->assertEquals(array('team', 'company'), $query->order);
$query->addOrderBy('age'); $query->addOrder('age');
$this->assertEquals(array('team', 'company', 'age'), $query->orderBy); $this->assertEquals(array('team', 'company', 'age'), $query->order);
} }
function testLimitOffset() function testLimitOffset()

Loading…
Cancel
Save