Unverified Commit 54fb5e08 authored by Sergei Morozov's avatar Sergei Morozov

Merge branch '2.11.x' into 3.0.x

parents 8b9a3200 ae76cccb
......@@ -46,6 +46,21 @@ Please use other database client applications for import, e.g.:
* For PostgreSQL: `psql [dbname] < data.sql`.
* For SQLite: `sqlite3 /path/to/file.db < data.sql`.
# Upgrade to 2.11
## Deprecated `ExpressionBuilder` methods
The usage of the `andX()` and `orX()` methods of the `ExpressionBuilder` class has been deprecated. Use `and()` and `or()` instead.
## Deprecated `CompositeExpression` methods
The usage of the `add()` and `addMultiple()` methods of the `CompositeExpression` class has been deprecated. Use `with()` instead, which returns a new instance.
In the future, the `add*()` methods will be removed and the class will be effectively immutable.
## Deprecated calling `QueryBuilder` methods with an array argument
Calling the `select()`, `addSelect()`, `groupBy()` and `addGroupBy()` methods with an array argument is deprecated.
# Upgrade to 2.10
## Deprecated `Doctrine\DBAL\Event\ConnectionEventArgs` methods
......
......@@ -332,13 +332,13 @@ Most notably you can use expressions to build nested And-/Or statements:
->select('id', 'name')
->from('users')
->where(
$queryBuilder->expr()->andX(
$queryBuilder->expr()->and(
$queryBuilder->expr()->eq('username', '?'),
$queryBuilder->expr()->eq('email', '?')
)
);
The ``andX()`` and ``orX()`` methods accept an arbitrary amount
The ``and()`` and ``or()`` methods accept an arbitrary amount
of arguments and can be nested in each other.
There is a bunch of methods to create comparisons and other SQL snippets
......
......@@ -49,6 +49,8 @@ class CompositeExpression implements Countable
/**
* Adds multiple parts to composite expression.
*
* @deprecated This class will be made immutable. Use with() instead.
*
* @param self[]|string[] $parts
*
* @return \Doctrine\DBAL\Query\Expression\CompositeExpression
......@@ -65,6 +67,8 @@ class CompositeExpression implements Countable
/**
* Adds an expression to composite expression.
*
* @deprecated This class will be made immutable. Use with() instead.
*
* @param mixed $part
*
* @return \Doctrine\DBAL\Query\Expression\CompositeExpression
......@@ -84,6 +88,25 @@ class CompositeExpression implements Countable
return $this;
}
/**
* Returns a new CompositeExpression with the given parts added.
*
* @param self|string $part
* @param self|string ...$parts
*/
public function with($part, ...$parts) : self
{
$that = clone $this;
$that->parts[] = $part;
foreach ($parts as $part) {
$that->parts[] = $part;
}
return $that;
}
/**
* Retrieves the amount of expressions on composite expression.
*
......
......@@ -3,6 +3,7 @@
namespace Doctrine\DBAL\Query\Expression;
use Doctrine\DBAL\Connection;
use function array_merge;
use function func_get_arg;
use function func_get_args;
use function func_num_args;
......@@ -39,13 +40,29 @@ class ExpressionBuilder
}
/**
* Creates a conjunction of the given boolean expressions.
* Creates a conjunction of the given expressions.
*
* Example:
* @param string|CompositeExpression $expression
* @param string|CompositeExpression ...$expressions
*/
public function and($expression, ...$expressions) : CompositeExpression
{
return new CompositeExpression(CompositeExpression::TYPE_AND, array_merge([$expression], $expressions));
}
/**
* Creates a disjunction of the given expressions.
*
* [php]
* // (u.type = ?) AND (u.role = ?)
* $expr->andX('u.type = ?', 'u.role = ?'));
* @param string|CompositeExpression $expression
* @param string|CompositeExpression ...$expressions
*/
public function or($expression, ...$expressions) : CompositeExpression
{
return new CompositeExpression(CompositeExpression::TYPE_OR, array_merge([$expression], $expressions));
}
/**
* @deprecated Use `and()` instead.
*
* @param mixed $x Optional clause. Defaults = null, but requires
* at least one defined when converting to string.
......@@ -58,13 +75,7 @@ class ExpressionBuilder
}
/**
* Creates a disjunction of the given boolean expressions.
*
* Example:
*
* [php]
* // (u.type = ?) OR (u.role = ?)
* $qb->where($qb->expr()->orX('u.type = ?', 'u.role = ?'));
* @deprecated Use `or()` instead.
*
* @param mixed $x Optional clause. Defaults = null, but requires
* at least one defined when converting to string.
......
......@@ -451,6 +451,8 @@ class QueryBuilder
* Specifies an item that is to be returned in the query result.
* Replaces any previously specified selections, if any.
*
* USING AN ARRAY ARGUMENT IS DEPRECATED. Pass each value as an individual argument.
*
* <code>
* $qb = $conn->createQueryBuilder()
* ->select('u.id', 'p.id')
......@@ -458,11 +460,12 @@ class QueryBuilder
* ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
* </code>
*
* @param mixed $select The selection expressions.
* @param string|string[]|null $select The selection expression. USING AN ARRAY OR NULL IS DEPRECATED.
* Pass each value as an individual argument.
*
* @return $this This QueryBuilder instance.
*/
public function select($select = null)
public function select($select = null/*, string ...$selects*/)
{
$this->type = self::SELECT;
......@@ -497,6 +500,8 @@ class QueryBuilder
/**
* Adds an item that is to be returned in the query result.
*
* USING AN ARRAY ARGUMENT IS DEPRECATED. Pass each value as an individual argument.
*
* <code>
* $qb = $conn->createQueryBuilder()
* ->select('u.id')
......@@ -505,11 +510,12 @@ class QueryBuilder
* ->leftJoin('u', 'phonenumbers', 'u.id = p.user_id');
* </code>
*
* @param mixed $select The selection expression.
* @param string|string[]|null $select The selection expression. USING AN ARRAY OR NULL IS DEPRECATED.
* Pass each value as an individual argument.
*
* @return $this This QueryBuilder instance.
*/
public function addSelect($select = null)
public function addSelect($select = null/*, string ...$selects*/)
{
$this->type = self::SELECT;
......@@ -823,7 +829,7 @@ class QueryBuilder
$where = $this->getQueryPart('where');
if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_AND) {
$where->addMultiple($args);
$where = $where->with(...$args);
} else {
array_unshift($args, $where);
$where = new CompositeExpression(CompositeExpression::TYPE_AND, $args);
......@@ -856,7 +862,7 @@ class QueryBuilder
$where = $this->getQueryPart('where');
if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_OR) {
$where->addMultiple($args);
$where = $where->with(...$args);
} else {
array_unshift($args, $where);
$where = new CompositeExpression(CompositeExpression::TYPE_OR, $args);
......@@ -869,6 +875,8 @@ class QueryBuilder
* Specifies a grouping over the results of the query.
* Replaces any previously specified groupings, if any.
*
* USING AN ARRAY ARGUMENT IS DEPRECATED. Pass each value as an individual argument.
*
* <code>
* $qb = $conn->createQueryBuilder()
* ->select('u.name')
......@@ -876,11 +884,12 @@ class QueryBuilder
* ->groupBy('u.id');
* </code>
*
* @param mixed $groupBy The grouping expression.
* @param string|string[] $groupBy The grouping expression. USING AN ARRAY IS DEPRECATED.
* Pass each value as an individual argument.
*
* @return $this This QueryBuilder instance.
*/
public function groupBy($groupBy)
public function groupBy($groupBy/*, string ...$groupBys*/)
{
if (empty($groupBy)) {
return $this;
......@@ -894,6 +903,8 @@ class QueryBuilder
/**
* Adds a grouping expression to the query.
*
* USING AN ARRAY ARGUMENT IS DEPRECATED. Pass each value as an individual argument.
*
* <code>
* $qb = $conn->createQueryBuilder()
* ->select('u.name')
......@@ -902,11 +913,12 @@ class QueryBuilder
* ->addGroupBy('u.createdAt');
* </code>
*
* @param mixed $groupBy The grouping expression.
* @param string|string[] $groupBy The grouping expression. USING AN ARRAY IS DEPRECATED.
* Pass each value as an individual argument.
*
* @return $this This QueryBuilder instance.
*/
public function addGroupBy($groupBy)
public function addGroupBy($groupBy/*, string ...$groupBys*/)
{
if (empty($groupBy)) {
return $this;
......@@ -998,7 +1010,7 @@ class QueryBuilder
$having = $this->getQueryPart('having');
if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_AND) {
$having->addMultiple($args);
$having = $having->with(...$args);
} else {
array_unshift($args, $having);
$having = new CompositeExpression(CompositeExpression::TYPE_AND, $args);
......@@ -1021,7 +1033,7 @@ class QueryBuilder
$having = $this->getQueryPart('having');
if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_OR) {
$having->addMultiple($args);
$having = $having->with(...$args);
} else {
array_unshift($args, $having);
$having = new CompositeExpression(CompositeExpression::TYPE_OR, $args);
......
......@@ -16,7 +16,7 @@ class CompositeExpressionTest extends DbalTestCase
self::assertCount(1, $expr);
$expr->add('u.group_id = 2');
$expr = $expr->with('u.group_id = 2');
self::assertCount(2, $expr);
}
......@@ -44,6 +44,26 @@ class CompositeExpressionTest extends DbalTestCase
self::assertCount(3, $expr);
}
public function testWith() : void
{
$expr = new CompositeExpression(CompositeExpression::TYPE_OR, ['u.group_id = 1']);
self::assertCount(1, $expr);
// test immutability
$expr->with(new CompositeExpression(CompositeExpression::TYPE_OR, ['u.user_id = 1']));
self::assertCount(1, $expr);
$expr = $expr->with(new CompositeExpression(CompositeExpression::TYPE_OR, ['u.user_id = 1']));
self::assertCount(2, $expr);
$expr = $expr->with('u.user_id = 1');
self::assertCount(3, $expr);
}
/**
* @param string[]|CompositeExpression[] $parts
*
......
......@@ -29,7 +29,19 @@ class ExpressionBuilderTest extends DbalTestCase
/**
* @param string[]|CompositeExpression[] $parts
*
* @dataProvider provideDataForAndX
* @dataProvider provideDataForAnd
*/
public function testAnd(array $parts, string $expected) : void
{
$composite = $this->expr->and(...$parts);
self::assertEquals($expected, (string) $composite);
}
/**
* @param string[]|CompositeExpression[] $parts
*
* @dataProvider provideDataForAnd
*/
public function testAndX(array $parts, string $expected) : void
{
......@@ -45,7 +57,7 @@ class ExpressionBuilderTest extends DbalTestCase
/**
* @return mixed[][]
*/
public static function provideDataForAndX() : iterable
public static function provideDataForAnd() : iterable
{
return [
[
......@@ -90,7 +102,19 @@ class ExpressionBuilderTest extends DbalTestCase
/**
* @param string[]|CompositeExpression[] $parts
*
* @dataProvider provideDataForOrX
* @dataProvider provideDataForOr
*/
public function testOr(array $parts, string $expected) : void
{
$composite = $this->expr->or(...$parts);
self::assertEquals($expected, (string) $composite);
}
/**
* @param string[]|CompositeExpression[] $parts
*
* @dataProvider provideDataForOr
*/
public function testOrX(array $parts, string $expected) : void
{
......@@ -106,7 +130,7 @@ class ExpressionBuilderTest extends DbalTestCase
/**
* @return mixed[][]
*/
public static function provideDataForOrX() : iterable
public static function provideDataForOr() : iterable
{
return [
[
......
......@@ -68,7 +68,7 @@ class QueryBuilderTest extends DbalTestCase
$qb->select('u.id')
->from('users', 'u')
->where($expr->andX($expr->eq('u.nickname', '?')));
->where($expr->and($expr->eq('u.nickname', '?')));
self::assertEquals('SELECT u.id FROM users u WHERE u.nickname = ?', (string) $qb);
}
......
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