Commit 745c2053 by Carsten Brandt

Merge pull request #2885 branch 'query-filter'

* query-filter: added CHANGELOG lines added tests for redis added proper tests for elasticsearch removed unnecessary code duplication adjusted tests typo renamed Query::filter() to Query::filterWhere() reverted elasticsearch rename of filter Adjusted search model code generated by Gii CRUD generator Added support for arbitrary number of parameters for NOT, AND, OR in filter methods of Query Gii CRUD generator now uses new addFilter method Query::filter() adjustments fixes #2002 Added tests for Query::filter() Conflicts: framework/db/QueryTrait.php
parents a440abad cc0d5b6f
...@@ -9,6 +9,7 @@ Yii Framework 2 elasticsearch extension Change Log ...@@ -9,6 +9,7 @@ Yii Framework 2 elasticsearch extension Change Log
- Enh #1313: made index and type available in `ActiveRecord::instantiate()` to allow creating records based on elasticsearch type when doing cross index/type search (cebe) - Enh #1313: made index and type available in `ActiveRecord::instantiate()` to allow creating records based on elasticsearch type when doing cross index/type search (cebe)
- Enh #1382: Added a debug toolbar panel for elasticsearch (cebe) - Enh #1382: Added a debug toolbar panel for elasticsearch (cebe)
- Enh #1765: Added support for primary key path mapping, pk can now be part of the attributes when mapping is defined (cebe) - Enh #1765: Added support for primary key path mapping, pk can now be part of the attributes when mapping is defined (cebe)
- Enh #2002: Added filterWhere() method to yii\elasticsearch\Query to allow easy addition of search filter conditions by ignoring empty search fields (samdark, cebe)
- Enh #2892: ActiveRecord dirty attributes are now reset after call to `afterSave()` so information about changed attributes is available in `afterSave`-event (cebe) - Enh #2892: ActiveRecord dirty attributes are now reset after call to `afterSave()` so information about changed attributes is available in `afterSave`-event (cebe)
- Chg #1765: Changed handling of ActiveRecord primary keys, removed getId(), use getPrimaryKey() instead (cebe) - Chg #1765: Changed handling of ActiveRecord primary keys, removed getId(), use getPrimaryKey() instead (cebe)
- Chg #2281: Renamed `ActiveRecord::create()` to `populateRecord()` and changed signature. This method will not call instantiate() anymore (cebe) - Chg #2281: Renamed `ActiveRecord::create()` to `populateRecord()` and changed signature. This method will not call instantiate() anymore (cebe)
......
...@@ -96,6 +96,7 @@ class Query extends Component implements QueryInterface ...@@ -96,6 +96,7 @@ class Query extends Component implements QueryInterface
public $facets = []; public $facets = [];
public function init() public function init()
{ {
parent::init(); parent::init();
...@@ -271,7 +272,6 @@ class Query extends Component implements QueryInterface ...@@ -271,7 +272,6 @@ class Query extends Component implements QueryInterface
foreach ($result['hits']['hits'] as $row) { foreach ($result['hits']['hits'] as $row) {
$column[] = isset($row['fields'][$field]) ? $row['fields'][$field] : null; $column[] = isset($row['fields'][$field]) ? $row['fields'][$field] : null;
} }
return $column; return $column;
} }
...@@ -316,7 +316,6 @@ class Query extends Component implements QueryInterface ...@@ -316,7 +316,6 @@ class Query extends Component implements QueryInterface
public function addFacet($name, $type, $options) public function addFacet($name, $type, $options)
{ {
$this->facets[$name] = [$type => $options]; $this->facets[$name] = [$type => $options];
return $this; return $this;
} }
...@@ -450,7 +449,6 @@ class Query extends Component implements QueryInterface ...@@ -450,7 +449,6 @@ class Query extends Component implements QueryInterface
public function query($query) public function query($query)
{ {
$this->query = $query; $this->query = $query;
return $this; return $this;
} }
...@@ -462,7 +460,6 @@ class Query extends Component implements QueryInterface ...@@ -462,7 +460,6 @@ class Query extends Component implements QueryInterface
public function filter($filter) public function filter($filter)
{ {
$this->filter = $filter; $this->filter = $filter;
return $this; return $this;
} }
...@@ -479,7 +476,6 @@ class Query extends Component implements QueryInterface ...@@ -479,7 +476,6 @@ class Query extends Component implements QueryInterface
{ {
$this->index = $index; $this->index = $index;
$this->type = $type; $this->type = $type;
return $this; return $this;
} }
...@@ -496,7 +492,6 @@ class Query extends Component implements QueryInterface ...@@ -496,7 +492,6 @@ class Query extends Component implements QueryInterface
} else { } else {
$this->fields = func_get_args(); $this->fields = func_get_args();
} }
return $this; return $this;
} }
...@@ -510,7 +505,6 @@ class Query extends Component implements QueryInterface ...@@ -510,7 +505,6 @@ class Query extends Component implements QueryInterface
public function timeout($timeout) public function timeout($timeout)
{ {
$this->timeout = $timeout; $this->timeout = $timeout;
return $this; return $this;
} }
} }
...@@ -400,10 +400,10 @@ class Generator extends \yii\gii\Generator ...@@ -400,10 +400,10 @@ class Generator extends \yii\gii\Generator
case Schema::TYPE_TIME: case Schema::TYPE_TIME:
case Schema::TYPE_DATETIME: case Schema::TYPE_DATETIME:
case Schema::TYPE_TIMESTAMP: case Schema::TYPE_TIMESTAMP:
$conditions[] = "\$this->addCondition(\$query, '{$column}');"; $conditions[] = "\$query->andFilterWhere(['{$column}' => \$this->{$column}]);";
break; break;
default: default:
$conditions[] = "\$this->addCondition(\$query, '{$column}', true);"; $conditions[] = "\$query->andFilterWhere(['like', '{$column}', \$this->{$column}]);";
break; break;
} }
} }
......
...@@ -70,23 +70,4 @@ class <?= $searchModelClass ?> extends Model ...@@ -70,23 +70,4 @@ class <?= $searchModelClass ?> extends Model
return $dataProvider; return $dataProvider;
} }
protected function addCondition($query, $attribute, $partialMatch = false)
{
if (($pos = strrpos($attribute, '.')) !== false) {
$modelAttribute = substr($attribute, $pos + 1);
} else {
$modelAttribute = $attribute;
}
$value = $this->$modelAttribute;
if (trim($value) === '') {
return;
}
if ($partialMatch) {
$query->andWhere(['like', $attribute, $value]);
} else {
$query->andWhere([$attribute => $value]);
}
}
} }
...@@ -6,6 +6,7 @@ Yii Framework 2 redis extension Change Log ...@@ -6,6 +6,7 @@ Yii Framework 2 redis extension Change Log
- Bug #1993: afterFind event in AR is now called after relations have been populated (cebe, creocoder) - Bug #1993: afterFind event in AR is now called after relations have been populated (cebe, creocoder)
- Enh #1773: keyPrefix property of Session and Cache is not restricted to alnum characters anymore (cebe) - Enh #1773: keyPrefix property of Session and Cache is not restricted to alnum characters anymore (cebe)
- Enh #2002: Added filterWhere() method to yii\redis\ActiveQuery to allow easy addition of search filter conditions by ignoring empty search fields (samdark, cebe)
- Enh #2892: ActiveRecord dirty attributes are now reset after call to `afterSave()` so information about changed attributes is available in `afterSave`-event (cebe) - Enh #2892: ActiveRecord dirty attributes are now reset after call to `afterSave()` so information about changed attributes is available in `afterSave`-event (cebe)
- Chg #2281: Renamed `ActiveRecord::create()` to `populateRecord()` and changed signature. This method will not call instantiate() anymore (cebe) - Chg #2281: Renamed `ActiveRecord::create()` to `populateRecord()` and changed signature. This method will not call instantiate() anymore (cebe)
- Chg #2146: Removed `ActiveRelation` class and moved the functionality to `ActiveQuery`. - Chg #2146: Removed `ActiveRelation` class and moved the functionality to `ActiveQuery`.
......
...@@ -7,6 +7,7 @@ Yii Framework 2 sphinx extension Change Log ...@@ -7,6 +7,7 @@ Yii Framework 2 sphinx extension Change Log
- Bug #1993: afterFind event in AR is now called after relations have been populated (cebe, creocoder) - Bug #1993: afterFind event in AR is now called after relations have been populated (cebe, creocoder)
- Bug #2160: SphinxQL does not support `OFFSET` (qiangxue, romeo7) - Bug #2160: SphinxQL does not support `OFFSET` (qiangxue, romeo7)
- Enh #1398: Refactor ActiveRecord to use BaseActiveRecord class of the framework (klimov-paul) - Enh #1398: Refactor ActiveRecord to use BaseActiveRecord class of the framework (klimov-paul)
- Enh #2002: Added filterWhere() method to yii\spinx\Query to allow easy addition of search filter conditions by ignoring empty search fields (samdark, cebe)
- Enh #2892: ActiveRecord dirty attributes are now reset after call to `afterSave()` so information about changed attributes is available in `afterSave`-event (cebe) - Enh #2892: ActiveRecord dirty attributes are now reset after call to `afterSave()` so information about changed attributes is available in `afterSave`-event (cebe)
- Chg #2281: Renamed `ActiveRecord::create()` to `populateRecord()` and changed signature. This method will not call instantiate() anymore (cebe) - Chg #2281: Renamed `ActiveRecord::create()` to `populateRecord()` and changed signature. This method will not call instantiate() anymore (cebe)
- Chg #2146: Removed `ActiveRelation` class and moved the functionality to `ActiveQuery`. - Chg #2146: Removed `ActiveRelation` class and moved the functionality to `ActiveQuery`.
......
...@@ -466,7 +466,25 @@ class Query extends Component implements QueryInterface ...@@ -466,7 +466,25 @@ class Query extends Component implements QueryInterface
{ {
$this->where = $condition; $this->where = $condition;
$this->addParams($params); $this->addParams($params);
return $this;
}
/**
* Sets the WHERE part of the query ignoring empty parameters.
*
* @param string|array $condition the conditions that should be put in the WHERE part. Please refer to [[where()]]
* on how to specify this parameter.
* @param array $params the parameters (name => value) to be bound to the query.
* @return static the query object itself
* @see andFilter()
* @see orFilter()
*/
public function filterWhere($condition, $params = [])
{
$condition = $this->filterCondition($condition);
if ($condition !== []) {
$this->where($condition, $params);
}
return $this; return $this;
} }
...@@ -488,7 +506,26 @@ class Query extends Component implements QueryInterface ...@@ -488,7 +506,26 @@ class Query extends Component implements QueryInterface
$this->where = ['and', $this->where, $condition]; $this->where = ['and', $this->where, $condition];
} }
$this->addParams($params); $this->addParams($params);
return $this;
}
/**
* Adds an additional WHERE condition to the existing one ignoring empty parameters.
* The new condition and the existing one will be joined using the 'AND' operator.
*
* @param string|array $condition the new WHERE condition. Please refer to [[where()]]
* on how to specify this parameter.
* @param array $params the parameters (name => value) to be bound to the query.
* @return static the query object itself
* @see filter()
* @see orFilter()
*/
public function andFilterWhere($condition, $params = [])
{
$condition = $this->filterCondition($condition);
if ($condition !== []) {
$this->andWhere($condition, $params);
}
return $this; return $this;
} }
...@@ -510,7 +547,26 @@ class Query extends Component implements QueryInterface ...@@ -510,7 +547,26 @@ class Query extends Component implements QueryInterface
$this->where = ['or', $this->where, $condition]; $this->where = ['or', $this->where, $condition];
} }
$this->addParams($params); $this->addParams($params);
return $this;
}
/**
* Adds an additional WHERE condition to the existing one ignoring empty parameters.
* The new condition and the existing one will be joined using the 'OR' operator.
*
* @param string|array $condition the new WHERE condition. Please refer to [[where()]]
* on how to specify this parameter.
* @param array $params the parameters (name => value) to be bound to the query.
* @return static the query object itself
* @see filter()
* @see andFilter()
*/
public function orFilterWhere($condition, $params = [])
{
$condition = $this->filterCondition($condition);
if ($condition !== []) {
$this->orWhere($condition, $params);
}
return $this; return $this;
} }
......
...@@ -114,6 +114,7 @@ Yii Framework 2 Change Log ...@@ -114,6 +114,7 @@ Yii Framework 2 Change Log
- Enh #1921: Grid view ActionColumn now allow to name buttons like `{controller/action}` (creocoder) - Enh #1921: Grid view ActionColumn now allow to name buttons like `{controller/action}` (creocoder)
- Enh #1973: `yii message/extract` is now able to generate `.po` files (SergeiKutanov, samdark) - Enh #1973: `yii message/extract` is now able to generate `.po` files (SergeiKutanov, samdark)
- Enh #1984: ActionFilter will now mark event as handled when action run is aborted (cebe) - Enh #1984: ActionFilter will now mark event as handled when action run is aborted (cebe)
- Enh #2002: Added filterWhere() method to yii\db\Query to allow easy addition of search filter conditions by ignoring empty search fields (samdark, cebe)
- Enh #2003: Added `filter` property to `ExistValidator` and `UniqueValidator` to support adding additional filtering conditions (qiangxue) - Enh #2003: Added `filter` property to `ExistValidator` and `UniqueValidator` to support adding additional filtering conditions (qiangxue)
- Enh #2008: `yii message/extract` is now able to save translation strings to database (kate-kate, samdark) - Enh #2008: `yii message/extract` is now able to save translation strings to database (kate-kate, samdark)
- Enh #2043: Added support for custom request body parsers (danschmidt5189, cebe) - Enh #2043: Added support for custom request body parsers (danschmidt5189, cebe)
......
...@@ -526,7 +526,6 @@ class Query extends Component implements QueryInterface ...@@ -526,7 +526,6 @@ class Query extends Component implements QueryInterface
{ {
$this->where = $condition; $this->where = $condition;
$this->addParams($params); $this->addParams($params);
return $this; return $this;
} }
...@@ -570,7 +569,65 @@ class Query extends Component implements QueryInterface ...@@ -570,7 +569,65 @@ class Query extends Component implements QueryInterface
$this->where = ['or', $this->where, $condition]; $this->where = ['or', $this->where, $condition];
} }
$this->addParams($params); $this->addParams($params);
return $this;
}
/**
* Sets the WHERE part of the query ignoring empty parameters.
*
* @param string|array $condition the conditions that should be put in the WHERE part. Please refer to [[where()]]
* on how to specify this parameter.
* @param array $params the parameters (name => value) to be bound to the query.
* @return static the query object itself
* @see andFilter()
* @see orFilter()
*/
public function filterWhere($condition, $params = [])
{
$condition = $this->filterCondition($condition);
if ($condition !== []) {
$this->where($condition, $params);
}
return $this;
}
/**
* Adds an additional WHERE condition to the existing one ignoring empty parameters.
* The new condition and the existing one will be joined using the 'AND' operator.
*
* @param string|array $condition the new WHERE condition. Please refer to [[where()]]
* on how to specify this parameter.
* @param array $params the parameters (name => value) to be bound to the query.
* @return static the query object itself
* @see filter()
* @see orFilter()
*/
public function andFilterWhere($condition, $params = [])
{
$condition = $this->filterCondition($condition);
if ($condition !== []) {
$this->andWhere($condition, $params);
}
return $this;
}
/**
* Adds an additional WHERE condition to the existing one ignoring empty parameters.
* The new condition and the existing one will be joined using the 'OR' operator.
*
* @param string|array $condition the new WHERE condition. Please refer to [[where()]]
* on how to specify this parameter.
* @param array $params the parameters (name => value) to be bound to the query.
* @return static the query object itself
* @see filter()
* @see andFilter()
*/
public function orFilterWhere($condition, $params = [])
{
$condition = $this->filterCondition($condition);
if ($condition !== []) {
$this->orWhere($condition, $params);
}
return $this; return $this;
} }
......
...@@ -144,6 +144,17 @@ interface QueryInterface ...@@ -144,6 +144,17 @@ interface QueryInterface
public function where($condition); public function where($condition);
/** /**
* Sets the WHERE part of the query ignoring empty parameters.
*
* @param array $condition the conditions that should be put in the WHERE part. Please refer to [[where()]]
* on how to specify this parameter.
* @return static the query object itself
* @see andFilterWhere()
* @see orFilterWhere()
*/
public function filterWhere($condition);
/**
* Adds an additional WHERE condition to the existing one. * Adds an additional WHERE condition to the existing one.
* The new condition and the existing one will be joined using the 'AND' operator. * The new condition and the existing one will be joined using the 'AND' operator.
* @param string|array $condition the new WHERE condition. Please refer to [[where()]] * @param string|array $condition the new WHERE condition. Please refer to [[where()]]
...@@ -155,6 +166,17 @@ interface QueryInterface ...@@ -155,6 +166,17 @@ interface QueryInterface
public function andWhere($condition); public function andWhere($condition);
/** /**
* Adds an additional WHERE condition to the existing one ignoring empty parameters.
* The new condition and the existing one will be joined using the 'AND' operator.
* @param string|array $condition the new WHERE condition. Please refer to [[where()]]
* on how to specify this parameter.
* @return static the query object itself
* @see filterWhere()
* @see orFilterWhere()
*/
public function andFilterWhere($condition);
/**
* Adds an additional WHERE condition to the existing one. * Adds an additional WHERE condition to the existing one.
* The new condition and the existing one will be joined using the 'OR' operator. * The new condition and the existing one will be joined using the 'OR' operator.
* @param string|array $condition the new WHERE condition. Please refer to [[where()]] * @param string|array $condition the new WHERE condition. Please refer to [[where()]]
...@@ -166,6 +188,17 @@ interface QueryInterface ...@@ -166,6 +188,17 @@ interface QueryInterface
public function orWhere($condition); public function orWhere($condition);
/** /**
* Adds an additional WHERE condition to the existing one ignoring empty parameters.
* The new condition and the existing one will be joined using the 'OR' operator.
* @param string|array $condition the new WHERE condition. Please refer to [[where()]]
* on how to specify this parameter.
* @return static the query object itself
* @see filterWhere()
* @see andFilterWhere()
*/
public function orFilterWhere($condition);
/**
* Sets the ORDER BY part of the query. * Sets the ORDER BY part of the query.
* @param string|array $columns the columns (and the directions) to be ordered by. * @param string|array $columns the columns (and the directions) to be ordered by.
* Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array * Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
namespace yii\db; namespace yii\db;
use yii\base\NotSupportedException;
/** /**
* The BaseQuery trait represents the minimum method set of a database Query. * The BaseQuery trait represents the minimum method set of a database Query.
* *
...@@ -126,6 +128,149 @@ trait QueryTrait ...@@ -126,6 +128,149 @@ trait QueryTrait
} }
/** /**
* Sets the WHERE part of the query but ignores [[isParameterNotEmpty|empty parameters]].
*
* This function can be used to pass fields of a search form directly as search condition
* by ignoring fields that have not been filled.
*
* @param array $condition the conditions that should be put in the WHERE part.
* See [[where()]] on how to specify this parameter.
* @return static the query object itself
* @see where()
* @see andFilterWhere()
* @see orFilterWhere()
*/
public function filterWhere($condition)
{
$condition = $this->filterCondition($condition);
if ($condition !== []) {
$this->where($condition);
}
return $this;
}
/**
* Adds an additional WHERE condition to the existing one but ignores [[isParameterNotEmpty|empty parameters]].
* The new condition and the existing one will be joined using the 'AND' operator.
* @param string|array $condition the new WHERE condition. Please refer to [[where()]]
* on how to specify this parameter.
* @return static the query object itself
* @see filterWhere()
* @see orFilterWhere()
*/
public function andFilterWhere($condition)
{
$condition = $this->filterCondition($condition);
if ($condition !== []) {
$this->andWhere($condition);
}
return $this;
}
/**
* Adds an additional WHERE condition to the existing one but ignores [[isParameterNotEmpty|empty parameters]].
* The new condition and the existing one will be joined using the 'OR' operator.
* @param string|array $condition the new WHERE condition. Please refer to [[where()]]
* on how to specify this parameter.
* @return static the query object itself
* @see filterWhere()
* @see andFilterWhere()
*/
public function orFilterWhere($condition)
{
$condition = $this->filterCondition($condition);
if ($condition !== []) {
$this->orWhere($condition);
}
return $this;
}
/**
* Returns a new condition with [[isParameterNotEmpty|empty parameters]] removed.
*
* @param array $condition original condition
* @return array condition with [[isParameterNotEmpty|empty parameters]] removed.
* @throws NotSupportedException if the condition format is not supported
*/
protected function filterCondition($condition)
{
if (is_array($condition) && isset($condition[0])) {
$operator = strtoupper($condition[0]);
switch ($operator) {
case 'NOT':
case 'AND':
case 'OR':
for ($i = 1, $operandsCount = count($condition); $i < $operandsCount; $i++) {
$subCondition = $this->filterCondition($condition[$i]);
if ($this->isParameterNotEmpty($subCondition)) {
$condition[$i] = $subCondition;
} else {
unset($condition[$i]);
}
}
$operandsCount = count($condition) - 1;
if ($operator === 'NOT' && $operandsCount === 0) {
$condition = [];
} else {
// reindex array
array_splice($condition, 0, 0);
if ($operandsCount === 1) {
$condition = $condition[1];
}
}
break;
case 'IN':
case 'NOT IN':
case 'LIKE':
case 'OR LIKE':
case 'NOT LIKE':
case 'OR NOT LIKE':
if (!$this->isParameterNotEmpty($condition[2])) {
$condition = [];
}
break;
case 'BETWEEN':
case 'NOT BETWEEN':
if (!$this->isParameterNotEmpty($condition[2]) && !$this->isParameterNotEmpty($condition[3])) {
$condition = [];
}
break;
default:
throw new NotSupportedException("filterWhere() does not support the '$operator' operator.");
}
} elseif (is_array($condition)) {
// hash format: 'column1' => 'value1', 'column2' => 'value2', ...
return array_filter($condition, [$this, 'isParameterNotEmpty']);
} else {
throw new NotSupportedException("filterWhere() does not support plain string conditions use where() instead.");
}
return $condition;
}
/**
* Returns `true` if value passed is not "empty".
*
* The value is considered "empty", if
*
* - it is `null`,
* - an empty string (`''`),
* - a string containing only whitespace characters,
* - or an empty array.
*
* @param $value
* @return boolean if parameter is empty
*/
protected function isParameterNotEmpty($value)
{
if (is_string($value)) {
$value = trim($value);
}
return $value !== '' && $value !== [] && $value !== null;
}
/**
* Sets the ORDER BY part of the query. * Sets the ORDER BY part of the query.
* @param string|array $columns the columns (and the directions) to be ordered by. * @param string|array $columns the columns (and the directions) to be ordered by.
* Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array * Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array
......
...@@ -151,6 +151,64 @@ class QueryTest extends ElasticSearchTestCase ...@@ -151,6 +151,64 @@ class QueryTest extends ElasticSearchTestCase
} }
public function testFilterWhere()
{
// should work with hash format
$query = new Query;
$query->filterWhere([
'id' => 0,
'title' => ' ',
'author_ids' => [],
]);
$this->assertEquals(['id' => 0], $query->where);
$query->andFilterWhere(['status' => null]);
$this->assertEquals(['id' => 0], $query->where);
$query->orFilterWhere(['name' => '']);
$this->assertEquals(['id' => 0], $query->where);
// should work with operator format
$query = new Query;
$condition = ['like', 'name', 'Alex'];
$query->filterWhere($condition);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['between', 'id', null, null]);
$this->assertEquals($condition, $query->where);
$query->orFilterWhere(['not between', 'id', null, null]);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['in', 'id', []]);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['not in', 'id', []]);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['not in', 'id', []]);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['like', 'id', '']);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['or like', 'id', '']);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['not like', 'id', ' ']);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['or not like', 'id', null]);
$this->assertEquals($condition, $query->where);
}
public function testFilterWhereRecursively()
{
$query = new Query();
$query->filterWhere(['and', ['like', 'name', ''], ['like', 'title', ''], ['id' => 1], ['not', ['like', 'name', '']]]);
$this->assertEquals(['id' => 1], $query->where);
}
// TODO test facets // TODO test facets
// TODO test complex where() every edge of QueryBuilder // TODO test complex where() every edge of QueryBuilder
......
...@@ -68,6 +68,24 @@ class QueryTest extends MongoDbTestCase ...@@ -68,6 +68,24 @@ class QueryTest extends MongoDbTestCase
); );
} }
public function testFilterWhere()
{
// should work with hash format
$query = new Query;
$query->filterWhere([
'id' => 0,
'title' => ' ',
'author_ids' => [],
]);
$this->assertEquals(['id' => 0], $query->where);
$query->andFilterWhere(['status' => null]);
$this->assertEquals(['id' => 0], $query->where);
$query->orFilterWhere(['name' => '']);
$this->assertEquals(['id' => 0], $query->where);
}
public function testOrder() public function testOrder()
{ {
$query = new Query; $query = new Query;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
namespace yiiunit\extensions\redis; namespace yiiunit\extensions\redis;
use yii\redis\ActiveQuery;
use yiiunit\data\ar\redis\ActiveRecord; use yiiunit\data\ar\redis\ActiveRecord;
use yiiunit\data\ar\redis\Customer; use yiiunit\data\ar\redis\Customer;
use yiiunit\data\ar\redis\OrderItem; use yiiunit\data\ar\redis\OrderItem;
...@@ -239,4 +240,62 @@ class ActiveRecordTest extends RedisTestCase ...@@ -239,4 +240,62 @@ class ActiveRecordTest extends RedisTestCase
$this->assertNull(OrderItem::find($pk)); $this->assertNull(OrderItem::find($pk));
$this->assertNotNull(OrderItem::find(['order_id' => 2, 'item_id' => 10])); $this->assertNotNull(OrderItem::find(['order_id' => 2, 'item_id' => 10]));
} }
public function testFilterWhere()
{
// should work with hash format
$query = new ActiveQuery();
$query->filterWhere([
'id' => 0,
'title' => ' ',
'author_ids' => [],
]);
$this->assertEquals(['id' => 0], $query->where);
$query->andFilterWhere(['status' => null]);
$this->assertEquals(['id' => 0], $query->where);
$query->orFilterWhere(['name' => '']);
$this->assertEquals(['id' => 0], $query->where);
// should work with operator format
$query = new ActiveQuery();
$condition = ['like', 'name', 'Alex'];
$query->filterWhere($condition);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['between', 'id', null, null]);
$this->assertEquals($condition, $query->where);
$query->orFilterWhere(['not between', 'id', null, null]);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['in', 'id', []]);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['not in', 'id', []]);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['not in', 'id', []]);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['like', 'id', '']);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['or like', 'id', '']);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['not like', 'id', ' ']);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['or not like', 'id', null]);
$this->assertEquals($condition, $query->where);
}
public function testFilterWhereRecursively()
{
$query = new ActiveQuery();
$query->filterWhere(['and', ['like', 'name', ''], ['like', 'title', ''], ['id' => 1], ['not', ['like', 'name', '']]]);
$this->assertEquals(['id' => 1], $query->where);
}
} }
...@@ -60,6 +60,70 @@ class QueryTest extends SphinxTestCase ...@@ -60,6 +60,70 @@ class QueryTest extends SphinxTestCase
$this->assertEquals([':id' => 1, ':name' => 'something', ':age' => '30'], $query->params); $this->assertEquals([':id' => 1, ':name' => 'something', ':age' => '30'], $query->params);
} }
public function testFilterWhere()
{
// should just call where() when string is passed
$query = new Query;
$query->filterWhere('id = :id', [':id' => null]);
$this->assertEquals('id = :id', $query->where);
$this->assertEquals([':id' => null], $query->params);
// should work with hash format
$query = new Query;
$query->filterWhere([
'id' => 0,
'title' => ' ',
'author_ids' => [],
]);
$this->assertEquals(['id' => 0], $query->where);
$query->andFilterWhere(['status' => null]);
$this->assertEquals(['id' => 0], $query->where);
$query->orFilterWhere(['name' => '']);
$this->assertEquals(['id' => 0], $query->where);
// should work with operator format
$query = new Query;
$condition = ['like', 'name', 'Alex'];
$query->filterWhere($condition);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['between', 'id', null, null]);
$this->assertEquals($condition, $query->where);
$query->orFilterWhere(['not between', 'id', null, null]);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['in', 'id', []]);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['not in', 'id', []]);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['not in', 'id', []]);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['like', 'id', '']);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['or like', 'id', '']);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['not like', 'id', ' ']);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['or not like', 'id', null]);
$this->assertEquals($condition, $query->where);
}
public function testFilterWhereRecursively()
{
$query = new Query();
$query->filterWhere(['and', ['like', 'name', ''], ['like', 'title', ''], ['id' => 1], ['not', ['like', 'name', '']]]);
$this->assertEquals(['id' => 1], $query->where);
}
public function testGroup() public function testGroup()
{ {
$query = new Query; $query = new Query;
......
...@@ -49,6 +49,70 @@ class QueryTest extends DatabaseTestCase ...@@ -49,6 +49,70 @@ class QueryTest extends DatabaseTestCase
$this->assertEquals([':id' => 1, ':name' => 'something', ':age' => '30'], $query->params); $this->assertEquals([':id' => 1, ':name' => 'something', ':age' => '30'], $query->params);
} }
public function testFilterWhere()
{
// should just call where() when string is passed
$query = new Query;
$query->filterWhere('id = :id', [':id' => null]);
$this->assertEquals('id = :id', $query->where);
$this->assertEquals([':id' => null], $query->params);
// should work with hash format
$query = new Query;
$query->filterWhere([
'id' => 0,
'title' => ' ',
'author_ids' => [],
]);
$this->assertEquals(['id' => 0], $query->where);
$query->andFilterWhere(['status' => null]);
$this->assertEquals(['id' => 0], $query->where);
$query->orFilterWhere(['name' => '']);
$this->assertEquals(['id' => 0], $query->where);
// should work with operator format
$query = new Query;
$condition = ['like', 'name', 'Alex'];
$query->filterWhere($condition);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['between', 'id', null, null]);
$this->assertEquals($condition, $query->where);
$query->orFilterWhere(['not between', 'id', null, null]);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['in', 'id', []]);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['not in', 'id', []]);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['not in', 'id', []]);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['like', 'id', '']);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['or like', 'id', '']);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['not like', 'id', ' ']);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['or not like', 'id', null]);
$this->assertEquals($condition, $query->where);
}
public function testFilterRecursively()
{
$query = new Query();
$query->filterWhere(['and', ['like', 'name', ''], ['like', 'title', ''], ['id' => 1], ['not', ['like', 'name', '']]]);
$this->assertEquals(['id' => 1], $query->where);
}
public function testJoin() public function testJoin()
{ {
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment