bug #42011 [Cache] Support decorated Dbal drivers in PdoAdapter (Jeroeny)
This PR was squashed before being merged into the 4.4 branch.
Discussion
----------
[Cache] Support decorated Dbal drivers in PdoAdapter
| Q | A
| ------------- | ---
| Branch? | 4.4
| Bug fix? | yes
| New feature? | no
| Deprecations? | no
| Tickets | Explanation in this PR
| License | MIT
Doctrine v3 supports middleware for Drivers. Upon creating the Connection, `middleware->wrap(Driver): Driver` [is called](https://github.com/doctrine/dbal/blob/3.1.x/src/DriverManager.php#L210), in which the middleware can wrap/decorate the Driver class. So that it can perform tracing [for example](https://github.com/getsentry/sentry-symfony/blob/master/src/Tracing/Doctrine/DBAL/TracingDriverMiddleware.php#L37).
When this happens, the Driver class inside the Connection is no longer one of Doctrine's well known Driver classes. The `PdoAdapter ` uses this class to determine the database platform. Which breaks once the Driver is decorated and no longer one of the classes [listed](https://github.com/symfony/symfony/blob/5.4/src/Symfony/Component/Cache/Adapter/PdoAdapter.php#L452) in the `PdoAdapter`.
Since Dbal exposes this middleware as a feature, I think it would be nice for the `PdoAdapter` to support this.
To solve this, the `getDatabasePlatform` can be used. This returns a `Doctrine\DBAL\Platforms\AbstractPlatform` which defines the abstract method `getName`. This returns a value very similar to the list in the `PdoAdapter`. The names don't match exactly, so therefor a small mapping is done to get right the name used in the adapter. As far as a I know, there'd be no other implications with this change.
Related: https://github.com/getsentry/sentry-symfony/issues/530
Commits
-------
58d74e30be
[Cache] Support decorated Dbal drivers in PdoAdapter
This commit is contained in:
commit
e5c96c4051
|
@ -25,6 +25,7 @@ foreach ($loader->getClassMap() as $class => $file) {
|
||||||
case false !== strpos($file = realpath($file), '/vendor/'):
|
case false !== strpos($file = realpath($file), '/vendor/'):
|
||||||
case false !== strpos($file, '/src/Symfony/Bridge/PhpUnit/'):
|
case false !== strpos($file, '/src/Symfony/Bridge/PhpUnit/'):
|
||||||
case false !== strpos($file, '/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Validation/Article.php'):
|
case false !== strpos($file, '/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Validation/Article.php'):
|
||||||
|
case false !== strpos($file, '/src/Symfony/Component/Cache/Tests/Fixtures/DriverWrapper.php'):
|
||||||
case false !== strpos($file, '/src/Symfony/Component/Config/Tests/Fixtures/BadFileName.php'):
|
case false !== strpos($file, '/src/Symfony/Component/Config/Tests/Fixtures/BadFileName.php'):
|
||||||
case false !== strpos($file, '/src/Symfony/Component/Config/Tests/Fixtures/BadParent.php'):
|
case false !== strpos($file, '/src/Symfony/Component/Config/Tests/Fixtures/BadParent.php'):
|
||||||
case false !== strpos($file, '/src/Symfony/Component/Config/Tests/Fixtures/ParseError.php'):
|
case false !== strpos($file, '/src/Symfony/Component/Config/Tests/Fixtures/ParseError.php'):
|
||||||
|
|
|
@ -11,10 +11,13 @@
|
||||||
|
|
||||||
namespace Symfony\Component\Cache\Tests\Adapter;
|
namespace Symfony\Component\Cache\Tests\Adapter;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Configuration;
|
||||||
|
use Doctrine\DBAL\Driver\Middleware;
|
||||||
use Doctrine\DBAL\DriverManager;
|
use Doctrine\DBAL\DriverManager;
|
||||||
use PHPUnit\Framework\SkippedTestSuiteError;
|
use PHPUnit\Framework\SkippedTestSuiteError;
|
||||||
use Psr\Cache\CacheItemPoolInterface;
|
use Psr\Cache\CacheItemPoolInterface;
|
||||||
use Symfony\Component\Cache\Adapter\PdoAdapter;
|
use Symfony\Component\Cache\Adapter\PdoAdapter;
|
||||||
|
use Symfony\Component\Cache\Tests\Fixtures\DriverWrapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group time-sensitive
|
* @group time-sensitive
|
||||||
|
@ -43,4 +46,29 @@ class PdoDbalAdapterTest extends AdapterTestCase
|
||||||
{
|
{
|
||||||
return new PdoAdapter(DriverManager::getConnection(['driver' => 'pdo_sqlite', 'path' => self::$dbFile]), '', $defaultLifetime);
|
return new PdoAdapter(DriverManager::getConnection(['driver' => 'pdo_sqlite', 'path' => self::$dbFile]), '', $defaultLifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testConfigureSchemaDecoratedDbalDriver()
|
||||||
|
{
|
||||||
|
$connection = DriverManager::getConnection(['driver' => 'pdo_sqlite', 'path' => self::$dbFile]);
|
||||||
|
if (!interface_exists(Middleware::class)) {
|
||||||
|
$this->markTestSkipped('doctrine/dbal v2 does not support custom drivers using middleware');
|
||||||
|
}
|
||||||
|
|
||||||
|
$middleware = $this->createMock(Middleware::class);
|
||||||
|
$middleware
|
||||||
|
->method('wrap')
|
||||||
|
->willReturn(new DriverWrapper($connection->getDriver()));
|
||||||
|
|
||||||
|
$config = new Configuration();
|
||||||
|
$config->setMiddlewares([$middleware]);
|
||||||
|
|
||||||
|
$connection = DriverManager::getConnection(['driver' => 'pdo_sqlite', 'path' => self::$dbFile], $config);
|
||||||
|
|
||||||
|
$adapter = new PdoAdapter($connection);
|
||||||
|
$adapter->createTable();
|
||||||
|
|
||||||
|
$item = $adapter->getItem('key');
|
||||||
|
$item->set('value');
|
||||||
|
$this->assertTrue($adapter->save($item));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Cache\Tests\Fixtures;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Connection;
|
||||||
|
use Doctrine\DBAL\Driver;
|
||||||
|
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||||
|
use Doctrine\DBAL\Schema\AbstractSchemaManager;
|
||||||
|
|
||||||
|
class DriverWrapper implements Driver
|
||||||
|
{
|
||||||
|
/** @var Driver */
|
||||||
|
private $driver;
|
||||||
|
|
||||||
|
public function __construct(Driver $driver)
|
||||||
|
{
|
||||||
|
$this->driver = $driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function connect(array $params, $username = null, $password = null, array $driverOptions = []): Driver\Connection
|
||||||
|
{
|
||||||
|
return $this->driver->connect($params, $username, $password, $driverOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDatabasePlatform(): AbstractPlatform
|
||||||
|
{
|
||||||
|
return $this->driver->getDatabasePlatform();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSchemaManager(Connection $conn, AbstractPlatform $platform): AbstractSchemaManager
|
||||||
|
{
|
||||||
|
return $this->driver->getSchemaManager($conn, $platform);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getExceptionConverter(): Driver\API\ExceptionConverter
|
||||||
|
{
|
||||||
|
return $this->driver->getExceptionConverter();
|
||||||
|
}
|
||||||
|
}
|
|
@ -448,6 +448,15 @@ trait PdoTrait
|
||||||
case $driver instanceof \Doctrine\DBAL\Driver\PDO\SQLSrv\Driver:
|
case $driver instanceof \Doctrine\DBAL\Driver\PDO\SQLSrv\Driver:
|
||||||
$this->driver = 'sqlsrv';
|
$this->driver = 'sqlsrv';
|
||||||
break;
|
break;
|
||||||
|
case $driver instanceof \Doctrine\DBAL\Driver:
|
||||||
|
$this->driver = [
|
||||||
|
'mssql' => 'sqlsrv',
|
||||||
|
'oracle' => 'oci',
|
||||||
|
'postgresql' => 'pgsql',
|
||||||
|
'sqlite' => 'sqlite',
|
||||||
|
'mysql' => 'mysql',
|
||||||
|
][$driver->getDatabasePlatform()->getName()] ?? \get_class($driver);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
$this->driver = \get_class($driver);
|
$this->driver = \get_class($driver);
|
||||||
break;
|
break;
|
||||||
|
|
Reference in New Issue