Browse Source

finished eager loading.

tags/2.0.0-beta
Qiang Xue 13 years ago
parent
commit
b90f94fe9a
  1. 46
      framework/db/ar/ActiveFinder.php
  2. 7
      framework/db/dao/QueryBuilder.php
  3. 4
      framework/db/dao/TableSchema.php
  4. 3
      tests/unit/framework/db/ar/ActiveRecordTest.php

46
framework/db/ar/ActiveFinder.php

@ -120,6 +120,11 @@ class ActiveFinder extends \yii\base\Object
$q = new Query;
$this->buildJoinQuery($joinTree, $q);
if ($this->_hasMany && ($query->limit > 0 || $query->offset > 0)) {
$this->limitQuery($query, $q);
}
$rows = $q->createCommand($this->connection)->queryAll();
foreach ($rows as $row) {
$joinTree->createRecord($row);
@ -202,7 +207,7 @@ class ActiveFinder extends \yii\base\Object
} elseif (is_array($relation->via)) {
// join via a pivoting table
$r = new ActiveRelation;
$r->name = 'pt' . $this->_joinCount;
$r->name = 'vt' . $this->_joinCount;
$r->hasMany = $relation->hasMany;
foreach ($relation->via as $name => $value) {
@ -288,6 +293,8 @@ class ActiveFinder extends \yii\base\Object
$quotedPrefixes = array(
'@.' => $this->connection->quoteTableName($element->query->tableAlias, true) . '.',
);
$query->limit = $element->query->limit;
$query->offset = $element->query->offset;
}
$qb = $this->connection->getQueryBuilder();
@ -436,4 +443,41 @@ class ActiveFinder extends \yii\base\Object
return $columns;
}
protected function limitQuery($activeQuery, $query)
{
$q = clone $query;
$modelClass = $activeQuery->modelClass;
$table = $modelClass::getMetaData()->table;
$q->select = array();
foreach ($table->primaryKey as $name) {
$q->select[] = $alias = $activeQuery->tableAlias . '.' . $name;
}
$q->distinct = true;
$rows = $q->createCommand($this->connection)->queryAll();
if (count($table->primaryKey) === 1) {
$name = $table->primaryKey[0];
$values = array();
foreach ($rows as $row) {
$values[] = $table->columns[$name]->typecast($row[$name]);
}
$query->andWhere(array('in', $activeQuery->tableAlias . '.' . $name, $values));
} else {
$ors = array('or');
$prefix = $this->connection->quoteTableName($activeQuery->tableAlias, true) . '.';
foreach ($rows as $row) {
$ands = array();
foreach ($table->primaryKey as $name) {
$value = $table->columns[$name]->typecast($row[$name]);
if (is_string($value)) {
$value = $this->connection->quoteValue($value);
}
$ands[] = $prefix . $this->connection->quoteColumnName($name, true) . '=' . $value;
}
$ors[] = implode(' AND ', $ands);
}
$query->andWhere($ors);
}
$query->limit = $query->offset = null;
}
}

7
framework/db/dao/QueryBuilder.php

@ -533,6 +533,7 @@ class QueryBuilder extends \yii\base\Object
}
}
if ($parts !== array()) {
$operator = strtoupper($operator);
return '(' . implode(") $operator (", $parts) . ')';
} else {
return '';
@ -580,6 +581,7 @@ class QueryBuilder extends \yii\base\Object
$column = $this->quoteColumnName($column);
}
$operator = strtoupper($operator);
return "$column $operator (" . implode(', ', $values) . ')';
}
@ -600,9 +602,9 @@ class QueryBuilder extends \yii\base\Object
}
if ($operator === 'like' || $operator === 'not like') {
$andor = ' and ';
$andor = ' AND ';
} else {
$andor = ' or ';
$andor = ' OR ';
$operator = $operator === 'or like' ? 'like' : 'not like';
}
@ -610,6 +612,7 @@ class QueryBuilder extends \yii\base\Object
$column = $this->quoteColumnName($column);
}
$operator = strtoupper($operator);
$parts = array();
foreach ($values as $value) {
$parts[] = "$column $operator " . $this->connection->quoteValue($value);

4
framework/db/dao/TableSchema.php

@ -41,7 +41,7 @@ class TableSchema extends \yii\base\Object
*/
public $quotedName;
/**
* @var array primary keys of this table.
* @var string[] primary keys of this table.
*/
public $primaryKey = array();
/**
@ -61,7 +61,7 @@ class TableSchema extends \yii\base\Object
*/
public $foreignKeys = array();
/**
* @var array column metadata of this table. Each array element is a [[ColumnSchema]] object, indexed by column names.
* @var ColumnSchema[] column metadata of this table. Each array element is a [[ColumnSchema]] object, indexed by column names.
*/
public $columns = array();

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

@ -250,6 +250,9 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
$this->assertEquals(1, $orders[0]->books[0]->id);
$this->assertEquals(2, $orders[0]->books[1]->id);
$this->assertEquals(2, $orders[1]->books[0]->id);
$orders = Order::find()->with('items')->order('@.id')->limit(2)->all();
$this->assertEquals(2, count($orders));
}
/*

Loading…
Cancel
Save