From f4398a14520a238e0d11cb6ad9b5078945e97829 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 28 Mar 2023 16:11:52 +0200 Subject: [PATCH] [Cache] Fix DBAL deprecations and stop using NUL chars in tags prefix --- .../ChoiceList/ORMQueryBuilderLoaderTest.php | 15 +++--- .../Cache/Adapter/AbstractTagAwareAdapter.php | 2 +- .../Cache/Adapter/DoctrineDbalAdapter.php | 50 +++++++++++-------- .../Cache/Adapter/TagAwareAdapter.php | 2 +- 4 files changed, 40 insertions(+), 29 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php index 5ae38eba3824b..c1cef742e3d28 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList; +use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Result; use Doctrine\DBAL\Types\GuidType; @@ -19,6 +20,8 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader; use Symfony\Bridge\Doctrine\Tests\DoctrineTestHelper; +use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity; +use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity; use Symfony\Bridge\Doctrine\Types\UlidType; use Symfony\Bridge\Doctrine\Types\UuidType; use Symfony\Component\Form\Exception\TransformationFailedException; @@ -35,12 +38,12 @@ protected function tearDown(): void public function testIdentifierTypeIsStringArray() { - $this->checkIdentifierType('Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity', Connection::PARAM_STR_ARRAY); + $this->checkIdentifierType(SingleStringIdEntity::class, class_exists(ArrayParameterType::class) ? ArrayParameterType::STRING : Connection::PARAM_STR_ARRAY); } public function testIdentifierTypeIsIntegerArray() { - $this->checkIdentifierType('Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity', Connection::PARAM_INT_ARRAY); + $this->checkIdentifierType(SingleIntIdEntity::class, class_exists(ArrayParameterType::class) ? ArrayParameterType::INTEGER : Connection::PARAM_INT_ARRAY); } protected function checkIdentifierType($classname, $expectedType) @@ -90,7 +93,7 @@ public function testFilterNonIntegerValues() $query->expects($this->once()) ->method('setParameter') - ->with('ORMQueryBuilderLoader_getEntitiesByIds_id', [1, 2, 3, '9223372036854775808'], Connection::PARAM_INT_ARRAY) + ->with('ORMQueryBuilderLoader_getEntitiesByIds_id', [1, 2, 3, '9223372036854775808'], class_exists(ArrayParameterType::class) ? ArrayParameterType::INTEGER : Connection::PARAM_INT_ARRAY) ->willReturn($query); $qb = $this->getMockBuilder(\Doctrine\ORM\QueryBuilder::class) @@ -126,7 +129,7 @@ public function testFilterEmptyUuids($entityClass) $query->expects($this->once()) ->method('setParameter') - ->with('ORMQueryBuilderLoader_getEntitiesByIds_id', ['71c5fd46-3f16-4abb-bad7-90ac1e654a2d', 'b98e8e11-2897-44df-ad24-d2627eb7f499'], Connection::PARAM_STR_ARRAY) + ->with('ORMQueryBuilderLoader_getEntitiesByIds_id', ['71c5fd46-3f16-4abb-bad7-90ac1e654a2d', 'b98e8e11-2897-44df-ad24-d2627eb7f499'], class_exists(ArrayParameterType::class) ? ArrayParameterType::STRING : Connection::PARAM_STR_ARRAY) ->willReturn($query); $qb = $this->getMockBuilder(\Doctrine\ORM\QueryBuilder::class) @@ -171,7 +174,7 @@ public function testFilterUid($entityClass) $query->expects($this->once()) ->method('setParameter') - ->with('ORMQueryBuilderLoader_getEntitiesByIds_id', [Uuid::fromString('71c5fd46-3f16-4abb-bad7-90ac1e654a2d')->toBinary(), Uuid::fromString('b98e8e11-2897-44df-ad24-d2627eb7f499')->toBinary()], Connection::PARAM_STR_ARRAY) + ->with('ORMQueryBuilderLoader_getEntitiesByIds_id', [Uuid::fromString('71c5fd46-3f16-4abb-bad7-90ac1e654a2d')->toBinary(), Uuid::fromString('b98e8e11-2897-44df-ad24-d2627eb7f499')->toBinary()], class_exists(ArrayParameterType::class) ? ArrayParameterType::STRING : Connection::PARAM_STR_ARRAY) ->willReturn($query); $qb = $this->getMockBuilder(\Doctrine\ORM\QueryBuilder::class) @@ -239,7 +242,7 @@ public function testEmbeddedIdentifierName() $query->expects($this->once()) ->method('setParameter') - ->with('ORMQueryBuilderLoader_getEntitiesByIds_id_value', [1, 2, 3], Connection::PARAM_INT_ARRAY) + ->with('ORMQueryBuilderLoader_getEntitiesByIds_id_value', [1, 2, 3], class_exists(ArrayParameterType::class) ? ArrayParameterType::INTEGER : Connection::PARAM_INT_ARRAY) ->willReturn($query); $qb = $this->getMockBuilder(\Doctrine\ORM\QueryBuilder::class) diff --git a/src/Symfony/Component/Cache/Adapter/AbstractTagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractTagAwareAdapter.php index f5cea93caa033..ef62b4fb21c7f 100644 --- a/src/Symfony/Component/Cache/Adapter/AbstractTagAwareAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/AbstractTagAwareAdapter.php @@ -35,7 +35,7 @@ abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagA use AbstractAdapterTrait; use ContractsTrait; - private const TAGS_PREFIX = "\0tags\0"; + private const TAGS_PREFIX = "\1tags\1"; protected function __construct(string $namespace = '', int $defaultLifetime = 0) { diff --git a/src/Symfony/Component/Cache/Adapter/DoctrineDbalAdapter.php b/src/Symfony/Component/Cache/Adapter/DoctrineDbalAdapter.php index 45097c24693d8..bf7545457f502 100644 --- a/src/Symfony/Component/Cache/Adapter/DoctrineDbalAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/DoctrineDbalAdapter.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Cache\Adapter; +use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; use Doctrine\DBAL\DriverManager; @@ -147,7 +148,7 @@ protected function doFetch(array $ids): iterable $ids, ], [ ParameterType::INTEGER, - Connection::PARAM_STR_ARRAY, + class_exists(ArrayParameterType::class) ? ArrayParameterType::STRING : Connection::PARAM_STR_ARRAY, ])->iterateNumeric(); foreach ($result as $row) { @@ -165,7 +166,7 @@ protected function doFetch(array $ids): iterable $expired, ], [ ParameterType::INTEGER, - Connection::PARAM_STR_ARRAY, + class_exists(ArrayParameterType::class) ? ArrayParameterType::STRING : Connection::PARAM_STR_ARRAY, ]); } } @@ -208,7 +209,7 @@ protected function doDelete(array $ids): bool { $sql = "DELETE FROM $this->table WHERE $this->idCol IN (?)"; try { - $this->conn->executeStatement($sql, [array_values($ids)], [Connection::PARAM_STR_ARRAY]); + $this->conn->executeStatement($sql, [array_values($ids)], [class_exists(ArrayParameterType::class) ? ArrayParameterType::STRING : Connection::PARAM_STR_ARRAY]); } catch (TableNotFoundException) { } @@ -264,35 +265,42 @@ protected function doSave(array $values, int $lifetime): array|bool $stmt = $this->conn->prepare($sql); } - // $id and $data are defined later in the loop. Binding is done by reference, values are read on execution. if ('sqlsrv' === $platformName || 'oci' === $platformName) { - $stmt->bindParam(1, $id); - $stmt->bindParam(2, $id); - $stmt->bindParam(3, $data, ParameterType::LARGE_OBJECT); + $bind = static function ($id, $data) use ($stmt) { + $stmt->bindValue(1, $id); + $stmt->bindValue(2, $id); + $stmt->bindValue(3, $data, ParameterType::LARGE_OBJECT); + $stmt->bindValue(6, $data, ParameterType::LARGE_OBJECT); + }; $stmt->bindValue(4, $lifetime, ParameterType::INTEGER); $stmt->bindValue(5, $now, ParameterType::INTEGER); - $stmt->bindParam(6, $data, ParameterType::LARGE_OBJECT); $stmt->bindValue(7, $lifetime, ParameterType::INTEGER); $stmt->bindValue(8, $now, ParameterType::INTEGER); } elseif (null !== $platformName) { - $stmt->bindParam(1, $id); - $stmt->bindParam(2, $data, ParameterType::LARGE_OBJECT); + $bind = static function ($id, $data) use ($stmt) { + $stmt->bindValue(1, $id); + $stmt->bindValue(2, $data, ParameterType::LARGE_OBJECT); + }; $stmt->bindValue(3, $lifetime, ParameterType::INTEGER); $stmt->bindValue(4, $now, ParameterType::INTEGER); } else { - $stmt->bindParam(1, $data, ParameterType::LARGE_OBJECT); $stmt->bindValue(2, $lifetime, ParameterType::INTEGER); $stmt->bindValue(3, $now, ParameterType::INTEGER); - $stmt->bindParam(4, $id); $insertStmt = $this->conn->prepare($insertSql); - $insertStmt->bindParam(1, $id); - $insertStmt->bindParam(2, $data, ParameterType::LARGE_OBJECT); $insertStmt->bindValue(3, $lifetime, ParameterType::INTEGER); $insertStmt->bindValue(4, $now, ParameterType::INTEGER); + + $bind = static function ($id, $data) use ($stmt, $insertStmt) { + $stmt->bindValue(1, $data, ParameterType::LARGE_OBJECT); + $stmt->bindValue(4, $id); + $insertStmt->bindValue(1, $id); + $insertStmt->bindValue(2, $data, ParameterType::LARGE_OBJECT); + }; } foreach ($values as $id => $data) { + $bind($id, $data); try { $rowCount = $stmt->executeStatement(); } catch (TableNotFoundException) { @@ -321,16 +329,16 @@ private function getPlatformName(): string $platform = $this->conn->getDatabasePlatform(); - return match (true) { + return $this->platformName = match (true) { $platform instanceof \Doctrine\DBAL\Platforms\MySQLPlatform, - $platform instanceof \Doctrine\DBAL\Platforms\MySQL57Platform => $this->platformName = 'mysql', - $platform instanceof \Doctrine\DBAL\Platforms\SqlitePlatform => $this->platformName = 'sqlite', + $platform instanceof \Doctrine\DBAL\Platforms\MySQL57Platform => 'mysql', + $platform instanceof \Doctrine\DBAL\Platforms\SqlitePlatform => 'sqlite', $platform instanceof \Doctrine\DBAL\Platforms\PostgreSQLPlatform, - $platform instanceof \Doctrine\DBAL\Platforms\PostgreSQL94Platform => $this->platformName = 'pgsql', - $platform instanceof \Doctrine\DBAL\Platforms\OraclePlatform => $this->platformName = 'oci', + $platform instanceof \Doctrine\DBAL\Platforms\PostgreSQL94Platform => 'pgsql', + $platform instanceof \Doctrine\DBAL\Platforms\OraclePlatform => 'oci', $platform instanceof \Doctrine\DBAL\Platforms\SQLServerPlatform, - $platform instanceof \Doctrine\DBAL\Platforms\SQLServer2012Platform => $this->platformName = 'sqlsrv', - default => $this->platformName = $platform::class, + $platform instanceof \Doctrine\DBAL\Platforms\SQLServer2012Platform => 'sqlsrv', + default => $platform::class, }; } diff --git a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php index 7525632e91a13..f64ac99c11b4c 100644 --- a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php @@ -38,7 +38,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac use ContractsTrait; use LoggerAwareTrait; - public const TAGS_PREFIX = "\0tags\0"; + public const TAGS_PREFIX = "\1tags\1"; private array $deferred = []; private AdapterInterface $pool;