Browse Source

..

tags/2.0.0-beta
Qiang Xue 13 years ago
parent
commit
71fc3dbe35
  1. 57
      framework/db/ar/ActiveFinder.php
  2. 112
      framework/db/ar/ActiveQuery.php

57
framework/db/ar/ActiveFinder.php

@ -10,6 +10,7 @@
namespace yii\db\ar; namespace yii\db\ar;
use yii\base\Object;
use yii\base\VectorIterator; use yii\base\VectorIterator;
use yii\db\dao\Query; use yii\db\dao\Query;
use yii\db\Exception; use yii\db\Exception;
@ -37,49 +38,19 @@ use yii\db\Exception;
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
class ActiveFinder extends \yii\base\Object implements \IteratorAggregate, \ArrayAccess, \Countable class ActiveFinder extends Object
{ {
/** /**
* @var string the name of the ActiveRecord class. * @var ActiveQuery
*/
public $modelClass;
/**
* @var Query the Query object
*/ */
public $query; public $query;
/**
* @var array list of relations that this query should be performed with
*/
public $with;
/**
* @var string the table alias to be used for query
*/
public $tableAlias;
/**
* @var string the name of the column that the result should be indexed by
*/
public $indexBy;
/**
* @var boolean whether to return query results as arrays
*/
public $asArray;
/**
* @var array list of scopes that should be applied to this query
*/
public $scopes;
/**
* @var array list of query results
*/
public $records;
public $sql;
/** /**
* @param string $modelClass the name of the ActiveRecord class. * @param ActiveQuery $query
*/ */
public function __construct($modelClass) public function __construct($query)
{ {
$this->modelClass = $modelClass; $this->query = $query;
$this->query = new Query;
} }
/** /**
@ -709,7 +680,6 @@ class ActiveFinder extends \yii\base\Object implements \IteratorAggregate, \Arra
{ {
// todo: inner join with one or multiple relations as filters // todo: inner join with one or multiple relations as filters
} }
protected function findRecords() protected function findRecords()
{ {
if (!empty($this->with)) { if (!empty($this->with)) {
@ -762,20 +732,6 @@ class ActiveFinder extends \yii\base\Object implements \IteratorAggregate, \Arra
} }
} }
protected function performCountQuery()
{
if ($this->sql === null) {
$this->initFrom($this->query);
$this->query->select = 'COUNT(*)';
$command = $this->query->createCommand($this->getDbConnection());
$this->sql = $command->getSql();
} else {
$command = $this->getDbConnection()->createCommand($this->sql);
$command->bindValues($this->query->params);
}
return $command->queryScalar();
}
protected function initFrom($query) protected function initFrom($query)
{ {
if ($query->from === null) { if ($query->from === null) {
@ -893,4 +849,5 @@ class ActiveFinder extends \yii\base\Object implements \IteratorAggregate, \Arra
$this->buildTableAlias($child, $count); $this->buildTableAlias($child, $count);
} }
} }
} }

112
framework/db/ar/ActiveQuery.php

@ -12,6 +12,7 @@ namespace yii\db\ar;
use yii\base\VectorIterator; use yii\base\VectorIterator;
use yii\db\dao\BaseQuery; use yii\db\dao\BaseQuery;
use yii\db\dao\Expression;
use yii\db\Exception; use yii\db\Exception;
/** /**
@ -136,12 +137,13 @@ class ActiveQuery extends BaseQuery implements \IteratorAggregate, \ArrayAccess,
public function value() public function value()
{ {
return 0; $result = $this->asArray()->one();
return $result === null ? null : reset($result);
} }
public function exists() public function exists()
{ {
return $this->select(array('1'))->asArray(true)->one() !== null; return $this->select(array(new Expression('1')))->asArray()->one() !== null;
} }
/** /**
@ -344,110 +346,4 @@ class ActiveQuery extends BaseQuery implements \IteratorAggregate, \ArrayAccess,
$query->from = array($tableName); $query->from = array($tableName);
} }
} }
protected function buildRelationalQuery()
{
$joinTree = new JoinElement($this, null, null);
$this->buildJoinTree($joinTree, $this->with);
$this->buildTableAlias($joinTree);
$query = new Query;
foreach ($joinTree->children as $child) {
$child->buildQuery($query);
}
$select = $joinTree->buildSelect($this->query->select);
if (!empty($query->select)) {
$this->query->select = array_merge($select, $query->select);
} else {
$this->query->select = $select;
}
if (!empty($query->where)) {
$this->query->andWhere('(' . implode(') AND (', $query->where) . ')');
}
if (!empty($query->having)) {
$this->query->andHaving('(' . implode(') AND (', $query->having) . ')');
}
if (!empty($query->join)) {
if ($this->query->join === null) {
$this->query->join = $query->join;
} else {
$this->query->join = array_merge($this->query->join, $query->join);
}
}
if (!empty($query->orderBy)) {
$this->query->addOrderBy($query->orderBy);
}
if (!empty($query->groupBy)) {
$this->query->addGroupBy($query->groupBy);
}
if (!empty($query->params)) {
$this->query->addParams($query->params);
}
return $joinTree;
}
/**
* @param JoinElement $parent
* @param array|string $with
* @param array $config
* @return null|JoinElement
* @throws \yii\db\Exception
*/
protected function buildJoinTree($parent, $with, $config = array())
{
if (is_array($with)) {
foreach ($with as $name => $value) {
if (is_string($value)) {
$this->buildJoinTree($parent, $value);
} elseif (is_string($name) && is_array($value)) {
$this->buildJoinTree($parent, $name, $value);
}
}
return null;
}
if (($pos = strrpos($with, '.')) !== false) {
$parent = $this->buildJoinTree($parent, substr($with, 0, $pos));
$with = substr($with, $pos + 1);
}
if (isset($parent->children[$with])) {
$child = $parent->children[$with];
$child->joinOnly = false;
} else {
$modelClass = $parent->relation->modelClass;
$relations = $modelClass::getMetaData()->relations;
if (!isset($relations[$with])) {
throw new Exception("$modelClass has no relation named '$with'.");
}
$relation = clone $relations[$with];
if ($relation->via !== null && isset($relations[$relation->via])) {
$relation->via = null;
$parent2 = $this->buildJoinTree($parent, $relation->via);
if ($parent2->joinOnly === null) {
$parent2->joinOnly = true;
}
$child = new JoinElement($relation, $parent2, $parent);
} else {
$child = new JoinElement($relation, $parent, $parent);
}
}
foreach ($config as $name => $value) {
$child->relation->$name = $value;
}
return $child;
}
protected function buildTableAlias($element, &$count = 0)
{
if ($element->relation->tableAlias === null) {
$element->relation->tableAlias = 't' . ($count++);
}
foreach ($element->children as $child) {
$this->buildTableAlias($child, $count);
}
}
} }

Loading…
Cancel
Save