Skip to content

Commit

Permalink
Added result caching for QueryBuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
twoleds committed Jul 27, 2022
1 parent de42378 commit a03afed
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 26 deletions.
81 changes: 71 additions & 10 deletions src/Query/QueryBuilder.php
Expand Up @@ -2,6 +2,7 @@

namespace Doctrine\DBAL\Query;

use Doctrine\DBAL\Cache\QueryCacheProfile;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\ParameterType;
Expand Down Expand Up @@ -137,6 +138,13 @@ class QueryBuilder
*/
private $boundCounter = 0;

/**
* The query cache profile used for caching results.
*
* @var QueryCacheProfile|null
*/
private $resultCacheProfile = null;

/**
* Initializes a new <tt>QueryBuilder</tt>.
*
Expand Down Expand Up @@ -208,7 +216,7 @@ public function getState()
*/
public function fetchAssociative()
{
return $this->connection->fetchAssociative($this->getSQL(), $this->params, $this->paramTypes);
return $this->executeQuery()->fetchAssociative();
}

/**
Expand All @@ -221,7 +229,7 @@ public function fetchAssociative()
*/
public function fetchNumeric()
{
return $this->connection->fetchNumeric($this->getSQL(), $this->params, $this->paramTypes);
return $this->executeQuery()->fetchNumeric();
}

/**
Expand All @@ -234,7 +242,7 @@ public function fetchNumeric()
*/
public function fetchOne()
{
return $this->connection->fetchOne($this->getSQL(), $this->params, $this->paramTypes);
return $this->executeQuery()->fetchOne();
}

/**
Expand All @@ -246,7 +254,7 @@ public function fetchOne()
*/
public function fetchAllNumeric(): array
{
return $this->connection->fetchAllNumeric($this->getSQL(), $this->params, $this->paramTypes);
return $this->executeQuery()->fetchAllNumeric();
}

/**
Expand All @@ -258,7 +266,7 @@ public function fetchAllNumeric(): array
*/
public function fetchAllAssociative(): array
{
return $this->connection->fetchAllAssociative($this->getSQL(), $this->params, $this->paramTypes);
return $this->executeQuery()->fetchAllAssociative();
}

/**
Expand All @@ -271,7 +279,7 @@ public function fetchAllAssociative(): array
*/
public function fetchAllKeyValue(): array
{
return $this->connection->fetchAllKeyValue($this->getSQL(), $this->params, $this->paramTypes);
return $this->executeQuery()->fetchAllKeyValue();
}

/**
Expand All @@ -285,7 +293,7 @@ public function fetchAllKeyValue(): array
*/
public function fetchAllAssociativeIndexed(): array
{
return $this->connection->fetchAllAssociativeIndexed($this->getSQL(), $this->params, $this->paramTypes);
return $this->executeQuery()->fetchAllAssociativeIndexed();
}

/**
Expand All @@ -297,7 +305,7 @@ public function fetchAllAssociativeIndexed(): array
*/
public function fetchFirstColumn(): array
{
return $this->connection->fetchFirstColumn($this->getSQL(), $this->params, $this->paramTypes);
return $this->executeQuery()->fetchFirstColumn();
}

/**
Expand All @@ -307,7 +315,12 @@ public function fetchFirstColumn(): array
*/
public function executeQuery(): Result
{
return $this->connection->executeQuery($this->getSQL(), $this->params, $this->paramTypes);
return $this->connection->executeQuery(
$this->getSQL(),
$this->params,
$this->paramTypes,
$this->resultCacheProfile
);
}

/**
Expand Down Expand Up @@ -342,7 +355,7 @@ public function execute()
'QueryBuilder::execute() is deprecated, use QueryBuilder::executeQuery() for SQL queries instead.'
);

return $this->connection->executeQuery($this->getSQL(), $this->params, $this->paramTypes);
return $this->executeQuery();
}

Deprecation::trigger(
Expand Down Expand Up @@ -1564,4 +1577,52 @@ public function __clone()
$this->params[$name] = clone $param;
}
}

/**
* Enables caching of the results of this query, for given amount of seconds
* and optionally specified witch key to use for the cache entry.
*
* @param int|null $lifetime How long the cache entry is valid, in seconds.
* @param string|null $cacheKey Key to use for the cache entry.
*
* @return $this
*/
public function enableResultCache(int $lifetime, ?string $cacheKey = null): self
{
$this->resultCacheProfile = new QueryCacheProfile($lifetime, $cacheKey);

return $this;
}

/**
* Disables caching of the results of this query.
*
* @return $this
*/
public function disableResultCache(): self
{
$this->resultCacheProfile = null;

return $this;
}

/**
* Gets the cache profile for the result caching.
*/
public function getResultCacheProfile(): ?QueryCacheProfile
{
return $this->resultCacheProfile;
}

/**
* Set a cache profile for the result caching.
*
* @return $this
*/
public function setResultCacheProfile(?QueryCacheProfile $cacheProfile): self
{
$this->resultCacheProfile = $cacheProfile;

return $this;
}
}
72 changes: 56 additions & 16 deletions tests/Query/QueryBuilderTest.php
Expand Up @@ -965,11 +965,16 @@ public function testFetchAssociative(
array $parameterTypes,
string $expectedSql
): void {
$qb = new QueryBuilder($this->conn);
$qb = new QueryBuilder($this->conn);
$mockedResult = $this->createMock(Result::class);

$this->conn->expects(self::once())
->method('fetchAssociative')
->method('executeQuery')
->with($expectedSql, $parameters, $parameterTypes)
->willReturn($mockedResult);

$mockedResult->expects(self::once())
->method('fetchAssociative')
->willReturn(['username' => 'jwage', 'password' => 'changeme']);

$row = $qb->select($select)
Expand All @@ -995,11 +1000,16 @@ public function testFetchNumeric(
array $parameterTypes,
string $expectedSql
): void {
$qb = new QueryBuilder($this->conn);
$qb = new QueryBuilder($this->conn);
$mockedResult = $this->createMock(Result::class);

$this->conn->expects(self::once())
->method('fetchNumeric')
->method('executeQuery')
->with($expectedSql, $parameters, $parameterTypes)
->willReturn($mockedResult);

$mockedResult->expects(self::once())
->method('fetchNumeric')
->willReturn(['jwage', 'changeme']);

$row = $qb->select($select)
Expand All @@ -1025,11 +1035,16 @@ public function testFetchOne(
array $parameterTypes,
string $expectedSql
): void {
$qb = new QueryBuilder($this->conn);
$qb = new QueryBuilder($this->conn);
$mockedResult = $this->createMock(Result::class);

$this->conn->expects(self::once())
->method('fetchOne')
->method('executeQuery')
->with($expectedSql, $parameters, $parameterTypes)
->willReturn($mockedResult);

$mockedResult->expects(self::once())
->method('fetchOne')
->willReturn('jwage');

$username = $qb->select($select)
Expand All @@ -1055,11 +1070,16 @@ public function testFetchAllAssociative(
array $parameterTypes,
string $expectedSql
): void {
$qb = new QueryBuilder($this->conn);
$qb = new QueryBuilder($this->conn);
$mockedResult = $this->createMock(Result::class);

$this->conn->expects(self::once())
->method('fetchAllAssociative')
->method('executeQuery')
->with($expectedSql, $parameters, $parameterTypes)
->willReturn($mockedResult);

$mockedResult->expects(self::once())
->method('fetchAllAssociative')
->willReturn(
[
['username' => 'jwage', 'password' => 'changeme'],
Expand Down Expand Up @@ -1096,11 +1116,16 @@ public function testFetchAllNumeric(
array $parameterTypes,
string $expectedSql
): void {
$qb = new QueryBuilder($this->conn);
$qb = new QueryBuilder($this->conn);
$mockedResult = $this->createMock(Result::class);

$this->conn->expects(self::once())
->method('fetchAllNumeric')
->method('executeQuery')
->with($expectedSql, $parameters, $parameterTypes)
->willReturn($mockedResult);

$mockedResult->expects(self::once())
->method('fetchAllNumeric')
->willReturn(
[
['jwage', 'changeme'],
Expand Down Expand Up @@ -1137,11 +1162,16 @@ public function testFetchAllKeyValue(
array $parameterTypes,
string $expectedSql
): void {
$qb = new QueryBuilder($this->conn);
$qb = new QueryBuilder($this->conn);
$mockedResult = $this->createMock(Result::class);

$this->conn->expects(self::once())
->method('fetchAllKeyValue')
->method('executeQuery')
->with($expectedSql, $parameters, $parameterTypes)
->willReturn($mockedResult);

$mockedResult->expects(self::once())
->method('fetchAllKeyValue')
->willReturn(
[
'jwage' => 'changeme',
Expand Down Expand Up @@ -1178,11 +1208,16 @@ public function testFetchAllAssociativeIndexed(
array $parameterTypes,
string $expectedSql
): void {
$qb = new QueryBuilder($this->conn);
$qb = new QueryBuilder($this->conn);
$mockedResult = $this->createMock(Result::class);

$this->conn->expects(self::once())
->method('fetchAllAssociativeIndexed')
->method('executeQuery')
->with($expectedSql, $parameters, $parameterTypes)
->willReturn($mockedResult);

$mockedResult->expects(self::once())
->method('fetchAllAssociativeIndexed')
->willReturn(
[
1 => [
Expand Down Expand Up @@ -1223,11 +1258,16 @@ public function testFetchFirstColumn(
array $parameterTypes,
string $expectedSql
): void {
$qb = new QueryBuilder($this->conn);
$qb = new QueryBuilder($this->conn);
$mockedResult = $this->createMock(Result::class);

$this->conn->expects(self::once())
->method('fetchFirstColumn')
->method('executeQuery')
->with($expectedSql, $parameters, $parameterTypes)
->willReturn($mockedResult);

$mockedResult->expects(self::once())
->method('fetchFirstColumn')
->willReturn(
[
'jwage',
Expand Down

0 comments on commit a03afed

Please sign in to comment.