Skip to content

Commit

Permalink
Merge branch '4.2.x' into 4.3.x
Browse files Browse the repository at this point in the history
* 4.2.x:
  Create stubs instead of mocks (#6564)
  [Bug] Query Cache mangled if saved by-reference (#6552)
  test: remove ->expects(self::any())
  Fix typo in PostgreSql documentation reference
  fix
  Acknowledge the existence of 3.10 (#6553)
  test: cover nested transactions
  • Loading branch information
derrabus committed Oct 21, 2024
2 parents 33f5589 + e729f88 commit ce220bc
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 46 deletions.
6 changes: 6 additions & 0 deletions .doctrine-project.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@
"slug": "4.0",
"maintained": false
},
{
"name": "3.10",
"branchName": "3.10.x",
"slug": "3.10",
"upcoming": true
},
{
"name": "3.9",
"branchName": "3.9.x",
Expand Down
28 changes: 18 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Doctrine DBAL

| [5.0-dev][5.0] | [4.3-dev][4.3] | [4.2][4.2] | [3.9][3.9] |
|:---------------------------------------------------:|:---------------------------------------------------:|:---------------------------------------------------:|:---------------------------------------------------:|
| [![GitHub Actions][GA 5.0 image]][GA 5.0] | [![GitHub Actions][GA 4.3 image]][GA 4.3] | [![GitHub Actions][GA 4.2 image]][GA 4.2] | [![GitHub Actions][GA 3.9 image]][GA 3.9] |
| [![AppVeyor][AppVeyor 5.0 image]][AppVeyor 5.0] | [![AppVeyor][AppVeyor 4.3 image]][AppVeyor 4.3] | [![AppVeyor][AppVeyor 4.2 image]][AppVeyor 4.2] | [![AppVeyor][AppVeyor 3.9 image]][AppVeyor 3.9] |
| [![Code Coverage][Coverage 5.0 image]][CodeCov 5.0] | [![Code Coverage][Coverage 4.3 image]][CodeCov 4.3] | [![Code Coverage][Coverage 4.2 image]][CodeCov 4.2] | [![Code Coverage][Coverage 3.9 image]][CodeCov 3.9] |
| N/A | N/A | [![Type Coverage][TypeCov image]][TypeCov] | N/A |
| [5.0-dev][5.0] | [4.3-dev][4.3] | [4.2][4.2] | [3.10][3.10] | [3.9][3.9] |
|:---------------------------------------------------:|:---------------------------------------------------:|:---------------------------------------------------:|:-----------------------------------------------------:|:---------------------------------------------------:|
| [![GitHub Actions][GA 5.0 image]][GA 5.0] | [![GitHub Actions][GA 4.3 image]][GA 4.3] | [![GitHub Actions][GA 4.2 image]][GA 4.2] | [![GitHub Actions][GA 3.10 image]][GA 3.10] | [![GitHub Actions][GA 3.9 image]][GA 3.9] |
| [![AppVeyor][AppVeyor 5.0 image]][AppVeyor 5.0] | [![AppVeyor][AppVeyor 4.3 image]][AppVeyor 4.3] | [![AppVeyor][AppVeyor 4.2 image]][AppVeyor 4.2] | [![AppVeyor][AppVeyor 3.10 image]][AppVeyor 3.10] | [![AppVeyor][AppVeyor 3.9 image]][AppVeyor 3.9] |
| [![Code Coverage][Coverage 5.0 image]][CodeCov 5.0] | [![Code Coverage][Coverage 4.3 image]][CodeCov 4.3] | [![Code Coverage][Coverage 4.2 image]][CodeCov 4.2] | [![Code Coverage][Coverage 3.10 image]][CodeCov 3.10] | [![Code Coverage][Coverage 3.9 image]][CodeCov 3.9] |
| N/A | N/A | [![Type Coverage][TypeCov image]][TypeCov] | N/A | N/A |

Powerful ***D***ata***B***ase ***A***bstraction ***L***ayer with many features for database schema introspection and schema management.

Expand All @@ -21,30 +21,38 @@ Powerful ***D***ata***B***ase ***A***bstraction ***L***ayer with many features f
[AppVeyor 5.0]: https://ci.appveyor.com/project/doctrine/dbal/branch/5.0.x
[AppVeyor 5.0 image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/5.0.x?svg=true
[GA 5.0]: https://github.com/doctrine/dbal/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A5.0.x
[GA 5.0 image]: https://github.com/doctrine/dbal/workflows/Continuous%20Integration/badge.svg?branch=5.0.x
[GA 5.0 image]: https://github.com/doctrine/dbal/actions/workflows/continuous-integration.yml/badge.svg?branch=5.0.x

[Coverage 4.3 image]: https://codecov.io/gh/doctrine/dbal/branch/4.3.x/graph/badge.svg
[4.3]: https://github.com/doctrine/dbal/tree/4.3.x
[CodeCov 4.3]: https://codecov.io/gh/doctrine/dbal/branch/4.3.x
[AppVeyor 4.3]: https://ci.appveyor.com/project/doctrine/dbal/branch/4.3.x
[AppVeyor 4.3 image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/4.3.x?svg=true
[GA 4.3]: https://github.com/doctrine/dbal/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A4.3.x
[GA 4.3 image]: https://github.com/doctrine/dbal/workflows/Continuous%20Integration/badge.svg?branch=4.3.x
[GA 4.3 image]: https://github.com/doctrine/dbal/actions/workflows/continuous-integration.yml/badge.svg?branch=4.3.x

[Coverage 4.2 image]: https://codecov.io/gh/doctrine/dbal/branch/4.2.x/graph/badge.svg
[4.2]: https://github.com/doctrine/dbal/tree/4.2.x
[CodeCov 4.2]: https://codecov.io/gh/doctrine/dbal/branch/4.2.x
[AppVeyor 4.2]: https://ci.appveyor.com/project/doctrine/dbal/branch/4.2.x
[AppVeyor 4.2 image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/4.2.x?svg=true
[GA 4.2]: https://github.com/doctrine/dbal/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A4.2.x
[GA 4.2 image]: https://github.com/doctrine/dbal/workflows/Continuous%20Integration/badge.svg?branch=4.2.x
[GA 4.2 image]: https://github.com/doctrine/dbal/actions/workflows/continuous-integration.yml/badge.svg?branch=4.2.x
[TypeCov]: https://shepherd.dev/github/doctrine/dbal
[TypeCov image]: https://shepherd.dev/github/doctrine/dbal/coverage.svg

[Coverage 3.10 image]: https://codecov.io/gh/doctrine/dbal/branch/3.10.x/graph/badge.svg
[3.10]: https://github.com/doctrine/dbal/tree/3.10.x
[CodeCov 3.10]: https://codecov.io/gh/doctrine/dbal/branch/3.10.x
[AppVeyor 3.10]: https://ci.appveyor.com/project/doctrine/dbal/branch/3.10.x
[AppVeyor 3.10 image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/3.10.x?svg=true
[GA 3.10]: https://github.com/doctrine/dbal/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A3.10.x
[GA 3.10 image]: https://github.com/doctrine/dbal/actions/workflows/continuous-integration.yml/badge.svg?branch=3.10.x

[Coverage 3.9 image]: https://codecov.io/gh/doctrine/dbal/branch/3.9.x/graph/badge.svg
[3.9]: https://github.com/doctrine/dbal/tree/3.9.x
[CodeCov 3.9]: https://codecov.io/gh/doctrine/dbal/branch/3.9.x
[AppVeyor 3.9]: https://ci.appveyor.com/project/doctrine/dbal/branch/3.9.x
[AppVeyor 3.9 image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/3.9.x?svg=true
[GA 3.9]: https://github.com/doctrine/dbal/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A3.9.x
[GA 3.9 image]: https://github.com/doctrine/dbal/workflows/Continuous%20Integration/badge.svg?branch=3.9.x
[GA 3.9 image]: https://github.com/doctrine/dbal/actions/workflows/continuous-integration.yml/badge.svg?branch=3.9.x
2 changes: 1 addition & 1 deletion docs/en/reference/schema-representation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ and absolutely not portable.
- **engine** (string): The DB engine used for the table. Currently only supported on MySQL.

- **unlogged** (boolean): Set a PostgreSQL table type as
`unlogged <https://www.postgresql.org/docs/current/sql-createtable.htmll>`_
`unlogged <https://www.postgresql.org/docs/current/sql-createtable.html>`_

Column
~~~~~~
Expand Down
4 changes: 2 additions & 2 deletions src/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,7 @@ public function executeCacheQuery(string $sql, array $params, array $types, Quer
}

if (isset($value[$realKey]) && $value[$realKey] instanceof ArrayResult) {
return new Result($value[$realKey], $this);
return new Result(clone $value[$realKey], $this);
}
} else {
$value = [];
Expand All @@ -837,7 +837,7 @@ public function executeCacheQuery(string $sql, array $params, array $types, Quer

$resultCache->save($item);

return new Result($value[$realKey], $this);
return new Result(clone $value[$realKey], $this);
}

/**
Expand Down
36 changes: 28 additions & 8 deletions tests/Connection/CachedQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,49 +8,60 @@
use Doctrine\DBAL\Cache\QueryCacheProfile;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\Cache\Adapter\ArrayAdapter;

class CachedQueryTest extends TestCase
{
public function testCachedQuery(): void
#[DataProvider('providePsrCacheImplementations')]
public function testCachedQuery(callable $psrCacheProvider): void
{
$cache = new ArrayAdapter();
$cache = $psrCacheProvider();

$connection = $this->createConnection(1, ['foo'], [['bar']]);
$qcp = new QueryCacheProfile(0, __FUNCTION__, $cache);

self::assertSame([['foo' => 'bar']], $connection->executeCacheQuery('SELECT 1', [], [], $qcp)
$firstResult = $connection->executeCacheQuery('SELECT 1', [], [], $qcp);
self::assertSame([['foo' => 'bar']], $firstResult
->fetchAllAssociative());
$firstResult->free();
$secondResult = $connection->executeCacheQuery('SELECT 1', [], [], $qcp);
self::assertSame([['foo' => 'bar']], $secondResult
->fetchAllAssociative());
$secondResult->free();
self::assertSame([['foo' => 'bar']], $connection->executeCacheQuery('SELECT 1', [], [], $qcp)
->fetchAllAssociative());

self::assertCount(1, $cache->getItem(__FUNCTION__)->get());
}

public function testCachedQueryWithChangedImplementationIsExecutedTwice(): void
#[DataProvider('providePsrCacheImplementations')]
public function testCachedQueryWithChangedImplementationIsExecutedTwice(callable $psrCacheProvider): void
{
$connection = $this->createConnection(2, ['baz'], [['qux']]);

self::assertSame([['baz' => 'qux']], $connection->executeCacheQuery(
'SELECT 1',
[],
[],
new QueryCacheProfile(0, __FUNCTION__, new ArrayAdapter()),
new QueryCacheProfile(0, __FUNCTION__, $psrCacheProvider()),
)->fetchAllAssociative());

self::assertSame([['baz' => 'qux']], $connection->executeCacheQuery(
'SELECT 1',
[],
[],
new QueryCacheProfile(0, __FUNCTION__, new ArrayAdapter()),
new QueryCacheProfile(0, __FUNCTION__, $psrCacheProvider()),
)->fetchAllAssociative());
}

public function testOldCacheFormat(): void
#[DataProvider('providePsrCacheImplementations')]
public function testOldCacheFormat(callable $psrCacheProvider): void
{
$connection = $this->createConnection(1, ['foo'], [['bar']]);
$cache = new ArrayAdapter();
$cache = $psrCacheProvider();
$qcp = new QueryCacheProfile(0, __FUNCTION__, $cache);

[$cacheKey, $realKey] = $qcp->generateCacheKeys('SELECT 1', [], [], []);
Expand Down Expand Up @@ -83,4 +94,13 @@ private function createConnection(int $expectedQueryCount, array $columnNames, a

return new Connection([], $driver);
}

/** @return array<non-empty-string, list<callable():CacheItemPoolInterface>> */
public static function providePsrCacheImplementations(): array
{
return [
'serialized' => [static fn () => new ArrayAdapter(0, true)],
'by-reference' => [static fn () => new ArrayAdapter(0, false)],
];
}
}
22 changes: 11 additions & 11 deletions tests/ConnectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ protected function setUp(): void

private function getExecuteStatementMockConnection(): Connection&MockObject
{
$driverMock = $this->createMock(Driver::class);
$driver = self::createStub(Driver::class);

return $this->getMockBuilder(Connection::class)
->onlyMethods(['executeStatement'])
->setConstructorArgs([[], $driverMock])
->setConstructorArgs([[], $driver])
->getMock();
}

Expand Down Expand Up @@ -146,9 +146,9 @@ public function testSetAutoCommit(): void

public function testConnectStartsTransactionInNoAutoCommitMode(): void
{
$driverMock = $this->createMock(Driver::class);
$driver = self::createStub(Driver::class);

$conn = new Connection([], $driverMock);
$conn = new Connection([], $driver);

$conn->setAutoCommit(false);

Expand All @@ -161,9 +161,9 @@ public function testConnectStartsTransactionInNoAutoCommitMode(): void

public function testCommitStartsTransactionInNoAutoCommitMode(): void
{
$driverMock = $this->createMock(Driver::class);
$driver = self::createStub(Driver::class);

$conn = new Connection([], $driverMock);
$conn = new Connection([], $driver);

$conn->setAutoCommit(false);
$conn->executeQuery('SELECT 1');
Expand All @@ -180,9 +180,9 @@ public static function resultProvider(): array

public function testRollBackStartsTransactionInNoAutoCommitMode(): void
{
$driverMock = $this->createMock(Driver::class);
$driver = self::createStub(Driver::class);

$conn = new Connection([], $driverMock);
$conn = new Connection([], $driver);

$conn->setAutoCommit(false);
$conn->executeQuery('SELECT 1');
Expand All @@ -198,12 +198,12 @@ public function testSwitchingAutoCommitModeCommitsAllCurrentTransactions(): void
->method('supportsSavepoints')
->willReturn(true);

$driverMock = $this->createMock(Driver::class);
$driverMock
$driver = self::createStub(Driver::class);
$driver
->method('getDatabasePlatform')
->willReturn($platform);

$conn = new Connection([], $driverMock);
$conn = new Connection([], $driver);

$conn->beginTransaction();
$conn->beginTransaction();
Expand Down
45 changes: 36 additions & 9 deletions tests/Functional/TransactionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception\ConnectionLost;
use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Tests\FunctionalTestCase;
use Doctrine\DBAL\Types\Types;

use function func_get_args;
use function restore_error_handler;
Expand All @@ -18,15 +20,6 @@

class TransactionTest extends FunctionalTestCase
{
protected function setUp(): void
{
if ($this->connection->getDatabasePlatform() instanceof AbstractMySQLPlatform) {
return;
}

self::markTestSkipped('Restricted to MySQL.');
}

public function testCommitFailure(): void
{
$this->expectConnectionLoss(static function (Connection $connection): void {
Expand All @@ -43,6 +36,10 @@ public function testRollbackFailure(): void

private function expectConnectionLoss(callable $scenario): void
{
if (! $this->connection->getDatabasePlatform() instanceof AbstractMySQLPlatform) {
self::markTestSkipped('Restricted to MySQL.');
}

$this->connection->executeStatement('SET SESSION wait_timeout=1');
$this->connection->beginTransaction();

Expand All @@ -67,4 +64,34 @@ private function expectConnectionLoss(callable $scenario): void
restore_error_handler();
}
}

public function testNestedTransactionWalkthrough(): void
{
if (! $this->connection->getDatabasePlatform()->supportsSavepoints()) {
self::markTestIncomplete('Broken when savepoints are not supported.');
}

$table = new Table('storage');
$table->addColumn('test_int', Types::INTEGER);
$table->setPrimaryKey(['test_int']);

$this->dropAndCreateTable($table);

$query = 'SELECT count(test_int) FROM storage';

self::assertSame('0', (string) $this->connection->fetchOne($query));

$result = $this->connection->transactional(
static fn (Connection $connection) => $connection->transactional(
static function (Connection $connection) use ($query) {
$connection->insert('storage', ['test_int' => 1]);

return $connection->fetchOne($query);
},
),
);

self::assertSame('1', (string) $result);
self::assertSame('1', (string) $this->connection->fetchOne($query));
}
}
4 changes: 2 additions & 2 deletions tests/Query/Expression/ExpressionBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ class ExpressionBuilderTest extends TestCase

protected function setUp(): void
{
$conn = $this->createMock(Connection::class);
$conn = self::createStub(Connection::class);

$this->expr = new ExpressionBuilder($conn);

$conn->expects(self::any())
$conn
->method('createExpressionBuilder')
->willReturn($this->expr);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/Types/DateImmutableTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public function testConvertsDateStringToPHPValue(): void

public function testResetTimeFractionsWhenConvertingToPHPValue(): void
{
$this->platform->expects(self::any())
$this->platform
->method('getDateFormatString')
->willReturn('Y-m-d');

Expand Down
2 changes: 1 addition & 1 deletion tests/Types/DateTimeImmutableTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public function testConvertsDateTimeStringToPHPValue(): void

public function testConvertsDateTimeStringWithMicrosecondsToPHPValue(): void
{
$this->platform->expects(self::any())
$this->platform
->method('getDateTimeFormatString')
->willReturn('Y-m-d H:i:s');

Expand Down
2 changes: 1 addition & 1 deletion tests/Types/TimeImmutableTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public function testConvertsTimeStringToPHPValue(): void

public function testResetDateFractionsWhenConvertingToPHPValue(): void
{
$this->platform->expects(self::any())
$this->platform
->method('getTimeFormatString')
->willReturn('H:i:s');

Expand Down

0 comments on commit ce220bc

Please sign in to comment.