From de35c62c4eddbf2be8d3a39ee3b5cb895d91a64e Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Sat, 1 Dec 2012 15:52:27 -0500 Subject: [PATCH] RAR WIP --- framework/db/ar/ActiveQuery.php | 41 +++++++++++++++++--- framework/db/ar/ActiveRecord.php | 10 +++-- framework/db/ar/Relation.php | 10 +++-- framework/db/dao/QueryBuilder.php | 78 +++++++++++++++++++++++++++++---------- 4 files changed, 106 insertions(+), 33 deletions(-) diff --git a/framework/db/ar/ActiveQuery.php b/framework/db/ar/ActiveQuery.php index fbec6c9..39195a1 100644 --- a/framework/db/ar/ActiveQuery.php +++ b/framework/db/ar/ActiveQuery.php @@ -107,6 +107,34 @@ class ActiveQuery extends BaseQuery return $class::getDbConnection(); } + public function asArray($value = true) + { + $this->asArray = $value; + return $this; + } + + public function with() + { + $this->with = func_get_args(); + if (isset($this->with[0]) && is_array($this->with[0])) { + // the parameter is given as an array + $this->with = $this->with[0]; + } + return $this; + } + + public function index($column) + { + $this->index = $column; + return $this; + } + + public function scopes($names) + { + $this->scopes = $names; + return $this; + } + /** * Sets the parameters about query caching. * This is a shortcut method to {@link CDbConnection::cache()}. @@ -153,13 +181,14 @@ class ActiveQuery extends BaseQuery $command = $db->createCommand($this->sql, $this->params); $rows = $command->queryAll(); $records = $this->createRecords($rows); - - foreach ($this->with as $name => $config) { - $relation = $model->$name(); - foreach ($config as $p => $v) { - $relation->$p = $v; + if ($records !== array()) { + foreach ($this->with as $name => $config) { + $relation = $model->$name(); + foreach ($config as $p => $v) { + $relation->$p = $v; + } + $relation->findWith($records); } - $relation->findWith($records); } return $records; diff --git a/framework/db/ar/ActiveRecord.php b/framework/db/ar/ActiveRecord.php index 0b3bb81..32861fe 100644 --- a/framework/db/ar/ActiveRecord.php +++ b/framework/db/ar/ActiveRecord.php @@ -68,11 +68,10 @@ abstract class ActiveRecord extends Model public static function model() { $className = get_called_class(); - if (isset(self::$_models[$className])) { - return self::$_models[$className]; - } else { - return self::$_models[$className] = new static; + if (!isset(self::$_models[$className])) { + self::$_models[$className] = new static; } + return self::$_models[$className]; } /** @@ -387,6 +386,7 @@ abstract class ActiveRecord extends Model return new HasOneRelation(array( 'modelClass' => $class, 'parentClass' => get_class($this), + 'parentRecords' => array($this), 'link' => $link, )); } @@ -396,6 +396,7 @@ abstract class ActiveRecord extends Model return new HasManyRelation(array( 'modelClass' => $class, 'parentClass' => get_class($this), + 'parentRecords' => array($this), 'link' => $link, )); } @@ -405,6 +406,7 @@ abstract class ActiveRecord extends Model return new ManyManyRelation(array( 'modelClass' => $class, 'parentClass' => get_class($this), + 'parentRecords' => array($this), 'leftLink' => $leftLink, 'joinTable' => $joinTable, 'rightLink' => $rightLink, diff --git a/framework/db/ar/Relation.php b/framework/db/ar/Relation.php index 50dba56..1362216 100644 --- a/framework/db/ar/Relation.php +++ b/framework/db/ar/Relation.php @@ -5,10 +5,14 @@ namespace yii\db\ar; class Relation extends ActiveQuery { public $parentClass; - public $parentRecords; - public function findWith($records) + public function findWith(&$parentRecords) { - + $this->andWhere(array('in', $links, $keys)); + $records = $this->find(); + foreach ($records as $record) { + // find the matching parent record(s) + // insert into the parent records(s) + } } } diff --git a/framework/db/dao/QueryBuilder.php b/framework/db/dao/QueryBuilder.php index bc5845a..e53dc79 100644 --- a/framework/db/dao/QueryBuilder.php +++ b/framework/db/dao/QueryBuilder.php @@ -469,16 +469,16 @@ class QueryBuilder extends \yii\base\Object public function buildCondition($condition) { static $builders = array( - 'and' => 'buildAndCondition', - 'or' => 'buildAndCondition', - 'between' => 'buildBetweenCondition', - 'not between' => 'buildBetweenCondition', - 'in' => 'buildInCondition', - 'not in' => 'buildInCondition', - 'like' => 'buildLikeCondition', - 'not like' => 'buildLikeCondition', - 'or like' => 'buildLikeCondition', - 'or not like' => 'buildLikeCondition', + 'AND' => 'buildAndCondition', + 'OR' => 'buildAndCondition', + 'BETWEEN' => 'buildBetweenCondition', + 'NOT BETWEEN' => 'buildBetweenCondition', + 'IN' => 'buildInCondition', + 'NOT IN' => 'buildInCondition', + 'LIKE' => 'buildLikeCondition', + 'NOT LIKE' => 'buildLikeCondition', + 'OR LIKE' => 'buildLikeCondition', + 'OR NOT LIKE' => 'buildLikeCondition', ); if (!is_array($condition)) { @@ -487,7 +487,7 @@ class QueryBuilder extends \yii\base\Object return ''; } if (isset($condition[0])) { // operator format: operator, operand 1, operand 2, ... - $operator = $condition[0]; + $operator = strtoupper($condition[0]); if (isset($builders[$operator])) { $method = $builders[$operator]; array_shift($condition); @@ -534,7 +534,6 @@ class QueryBuilder extends \yii\base\Object } } if ($parts !== array()) { - $operator = strtoupper($operator); return '(' . implode(") $operator (", $parts) . ')'; } else { return ''; @@ -570,22 +569,62 @@ class QueryBuilder extends \yii\base\Object $values = array($values); } - if ($values === array()) { + if ($values === array() || $column === array()) { return $operator === 'in' ? '0=1' : ''; } + if (is_array($column)) { + if (count($column) > 1) { + return $this->buildCompositeInCondition($operator, $column, $values); + } else { + $column = reset($column); + foreach ($values as $i => $value) { + if (is_array($value)) { + $values[$i] = isset($value[$column]) ? $value[$column] : null; + } else { + $values[$i] = null; + } + } + } + } + foreach ($values as $i => $value) { - $values[$i] = is_string($value) ? $this->connection->quoteValue($value) : (string)$value; + if ($value === null) { + $values[$i] = 'NULL'; + } else { + $values[$i] = is_string($value) ? $this->connection->quoteValue($value) : (string)$value; + } } if (strpos($column, '(') === false) { $column = $this->quoteColumnName($column); } - $operator = strtoupper($operator); return "$column $operator (" . implode(', ', $values) . ')'; } + protected function buildCompositeInCondition($operator, $columns, $values) + { + foreach ($columns as $i => $column) { + if (strpos($column, '(') === false) { + $columns[$i] = $this->quoteColumnName($column); + } + } + $vss = array(); + foreach ($values as $value) { + $vs = array(); + foreach ($columns as $column) { + if (isset($value[$column])) { + $vs[] = is_string($value[$column]) ? $this->connection->quoteValue($value[$column]) : (string)$value[$column]; + } else { + $vs[] = 'NULL'; + } + } + $vss[] = '(' . implode(', ', $vs) . ')'; + } + return '(' . implode(', ', $columns) . ") $operator (" . implode(', ', $vss) . ')'; + } + private function buildLikeCondition($operator, $operands) { if (!isset($operands[0], $operands[1])) { @@ -599,21 +638,20 @@ class QueryBuilder extends \yii\base\Object } if ($values === array()) { - return $operator === 'like' || $operator === 'or like' ? '0=1' : ''; + return $operator === 'LIKE' || $operator === 'OR LIKE' ? '0=1' : ''; } - if ($operator === 'like' || $operator === 'not like') { + if ($operator === 'LIKE' || $operator === 'NOT LIKE') { $andor = ' AND '; } else { $andor = ' OR '; - $operator = $operator === 'or like' ? 'like' : 'not like'; + $operator = $operator === 'OR LIKE' ? 'LIKE' : 'NOT LIKE'; } if (strpos($column, '(') === false) { $column = $this->quoteColumnName($column); } - $operator = strtoupper($operator); $parts = array(); foreach ($values as $value) { $parts[] = "$column $operator " . $this->connection->quoteValue($value); @@ -730,7 +768,7 @@ class QueryBuilder extends \yii\base\Object $table = $driver->quoteTableName($table); } } - $joins[$i] = strtoupper($join[0]) . ' ' . $table; + $joins[$i] = $join[0] . ' ' . $table; if (isset($join[2])) { $condition = $this->buildCondition($join[2]); if ($condition !== '') {