diff --git a/lib/Doctrine/DBAL/Cache/QueryCacheProfile.php b/lib/Doctrine/DBAL/Cache/QueryCacheProfile.php index 330eec91f23..19f7a6096f1 100644 --- a/lib/Doctrine/DBAL/Cache/QueryCacheProfile.php +++ b/lib/Doctrine/DBAL/Cache/QueryCacheProfile.php @@ -88,17 +88,22 @@ public function getCacheKey() } /** - * Generates the real cache key from query, params and types. + * Generates the real cache key from query, params, types and connection parameters. * * @param string $query * @param array $params * @param array $types + * @param array $connectionParams * * @return array */ - public function generateCacheKeys($query, $params, $types) + public function generateCacheKeys($query, $params, $types, array $connectionParams = []) { - $realCacheKey = $query . "-" . serialize($params) . "-" . serialize($types); + $realCacheKey = 'query=' . $query . + '¶ms=' . serialize($params) . + '&types=' . serialize($types) . + '&connectionParams=' . serialize($connectionParams); + // should the key be automatically generated using the inputs or is the cache key set? if ($this->cacheKey === null) { $cacheKey = sha1($realCacheKey); diff --git a/lib/Doctrine/DBAL/Connection.php b/lib/Doctrine/DBAL/Connection.php index 6f6b0b81d9d..61afb7b8e8e 100644 --- a/lib/Doctrine/DBAL/Connection.php +++ b/lib/Doctrine/DBAL/Connection.php @@ -879,7 +879,7 @@ public function executeCacheQuery($query, $params, $types, QueryCacheProfile $qc throw CacheException::noResultDriverConfigured(); } - list($cacheKey, $realKey) = $qcp->generateCacheKeys($query, $params, $types); + list($cacheKey, $realKey) = $qcp->generateCacheKeys($query, $params, $types, $this->getParams()); // fetch the row pointers entry if ($data = $resultCache->fetch($cacheKey)) { diff --git a/tests/Doctrine/Tests/DBAL/Cache/QueryCacheProfileTest.php b/tests/Doctrine/Tests/DBAL/Cache/QueryCacheProfileTest.php new file mode 100644 index 00000000000..88219f215d5 --- /dev/null +++ b/tests/Doctrine/Tests/DBAL/Cache/QueryCacheProfileTest.php @@ -0,0 +1,145 @@ +queryCacheProfile = new QueryCacheProfile(self::LIFETIME, self::CACHE_KEY); + } + + public function testShouldUseTheGivenCacheKeyIfPresent() + { + $query = 'SELECT * FROM foo WHERE bar = ?'; + $params = [666]; + $types = [PDO::PARAM_INT]; + + $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->assertEquals(self::CACHE_KEY, $cacheKey, 'The returned cache key should match the given one'); + } + + public function testShouldGenerateAnAutomaticKeyIfNoKeyHasBeenGiven() + { + $query = 'SELECT * FROM foo WHERE bar = ?'; + $params = [666]; + $types = [PDO::PARAM_INT]; + + $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->assertNotEquals( + self::CACHE_KEY, + $cacheKey, + 'The returned cache key should be generated automatically' + ); + + $this->assertNotEmpty($cacheKey, 'The generated cache key should not be empty'); + } + + public function testShouldGenerateDifferentKeysForSameQueryAndParamsAndDifferentConnections() + { + $query = 'SELECT * FROM foo WHERE bar = ?'; + $params = [666]; + $types = [PDO::PARAM_INT]; + + $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 + ); + + $connectionParams['host'] = 'a_different_host'; + + list($secondCacheKey) = $this->queryCacheProfile->generateCacheKeys( + $query, + $params, + $types, + $connectionParams + ); + + $this->assertNotEquals($firstCacheKey, $secondCacheKey, 'Cache keys should be different'); + } + + public function testShouldGenerateSameKeysIfNoneOfTheParamsChanges() + { + $query = 'SELECT * FROM foo WHERE bar = ?'; + $params = [666]; + $types = [PDO::PARAM_INT]; + + $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 + ); + + list($secondCacheKey) = $this->queryCacheProfile->generateCacheKeys( + $query, + $params, + $types, + $connectionParams + ); + + $this->assertEquals($firstCacheKey, $secondCacheKey, 'Cache keys should be the same'); + } +} diff --git a/tests/Doctrine/Tests/DBAL/ConnectionTest.php b/tests/Doctrine/Tests/DBAL/ConnectionTest.php index ff414a86ed2..ccc37ade492 100644 --- a/tests/Doctrine/Tests/DBAL/ConnectionTest.php +++ b/tests/Doctrine/Tests/DBAL/ConnectionTest.php @@ -2,12 +2,16 @@ namespace Doctrine\Tests\DBAL; +use Doctrine\Common\Cache\Cache; use Doctrine\Common\EventManager; +use Doctrine\DBAL\Cache\QueryCacheProfile; use Doctrine\DBAL\Configuration; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver; use Doctrine\DBAL\Events; use Doctrine\Tests\Mocks\DriverConnectionMock; use Doctrine\Tests\Mocks\DriverMock; +use Doctrine\DBAL\Cache\ArrayStatement; class ConnectionTest extends \Doctrine\Tests\DbalTestCase { @@ -670,4 +674,42 @@ public function testPlatformDetectionIsTriggerOnlyOnceOnRetrievingPlatform() $this->assertSame($platformMock, $connection->getDatabasePlatform()); } + + public function testConnectionParamsArePassedToTheQueryCacheProfileInExecuteCacheQuery() + { + $resultCacheDriverMock = $this->createMock(Cache::class); + + $resultCacheDriverMock + ->expects($this->atLeastOnce()) + ->method('fetch') + ->with('cacheKey') + ->will($this->returnValue(['realKey' => []])); + + $query = 'SELECT * FROM foo WHERE bar = ?'; + $params = [666]; + $types = [\PDO::PARAM_INT]; + + /* @var $queryCacheProfileMock QueryCacheProfile|\PHPUnit_Framework_MockObject_MockObject */ + $queryCacheProfileMock = $this->createMock(QueryCacheProfile::class); + + $queryCacheProfileMock + ->expects($this->any()) + ->method('getResultCacheDriver') + ->will($this->returnValue($resultCacheDriverMock)); + + // This is our main expectation + $queryCacheProfileMock + ->expects($this->once()) + ->method('generateCacheKeys') + ->with($query, $params, $types, $this->params) + ->will($this->returnValue(['cacheKey', 'realKey'])); + + /* @var $driver Driver */ + $driver = $this->createMock(Driver::class); + + $this->assertInstanceOf( + ArrayStatement::class, + (new Connection($this->params, $driver))->executeCacheQuery($query, $params, $types, $queryCacheProfileMock) + ); + } } diff --git a/tests/Doctrine/Tests/DBAL/Schema/DB2SchemaManagerTest.php b/tests/Doctrine/Tests/DBAL/Schema/DB2SchemaManagerTest.php index 69da08db4af..d524afe9c45 100644 --- a/tests/Doctrine/Tests/DBAL/Schema/DB2SchemaManagerTest.php +++ b/tests/Doctrine/Tests/DBAL/Schema/DB2SchemaManagerTest.php @@ -27,13 +27,13 @@ final class DB2SchemaManagerTest extends \PHPUnit_Framework_TestCase protected function setUp() { $eventManager = new EventManager(); - $driverMock = $this->getMock(Driver::class); - $platform = $this->getMock(DB2Platform::class); - $this->conn = $this->getMock( - Connection::class, - ['fetchAll'], - [['platform' => $platform], $driverMock, new Configuration(), $eventManager] - ); + $driverMock = $this->createMock(Driver::class); + $platform = $this->createMock(DB2Platform::class); + $this->conn = $this + ->getMockBuilder(Connection::class) + ->setMethods(['fetchAll']) + ->setConstructorArgs([['platform' => $platform], $driverMock, new Configuration(), $eventManager]) + ->getMock(); $this->manager = new DB2SchemaManager($this->conn); } diff --git a/tests/travis/pgsql.travis.xml b/tests/travis/pgsql.travis.xml index 934a5a5333d..0298a5ce1cb 100644 --- a/tests/travis/pgsql.travis.xml +++ b/tests/travis/pgsql.travis.xml @@ -34,4 +34,4 @@ locking_functional - \ No newline at end of file + diff --git a/tests/travis/sqlite.travis.xml b/tests/travis/sqlite.travis.xml index 6c22315150c..1460f0b8eb5 100644 --- a/tests/travis/sqlite.travis.xml +++ b/tests/travis/sqlite.travis.xml @@ -21,4 +21,4 @@ locking_functional - \ No newline at end of file +