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, '/src/Symfony/Bridge/PhpUnit/'):
|
||||
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/BadParent.php'):
|
||||
case false !== strpos($file, '/src/Symfony/Component/Config/Tests/Fixtures/ParseError.php'):
|
||||
|
|
|
@ -11,10 +11,13 @@
|
|||
|
||||
namespace Symfony\Component\Cache\Tests\Adapter;
|
||||
|
||||
use Doctrine\DBAL\Configuration;
|
||||
use Doctrine\DBAL\Driver\Middleware;
|
||||
use Doctrine\DBAL\DriverManager;
|
||||
use PHPUnit\Framework\SkippedTestSuiteError;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
use Symfony\Component\Cache\Adapter\PdoAdapter;
|
||||
use Symfony\Component\Cache\Tests\Fixtures\DriverWrapper;
|
||||
|
||||
/**
|
||||
* @group time-sensitive
|
||||
|
@ -43,4 +46,29 @@ class PdoDbalAdapterTest extends AdapterTestCase
|
|||
{
|
||||
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:
|
||||
$this->driver = 'sqlsrv';
|
||||
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:
|
||||
$this->driver = \get_class($driver);
|
||||
break;
|
||||
|
|
Reference in New Issue