Removed ServerInfoAwareConnection#requiresQueryForServerVersion() as implementation detail

Testing the implementations of this method requires partial mocking of the implementing class which makes it impossible to make them `final` (#3590).

Additionally, this API breaks the encapsulation of the driver layer: instead of exposing the fact of whether the connection will perform a query to detect the server version, the driver should just instantiate a platform corresponding to a connection.

The rationale behind introducing this method (#487) is really questionable:

> This is also required for drivers that cannot return the database server version without an additional query (performance reasons).

1. There's no evidence that an underlying driver that exposes the server version via its API doesn't make a request of any kind to the server.
2. For an application that works with any realistic database, a query like `SELECT VERSION()` wouldn't be a performance bottleneck.
3. Even if it was, it's always possible to specify the platform version upfront. Otherwise, the current logic of falling back to a default platform may cause undefined behavior of the application (we don't test the compatibility of the lowest level of the DBAL platform with all supported server versions). Remember, “If it doesn’t work, it doesn’t matter how fast it doesn’t work.”

In addition to the above, the only driver that doesn't support the platform version detection via the underlying driver API is `sqsql` which is barely supported.
parent f37a88ed
# Upgrade to 3.0 # Upgrade to 3.0
## BC BREAK: `ServerInfoAwareConnection::requiresQueryForServerVersion()` is removed.
The `ServerInfoAwareConnection::requiresQueryForServerVersion()` method has been removed as an implementation detail which is the same for almost all supported drivers.
## BC BREAK: PingableConnection and ServerInfoAwareConnection interfaces now extends Connection ## BC BREAK: PingableConnection and ServerInfoAwareConnection interfaces now extends Connection
All implementations of the `PingableConnection` and `ServerInfoAwareConnection` interfaces have to implement the methods defined in the `Connection` interface as well. All implementations of the `PingableConnection` and `ServerInfoAwareConnection` interfaces have to implement the methods defined in the `Connection` interface as well.
......
...@@ -393,7 +393,7 @@ class Connection implements DriverConnection ...@@ -393,7 +393,7 @@ class Connection implements DriverConnection
$connection = $this->getWrappedConnection(); $connection = $this->getWrappedConnection();
// Automatic platform version detection. // Automatic platform version detection.
if ($connection instanceof ServerInfoAwareConnection && ! $connection->requiresQueryForServerVersion()) { if ($connection instanceof ServerInfoAwareConnection) {
return $connection->getServerVersion(); return $connection->getServerVersion();
} }
......
...@@ -59,14 +59,6 @@ class DB2Connection implements ServerInfoAwareConnection ...@@ -59,14 +59,6 @@ class DB2Connection implements ServerInfoAwareConnection
return $serverInfo->DBMS_VER; return $serverInfo->DBMS_VER;
} }
/**
* {@inheritdoc}
*/
public function requiresQueryForServerVersion() : bool
{
return false;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
......
...@@ -117,14 +117,6 @@ class MysqliConnection implements PingableConnection, ServerInfoAwareConnection ...@@ -117,14 +117,6 @@ class MysqliConnection implements PingableConnection, ServerInfoAwareConnection
return $majorVersion . '.' . $minorVersion . '.' . $patchVersion; return $majorVersion . '.' . $minorVersion . '.' . $patchVersion;
} }
/**
* {@inheritdoc}
*/
public function requiresQueryForServerVersion() : bool
{
return false;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
......
...@@ -85,14 +85,6 @@ class OCI8Connection implements Connection, ServerInfoAwareConnection ...@@ -85,14 +85,6 @@ class OCI8Connection implements Connection, ServerInfoAwareConnection
return $matches[1]; return $matches[1];
} }
/**
* {@inheritdoc}
*/
public function requiresQueryForServerVersion() : bool
{
return false;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
......
...@@ -105,14 +105,6 @@ class PDOConnection implements ServerInfoAwareConnection ...@@ -105,14 +105,6 @@ class PDOConnection implements ServerInfoAwareConnection
} }
} }
/**
* {@inheritdoc}
*/
public function requiresQueryForServerVersion() : bool
{
return false;
}
/** /**
* Creates a wrapped statement * Creates a wrapped statement
*/ */
......
...@@ -144,14 +144,6 @@ class SQLAnywhereConnection implements ServerInfoAwareConnection ...@@ -144,14 +144,6 @@ class SQLAnywhereConnection implements ServerInfoAwareConnection
return "'" . sasql_escape_string($this->connection, $input) . "'"; return "'" . sasql_escape_string($this->connection, $input) . "'";
} }
/**
* {@inheritdoc}
*/
public function requiresQueryForServerVersion() : bool
{
return true;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
* *
......
...@@ -59,14 +59,6 @@ class SQLSrvConnection implements ServerInfoAwareConnection ...@@ -59,14 +59,6 @@ class SQLSrvConnection implements ServerInfoAwareConnection
return $serverInfo['SQLServerVersion']; return $serverInfo['SQLServerVersion'];
} }
/**
* {@inheritdoc}
*/
public function requiresQueryForServerVersion() : bool
{
return false;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
......
...@@ -13,11 +13,4 @@ interface ServerInfoAwareConnection extends Connection ...@@ -13,11 +13,4 @@ interface ServerInfoAwareConnection extends Connection
* Returns the version number of the database server connected to. * Returns the version number of the database server connected to.
*/ */
public function getServerVersion() : string; public function getServerVersion() : string;
/**
* Checks whether a query is required to retrieve the database server version.
*
* @return bool True if a query is required to retrieve the database server version, false otherwise.
*/
public function requiresQueryForServerVersion() : bool;
} }
...@@ -687,10 +687,6 @@ class ConnectionTest extends DbalTestCase ...@@ -687,10 +687,6 @@ class ConnectionTest extends DbalTestCase
->method('connect') ->method('connect')
->will($this->returnValue($driverConnectionMock)); ->will($this->returnValue($driverConnectionMock));
$driverConnectionMock->expects($this->once())
->method('requiresQueryForServerVersion')
->will($this->returnValue(false));
$driverConnectionMock->expects($this->once()) $driverConnectionMock->expects($this->once())
->method('getServerVersion') ->method('getServerVersion')
->will($this->returnValue('6.6.6')); ->will($this->returnValue('6.6.6'));
......
<?php
declare(strict_types=1);
namespace Doctrine\Tests\DBAL\Driver\IBMDB2;
use Doctrine\DBAL\Driver\IBMDB2\DB2Connection;
use Doctrine\Tests\DbalTestCase;
use PHPUnit\Framework\MockObject\MockObject;
use function extension_loaded;
class DB2ConnectionTest extends DbalTestCase
{
/**
* The ibm_db2 driver connection mock under test.
*
* @var DB2Connection|MockObject
*/
private $connectionMock;
protected function setUp() : void
{
if (! extension_loaded('ibm_db2')) {
$this->markTestSkipped('ibm_db2 is not installed.');
}
parent::setUp();
$this->connectionMock = $this->getMockBuilder(DB2Connection::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
}
public function testDoesNotRequireQueryForServerVersion() : void
{
self::assertFalse($this->connectionMock->requiresQueryForServerVersion());
}
}
...@@ -8,20 +8,12 @@ use Doctrine\DBAL\Driver\Mysqli\Exception\ConnectionError; ...@@ -8,20 +8,12 @@ use Doctrine\DBAL\Driver\Mysqli\Exception\ConnectionError;
use Doctrine\DBAL\Driver\Mysqli\MysqliConnection; use Doctrine\DBAL\Driver\Mysqli\MysqliConnection;
use Doctrine\DBAL\Platforms\MySqlPlatform; use Doctrine\DBAL\Platforms\MySqlPlatform;
use Doctrine\Tests\DbalFunctionalTestCase; use Doctrine\Tests\DbalFunctionalTestCase;
use PHPUnit\Framework\MockObject\MockObject;
use function extension_loaded; use function extension_loaded;
use function restore_error_handler; use function restore_error_handler;
use function set_error_handler; use function set_error_handler;
class MysqliConnectionTest extends DbalFunctionalTestCase class MysqliConnectionTest extends DbalFunctionalTestCase
{ {
/**
* The mysqli driver connection mock under test.
*
* @var MysqliConnection|MockObject
*/
private $connectionMock;
protected function setUp() : void protected function setUp() : void
{ {
if (! extension_loaded('mysqli')) { if (! extension_loaded('mysqli')) {
...@@ -30,18 +22,11 @@ class MysqliConnectionTest extends DbalFunctionalTestCase ...@@ -30,18 +22,11 @@ class MysqliConnectionTest extends DbalFunctionalTestCase
parent::setUp(); parent::setUp();
if (! $this->connection->getDatabasePlatform() instanceof MySqlPlatform) { if ($this->connection->getDatabasePlatform() instanceof MySqlPlatform) {
$this->markTestSkipped('MySQL only test.'); return;
} }
$this->connectionMock = $this->getMockBuilder(MysqliConnection::class) $this->markTestSkipped('MySQL only test.');
->disableOriginalConstructor()
->getMockForAbstractClass();
}
public function testDoesNotRequireQueryForServerVersion() : void
{
self::assertFalse($this->connectionMock->requiresQueryForServerVersion());
} }
public function testRestoresErrorHandlerOnException() : void public function testRestoresErrorHandlerOnException() : void
......
<?php
declare(strict_types=1);
namespace Doctrine\Tests\DBAL\Driver\OCI8;
use Doctrine\DBAL\Driver\OCI8\OCI8Connection;
use Doctrine\Tests\DbalTestCase;
use PHPUnit\Framework\MockObject\MockObject;
use function extension_loaded;
class OCI8ConnectionTest extends DbalTestCase
{
/**
* The oci8 driver connection mock under test.
*
* @var OCI8Connection|MockObject
*/
private $connectionMock;
protected function setUp() : void
{
if (! extension_loaded('oci8')) {
$this->markTestSkipped('oci8 is not installed.');
}
parent::setUp();
$this->connectionMock = $this->getMockBuilder(OCI8Connection::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
}
public function testDoesNotRequireQueryForServerVersion() : void
{
self::assertFalse($this->connectionMock->requiresQueryForServerVersion());
}
}
<?php
declare(strict_types=1);
namespace Doctrine\Tests\DBAL\Driver\SQLAnywhere;
use Doctrine\DBAL\Driver\SQLAnywhere\SQLAnywhereConnection;
use Doctrine\Tests\DbalTestCase;
use PHPUnit\Framework\MockObject\MockObject;
use function extension_loaded;
class SQLAnywhereConnectionTest extends DbalTestCase
{
/**
* The sqlanywhere driver connection mock under test.
*
* @var SQLAnywhereConnection|MockObject
*/
private $connectionMock;
protected function setUp() : void
{
if (! extension_loaded('sqlanywhere')) {
$this->markTestSkipped('sqlanywhere is not installed.');
}
parent::setUp();
$this->connectionMock = $this->getMockBuilder(SQLAnywhereConnection::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
}
public function testRequiresQueryForServerVersion() : void
{
self::assertTrue($this->connectionMock->requiresQueryForServerVersion());
}
}
<?php
declare(strict_types=1);
namespace Doctrine\Tests\DBAL\Driver\SQLSrv;
use Doctrine\DBAL\Driver\SQLSrv\SQLSrvConnection;
use Doctrine\Tests\DbalTestCase;
use PHPUnit\Framework\MockObject\MockObject;
use function extension_loaded;
class SQLSrvConnectionTest extends DbalTestCase
{
/**
* The sqlsrv driver connection mock under test.
*
* @var SQLSrvConnection|MockObject
*/
private $connectionMock;
protected function setUp() : void
{
if (! extension_loaded('sqlsrv')) {
$this->markTestSkipped('sqlsrv is not installed.');
}
parent::setUp();
$this->connectionMock = $this->getMockBuilder(SQLSrvConnection::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
}
public function testDoesNotRequireQueryForServerVersion() : void
{
self::assertFalse($this->connectionMock->requiresQueryForServerVersion());
}
}
...@@ -46,11 +46,6 @@ class PDOConnectionTest extends DbalFunctionalTestCase ...@@ -46,11 +46,6 @@ class PDOConnectionTest extends DbalFunctionalTestCase
parent::tearDown(); parent::tearDown();
} }
public function testDoesNotRequireQueryForServerVersion() : void
{
self::assertFalse($this->driverConnection->requiresQueryForServerVersion());
}
public function testThrowsWrappedExceptionOnConstruct() : void public function testThrowsWrappedExceptionOnConstruct() : void
{ {
$this->expectException(PDOException::class); $this->expectException(PDOException::class);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment