From 017991a0a8a4e0716d9d94a34c3de8ef4a5fe202 Mon Sep 17 00:00:00 2001 From: Full Date: Thu, 22 Feb 2018 21:39:55 +0100 Subject: [PATCH] Connection parameters are cached hashed --- lib/Doctrine/DBAL/Cache/QueryCacheProfile.php | 27 ++-- .../DBAL/Cache/QueryCacheProfileTest.php | 150 +++++++++--------- 2 files changed, 89 insertions(+), 88 deletions(-) diff --git a/lib/Doctrine/DBAL/Cache/QueryCacheProfile.php b/lib/Doctrine/DBAL/Cache/QueryCacheProfile.php index 883f3b7c881..a722681ce43 100644 --- a/lib/Doctrine/DBAL/Cache/QueryCacheProfile.php +++ b/lib/Doctrine/DBAL/Cache/QueryCacheProfile.php @@ -20,18 +20,19 @@ namespace Doctrine\DBAL\Cache; use Doctrine\Common\Cache\Cache; +use function hash; +use function serialize; +use function sha1; /** * Query Cache Profile handles the data relevant for query caching. * * It is a value object, setter methods return NEW instances. - * - * @author Benjamin Eberlei */ class QueryCacheProfile { /** - * @var \Doctrine\Common\Cache\Cache|null + * @var Cache|null */ private $resultCacheDriver; @@ -46,19 +47,18 @@ class QueryCacheProfile private $cacheKey; /** - * @param int $lifetime - * @param string|null $cacheKey - * @param \Doctrine\Common\Cache\Cache|null $resultCache + * @param int $lifetime + * @param string|null $cacheKey */ - public function __construct($lifetime = 0, $cacheKey = null, Cache $resultCache = null) + public function __construct($lifetime = 0, $cacheKey = null, ?Cache $resultCache = null) { - $this->lifetime = $lifetime; - $this->cacheKey = $cacheKey; + $this->lifetime = $lifetime; + $this->cacheKey = $cacheKey; $this->resultCacheDriver = $resultCache; } /** - * @return \Doctrine\Common\Cache\Cache|null + * @return Cache|null */ public function getResultCacheDriver() { @@ -76,7 +76,7 @@ public function getLifetime() /** * @return string * - * @throws \Doctrine\DBAL\Cache\CacheException + * @throws CacheException */ public function getCacheKey() { @@ -102,7 +102,7 @@ public function generateCacheKeys($query, $params, $types, array $connectionPara $realCacheKey = 'query=' . $query . '¶ms=' . serialize($params) . '&types=' . serialize($types) . - '&connectionParams=' . serialize($connectionParams); + '&connectionParams=' . hash('sha256', serialize($connectionParams)); // should the key be automatically generated using the inputs or is the cache key set? if ($this->cacheKey === null) { @@ -111,11 +111,10 @@ public function generateCacheKeys($query, $params, $types, array $connectionPara $cacheKey = $this->cacheKey; } - return array($cacheKey, $realCacheKey); + return [$cacheKey, $realCacheKey]; } /** - * @param \Doctrine\Common\Cache\Cache $cache * * @return \Doctrine\DBAL\Cache\QueryCacheProfile */ diff --git a/tests/Doctrine/Tests/DBAL/Cache/QueryCacheProfileTest.php b/tests/Doctrine/Tests/DBAL/Cache/QueryCacheProfileTest.php index 553af666784..5bc77c911c3 100644 --- a/tests/Doctrine/Tests/DBAL/Cache/QueryCacheProfileTest.php +++ b/tests/Doctrine/Tests/DBAL/Cache/QueryCacheProfileTest.php @@ -5,15 +5,44 @@ use Doctrine\DBAL\Cache\QueryCacheProfile; use Doctrine\DBAL\ParameterType; use Doctrine\Tests\DbalTestCase; +use function parse_str; class QueryCacheProfileTest extends DbalTestCase { - const LIFETIME = 3600; - const CACHE_KEY = 'user_specified_cache_key'; + private const LIFETIME = 3600; + private const CACHE_KEY = 'user_specified_cache_key'; - /** @var QueryCacheProfile */ + /** + * @var QueryCacheProfile + */ private $queryCacheProfile; + /** + * @var string + */ + private $query = 'SELECT * FROM foo WHERE bar = ?'; + + /** + * @var int[] + */ + private $params = [666]; + + /** + * @var string[] + */ + private $types = [ParameterType::INTEGER]; + + /** + * @var string[] + */ + private $connectionParams = [ + 'dbname' => 'database_name', + 'user' => 'database_user', + 'password' => 'database_password', + 'host' => 'database_host', + 'driver' => 'database_driver', + ]; + protected function setUp() { $this->queryCacheProfile = new QueryCacheProfile(self::LIFETIME, self::CACHE_KEY); @@ -21,23 +50,11 @@ protected function setUp() public function testShouldUseTheGivenCacheKeyIfPresent() { - $query = 'SELECT * FROM foo WHERE bar = ?'; - $params = [666]; - $types = [ParameterType::INTEGER]; - - $connectionParams = array( - 'dbname' => 'database_name', - 'user' => 'database_user', - 'password' => 'database_password', - 'host' => 'database_host', - 'driver' => 'database_driver' - ); - list($cacheKey) = $this->queryCacheProfile->generateCacheKeys( - $query, - $params, - $types, - $connectionParams + $this->query, + $this->params, + $this->types, + $this->connectionParams ); self::assertEquals(self::CACHE_KEY, $cacheKey, 'The returned cache key should match the given one'); @@ -45,25 +62,13 @@ public function testShouldUseTheGivenCacheKeyIfPresent() public function testShouldGenerateAnAutomaticKeyIfNoKeyHasBeenGiven() { - $query = 'SELECT * FROM foo WHERE bar = ?'; - $params = [666]; - $types = [ParameterType::INTEGER]; - - $connectionParams = array( - 'dbname' => 'database_name', - 'user' => 'database_user', - 'password' => 'database_password', - 'host' => 'database_host', - 'driver' => 'database_driver' - ); - $this->queryCacheProfile = $this->queryCacheProfile->setCacheKey(null); list($cacheKey) = $this->queryCacheProfile->generateCacheKeys( - $query, - $params, - $types, - $connectionParams + $this->query, + $this->params, + $this->types, + $this->connectionParams ); self::assertNotEquals( @@ -77,67 +82,64 @@ public function testShouldGenerateAnAutomaticKeyIfNoKeyHasBeenGiven() public function testShouldGenerateDifferentKeysForSameQueryAndParamsAndDifferentConnections() { - $query = 'SELECT * FROM foo WHERE bar = ?'; - $params = [666]; - $types = [ParameterType::INTEGER]; - - $connectionParams = array( - 'dbname' => 'database_name', - 'user' => 'database_user', - 'password' => 'database_password', - 'host' => 'database_host', - 'driver' => 'database_driver' - ); - $this->queryCacheProfile = $this->queryCacheProfile->setCacheKey(null); list($firstCacheKey) = $this->queryCacheProfile->generateCacheKeys( - $query, - $params, - $types, - $connectionParams + $this->query, + $this->params, + $this->types, + $this->connectionParams ); - $connectionParams['host'] = 'a_different_host'; + $this->connectionParams['host'] = 'a_different_host'; list($secondCacheKey) = $this->queryCacheProfile->generateCacheKeys( - $query, - $params, - $types, - $connectionParams + $this->query, + $this->params, + $this->types, + $this->connectionParams ); self::assertNotEquals($firstCacheKey, $secondCacheKey, 'Cache keys should be different'); } - public function testShouldGenerateSameKeysIfNoneOfTheParamsChanges() + public function testConnectionParamsShouldBeHashed() { - $query = 'SELECT * FROM foo WHERE bar = ?'; - $params = [666]; - $types = [ParameterType::INTEGER]; + $this->queryCacheProfile = $this->queryCacheProfile->setCacheKey(null); - $connectionParams = array( - 'dbname' => 'database_name', - 'user' => 'database_user', - 'password' => 'database_password', - 'host' => 'database_host', - 'driver' => 'database_driver' + list($cacheKey, $queryString) = $this->queryCacheProfile->generateCacheKeys( + $this->query, + $this->params, + $this->types, + $this->connectionParams ); + $params = []; + parse_str($queryString, $params); + + self::assertArrayHasKey('connectionParams', $params); + + foreach ($this->connectionParams as $param) { + self::assertNotContains($param, $params['connectionParams']); + } + } + + public function testShouldGenerateSameKeysIfNoneOfTheParamsChanges() + { $this->queryCacheProfile = $this->queryCacheProfile->setCacheKey(null); list($firstCacheKey) = $this->queryCacheProfile->generateCacheKeys( - $query, - $params, - $types, - $connectionParams + $this->query, + $this->params, + $this->types, + $this->connectionParams ); list($secondCacheKey) = $this->queryCacheProfile->generateCacheKeys( - $query, - $params, - $types, - $connectionParams + $this->query, + $this->params, + $this->types, + $this->connectionParams ); self::assertEquals($firstCacheKey, $secondCacheKey, 'Cache keys should be the same');