Commit a8663d87 authored by Benni Mack's avatar Benni Mack Committed by Georg Ringer
Browse files

[TASK] DBAL: Extend custom drivers from abstract drivers

TYPO3 Core has its own implementation of driver classes
for database abstraction by effectively overriding e.g.
the PDO Statement class with TYPO3's Statment class
to ensure that resources are strings to be completely
transparent with Database abstraction.

Doctrine DBAL 3.0 will force Drivers to either
switch to composition or extend from the Abstract Driver classes.

This change switches TYPO3's native implementation
to extend from Abstract Driver classes, ensuring
forward-compatibility with Doctrine DBAL 3.0
for TYPO3 v11 with Drivers.

Resolves: #93076
Releases: master
Change-Id: I32b886fe13bc7b5c759c1d127b31fe6d3ba94141
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/67115

Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Tested-by: Georg Ringer's avatarGeorg Ringer <georg.ringer@gmail.com>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Georg Ringer's avatarGeorg Ringer <georg.ringer@gmail.com>
parent 9dbd2767
......@@ -17,8 +17,8 @@ declare(strict_types=1);
namespace TYPO3\CMS\Core\Database\Driver;
use Doctrine\DBAL\Driver\PDO\Connection as DoctrineDbalPDOConnection;
use Doctrine\DBAL\Driver\PDO\Exception as PDOException;
use Doctrine\DBAL\Driver\PDOConnection as DoctrineDbalPDOConnection;
use PDO;
/**
......
......@@ -17,7 +17,7 @@ declare(strict_types=1);
namespace TYPO3\CMS\Core\Database\Driver\PDOMySql;
use Doctrine\DBAL\Driver\PDOMySql\Driver as DoctrinePDOMySqlDriver;
use Doctrine\DBAL\Driver\AbstractMySQLDriver;
use Doctrine\DBAL\Exception as DBALException;
use PDOException;
use TYPO3\CMS\Core\Database\Driver\PDOConnection;
......@@ -26,7 +26,7 @@ use TYPO3\CMS\Core\Database\Driver\PDOConnection;
* This is a full "clone" of the class of package doctrine/dbal. Scope is to use the PDOConnection of TYPO3.
* All private methods have to be checked on every release of doctrine/dbal.
*/
class Driver extends DoctrinePDOMySqlDriver
class Driver extends AbstractMySQLDriver
{
/**
* {@inheritdoc}
......@@ -51,4 +51,47 @@ class Driver extends DoctrinePDOMySqlDriver
return $conn;
}
/**
* Constructs the MySql PDO DSN.
*
* @param mixed[] $params
*
* @return string The DSN.
*/
protected function constructPdoDsn(array $params)
{
$dsn = 'mysql:';
if (isset($params['host']) && $params['host'] !== '') {
$dsn .= 'host=' . $params['host'] . ';';
}
if (isset($params['port'])) {
$dsn .= 'port=' . $params['port'] . ';';
}
if (isset($params['dbname'])) {
$dsn .= 'dbname=' . $params['dbname'] . ';';
}
if (isset($params['unix_socket'])) {
$dsn .= 'unix_socket=' . $params['unix_socket'] . ';';
}
if (isset($params['charset'])) {
$dsn .= 'charset=' . $params['charset'] . ';';
}
return $dsn;
}
/**
* {@inheritdoc}
*
* @deprecated
*/
public function getName()
{
return 'pdo_mysql';
}
}
......@@ -17,7 +17,7 @@ declare(strict_types=1);
namespace TYPO3\CMS\Core\Database\Driver\PDOPgSql;
use Doctrine\DBAL\Driver\PDOPgSql\Driver as DoctrineDbalPDOPgSqlDriver;
use Doctrine\DBAL\Driver\AbstractPostgreSQLDriver;
use Doctrine\DBAL\Exception as DBALException;
use PDO;
use PDOException;
......@@ -27,7 +27,7 @@ use TYPO3\CMS\Core\Database\Driver\PDOConnection;
* This is a full "clone" of the class of package doctrine/dbal. Scope is to use the PDOConnection of TYPO3.
* All private methods have to be checked on every release of doctrine/dbal.
*/
class Driver extends DoctrineDbalPDOPgSqlDriver
class Driver extends AbstractPostgreSQLDriver
{
/**
* {@inheritdoc}
......@@ -66,7 +66,11 @@ class Driver extends DoctrineDbalPDOPgSqlDriver
}
/**
* {@inheritdoc}
* Constructs the Postgres PDO DSN.
*
* @param mixed[] $params
*
* @return string The DSN.
*/
private function _constructPdoDsn(array $params)
{
......@@ -117,4 +121,14 @@ class Driver extends DoctrineDbalPDOPgSqlDriver
return $dsn;
}
/**
* {@inheritdoc}
*
* @deprecated
*/
public function getName()
{
return 'pdo_pgsql';
}
}
......@@ -17,8 +17,9 @@ declare(strict_types=1);
namespace TYPO3\CMS\Core\Database\Driver\PDOSqlite;
use Doctrine\DBAL\Driver\PDOSqlite\Driver as DoctrinePDOSqliteDriver;
use Doctrine\DBAL\Driver\AbstractSQLiteDriver;
use Doctrine\DBAL\Exception as DBALException;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use PDOException;
use TYPO3\CMS\Core\Database\Driver\PDOConnection;
......@@ -26,8 +27,17 @@ use TYPO3\CMS\Core\Database\Driver\PDOConnection;
* This is a full "clone" of the class of package doctrine/dbal. Scope is to use the PDOConnection of TYPO3.
* All private methods have to be checked on every release of doctrine/dbal.
*/
class Driver extends DoctrinePDOSqliteDriver
class Driver extends AbstractSQLiteDriver
{
/**
* @var mixed[]
*/
protected $_userDefinedFunctions = [
'sqrt' => ['callback' => [SqlitePlatform::class, 'udfSqrt'], 'numArgs' => 1],
'mod' => ['callback' => [SqlitePlatform::class, 'udfMod'], 'numArgs' => 2],
'locate' => ['callback' => [SqlitePlatform::class, 'udfLocate'], 'numArgs' => -1],
];
/**
* {@inheritdoc}
*/
......@@ -58,4 +68,33 @@ class Driver extends DoctrinePDOSqliteDriver
return $pdo;
}
/**
* Constructs the Sqlite PDO DSN.
*
* @param mixed[] $params
*
* @return string The DSN.
*/
protected function _constructPdoDsn(array $params)
{
$dsn = 'sqlite:';
if (isset($params['path'])) {
$dsn .= $params['path'];
} elseif (isset($params['memory'])) {
$dsn .= ':memory:';
}
return $dsn;
}
/**
* {@inheritdoc}
*
* @deprecated
*/
public function getName()
{
return 'pdo_sqlite';
}
}
......@@ -17,15 +17,18 @@ declare(strict_types=1);
namespace TYPO3\CMS\Core\Database\Driver\PDOSqlsrv;
use Doctrine\DBAL\Driver\Result;
use PDO;
/**
* This is a full "clone" of the class of package doctrine/dbal. Scope is to use the PDOConnection of TYPO3.
* All private methods have to be checked on every release of doctrine/dbal.
*/
class Connection extends \Doctrine\DBAL\Driver\PDOSqlsrv\Connection
class Connection extends \Doctrine\DBAL\Driver\PDO\Connection
{
/**
* @internal The connection can be only instantiated by its driver.
*
* {@inheritdoc}
*/
public function __construct($dsn, $user = null, $password = null, ?array $options = null)
......@@ -33,4 +36,23 @@ class Connection extends \Doctrine\DBAL\Driver\PDOSqlsrv\Connection
parent::__construct($dsn, $user, $password, $options);
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, [Statement::class, []]);
}
/**
* {@inheritDoc}
*/
public function lastInsertId($name = null)
{
if ($name === null) {
return parent::lastInsertId($name);
}
$stmt = $this->prepare('SELECT CONVERT(VARCHAR(MAX), current_value) FROM sys.sequences WHERE name = ?');
$stmt->execute([$name]);
if ($stmt instanceof Result) {
return $stmt->fetchOne();
}
return $stmt->fetchColumn();
}
}
......@@ -17,11 +17,14 @@ declare(strict_types=1);
namespace TYPO3\CMS\Core\Database\Driver\PDOSqlsrv;
use Doctrine\DBAL\Driver\AbstractSQLServerDriver;
use Doctrine\DBAL\Driver\AbstractSQLServerDriver\Exception\PortWithoutHost;
/**
* This is a full "clone" of the class of package doctrine/dbal. Scope is to use the PDOConnection of TYPO3.
* All private methods have to be checked on every release of doctrine/dbal.
*/
class Driver extends \Doctrine\DBAL\Driver\PDOSqlsrv\Driver
class Driver extends AbstractSQLServerDriver
{
/**
* {@inheritdoc}
......@@ -39,7 +42,12 @@ class Driver extends \Doctrine\DBAL\Driver\PDOSqlsrv\Driver
}
/**
* {@inheritdoc}
* Constructs the Sqlsrv PDO DSN.
*
* @param mixed[] $params
* @param string[] $connectionOptions
*
* @return string The DSN.
*/
private function _constructPdoDsn(array $params, array $connectionOptions)
{
......@@ -47,10 +55,12 @@ class Driver extends \Doctrine\DBAL\Driver\PDOSqlsrv\Driver
if (isset($params['host'])) {
$dsn .= $params['host'];
}
if (isset($params['port']) && ! empty($params['port'])) {
$dsn .= ',' . $params['port'];
if (isset($params['port'])) {
$dsn .= ',' . $params['port'];
}
} elseif (isset($params['port'])) {
throw PortWithoutHost::new();
}
if (isset($params['dbname'])) {
......@@ -64,9 +74,6 @@ class Driver extends \Doctrine\DBAL\Driver\PDOSqlsrv\Driver
return $dsn . $this->getConnectionOptionsDsn($connectionOptions);
}
/**
* {@inheritdoc}
*/
private function splitOptions(array $options): array
{
$driverOptions = [];
......@@ -84,7 +91,9 @@ class Driver extends \Doctrine\DBAL\Driver\PDOSqlsrv\Driver
}
/**
* {@inheritdoc}
* Converts a connection options array to the DSN
*
* @param string[] $connectionOptions
*/
private function getConnectionOptionsDsn(array $connectionOptions): string
{
......@@ -99,9 +108,11 @@ class Driver extends \Doctrine\DBAL\Driver\PDOSqlsrv\Driver
/**
* {@inheritdoc}
*
* @deprecated
*/
public function getName()
{
return parent::getName();
return 'pdo_sqlsrv';
}
}
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