Unverified Commit 43819af1 authored by Sergei Morozov's avatar Sergei Morozov

Merge branch '3.0.x'

parents 77087e73 54fb5e08
......@@ -21,7 +21,7 @@ before_commands:
tools:
external_code_coverage:
timeout: 3600
runs: 29 # 24x Travis (jobs with COVERAGE=yes) + 3x AppVeyor (jobs with coverage=yes) + 2x ContinuousPHP
runs: 26 # 21x Travis (jobs with COVERAGE=yes) + 3x AppVeyor (jobs with coverage=yes) + 2x ContinuousPHP
filter:
excluded_paths:
......
......@@ -17,7 +17,11 @@ before_script:
- if [[ "$DB" == "mysql" || "$DB" == "mysqli" || "$DB" == *"mariadb"* ]]; then mysql < tests/travis/create-mysql-schema.sql; fi;
install:
- travis_retry composer -n install --prefer-dist
- |
if [[ $TRAVIS_PHP_VERSION = "nightly" ]]; then
export COMPOSER_FLAGS="--ignore-platform-reqs"
fi
- travis_retry composer -n install --prefer-dist $COMPOSER_FLAGS
script:
- |
......@@ -302,6 +306,63 @@ jobs:
before_script:
- bash ./tests/travis/install-db2.sh
- bash ./tests/travis/install-db2-ibm_db2.sh
- stage: Test
php: nightly
env: DB=mysql.docker MYSQL_VERSION=8.0
sudo: required
services:
- docker
before_script:
- bash ./tests/travis/install-mysql-8.0.sh
- stage: Test
php: nightly
env: DB=mysqli.docker MYSQL_VERSION=8.0
sudo: required
services:
- docker
before_script:
- bash ./tests/travis/install-mysql-8.0.sh
- stage: Test
php: nightly
env: DB=mariadb MARIADB_VERSION=10.3
addons:
mariadb: 10.3
- stage: Test
php: nightly
env: DB=mariadb.mysqli MARIADB_VERSION=10.3
addons:
mariadb: 10.3
- stage: Test
php: nightly
env: DB=pgsql POSTGRESQL_VERSION=11.0
sudo: required
services:
- docker
before_script:
- bash ./tests/travis/install-postgres-11.sh
- stage: Test
php: nightly
env: DB=sqlite
- stage: Test
php: nightly
env: DB=sqlsrv
sudo: required
services:
- docker
before_script:
- bash ./tests/travis/install-sqlsrv-dependencies.sh
- bash ./tests/travis/install-mssql-sqlsrv.sh
- bash ./tests/travis/install-mssql.sh
- stage: Test
php: nightly
env: DB=pdo_sqlsrv
sudo: required
services:
- docker
before_script:
- bash ./tests/travis/install-sqlsrv-dependencies.sh
- bash ./tests/travis/install-mssql-pdo_sqlsrv.sh
- bash ./tests/travis/install-mssql.sh
- stage: Test
if: type = cron
......@@ -313,3 +374,4 @@ jobs:
allow_failures:
- env: DEPENDENCIES=dev
- php: nightly
......@@ -390,6 +390,21 @@ The Drizzle project is abandoned and is therefore not supported by Doctrine DBAL
Use binary fields of a size which fits all target platforms, or use blob explicitly instead.
- Binary fields are no longer represented as streams in PHP. They are represented as strings.
# 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
......
......@@ -17,7 +17,6 @@ use stdClass;
use function array_key_exists;
use function assert;
use function count;
use function func_get_args;
use function is_array;
use function is_int;
use function is_object;
......@@ -228,7 +227,7 @@ final class SQLAnywhereStatement implements IteratorAggregate, Statement
switch ($fetchMode) {
case FetchMode::CUSTOM_OBJECT:
while (($row = $this->fetch(...func_get_args())) !== false) {
while (($row = $this->fetch($fetchMode, ...$args)) !== false) {
$rows[] = $row;
}
......
......@@ -51,6 +51,8 @@ class CompositeExpression implements Countable
/**
* Adds multiple parts to composite expression.
*
* @deprecated This class will be made immutable. Use with() instead.
*
* @param array<int, self|string> $parts
*
* @return $this
......@@ -67,6 +69,8 @@ class CompositeExpression implements Countable
/**
* Adds an expression to composite expression.
*
* @deprecated This class will be made immutable. Use with() instead.
*
* @param self|string $part
*
* @return $this
......@@ -86,6 +90,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.
*/
......
......@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Query\Expression;
use Doctrine\DBAL\Connection;
use function array_merge;
use function implode;
use function sprintf;
......@@ -40,11 +41,27 @@ class ExpressionBuilder
/**
* 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 string|CompositeExpression ...$expressions Requires at least one defined when converting to string.
*/
......@@ -54,13 +71,7 @@ class ExpressionBuilder
}
/**
* Creates a disjunction of the given expressions.
*
* Example:
*
* [php]
* // (u.type = ?) OR (u.role = ?)
* $qb->where($qb->expr()->orX('u.type = ?', 'u.role = ?'));
* @deprecated Use `or()` instead.
*
* @param string|CompositeExpression ...$expressions Requires at least one defined when converting to string.
*/
......
<?php
declare(strict_types=1);
namespace Doctrine\Tests\DBAL\Functional;
use Doctrine\DBAL\Driver\Exception\UnknownFetchMode;
use Doctrine\DBAL\Driver\PDOConnection;
use Doctrine\DBAL\Schema\Table;
use Doctrine\Tests\DbalFunctionalTestCase;
use PDO;
/**
* @requires extension pdo
*/
class PDOStatementTest extends DbalFunctionalTestCase
{
protected function setUp() : void
{
parent::setUp();
if (! $this->connection->getWrappedConnection() instanceof PDOConnection) {
$this->markTestSkipped('PDO-only test');
}
$table = new Table('stmt_test');
$table->addColumn('id', 'integer');
$table->addColumn('name', 'string', ['length' => 8]);
$this->connection->getSchemaManager()->dropAndCreateTable($table);
}
public function testPDOSpecificModeIsAccepted() : void
{
$this->connection->insert('stmt_test', [
'id' => 1,
'name' => 'Alice',
]);
$this->connection->insert('stmt_test', [
'id' => 2,
'name' => 'Bob',
]);
$this->expectException(UnknownFetchMode::class);
$this->expectExceptionMessage('Unknown fetch mode 12.');
$data = $this->connection->query('SELECT id, name FROM stmt_test ORDER BY id')
->fetchAll(PDO::FETCH_KEY_PAIR);
self::assertSame([
1 => 'Alice',
2 => 'Bob',
], $data);
}
}
......@@ -18,7 +18,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);
}
......@@ -42,6 +42,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
*
......
......@@ -31,7 +31,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
{
......@@ -47,7 +59,7 @@ class ExpressionBuilderTest extends DbalTestCase
/**
* @return mixed[][]
*/
public static function provideDataForAndX() : iterable
public static function provideDataForAnd() : iterable
{
return [
[
......@@ -92,7 +104,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
{
......@@ -108,7 +132,7 @@ class ExpressionBuilderTest extends DbalTestCase
/**
* @return mixed[][]
*/
public static function provideDataForOrX() : iterable
public static function provideDataForOr() : iterable
{
return [
[
......
......@@ -70,7 +70,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