From 3ce1f76fbc191207f3a23c72a2df211550ac3845 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Wed, 1 Sep 2021 00:12:25 +0200 Subject: [PATCH] Fix tests failing with DBAL 3 --- composer.json | 3 +- .../RememberMe/DoctrineTokenProvider.php | 17 +++--- .../DoctrineDataCollectorTest.php | 36 +++++++------ .../DoctrinePingConnectionMiddlewareTest.php | 9 ++-- src/Symfony/Bridge/Doctrine/composer.json | 4 +- .../Component/Cache/Traits/PdoTrait.php | 54 +++++++++++-------- src/Symfony/Component/Cache/composer.json | 4 +- .../Transport/Doctrine/ConnectionTest.php | 12 ++++- .../Doctrine/DoctrineIntegrationTest.php | 10 +++- .../Transport/Doctrine/Connection.php | 12 ++++- 10 files changed, 103 insertions(+), 58 deletions(-) diff --git a/composer.json b/composer.json index da8e66b784de0..1e73439a2dd1e 100644 --- a/composer.json +++ b/composer.json @@ -123,7 +123,7 @@ "doctrine/cache": "^1.6|^2.0", "doctrine/collections": "~1.0", "doctrine/data-fixtures": "^1.1", - "doctrine/dbal": "^2.6|^3.0", + "doctrine/dbal": "^2.7|^3.0", "doctrine/orm": "^2.6.3", "guzzlehttp/promises": "^1.4", "masterminds/html5": "^2.6", @@ -143,6 +143,7 @@ "twig/markdown-extra": "^2.12|^3" }, "conflict": { + "doctrine/dbal": "<2.7", "egulias/email-validator": "~3.0.0", "masterminds/html5": "<2.6", "monolog/monolog": ">=2", diff --git a/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php b/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php index 4b63652ae8058..8f8256f6cb99b 100644 --- a/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php +++ b/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php @@ -13,6 +13,7 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\Driver\Result as DriverResult; +use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Result; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; @@ -63,7 +64,7 @@ public function loadTokenBySeries($series) $sql = 'SELECT class, username, value, lastUsed AS last_used' .' FROM rememberme_token WHERE series=:series'; $paramValues = ['series' => $series]; - $paramTypes = ['series' => \PDO::PARAM_STR]; + $paramTypes = ['series' => ParameterType::STRING]; $stmt = $this->conn->executeQuery($sql, $paramValues, $paramTypes); $row = $stmt instanceof Result || $stmt instanceof DriverResult ? $stmt->fetchAssociative() : $stmt->fetch(\PDO::FETCH_ASSOC); @@ -81,7 +82,7 @@ public function deleteTokenBySeries($series) { $sql = 'DELETE FROM rememberme_token WHERE series=:series'; $paramValues = ['series' => $series]; - $paramTypes = ['series' => \PDO::PARAM_STR]; + $paramTypes = ['series' => ParameterType::STRING]; if (method_exists($this->conn, 'executeStatement')) { $this->conn->executeStatement($sql, $paramValues, $paramTypes); } else { @@ -102,9 +103,9 @@ public function updateToken($series, $tokenValue, \DateTime $lastUsed) 'series' => $series, ]; $paramTypes = [ - 'value' => \PDO::PARAM_STR, + 'value' => ParameterType::STRING, 'lastUsed' => self::$useDeprecatedConstants ? Type::DATETIME : Types::DATETIME_MUTABLE, - 'series' => \PDO::PARAM_STR, + 'series' => ParameterType::STRING, ]; if (method_exists($this->conn, 'executeStatement')) { $updated = $this->conn->executeStatement($sql, $paramValues, $paramTypes); @@ -132,10 +133,10 @@ public function createNewToken(PersistentTokenInterface $token) 'lastUsed' => $token->getLastUsed(), ]; $paramTypes = [ - 'class' => \PDO::PARAM_STR, - 'username' => \PDO::PARAM_STR, - 'series' => \PDO::PARAM_STR, - 'value' => \PDO::PARAM_STR, + 'class' => ParameterType::STRING, + 'username' => ParameterType::STRING, + 'series' => ParameterType::STRING, + 'value' => ParameterType::STRING, 'lastUsed' => self::$useDeprecatedConstants ? Type::DATETIME : Types::DATETIME_MUTABLE, ]; if (method_exists($this->conn, 'executeStatement')) { diff --git a/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php index 9c31d6d7e76b4..35fc48ff1536f 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php @@ -11,9 +11,9 @@ namespace Symfony\Bridge\Doctrine\Tests\DataCollector; +use Doctrine\DBAL\Connection; use Doctrine\DBAL\Logging\DebugStack; -use Doctrine\DBAL\Platforms\MySqlPlatform; -use Doctrine\DBAL\Version; +use Doctrine\DBAL\Platforms\MySQLPlatform; use Doctrine\Persistence\ManagerRegistry; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\DataCollector\DoctrineDataCollector; @@ -22,6 +22,9 @@ use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Dumper\CliDumper; +// Doctrine DBAL 2 compatibility +class_exists(\Doctrine\DBAL\Platforms\MySqlPlatform::class); + class DoctrineDataCollectorTest extends TestCase { public function testCollectConnections() @@ -93,6 +96,8 @@ public function testCollectQueries($param, $types, $expected, $explainable, bool $dumper->setColors(false); $collectedParam->dump($dumper); $this->assertStringMatchesFormat($expected, print_r(stream_get_contents($out, -1, 0), true)); + } elseif (\is_string($expected)) { + $this->assertStringMatchesFormat($expected, $collectedParam); } else { $this->assertEquals($expected, $collectedParam); } @@ -150,7 +155,7 @@ public function testReset() /** * @dataProvider paramProvider */ - public function testSerialization($param, $types, $expected, $explainable, bool $runnable = true) + public function testSerialization($param, array $types, $expected, $explainable, bool $runnable = true) { $queries = [ ['sql' => 'SELECT * FROM table1 WHERE field1 = ?1', 'params' => [$param], 'types' => $types, 'executionMS' => 1], @@ -167,6 +172,8 @@ public function testSerialization($param, $types, $expected, $explainable, bool $dumper->setColors(false); $collectedParam->dump($dumper); $this->assertStringMatchesFormat($expected, print_r(stream_get_contents($out, -1, 0), true)); + } elseif (\is_string($expected)) { + $this->assertStringMatchesFormat($expected, $collectedParam); } else { $this->assertEquals($expected, $collectedParam); } @@ -175,9 +182,9 @@ public function testSerialization($param, $types, $expected, $explainable, bool $this->assertSame($runnable, $collectedQueries['default'][0]['runnable']); } - public function paramProvider() + public function paramProvider(): array { - $tests = [ + return [ ['some value', [], 'some value', true], [1, [], 1, true], [true, [], true, true], @@ -207,30 +214,25 @@ public function paramProvider() , false, ], - ]; - - if (version_compare(Version::VERSION, '2.6', '>=')) { - $tests[] = ['this is not a date', ['date'], "⚠ Could not convert PHP value 'this is not a date' of type 'string' to type 'date'. Expected one of the following types: null, DateTime", false, false]; - $tests[] = [ + ['this is not a date', ['date'], "⚠ Could not convert PHP value 'this is not a date'%S to type %Sdate%S. Expected one of the following types: null, DateTime", false, false], + [ new \stdClass(), ['date'], <<getMockBuilder(\Doctrine\DBAL\Connection::class) + $connection = $this->getMockBuilder(Connection::class) ->disableOriginalConstructor() ->getMock(); $connection->expects($this->any()) diff --git a/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php b/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php index f99a48527c442..be63ef923dfbc 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php @@ -103,9 +103,12 @@ public function testInvalidEntityManagerThrowsException() public function testMiddlewareNoPingInNonWorkerContext() { - $this->connection->expects($this->never()) - ->method('ping') - ->willReturn(false); + // This method has been removed in DBAL 3.0 + if (method_exists(Connection::class, 'ping')) { + $this->connection->expects($this->never()) + ->method('ping') + ->willReturn(false); + } $this->connection->expects($this->never()) ->method('close') diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 0da77033b3334..79961033bc0a6 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -43,10 +43,12 @@ "doctrine/annotations": "^1.10.4", "doctrine/collections": "~1.0", "doctrine/data-fixtures": "^1.1", - "doctrine/dbal": "^2.6|^3.0", + "doctrine/dbal": "^2.7|^3.0", "doctrine/orm": "^2.6.3" }, "conflict": { + "doctrine/dbal": "<2.7", + "doctrine/orm": "<2.6.3", "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", "symfony/dependency-injection": "<3.4", "symfony/form": "<4.4", diff --git a/src/Symfony/Component/Cache/Traits/PdoTrait.php b/src/Symfony/Component/Cache/Traits/PdoTrait.php index a2129c459b6f7..f069248a75e50 100644 --- a/src/Symfony/Component/Cache/Traits/PdoTrait.php +++ b/src/Symfony/Component/Cache/Traits/PdoTrait.php @@ -17,6 +17,7 @@ use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\Exception; use Doctrine\DBAL\Exception\TableNotFoundException; +use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Schema\Schema; use Symfony\Component\Cache\Exception\InvalidArgumentException; use Symfony\Component\Cache\Marshaller\DefaultMarshaller; @@ -166,17 +167,20 @@ public function prune() $deleteSql .= " AND $this->idCol LIKE :namespace"; } + $connection = $this->getConnection(); + $useDbalConstants = $connection instanceof Connection; + try { - $delete = $this->getConnection()->prepare($deleteSql); + $delete = $connection->prepare($deleteSql); } catch (TableNotFoundException $e) { return true; } catch (\PDOException $e) { return true; } - $delete->bindValue(':time', time(), \PDO::PARAM_INT); + $delete->bindValue(':time', time(), $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); if ('' !== $this->namespace) { - $delete->bindValue(':namespace', sprintf('%s%%', $this->namespace), \PDO::PARAM_STR); + $delete->bindValue(':namespace', sprintf('%s%%', $this->namespace), $useDbalConstants ? ParameterType::STRING : \PDO::PARAM_STR); } try { return $delete->execute(); @@ -192,13 +196,16 @@ public function prune() */ protected function doFetch(array $ids) { + $connection = $this->getConnection(); + $useDbalConstants = $connection instanceof Connection; + $now = time(); $expired = []; $sql = str_pad('', (\count($ids) << 1) - 1, '?,'); $sql = "SELECT $this->idCol, CASE WHEN $this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > ? THEN $this->dataCol ELSE NULL END FROM $this->table WHERE $this->idCol IN ($sql)"; - $stmt = $this->getConnection()->prepare($sql); - $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT); + $stmt = $connection->prepare($sql); + $stmt->bindValue($i = 1, $now, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); foreach ($ids as $id) { $stmt->bindValue(++$i, $id); } @@ -222,8 +229,8 @@ protected function doFetch(array $ids) if ($expired) { $sql = str_pad('', (\count($expired) << 1) - 1, '?,'); $sql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= ? AND $this->idCol IN ($sql)"; - $stmt = $this->getConnection()->prepare($sql); - $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT); + $stmt = $connection->prepare($sql); + $stmt->bindValue($i = 1, $now, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); foreach ($expired as $id) { $stmt->bindValue(++$i, $id); } @@ -236,11 +243,14 @@ protected function doFetch(array $ids) */ protected function doHave($id) { + $connection = $this->getConnection(); + $useDbalConstants = $connection instanceof Connection; + $sql = "SELECT 1 FROM $this->table WHERE $this->idCol = :id AND ($this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > :time)"; - $stmt = $this->getConnection()->prepare($sql); + $stmt = $connection->prepare($sql); $stmt->bindValue(':id', $id); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); + $stmt->bindValue(':time', time(), $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); $result = $stmt->execute(); return (bool) (\is_object($result) ? $result->fetchOne() : $stmt->fetchColumn()); @@ -303,6 +313,8 @@ protected function doSave(array $values, int $lifetime) } $conn = $this->getConnection(); + $useDbalConstants = $conn instanceof Connection; + $driver = $this->driver; $insertSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time)"; @@ -354,25 +366,25 @@ protected function doSave(array $values, int $lifetime) if ('sqlsrv' === $driver || 'oci' === $driver) { $stmt->bindParam(1, $id); $stmt->bindParam(2, $id); - $stmt->bindParam(3, $data, \PDO::PARAM_LOB); - $stmt->bindValue(4, $lifetime, \PDO::PARAM_INT); - $stmt->bindValue(5, $now, \PDO::PARAM_INT); - $stmt->bindParam(6, $data, \PDO::PARAM_LOB); - $stmt->bindValue(7, $lifetime, \PDO::PARAM_INT); - $stmt->bindValue(8, $now, \PDO::PARAM_INT); + $stmt->bindParam(3, $data, $useDbalConstants ? ParameterType::LARGE_OBJECT : \PDO::PARAM_LOB); + $stmt->bindValue(4, $lifetime, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); + $stmt->bindValue(5, $now, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); + $stmt->bindParam(6, $data, $useDbalConstants ? ParameterType::LARGE_OBJECT : \PDO::PARAM_LOB); + $stmt->bindValue(7, $lifetime, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); + $stmt->bindValue(8, $now, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); } else { $stmt->bindParam(':id', $id); - $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $stmt->bindValue(':lifetime', $lifetime, \PDO::PARAM_INT); - $stmt->bindValue(':time', $now, \PDO::PARAM_INT); + $stmt->bindParam(':data', $data, $useDbalConstants ? ParameterType::LARGE_OBJECT : \PDO::PARAM_LOB); + $stmt->bindValue(':lifetime', $lifetime, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); + $stmt->bindValue(':time', $now, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); } if (null === $driver) { $insertStmt = $conn->prepare($insertSql); $insertStmt->bindParam(':id', $id); - $insertStmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $insertStmt->bindValue(':lifetime', $lifetime, \PDO::PARAM_INT); - $insertStmt->bindValue(':time', $now, \PDO::PARAM_INT); + $insertStmt->bindParam(':data', $data, $useDbalConstants ? ParameterType::LARGE_OBJECT : \PDO::PARAM_LOB); + $insertStmt->bindValue(':lifetime', $lifetime, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); + $insertStmt->bindValue(':time', $now, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); } foreach ($values as $id => $data) { diff --git a/src/Symfony/Component/Cache/composer.json b/src/Symfony/Component/Cache/composer.json index d71f2169e03c2..72bd68fbe31dd 100644 --- a/src/Symfony/Component/Cache/composer.json +++ b/src/Symfony/Component/Cache/composer.json @@ -33,7 +33,7 @@ "require-dev": { "cache/integration-tests": "dev-master", "doctrine/cache": "^1.6|^2.0", - "doctrine/dbal": "^2.6|^3.0", + "doctrine/dbal": "^2.7|^3.0", "predis/predis": "^1.1", "psr/simple-cache": "^1.0", "symfony/config": "^4.2|^5.0", @@ -43,7 +43,7 @@ "symfony/var-dumper": "^4.4|^5.0" }, "conflict": { - "doctrine/dbal": "<2.6", + "doctrine/dbal": "<2.7", "symfony/dependency-injection": "<3.4", "symfony/http-kernel": "<4.4|>=5.0", "symfony/var-dumper": "<4.4" diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php index d8b1447257ba1..5bc7dddcd2934 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php @@ -140,7 +140,11 @@ private function getDBALConnectionMock() $schemaConfig->method('getMaxIdentifierLength')->willReturn(63); $schemaConfig->method('getDefaultTableOptions')->willReturn([]); $schemaManager->method('createSchemaConfig')->willReturn($schemaConfig); - $driverConnection->method('getSchemaManager')->willReturn($schemaManager); + if (method_exists(DBALConnection::class, 'createSchemaManager')) { + $driverConnection->method('createSchemaManager')->willReturn($schemaManager); + } else { + $driverConnection->method('getSchemaManager')->willReturn($schemaManager); + } return $driverConnection; } @@ -428,7 +432,11 @@ public function testSetupIndices(string $platformClass, array $expectedIndices) $expectedTable->addIndex($indexColumns); } $schemaManager->method('createSchema')->willReturn($schema); - $driverConnection->method('getSchemaManager')->willReturn($schemaManager); + if (method_exists(DBALConnection::class, 'createSchemaManager')) { + $driverConnection->method('createSchemaManager')->willReturn($schemaManager); + } else { + $driverConnection->method('getSchemaManager')->willReturn($schemaManager); + } $platformMock = $this->createMock($platformClass); $platformMock diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/DoctrineIntegrationTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/DoctrineIntegrationTest.php index d0b531387033e..2bc70871baf5c 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/DoctrineIntegrationTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/DoctrineIntegrationTest.php @@ -14,6 +14,7 @@ use Doctrine\DBAL\Driver\Result as DriverResult; use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\Result; +use Doctrine\DBAL\Schema\AbstractSchemaManager; use PHPUnit\Framework\TestCase; use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage; use Symfony\Component\Messenger\Transport\Doctrine\Connection; @@ -175,7 +176,7 @@ public function testItRetrieveTheMessageThatIsOlderThanRedeliverTimeout() public function testTheTransportIsSetupOnGet() { - $this->assertFalse($this->driverConnection->getSchemaManager()->tablesExist('messenger_messages')); + $this->assertFalse($this->createSchemaManager()->tablesExist('messenger_messages')); $this->assertNull($this->connection->get()); $this->connection->send('the body', ['my' => 'header']); @@ -187,4 +188,11 @@ private function formatDateTime(\DateTime $dateTime) { return $dateTime->format($this->driverConnection->getDatabasePlatform()->getDateTimeFormatString()); } + + private function createSchemaManager(): AbstractSchemaManager + { + return method_exists($this->driverConnection, 'createSchemaManager') + ? $this->driverConnection->createSchemaManager() + : $this->driverConnection->getSchemaManager(); + } } diff --git a/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php b/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php index e936ca09e871f..063724b976219 100644 --- a/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php +++ b/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php @@ -20,6 +20,7 @@ use Doctrine\DBAL\Platforms\MySqlPlatform; use Doctrine\DBAL\Query\QueryBuilder; use Doctrine\DBAL\Result; +use Doctrine\DBAL\Schema\AbstractSchemaManager; use Doctrine\DBAL\Schema\Comparator; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\Synchronizer\SchemaSynchronizer; @@ -377,7 +378,7 @@ private function executeStatement(string $sql, array $parameters = [], array $ty private function getSchema(): Schema { - $schema = new Schema([], [], $this->driverConnection->getSchemaManager()->createSchemaConfig()); + $schema = new Schema([], [], $this->createSchemaManager()->createSchemaConfig()); $table = $schema->createTable($this->configuration['table_name']); $table->addColumn('id', self::$useDeprecatedConstants ? Type::BIGINT : Types::BIGINT) ->setAutoincrement(true) @@ -421,7 +422,7 @@ private function updateSchema(): void } $comparator = new Comparator(); - $schemaDiff = $comparator->compare($this->driverConnection->getSchemaManager()->createSchema(), $this->getSchema()); + $schemaDiff = $comparator->compare($this->createSchemaManager()->createSchema(), $this->getSchema()); foreach ($schemaDiff->toSaveSql($this->driverConnection->getDatabasePlatform()) as $sql) { if (method_exists($this->driverConnection, 'executeStatement')) { @@ -431,4 +432,11 @@ private function updateSchema(): void } } } + + private function createSchemaManager(): AbstractSchemaManager + { + return method_exists($this->driverConnection, 'createSchemaManager') + ? $this->driverConnection->createSchemaManager() + : $this->driverConnection->getSchemaManager(); + } }