ActiveFinder.php 16.5 KB
Newer Older
Qiang Xue committed
1 2
<?php
/**
Qiang Xue committed
3
 * ActiveFinder class file.
Qiang Xue committed
4 5 6 7 8 9 10 11 12
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @link http://www.yiiframework.com/
 * @copyright Copyright &copy; 2008-2012 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

namespace yii\db\ar;

Qiang Xue committed
13
use yii\base\Object;
Qiang Xue committed
14
use yii\base\VectorIterator;
Qiang Xue committed
15
use yii\db\dao\Query;
Qiang Xue committed
16
use yii\db\Exception;
Qiang Xue committed
17

Qiang Xue committed
18 19
/**
 * ActiveFinder.php is ...
Qiang Xue committed
20
 *
Qiang Xue committed
21 22
 * @property integer $count
 *
Qiang Xue committed
23 24 25
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
Qiang Xue committed
26
class ActiveFinder extends \yii\base\Object
Qiang Xue committed
27
{
.  
Qiang Xue committed
28
	/**
Qiang Xue committed
29
	 * @var \yii\db\dao\Connection
.  
Qiang Xue committed
30
	 */
Qiang Xue committed
31
	public $connection;
Qiang Xue committed
32

Qiang Xue committed
33
	public function __construct($connection, $config = array())
Qiang Xue committed
34
	{
Qiang Xue committed
35
		$this->connection = $connection;
Qiang Xue committed
36
		parent::__construct($config);
Qiang Xue committed
37 38 39
	}

	/**
Qiang Xue committed
40
	 * @param ActiveQuery $query
Qiang Xue committed
41
	 */
Qiang Xue committed
42
	public function find($query, $returnScalar = false)
Qiang Xue committed
43
	{
Qiang Xue committed
44
		if (!empty($query->with)) {
Qiang Xue committed
45
			return $this->findWithRelations($query, $returnScalar);
Qiang Xue committed
46 47
		}

Qiang Xue committed
48 49
		if ($query->sql !== null) {
			$sql = $query->sql;
Qiang Xue committed
50
		} else {
Qiang Xue committed
51 52
			$modelClass = $query->modelClass;
			$tableName = $modelClass::tableName();
Qiang Xue committed
53 54 55 56 57 58
			if ($query->from === null) {
				if ($query->tableAlias !== null) {
					$tableName .= ' ' . $query->tableAlias;
				}
				$query->from = array($tableName);
			}
Qiang Xue committed
59 60
			$this->applyScopes($query);
			$sql = $this->connection->getQueryBuilder()->build($query);
Qiang Xue committed
61 62 63 64 65

			if ($query->tableAlias !== null) {
				$alias = $this->connection->quoteTableName($query->tableAlias) . '.';
			} else {
				$alias = $this->connection->quoteTableName($tableName) . '.';
Qiang Xue committed
66
			}
Qiang Xue committed
67 68 69 70 71
			$tokens = array(
				'@.' => $alias,
				$this->connection->quoteTableName('@', true) . '.' => $alias,
			);
			$sql = strtr($sql, $tokens);
Qiang Xue committed
72
		}
Qiang Xue committed
73
		$command = $this->connection->createCommand($sql, $query->params);
Qiang Xue committed
74

Qiang Xue committed
75 76 77 78 79 80
		if ($returnScalar) {
			return $command->queryScalar();
		} else {
			$rows = $command->queryAll();
			return $this->createRecords($query, $rows);
		}
81 82
	}

Qiang Xue committed
83 84 85 86 87 88 89 90 91
	private $_joinCount;
	private $_tableAliases;
	private $_hasMany;

	/**
	 * @param ActiveQuery $query
	 * @return array
	 */
	protected function findWithRelations($query, $returnScalar = false)
92
	{
Qiang Xue committed
93 94 95 96 97 98 99 100 101
		$this->_joinCount = 0;
		$this->_tableAliases = array();
		$this->_hasMany = false;
		$joinTree = new JoinElement($this->_joinCount++, $query, null, null);

		if ($query->sql !== null) {
			$command = $this->connection->createCommand($query->sql, $query->params);
			if ($returnScalar) {
				return $command->queryScalar();
Qiang Xue committed
102
			}
Qiang Xue committed
103 104 105 106 107 108 109 110 111 112 113
			$rows = $command->queryAll();
			$records = $this->createRecords($query, $rows);
			$modelClass = $query->modelClass;
			$table = $modelClass::getMetaData()->table;
			foreach ($records as $record) {
				$pk = array();
				foreach ($table->primaryKey as $name) {
					$pk[] = $record[$name];
				}
				$pk = count($pk) === 1 ? $pk[0] : serialize($pk);
				$joinTree->records[$pk] = $record;
Qiang Xue committed
114
			}
Qiang Xue committed
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133

			$q = new ActiveQuery($modelClass);
			$q->with = $query->with;
			$q->tableAlias = 't';
			$q->asArray = $query->asArray;
			$q->index = $query->index;
			$q->select = $table->primaryKey;
			$this->addPkCondition($q, $table, $rows, 't.');
			$joinTree->query = $query = $q;
		}

		$this->buildJoinTree($joinTree, $query->with);
		$this->initJoinTree($joinTree);

		$q = new Query;
		$this->buildJoinQuery($joinTree, $q, $returnScalar);

		if ($returnScalar) {
			return $q->createCommand($this->connection)->queryScalar();
Qiang Xue committed
134
		} else {
Qiang Xue committed
135 136
			if ($this->_hasMany && ($query->limit > 0 || $query->offset > 0)) {
				$this->limitQuery($query, $q);
Qiang Xue committed
137
			}
Qiang Xue committed
138 139 140 141
			$command = $q->createCommand($this->connection);
			$rows = $command->queryAll();
			$joinTree->populateData($rows);
			return $query->index === null ? array_values($joinTree->records) : $joinTree->records;
Qiang Xue committed
142 143 144
		}
	}

Qiang Xue committed
145 146 147 148 149
	/**
	 * @param ActiveRecord $record
	 * @param ActiveRelation $relation
	 * @return array
	 */
Qiang Xue committed
150
	public function findWithRecord($record, $relation)
Qiang Xue committed
151
	{
Qiang Xue committed
152 153 154 155
		$this->_joinCount = 0;
		$this->_tableAliases = array();
		$this->_hasMany = false;
		$query = new ActiveQuery(get_class($record));
Qiang Xue committed
156 157 158 159 160
		$modelClass = $query->modelClass;
		$table = $modelClass::getMetaData()->table;
		$query->select = $table->primaryKey;
		$query->limit = $relation->limit;
		$query->offset = $relation->offset;
Qiang Xue committed
161 162
		$joinTree = new JoinElement($this->_joinCount++, $query, null, null);
		$child = $this->buildJoinTree($joinTree, $relation->name);
Qiang Xue committed
163 164
		$child->query = $relation;
		$child->container = null;
Qiang Xue committed
165 166
		$this->buildJoinTree($child, $relation->with);
		$this->initJoinTree($joinTree);
Qiang Xue committed
167

Qiang Xue committed
168 169
		$pk = $record->getPrimaryKey(true);
		$this->addPkCondition($query, $table, array($pk), $query->tableAlias . '.');
Qiang Xue committed
170 171 172 173 174 175 176 177 178

		$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();
Qiang Xue committed
179
		$child->populateData($rows);
Qiang Xue committed
180

Qiang Xue committed
181 182
		$records = $relation->index === null ? array_values($child->records) : $child->records;
		if ($relation->hasMany) {
Qiang Xue committed
183 184
			return $records;
		} else {
Qiang Xue committed
185
			return $records === array() ? null : reset($records);
Qiang Xue committed
186
		}
Qiang Xue committed
187 188
	}

Qiang Xue committed
189
	protected function createRecords($query, $rows)
Qiang Xue committed
190
	{
Qiang Xue committed
191 192 193 194 195 196 197 198 199
		$records = array();
		if ($query->asArray) {
			if ($query->index === null) {
				return $rows;
			}
			foreach ($rows as $row) {
				$records[$row[$query->index]] = $row;
			}
		} else {
200
			/** @var $class ActiveRecord */
Qiang Xue committed
201 202 203 204 205 206 207 208
			$class = $query->modelClass;
			if ($query->index === null) {
				foreach ($rows as $row) {
					$records[] = $class::create($row);
				}
			} else {
				foreach ($rows as $row) {
					$records[$row[$query->index]] = $class::create($row);
209 210 211
				}
			}
		}
Qiang Xue committed
212
		return $records;
Qiang Xue committed
213 214
	}

Qiang Xue committed
215 216
	protected function applyScopes($query)
	{
217
		/** @var $class ActiveRecord */
Qiang Xue committed
218 219
		$class = $query->modelClass;
		$class::defaultScope($query);
Qiang Xue committed
220
		if (is_array($query->scopes)) {
221
			$model = new $class;
Qiang Xue committed
222
			foreach ($query->scopes as $name => $params) {
223 224
				if (is_string($params)) {
					// scope name only without parameters
Qiang Xue committed
225
					$name = $params;
Qiang Xue committed
226 227
					$params = array();
				}
228
				if (method_exists($class, $name)) {
Qiang Xue committed
229
					array_unshift($params, $query);
230
					call_user_func_array(array($model, $name), $params);
Qiang Xue committed
231
				} else {
Qiang Xue committed
232 233
					throw new Exception("$class has no scope named '$name'.");
				}
Qiang Xue committed
234 235 236 237
			}
		}
	}

Qiang Xue committed
238 239 240
	/**
	 * @param JoinElement $parent
	 * @param array|string $with
241
	 * @param array|\Closure $config
Qiang Xue committed
242 243 244
	 * @return null|JoinElement
	 * @throws \yii\db\Exception
	 */
Qiang Xue committed
245
	protected function buildJoinTree($parent, $with, $config = array())
Qiang Xue committed
246
	{
Qiang Xue committed
247 248 249
		if (empty($with)) {
			return null;
		}
Qiang Xue committed
250 251
		if (is_array($with)) {
			foreach ($with as $name => $value) {
Qiang Xue committed
252
				if (is_array($value) || $value instanceof \Closure) {
Qiang Xue committed
253
					$this->buildJoinTree($parent, $name, $value);
Qiang Xue committed
254 255
				} else {
					$this->buildJoinTree($parent, $value);
Qiang Xue committed
256 257 258 259 260 261
				}
			}
			return null;
		}

		if (($pos = strrpos($with, '.')) !== false) {
Qiang Xue committed
262
			$parent = $this->buildJoinTree($parent, substr($with, 0, $pos));
Qiang Xue committed
263 264 265 266 267 268
			$with = substr($with, $pos + 1);
		}

		if (isset($parent->children[$with])) {
			$child = $parent->children[$with];
		} else {
Qiang Xue committed
269
			$modelClass = $parent->query->modelClass;
Qiang Xue committed
270 271 272 273 274
			$relations = $modelClass::getMetaData()->relations;
			if (!isset($relations[$with])) {
				throw new Exception("$modelClass has no relation named '$with'.");
			}
			$relation = clone $relations[$with];
Qiang Xue committed
275
			if (is_string($relation->via)) {
276
				// join via an existing relation
Qiang Xue committed
277
				$parent2 = $this->buildJoinTree($parent, $relation->via);
Qiang Xue committed
278 279 280
				if ($parent2->query->select === null) {
					$parent2->query->select = false;
					unset($parent2->container->relations[$parent2->query->name]);
Qiang Xue committed
281
				}
Qiang Xue committed
282
				$child = new JoinElement($this->_joinCount++, $relation, $parent2, $parent);
Qiang Xue committed
283 284 285
			} elseif (is_array($relation->via)) {
				// join via a pivoting table
				$r = new ActiveRelation;
Qiang Xue committed
286
				$r->name = 'vt' . $this->_joinCount;
Qiang Xue committed
287 288 289 290 291 292 293 294 295 296 297 298 299 300
				$r->hasMany = $relation->hasMany;

				foreach ($relation->via as $name => $value) {
					$r->$name = $value;
				}

				$r->select = false;
				if ($r->joinType === null) {
					$r->joinType = $relation->joinType;
				}

				$parent2 = new JoinElement($this->_joinCount++, $r, $parent, $parent);
				$child = new JoinElement($this->_joinCount++, $relation, $parent2, $parent);

Qiang Xue committed
301
			} else {
Qiang Xue committed
302
				$child = new JoinElement($this->_joinCount++, $relation, $parent, $parent);
Qiang Xue committed
303 304 305
			}
		}

Qiang Xue committed
306
		if ($config instanceof \Closure) {
Qiang Xue committed
307
			$config($child->query);
Qiang Xue committed
308 309 310 311
		} else {
			foreach ($config as $name => $value) {
				$child->query->$name = $value;
			}
Qiang Xue committed
312 313 314 315
		}

		return $child;
	}
Qiang Xue committed
316

Qiang Xue committed
317 318 319
	/**
	 * @param JoinElement $element
	 */
Qiang Xue committed
320
	protected function initJoinTree($element)
Qiang Xue committed
321
	{
Qiang Xue committed
322 323 324 325 326 327
		if ($element->query->tableAlias !== null) {
			$alias = $element->query->tableAlias;
		} elseif ($element->query instanceof ActiveRelation) {
			$alias = $element->query->name;
		} else {
			$alias = 't';
Qiang Xue committed
328
		}
329 330 331 332 333 334 335 336
		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;
			}
		}
Qiang Xue committed
337 338 339 340 341 342 343
		$count = 0;
		while (isset($this->_tableAliases[$alias])) {
			$alias = 't' . $count++;
		}
		$this->_tableAliases[$alias] = true;
		$element->query->tableAlias = $alias;

Qiang Xue committed
344
		if ($element->records !== array()) {
Qiang Xue committed
345 346 347 348 349 350
			$this->applyScopes($element->query);
		}

		if ($element->container !== null && $element->query->asArray === null) {
			$element->query->asArray = $element->container->query->asArray;
		}
Qiang Xue committed
351

Qiang Xue committed
352
		foreach ($element->children as $child) {
Qiang Xue committed
353
			$this->initJoinTree($child);
Qiang Xue committed
354 355
		}
	}
Qiang Xue committed
356 357 358

	/**
	 * @param JoinElement $element
Qiang Xue committed
359
	 * @param \yii\db\dao\Query $query
Qiang Xue committed
360
	 */
Qiang Xue committed
361
	protected function buildJoinQuery($element, $query, $keepSelect = false)
Qiang Xue committed
362
	{
Qiang Xue committed
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
		if ($element->parent) {
			$prefixes = array(
				'@.' => $element->query->tableAlias . '.',
				'?.' => $element->parent->query->tableAlias . '.',
			);
			$quotedPrefixes = array(
				'@.' => $this->connection->quoteTableName($element->query->tableAlias, true) . '.',
				'?.' => $this->connection->quoteTableName($element->parent->query->tableAlias, true) . '.',
			);
		} else {
			$prefixes = array(
				'@.' => $element->query->tableAlias . '.',
			);
			$quotedPrefixes = array(
				'@.' => $this->connection->quoteTableName($element->query->tableAlias, true) . '.',
			);
Qiang Xue committed
379 380
			$query->limit = $element->query->limit;
			$query->offset = $element->query->offset;
Qiang Xue committed
381 382 383
		}

		$qb = $this->connection->getQueryBuilder();
Qiang Xue committed
384

Qiang Xue committed
385 386 387 388 389 390 391 392 393 394 395 396 397 398
		if ($keepSelect) {
			if (!empty($element->query->select)) {
				$select = $element->query->select;
				if (is_string($select)) {
					$select = explode(',', $select);
				}
				foreach ($select as $column) {
					$query->select[] = strtr(trim($column), $prefixes);
				}
			}
		} else {
			foreach ($this->buildSelect($element, $element->query->select) as $column) {
				$query->select[] = strtr($column, $prefixes);
			}
Qiang Xue committed
399 400
		}

Qiang Xue committed
401 402 403 404 405 406 407 408 409 410 411
		if ($element->query instanceof ActiveQuery) {
			if ($element->query->from === null) {
				$modelClass = $element->query->modelClass;
				$tableName = $modelClass::tableName();
				if ($element->query->tableAlias !== null) {
					$tableName .= ' ' . $element->query->tableAlias;
				}
				$query->from = array($tableName);
			} else {
				$query->from = $element->query->from;
			}
Qiang Xue committed
412 413
		}

Qiang Xue committed
414 415
		if (($where = $qb->buildCondition($element->query->where)) !== '') {
			$query->andWhere(strtr($where, $quotedPrefixes));
Qiang Xue committed
416 417
		}

Qiang Xue committed
418 419
		if (($having = $qb->buildCondition($element->query->having)) !== '') {
			$query->andHaving(strtr($having, $quotedPrefixes));
Qiang Xue committed
420 421
		}

Qiang Xue committed
422
		if ($element->query instanceof ActiveRelation) {
Qiang Xue committed
423
			$joinType = $element->query->joinType ?: 'LEFT JOIN';
Qiang Xue committed
424 425 426 427 428 429
			if ($element->query->modelClass !== null) {
				$modelClass = $element->query->modelClass;
				$tableName = $this->connection->quoteTableName($modelClass::tableName());
			} else {
				$tableName = $this->connection->quoteTableName($element->query->table);
			}
Qiang Xue committed
430 431
			$tableAlias = $this->connection->quoteTableName($element->query->tableAlias);
			$join = "$joinType $tableName $tableAlias";
Qiang Xue committed
432 433 434 435 436 437 438 439 440 441 442
			$on = '';
			if (is_array($element->query->link)) {
				foreach ($element->query->link as $pk => $fk) {
					$pk = $quotedPrefixes['@.'] . $this->connection->quoteColumnName($pk, true);
					$fk = $quotedPrefixes['?.'] . $this->connection->quoteColumnName($fk, true);
					if ($on !== '') {
						$on .= ' AND ';
					}
					$on .= "$pk = $fk";
				}
			}
Qiang Xue committed
443
			if ($element->query->on !== null) {
Qiang Xue committed
444 445 446 447 448 449 450 451 452
				$condition = strtr($qb->buildCondition($element->query->on), $quotedPrefixes);
				if ($on !== '') {
					$on .= " AND ($condition)";
				} else {
					$on = $condition;
				}
			}
			if ($on !== '') {
				$join .= ' ON ' . $on;
Qiang Xue committed
453 454
			}
			$query->join[] = $join;
Qiang Xue committed
455 456 457
		}

		if ($element->query->join !== null) {
Qiang Xue committed
458 459 460 461 462 463 464 465 466 467
			if (is_array($element->query->join)) {
				foreach ($element->query->join as $join) {
					if (is_array($join) && isset($join[2])) {
						$join[2] = strtr($join[2], $quotedPrefixes);
					}
					$query->join[] = $join;
				}
			} else {
				$query->join[] = strtr($element->query->join, $quotedPrefixes);
			}
Qiang Xue committed
468 469
		}

470 471 472
		if ($element->query->orderBy !== null) {
			if (!is_array($element->query->orderBy)) {
				$element->query->orderBy = preg_split('/\s*,\s*/', trim($element->query->orderBy), -1, PREG_SPLIT_NO_EMPTY);
Qiang Xue committed
473
			}
474 475
			foreach ($element->query->orderBy as $order) {
				$query->orderBy[] = strtr($order, $prefixes);
Qiang Xue committed
476 477 478
			}
		}

479 480 481
		if ($element->query->groupBy !== null) {
			if (!is_array($element->query->groupBy)) {
				$element->query->groupBy = preg_split('/\s*,\s*/', trim($element->query->groupBy), -1, PREG_SPLIT_NO_EMPTY);
Qiang Xue committed
482
			}
483 484
			foreach ($element->query->groupBy as $group) {
				$query->groupBy[] = strtr($group, $prefixes);
Qiang Xue committed
485 486 487 488 489 490 491 492
			}
		}

		if ($element->query->params !== null) {
			$query->addParams($element->query->params);
		}

		foreach ($element->children as $child) {
Qiang Xue committed
493
			$this->buildJoinQuery($child, $query, $keepSelect);
Qiang Xue committed
494 495 496 497 498 499 500 501 502 503 504 505 506
		}
	}

	protected function buildSelect($element, $select)
	{
		if ($select === false) {
			return array();
		}
		$modelClass = $element->query->modelClass;
		$table = $modelClass::getMetaData()->table;
		$columns = array();
		$columnCount = 0;
		$prefix = $element->query->tableAlias;
Qiang Xue committed
507 508 509 510 511 512 513 514

		foreach ($table->primaryKey as $column) {
			$alias = "c{$element->id}_" . ($columnCount++);
			$columns[] = "$prefix.$column AS $alias";
			$element->pkAlias[$column] = $alias;
			$element->columnAliases[$alias] = $column;
		}

Qiang Xue committed
515 516
		if (empty($select) || $select === '*') {
			foreach ($table->columns as $column) {
Qiang Xue committed
517 518 519 520
				if (!isset($element->pkAlias[$column->name])) {
					$alias = "c{$element->id}_" . ($columnCount++);
					$columns[] = "$prefix.{$column->name} AS $alias";
					$element->columnAliases[$alias] = $column->name;
Qiang Xue committed
521 522 523 524 525 526 527 528 529 530 531 532 533
				}
			}
		} else {
			if (is_string($select)) {
				$select = explode(',', $select);
			}
			foreach ($select as $column) {
				$column = trim($column);
				if (preg_match('/^(.*?)\s+AS\s+(\w+)$/im', $column, $matches)) {
					// if the column is already aliased
					$element->columnAliases[$matches[2]] = $matches[2];
					$columns[] = $column;
				} elseif (!isset($element->pkAlias[$column])) {
Qiang Xue committed
534
					$alias = "c{$element->id}_" . ($columnCount++);
Qiang Xue committed
535 536 537 538 539
					if (strpos($column, '(') !== false) {
						$columns[] = "$column AS $alias";
					} else {
						$columns[] = "$prefix.$column AS $alias";
					}
Qiang Xue committed
540 541 542 543 544
					$element->columnAliases[$alias] = $column;
				}
			}
		}

Qiang Xue committed
545 546 547 548 549 550 551 552 553 554 555 556
		// determine the actual index column(s)
		if ($element->query->index !== null) {
			$index = array_search($element->query->index, $element->columnAliases);
		}
		if (empty($index)) {
			$index = $element->pkAlias;
			if (count($index) === 1) {
				$index = reset($element->pkAlias);
			}
		}
		$element->key = $index;

Qiang Xue committed
557 558
		return $columns;
	}
Qiang Xue committed
559 560 561 562 563 564 565 566 567 568 569 570

	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();
571 572 573 574 575 576 577
		$prefix = $activeQuery->tableAlias . '.';
		$this->addPkCondition($query, $table, $rows, $prefix);
		$query->limit = $query->offset = null;
	}

	protected function addPkCondition($query, $table, $rows, $prefix)
	{
Qiang Xue committed
578
		if (count($table->primaryKey) === 1 && count($rows) > 1) {
Qiang Xue committed
579 580 581 582 583
			$name = $table->primaryKey[0];
			$values = array();
			foreach ($rows as $row) {
				$values[] = $table->columns[$name]->typecast($row[$name]);
			}
584
			$query->andWhere(array('in', $prefix . $name, $values));
Qiang Xue committed
585 586 587
		} else {
			$ors = array('or');
			foreach ($rows as $row) {
588
				$hash = array();
Qiang Xue committed
589 590 591 592 593
				foreach ($table->primaryKey as $name) {
					$value = $table->columns[$name]->typecast($row[$name]);
					if (is_string($value)) {
						$value = $this->connection->quoteValue($value);
					}
594
					$hash[$prefix . $name] = $value;
Qiang Xue committed
595
				}
596
				$ors[] = $hash;
Qiang Xue committed
597 598 599 600
			}
			$query->andWhere($ors);
		}
	}
Qiang Xue committed
601
}