Skip to content

Commit

Permalink
Add the ability to disable cache
Browse files Browse the repository at this point in the history
  • Loading branch information
msmakouz committed Oct 26, 2023
1 parent 73d5f47 commit 403839f
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 3 deletions.
23 changes: 23 additions & 0 deletions src/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Cycle\Database;

use Cycle\Database\Driver\Driver;
use Cycle\Database\Driver\DriverInterface;
use Cycle\Database\Query\DeleteQuery;
use Cycle\Database\Query\InsertQuery;
Expand Down Expand Up @@ -208,4 +209,26 @@ public function rollback(): bool
{
return $this->getDriver(self::WRITE)->rollbackTransaction();
}

public function withoutCache(): self
{
$database = clone $this;

if ($this->readDriver instanceof Driver && $database->readDriver !== $database->driver) {
$database->readDriver = $database->readDriver->withoutCache();
}

if ($this->driver instanceof Driver) {
if ($database->readDriver === $database->driver) {
$database->readDriver = $database->readDriver->withoutCache();
$database->driver = $database->readDriver;
} else {
$database->driver = $database->driver->withoutCache();
}

return $database;
}

return $this;
}
}
5 changes: 5 additions & 0 deletions src/DatabaseInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,9 @@ public function commit(): bool;
* Rollback the active database transaction.
*/
public function rollback(): bool;

/**
* Will be added in next major release.
*/
// public function withoutCache(): self;
}
17 changes: 14 additions & 3 deletions src/Driver/Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,20 @@ abstract class Driver implements DriverInterface, NamedInterface, LoggerAwareInt
/** @var PDOStatement[]|PDOStatementInterface[] */
protected array $queryCache = [];
private ?string $name = null;
private bool $useCache = true;

protected function __construct(
protected DriverConfig $config,
HandlerInterface $schemaHandler,
protected CompilerInterface $queryCompiler,
BuilderInterface $queryBuilder
) {
$this->useCache = $this->config->queryCache;

$this->schemaHandler = $schemaHandler->withDriver($this);
$this->queryBuilder = $queryBuilder->withDriver($this);

if ($this->config->queryCache && $queryCompiler instanceof CachingCompilerInterface) {
if ($this->useCache && $queryCompiler instanceof CachingCompilerInterface) {
$this->queryCompiler = new CompilerCache($queryCompiler);
}

Expand Down Expand Up @@ -96,6 +99,14 @@ public function isReadonly(): bool
return $this->config->readonly;
}

public function withoutCache(): static
{
$driver = clone $this;
$driver->useCache = false;

return $driver;
}

/**
* Disconnect and destruct.
*/
Expand Down Expand Up @@ -480,12 +491,12 @@ protected function statement(string $query, iterable $parameters = [], bool $ret
*/
protected function prepare(string $query): PDOStatement|PDOStatementInterface
{
if ($this->config->queryCache && isset($this->queryCache[$query])) {
if ($this->useCache && isset($this->queryCache[$query])) {
return $this->queryCache[$query];
}

$statement = $this->getPDO()->prepare($query);
if ($this->config->queryCache) {
if ($this->useCache) {
$this->queryCache[$query] = $statement;
}

Expand Down
135 changes: 135 additions & 0 deletions tests/Database/Unit/DatabaseTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?php

declare(strict_types=1);

namespace Cycle\Database\Tests\Unit;

use Cycle\Database\Database;
use Cycle\Database\Driver\Driver;
use Cycle\Database\Driver\DriverInterface;
use PHPUnit\Framework\TestCase;

final class DatabaseTest extends TestCase
{
public function testWithoutCacheWithoutReadDriver(): void
{
$driver = $this->createMock(Driver::class);

$driver
->expects($this->once())
->method('withoutCache');

$database = new Database('default', '', $driver);

$newDb = $database->withoutCache();

$ref = new \ReflectionProperty($newDb, 'readDriver');
$ref->setAccessible(true);

$this->assertNull($ref->getValue($newDb));
$this->assertNotSame($driver, $newDb->getDriver());
}

public function testWithoutCacheWithSameDriverAndReadDriver(): void
{
$driver = $this->createMock(Driver::class);

$driver
->expects($this->once())
->method('withoutCache');

$database = new Database('default', '', $driver, $driver);

$newDb = $database->withoutCache();

$refDriver = new \ReflectionProperty($newDb, 'driver');
$refDriver->setAccessible(true);

$refReadDriver = new \ReflectionProperty($newDb, 'readDriver');
$refReadDriver->setAccessible(true);

$this->assertSame($refDriver->getValue($newDb), $refReadDriver->getValue($newDb));
}

public function testWithoutCacheWithDriverAndReadDriver(): void
{
$driver = $this->createMock(Driver::class);
$readDriver = $this->createMock(Driver::class);

$driver
->expects($this->once())
->method('withoutCache');

$readDriver
->expects($this->once())
->method('withoutCache');

$database = new Database('default', '', $driver, $readDriver);

$newDb = $database->withoutCache();

$refDriver = new \ReflectionProperty($newDb, 'driver');
$refDriver->setAccessible(true);

$refReadDriver = new \ReflectionProperty($newDb, 'readDriver');
$refReadDriver->setAccessible(true);

$this->assertNotSame($refDriver->getValue($newDb), $refReadDriver->getValue($newDb));
$this->assertNotSame($driver, $refDriver->getValue($newDb));
$this->assertNotSame($readDriver, $refReadDriver->getValue($newDb));
}

public function testWithoutCacheWithoutReadDriverAndWithoutMethod(): void
{
$driver = $this->createMock(DriverInterface::class);

$database = new Database('default', '', $driver);

$newDb = $database->withoutCache();

$ref = new \ReflectionProperty($newDb, 'readDriver');
$ref->setAccessible(true);

$this->assertNull($ref->getValue($newDb));
$this->assertSame($driver, $newDb->getDriver());
}

public function testWithoutCacheWithDriverAndReadDriverWithoutMethod(): void
{
$driver = $this->createMock(DriverInterface::class);
$readDriver = $this->createMock(DriverInterface::class);

$database = new Database('default', '', $driver, $readDriver);

$newDb = $database->withoutCache();

$refDriver = new \ReflectionProperty($newDb, 'driver');
$refDriver->setAccessible(true);

$refReadDriver = new \ReflectionProperty($newDb, 'readDriver');
$refReadDriver->setAccessible(true);

$this->assertNotSame($refDriver->getValue($newDb), $refReadDriver->getValue($newDb));
$this->assertSame($driver, $refDriver->getValue($newDb));
$this->assertSame($readDriver, $refReadDriver->getValue($newDb));
}

public function testWithoutCacheWithSameDriversAndWithoutMethod(): void
{
$driver = $this->createMock(DriverInterface::class);

$database = new Database('default', '', $driver, $driver);

$newDb = $database->withoutCache();

$refDriver = new \ReflectionProperty($newDb, 'driver');
$refDriver->setAccessible(true);

$refReadDriver = new \ReflectionProperty($newDb, 'readDriver');
$refReadDriver->setAccessible(true);

$this->assertSame($refDriver->getValue($newDb), $refReadDriver->getValue($newDb));
$this->assertSame($driver, $refDriver->getValue($newDb));
$this->assertSame($driver, $refReadDriver->getValue($newDb));
}
}
34 changes: 34 additions & 0 deletions tests/Database/Unit/Driver/AbstractDriverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,40 @@ public function testLogsWithEnabledInterpolation(): void
);
}

public function testUseCacheFromConfig(): void
{
$ref = new \ReflectionProperty(Driver::class, 'useCache');
$ref->setAccessible(true);

$this->assertTrue($ref->getValue(TestDriver::create(new SQLiteDriverConfig(queryCache: true))));
$this->assertFalse($ref->getValue(TestDriver::create(new SQLiteDriverConfig(queryCache: false))));
}

public function testWithoutCache(): void
{
$ref = new \ReflectionProperty(Driver::class, 'useCache');
$ref->setAccessible(true);

$driver = TestDriver::create(new SQLiteDriverConfig(queryCache: true));

$this->assertTrue($ref->getValue($driver));
$this->assertFalse($ref->getValue($driver->withoutCache()));
}

public function testPdoNotClonedAfterCacheDisabled(): void
{
$ref = new \ReflectionMethod(Driver::class, 'getPDO');
$ref->setAccessible(true);

$driver = TestDriver::create(new SQLiteDriverConfig(queryCache: true));
$oldPDO = $ref->invoke($driver);

$driver = $driver->withoutCache();
$newPDO = $ref->invoke($driver);

$this->assertSame($oldPDO, $newPDO);
}

private function checkImmutability(DriverInterface $driver, DriverInterface $newDriver): void
{
// Immutability
Expand Down

0 comments on commit 403839f

Please sign in to comment.