Files
yii2/tests/framework/db/QueryTest.php
Robert Korulczyk ba0ab403b5 Added php-cs-fixer coding standards validation to Travis CI (#14100)
* php-cs-fixer: PSR2 rule.

* php-cs-fixer: PSR2 rule - fix views.

* Travis setup refactoring.

* Add php-cs-fixer to travis cs tests.

* Fix tests on hhvm-3.12

* improve travis config

* composer update

* revert composer update

* improve travis config

* Fix CS.

* Extract config to separate classes.

* Extract config to separate classes.

* Add file header.

* Force short array syntax.

* binary_operator_spaces fixer

* Fix broken tests

* cast_spaces fixer

* concat_space fixer

* dir_constant fixer

* ereg_to_preg fixer

* function_typehint_space fixer

* hash_to_slash_comment fixer

* is_null fixer

* linebreak_after_opening_tag fixer

* lowercase_cast fixer

* magic_constant_casing fixer

* modernize_types_casting fixer

* native_function_casing fixer

* new_with_braces fixer

* no_alias_functions fixer

* no_blank_lines_after_class_opening fixer

* no_blank_lines_after_phpdoc fixer

* no_empty_comment fixer

* no_empty_phpdoc fixer

* no_empty_statement fixer

* no_extra_consecutive_blank_lines fixer

* no_leading_import_slash fixer

* no_leading_namespace_whitespace fixer

* no_mixed_echo_print fixer

* no_multiline_whitespace_around_double_arrow fixer

* no_multiline_whitespace_before_semicolons fixer

* no_php4_constructor fixer

* no_short_bool_cast fixer

* no_singleline_whitespace_before_semicolons fixer

* no_spaces_around_offset fixer

* no_trailing_comma_in_list_call fixer

* no_trailing_comma_in_singleline_array fixer

* no_unneeded_control_parentheses fixer

* no_unused_imports fixer

* no_useless_return fixer

* no_whitespace_before_comma_in_array fixer

* no_whitespace_in_blank_line fixer

* not_operator_with_successor_space fixer

* object_operator_without_whitespace fixer

* ordered_imports fixer

* php_unit_construct fixer

* php_unit_dedicate_assert fixer

* php_unit_fqcn_annotation fixer

* phpdoc_indent fixer

* phpdoc_no_access fixer

* phpdoc_no_empty_return fixer

* phpdoc_no_package fixer

* phpdoc_no_useless_inheritdoc fixer

* Fix broken tests

* phpdoc_return_self_reference fixer

* phpdoc_single_line_var_spacing fixer

* phpdoc_single_line_var_spacing fixer

* phpdoc_to_comment fixer

* phpdoc_trim fixer

* phpdoc_var_without_name fixer

* psr4 fixer

* self_accessor fixer

* short_scalar_cast fixer

* single_blank_line_before_namespace fixer

* single_quote fixer

* standardize_not_equals fixer

* ternary_operator_spaces fixer

* trailing_comma_in_multiline_array fixer

* trim_array_spaces fixer

* protected_to_private fixer

* unary_operator_spaces fixer

* whitespace_after_comma_in_array fixer

* `parent::setRules()` -> `$this->setRules()`

* blank_line_after_opening_tag fixer

* Update finder config.

* Revert changes for YiiRequirementChecker.

* Fix array formatting.

* Add missing import.

* Fix CS for new code merged from master.

* Fix some indentation issues.
2017-06-12 12:25:45 +03:00

541 lines
18 KiB
PHP

<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yiiunit\framework\db;
use yii\db\Connection;
use yii\db\Expression;
use yii\db\Query;
use yii\db\Schema;
abstract class QueryTest extends DatabaseTestCase
{
public function testSelect()
{
// default
$query = new Query();
$query->select('*');
$this->assertEquals(['*'], $query->select);
$this->assertNull($query->distinct);
$this->assertEquals(null, $query->selectOption);
$query = new Query();
$query->select('id, name', 'something')->distinct(true);
$this->assertEquals(['id', 'name'], $query->select);
$this->assertTrue($query->distinct);
$this->assertEquals('something', $query->selectOption);
$query = new Query();
$query->addSelect('email');
$this->assertEquals(['email'], $query->select);
$query = new Query();
$query->select('id, name');
$query->addSelect('email');
$this->assertEquals(['id', 'name', 'email'], $query->select);
}
public function testFrom()
{
$query = new Query();
$query->from('user');
$this->assertEquals(['user'], $query->from);
}
public function testWhere()
{
$query = new Query();
$query->where('id = :id', [':id' => 1]);
$this->assertEquals('id = :id', $query->where);
$this->assertEquals([':id' => 1], $query->params);
$query->andWhere('name = :name', [':name' => 'something']);
$this->assertEquals(['and', 'id = :id', 'name = :name'], $query->where);
$this->assertEquals([':id' => 1, ':name' => 'something'], $query->params);
$query->orWhere('age = :age', [':age' => '30']);
$this->assertEquals(['or', ['and', 'id = :id', 'name = :name'], 'age = :age'], $query->where);
$this->assertEquals([':id' => 1, ':name' => 'something', ':age' => '30'], $query->params);
}
public function testFilterWhereWithHashFormat()
{
$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 testFilterWhereWithOperatorFormat()
{
$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(['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);
$query->andFilterWhere(['or', ['eq', 'id', null], ['eq', 'id', []]]);
$this->assertEquals($condition, $query->where);
}
public function testFilterHavingWithHashFormat()
{
$query = new Query();
$query->filterHaving([
'id' => 0,
'title' => ' ',
'author_ids' => [],
]);
$this->assertEquals(['id' => 0], $query->having);
$query->andFilterHaving(['status' => null]);
$this->assertEquals(['id' => 0], $query->having);
$query->orFilterHaving(['name' => '']);
$this->assertEquals(['id' => 0], $query->having);
}
public function testFilterHavingWithOperatorFormat()
{
$query = new Query();
$condition = ['like', 'name', 'Alex'];
$query->filterHaving($condition);
$this->assertEquals($condition, $query->having);
$query->andFilterHaving(['between', 'id', null, null]);
$this->assertEquals($condition, $query->having);
$query->orFilterHaving(['not between', 'id', null, null]);
$this->assertEquals($condition, $query->having);
$query->andFilterHaving(['in', 'id', []]);
$this->assertEquals($condition, $query->having);
$query->andFilterHaving(['not in', 'id', []]);
$this->assertEquals($condition, $query->having);
$query->andFilterHaving(['like', 'id', '']);
$this->assertEquals($condition, $query->having);
$query->andFilterHaving(['or like', 'id', '']);
$this->assertEquals($condition, $query->having);
$query->andFilterHaving(['not like', 'id', ' ']);
$this->assertEquals($condition, $query->having);
$query->andFilterHaving(['or not like', 'id', null]);
$this->assertEquals($condition, $query->having);
$query->andFilterHaving(['or', ['eq', 'id', null], ['eq', 'id', []]]);
$this->assertEquals($condition, $query->having);
}
public function testFilterRecursively()
{
$query = new Query();
$query->filterWhere(['and', ['like', 'name', ''], ['like', 'title', ''], ['id' => 1], ['not', ['like', 'name', '']]]);
$this->assertEquals(['and', ['id' => 1]], $query->where);
}
/*public function testJoin()
{
}*/
public function testGroup()
{
$query = new Query();
$query->groupBy('team');
$this->assertEquals(['team'], $query->groupBy);
$query->addGroupBy('company');
$this->assertEquals(['team', 'company'], $query->groupBy);
$query->addGroupBy('age');
$this->assertEquals(['team', 'company', 'age'], $query->groupBy);
}
public function testHaving()
{
$query = new Query();
$query->having('id = :id', [':id' => 1]);
$this->assertEquals('id = :id', $query->having);
$this->assertEquals([':id' => 1], $query->params);
$query->andHaving('name = :name', [':name' => 'something']);
$this->assertEquals(['and', 'id = :id', 'name = :name'], $query->having);
$this->assertEquals([':id' => 1, ':name' => 'something'], $query->params);
$query->orHaving('age = :age', [':age' => '30']);
$this->assertEquals(['or', ['and', 'id = :id', 'name = :name'], 'age = :age'], $query->having);
$this->assertEquals([':id' => 1, ':name' => 'something', ':age' => '30'], $query->params);
}
public function testOrder()
{
$query = new Query();
$query->orderBy('team');
$this->assertEquals(['team' => SORT_ASC], $query->orderBy);
$query->addOrderBy('company');
$this->assertEquals(['team' => SORT_ASC, 'company' => SORT_ASC], $query->orderBy);
$query->addOrderBy('age');
$this->assertEquals(['team' => SORT_ASC, 'company' => SORT_ASC, 'age' => SORT_ASC], $query->orderBy);
$query->addOrderBy(['age' => SORT_DESC]);
$this->assertEquals(['team' => SORT_ASC, 'company' => SORT_ASC, 'age' => SORT_DESC], $query->orderBy);
$query->addOrderBy('age ASC, company DESC');
$this->assertEquals(['team' => SORT_ASC, 'company' => SORT_DESC, 'age' => SORT_ASC], $query->orderBy);
$expression = new Expression('SUBSTR(name, 3, 4) DESC, x ASC');
$query->orderBy($expression);
$this->assertEquals([$expression], $query->orderBy);
$expression = new Expression('SUBSTR(name, 3, 4) DESC, x ASC');
$query->addOrderBy($expression);
$this->assertEquals([$expression, $expression], $query->orderBy);
}
public function testLimitOffset()
{
$query = new Query();
$query->limit(10)->offset(5);
$this->assertEquals(10, $query->limit);
$this->assertEquals(5, $query->offset);
}
public function testLimitOffsetWithExpression()
{
$query = (new Query())->from('customer')->select('id')->orderBy('id');
$query
->limit(new Expression('1 + 1'))
->offset(new Expression('1 + 0'));
$result = $query->column($this->getConnection());
$this->assertCount(2, $result);
$this->assertNotContains(1, $result);
$this->assertContains(2, $result);
$this->assertContains(3, $result);
}
public function testUnion()
{
$connection = $this->getConnection();
$query = new Query();
$query->select(['id', 'name'])
->from('item')
->limit(2)
->union(
(new Query())
->select(['id', 'name'])
->from(['category'])
->limit(2)
);
$result = $query->all($connection);
$this->assertNotEmpty($result);
$this->assertCount(4, $result);
}
public function testOne()
{
$db = $this->getConnection();
$result = (new Query())->from('customer')->where(['status' => 2])->one($db);
$this->assertEquals('user3', $result['name']);
$result = (new Query())->from('customer')->where(['status' => 3])->one($db);
$this->assertFalse($result);
}
public function testExists()
{
$db = $this->getConnection();
$result = (new Query())->from('customer')->where(['status' => 2])->exists($db);
$this->assertTrue($result);
$result = (new Query())->from('customer')->where(['status' => 3])->exists($db);
$this->assertFalse($result);
}
public function testColumn()
{
$db = $this->getConnection();
$result = (new Query())->select('name')->from('customer')->orderBy(['id' => SORT_DESC])->column($db);
$this->assertEquals(['user3', 'user2', 'user1'], $result);
// https://github.com/yiisoft/yii2/issues/7515
$result = (new Query())->from('customer')
->select('name')
->orderBy(['id' => SORT_DESC])
->indexBy('id')
->column($db);
$this->assertEquals([3 => 'user3', 2 => 'user2', 1 => 'user1'], $result);
// https://github.com/yiisoft/yii2/issues/12649
$result = (new Query())->from('customer')
->select(['name', 'id'])
->orderBy(['id' => SORT_DESC])
->indexBy(function ($row) {
return $row['id'] * 2;
})
->column($db);
$this->assertEquals([6 => 'user3', 4 => 'user2', 2 => 'user1'], $result);
$result = (new Query())->from('customer')
->select(['name'])
->indexBy('name')
->orderBy(['id' => SORT_DESC])
->column($db);
$this->assertEquals(['user3' => 'user3', 'user2' => 'user2', 'user1' => 'user1'], $result);
}
public function testCount()
{
$db = $this->getConnection();
$count = (new Query())->from('customer')->count('*', $db);
$this->assertEquals(3, $count);
$count = (new Query())->from('customer')->where(['status' => 2])->count('*', $db);
$this->assertEquals(1, $count);
$count = (new Query())->select('[[status]], COUNT([[id]])')->from('customer')->groupBy('status')->count('*', $db);
$this->assertEquals(2, $count);
// testing that orderBy() should be ignored here as it does not affect the count anyway.
$count = (new Query())->from('customer')->orderBy('status')->count('*', $db);
$this->assertEquals(3, $count);
$count = (new Query())->from('customer')->orderBy('id')->limit(1)->count('*', $db);
$this->assertEquals(3, $count);
}
/**
* @depends testFilterWhereWithHashFormat
* @depends testFilterWhereWithOperatorFormat
*/
public function testAndFilterCompare()
{
$query = new Query();
$result = $query->andFilterCompare('name', null);
$this->assertInstanceOf('yii\db\Query', $result);
$this->assertNull($query->where);
$query->andFilterCompare('name', '');
$this->assertNull($query->where);
$query->andFilterCompare('name', 'John Doe');
$condition = ['=', 'name', 'John Doe'];
$this->assertEquals($condition, $query->where);
$condition = ['and', $condition, ['like', 'name', 'Doe']];
$query->andFilterCompare('name', 'Doe', 'like');
$this->assertEquals($condition, $query->where);
$condition[] = ['>', 'rating', '9'];
$query->andFilterCompare('rating', '>9');
$this->assertEquals($condition, $query->where);
$condition[] = ['<=', 'value', '100'];
$query->andFilterCompare('value', '<=100');
$this->assertEquals($condition, $query->where);
}
/**
* @see https://github.com/yiisoft/yii2/issues/8068
*
* @depends testCount
*/
public function testCountHavingWithoutGroupBy()
{
if (!in_array($this->driverName, ['mysql'])) {
$this->markTestSkipped("{$this->driverName} does not support having without group by.");
}
$db = $this->getConnection();
$count = (new Query())->from('customer')->having(['status' => 2])->count('*', $db);
$this->assertEquals(1, $count);
}
public function testEmulateExecution()
{
$db = $this->getConnection();
$this->assertGreaterThan(0, (new Query())->from('customer')->count('*', $db));
$rows = (new Query())
->from('customer')
->emulateExecution()
->all($db);
$this->assertSame([], $rows);
$row = (new Query())
->from('customer')
->emulateExecution()
->one($db);
$this->assertFalse($row);
$exists = (new Query())
->from('customer')
->emulateExecution()
->exists($db);
$this->assertFalse($exists);
$count = (new Query())
->from('customer')
->emulateExecution()
->count('*', $db);
$this->assertSame(0, $count);
$sum = (new Query())
->from('customer')
->emulateExecution()
->sum('id', $db);
$this->assertSame(0, $sum);
$sum = (new Query())
->from('customer')
->emulateExecution()
->average('id', $db);
$this->assertSame(0, $sum);
$max = (new Query())
->from('customer')
->emulateExecution()
->max('id', $db);
$this->assertNull($max);
$min = (new Query())
->from('customer')
->emulateExecution()
->min('id', $db);
$this->assertNull($min);
$scalar = (new Query())
->select(['id'])
->from('customer')
->emulateExecution()
->scalar($db);
$this->assertNull($scalar);
$column = (new Query())
->select(['id'])
->from('customer')
->emulateExecution()
->column($db);
$this->assertSame([], $column);
}
/**
* @param Connection $db
* @param string $tableName
* @param string $columnName
* @param array $condition
* @param string $operator
* @return int
*/
protected function countLikeQuery(Connection $db, $tableName, $columnName, array $condition, $operator = 'or')
{
$whereCondition = [$operator];
foreach ($condition as $value) {
$whereCondition[] = ['like', $columnName, $value];
}
$result = (new Query())
->from($tableName)
->where($whereCondition)
->count('*', $db);
if (is_numeric($result)) {
$result = (int) $result;
}
return $result;
}
/**
* @see https://github.com/yiisoft/yii2/issues/13745
*/
public function testMultipleLikeConditions()
{
$db = $this->getConnection();
$tableName = 'like_test';
$columnName = 'col';
if ($db->getSchema()->getTableSchema($tableName) !== null) {
$db->createCommand()->dropTable($tableName)->execute();
}
$db->createCommand()->createTable($tableName, [
$columnName => $db->getSchema()->createColumnSchemaBuilder(Schema::TYPE_STRING, 64),
])->execute();
$db->createCommand()->batchInsert($tableName, ['col'], [
['test0'],
['test\1'],
['test\2'],
['foo%'],
['%bar'],
['%baz%'],
])->execute();
// Basic tests
$this->assertSame(1, $this->countLikeQuery($db, $tableName, $columnName, ['test0']));
$this->assertSame(2, $this->countLikeQuery($db, $tableName, $columnName, ['test\\']));
$this->assertSame(0, $this->countLikeQuery($db, $tableName, $columnName, ['test%']));
$this->assertSame(3, $this->countLikeQuery($db, $tableName, $columnName, ['%']));
// Multiple condition tests
$this->assertSame(2, $this->countLikeQuery($db, $tableName, $columnName, [
'test0',
'test\1',
]));
$this->assertSame(3, $this->countLikeQuery($db, $tableName, $columnName, [
'test0',
'test\1',
'test\2',
]));
$this->assertSame(3, $this->countLikeQuery($db, $tableName, $columnName, [
'foo',
'%ba',
]));
}
}