Type: New Feature
Affects Version/s: None
Fix Version/s: 2.5
Security Level: All
This issue is created automatically through a Github pull request on behalf of deeky666:
As more and more vendor version specific platforms evolve, it is time to make an approach of autodetecting and using the correct platform on connection. This is done by introducing two new interfaces `Doctrine\DBAL\VersionAwarePlatformDriver` and `Doctrine\DBAL\Driver\ServerInfoAwareConnection` which are implemented by Doctrine's driver and driver connection classes. They are introduced to keep BC for custom driver / driver connection classes.
`VersionAwarePlatformDriver::createDatabasePlatformForVersion($version)` is responsible for evaluating a given vendor specific version number and instantiating the correct platform for it. The current implementations normalize the given version string and use `version_compare()` for evaluation.
`ServerInfoAwareConnection::getServerVersion()` is responsible for returning the normalized version string of the database server currently connected to. `ServerInfoAwareConnection::requiresQueryForServerVersion()` defines whether receiving that information requires an additional database query or not which is important for `Doctrine\DBAL\Connection` as described in the following.
`Doctrine\DBAL\Connection` now takes an additional (optional) connection parameter `serverVersion` which the user can pass to skip platform autodetection and define the desired platform version straight away. This is also required for drivers that cannot return the database server version without an additional query (performance reasons). Platform version detection is now done in the following order of precedence:
1. Evaluate `platform` connection parameter and return an instance of that class if given.
2. Evaluate if the underlying driver is capable of creating platform instances by version. If not, return the default platform instance that would be returned by the current implementation.
3. Evaluate if `serverVersion` connection parameter is given and return the appropriate platform instance for that version.
4. Evaluate if the underlying driver connection can return the server version and can return it without the need of an additional query -> return the appropriate platform instance for that version.
5. Otherwise return the default platform instance that would be returned by the current implementation.
As a positive side effect while implementing the new interfaces, the driver classes were refactored by extracting abstract base driver classes for each vendor. This removes a lot of duplicated code in the driver classes that are related to the same database vendor. Please also note, that `DrizzlePDOMySql` now directly inherits from `Doctrine\DBAL\Driver\PDOMySql\Driver` to come around additional code duplication.
The only BC break introduced by this PR should be the visibility change of `Doctrine\DBAL\Connection::$_platform` from protected to private (as wished by @beberlei).
The only drawback of this implementation is that `Doctrine\DBAL\Connection::getDatabasePlatform()` now needs to do the real connect (if uninitialized) under some circumstances when it needs to autodetect the server version from the driver connection. Therefore I had to change the initialization of temporary connections in the functional test suite a little bit, so that calling `Doctrine\DBAL\Connection::getDatabasePlatform()` does not raise an error if the supplied temporary database does not exist. I think this is acceptable as it is not necessary to connect to a specific database anyways when only needing to drop and create the real test database.
As soon as the doctrine team agrees on this approach, I will add some more test and documentation for this. Until then this is a WIP PR.