Commit 2cb7a089 authored by Benni Mack's avatar Benni Mack
Browse files

[BUGFIX] Add createSchemaManager to DBAL Connection

This change adds the new createSchemaManager() to
our Doctrine DBAL Connection subclass to make it
forward-compatible with Doctrine DBAL 3.x.

createSchemaManager() is introduced with DBAL 3.x and
is replacing getSchemaManager() which will be removed
in Doctrine DBAL 4.

Since this is a very lowlevel change, the method
can be added without most notice for extension authors.

Resolves: #96286
Releases: main, 11.5
Change-Id: Ifdccc2b0dff443bfe38d23a1bd1333b5c7c5db40
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/72555


Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent 88a4a857
...@@ -7263,7 +7263,7 @@ class DataHandler implements LoggerAwareInterface ...@@ -7263,7 +7263,7 @@ class DataHandler implements LoggerAwareInterface
$platform = $connection->getDatabasePlatform(); $platform = $connection->getDatabasePlatform();
if ($platform instanceof SQLServerPlatform) { if ($platform instanceof SQLServerPlatform) {
// mssql needs to set proper PARAM_LOB and others to update fields // mssql needs to set proper PARAM_LOB and others to update fields
$tableDetails = $connection->getSchemaManager()->listTableDetails($table); $tableDetails = $connection->createSchemaManager()->listTableDetails($table);
foreach ($fieldArray as $columnName => $columnValue) { foreach ($fieldArray as $columnName => $columnValue) {
$types[$columnName] = $tableDetails->getColumn($columnName)->getType()->getBindingType(); $types[$columnName] = $tableDetails->getColumn($columnName)->getType()->getBindingType();
} }
...@@ -8012,7 +8012,7 @@ class DataHandler implements LoggerAwareInterface ...@@ -8012,7 +8012,7 @@ class DataHandler implements LoggerAwareInterface
->fetchAssociative(); ->fetchAssociative();
// If the current record exists (which it should...), begin comparison: // If the current record exists (which it should...), begin comparison:
if (is_array($currentRecord)) { if (is_array($currentRecord)) {
$tableDetails = $connection->getSchemaManager()->listTableDetails($table); $tableDetails = $connection->createSchemaManager()->listTableDetails($table);
$columnRecordTypes = []; $columnRecordTypes = [];
foreach ($currentRecord as $columnName => $_) { foreach ($currentRecord as $columnName => $_) {
$columnRecordTypes[$columnName] = ''; $columnRecordTypes[$columnName] = '';
......
...@@ -24,6 +24,7 @@ use Doctrine\DBAL\Driver\ServerInfoAwareConnection; ...@@ -24,6 +24,7 @@ use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\Platforms\PostgreSQL94Platform as PostgreSqlPlatform; use Doctrine\DBAL\Platforms\PostgreSQL94Platform as PostgreSqlPlatform;
use Doctrine\DBAL\Platforms\SQLServer2012Platform; use Doctrine\DBAL\Platforms\SQLServer2012Platform;
use Doctrine\DBAL\Result; use Doctrine\DBAL\Result;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\VersionAwarePlatformDriver; use Doctrine\DBAL\VersionAwarePlatformDriver;
use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait; use Psr\Log\LoggerAwareTrait;
...@@ -413,6 +414,17 @@ class Connection extends \Doctrine\DBAL\Connection implements LoggerAwareInterfa ...@@ -413,6 +414,17 @@ class Connection extends \Doctrine\DBAL\Connection implements LoggerAwareInterfa
return $version; return $version;
} }
/**
* Creates a SchemaManager that can be used to inspect or change the
* database schema through the connection.
*
* This is a copy from Doctrine DBAL 3.x, and can be removed once Doctrine DBAL 3.2 is included
*/
public function createSchemaManager(): AbstractSchemaManager
{
return $this->_driver->getSchemaManager($this);
}
/** /**
* Execute commands after initializing a new connection. * Execute commands after initializing a new connection.
* *
......
...@@ -215,7 +215,7 @@ class ConnectionMigrator ...@@ -215,7 +215,7 @@ class ConnectionMigrator
protected function buildSchemaDiff(bool $renameUnused = true): SchemaDiff protected function buildSchemaDiff(bool $renameUnused = true): SchemaDiff
{ {
// Build the schema definitions // Build the schema definitions
$fromSchema = $this->connection->getSchemaManager()->createSchema(); $fromSchema = $this->connection->createSchemaManager()->createSchema();
$toSchema = $this->buildExpectedSchemaDefinitions($this->connectionName); $toSchema = $this->buildExpectedSchemaDefinitions($this->connectionName);
// Add current table options to the fromSchema // Add current table options to the fromSchema
......
...@@ -183,7 +183,7 @@ class MetaDataRepository implements SingletonInterface ...@@ -183,7 +183,7 @@ class MetaDataRepository implements SingletonInterface
$types = []; $types = [];
if ($connection->getDatabasePlatform() instanceof SQLServerPlatform) { if ($connection->getDatabasePlatform() instanceof SQLServerPlatform) {
// mssql needs to set proper PARAM_LOB and others to update fields // mssql needs to set proper PARAM_LOB and others to update fields
$tableDetails = $connection->getSchemaManager()->listTableDetails($this->tableName); $tableDetails = $connection->createSchemaManager()->listTableDetails($this->tableName);
foreach ($updateRow as $columnName => $columnValue) { foreach ($updateRow as $columnName => $columnValue) {
$types[$columnName] = $tableDetails->getColumn($columnName)->getType()->getBindingType(); $types[$columnName] = $tableDetails->getColumn($columnName)->getType()->getBindingType();
} }
...@@ -230,7 +230,7 @@ class MetaDataRepository implements SingletonInterface ...@@ -230,7 +230,7 @@ class MetaDataRepository implements SingletonInterface
if (empty($this->tableFields)) { if (empty($this->tableFields)) {
$this->tableFields = GeneralUtility::makeInstance(ConnectionPool::class) $this->tableFields = GeneralUtility::makeInstance(ConnectionPool::class)
->getConnectionForTable($this->tableName) ->getConnectionForTable($this->tableName)
->getSchemaManager() ->createSchemaManager()
->listTableColumns($this->tableName); ->listTableColumns($this->tableName);
} }
......
...@@ -359,7 +359,7 @@ class ProcessedFileRepository extends AbstractRepository implements LoggerAwareI ...@@ -359,7 +359,7 @@ class ProcessedFileRepository extends AbstractRepository implements LoggerAwareI
if (empty($this->tableColumns[$this->table])) { if (empty($this->tableColumns[$this->table])) {
$this->tableColumns[$this->table] = GeneralUtility::makeInstance(ConnectionPool::class) $this->tableColumns[$this->table] = GeneralUtility::makeInstance(ConnectionPool::class)
->getConnectionForTable($this->table) ->getConnectionForTable($this->table)
->getSchemaManager() ->createSchemaManager()
->listTableColumns($this->table); ->listTableColumns($this->table);
} }
......
...@@ -66,7 +66,7 @@ class SchemaMigratorTest extends FunctionalTestCase ...@@ -66,7 +66,7 @@ class SchemaMigratorTest extends FunctionalTestCase
$this->subject = GeneralUtility::makeInstance(SchemaMigrator::class); $this->subject = GeneralUtility::makeInstance(SchemaMigrator::class);
$this->sqlReader = GeneralUtility::makeInstance(SqlReader::class); $this->sqlReader = GeneralUtility::makeInstance(SqlReader::class);
$this->connectionPool = GeneralUtility::makeInstance(ConnectionPool::class); $this->connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
$this->schemaManager = $this->connectionPool->getConnectionForTable($this->tableName)->getSchemaManager(); $this->schemaManager = $this->connectionPool->getConnectionForTable($this->tableName)->createSchemaManager();
$this->prepareTestTable(); $this->prepareTestTable();
} }
......
...@@ -81,7 +81,7 @@ class Typo3DbBackend implements BackendInterface, SingletonInterface ...@@ -81,7 +81,7 @@ class Typo3DbBackend implements BackendInterface, SingletonInterface
$platform = $connection->getDatabasePlatform(); $platform = $connection->getDatabasePlatform();
if ($platform instanceof SQLServerPlatform) { if ($platform instanceof SQLServerPlatform) {
// mssql needs to set proper PARAM_LOB and others to update fields // mssql needs to set proper PARAM_LOB and others to update fields
$tableDetails = $connection->getSchemaManager()->listTableDetails($tableName); $tableDetails = $connection->createSchemaManager()->listTableDetails($tableName);
foreach ($fieldValues as $columnName => $columnValue) { foreach ($fieldValues as $columnName => $columnValue) {
$types[$columnName] = $tableDetails->getColumn($columnName)->getType()->getBindingType(); $types[$columnName] = $tableDetails->getColumn($columnName)->getType()->getBindingType();
} }
...@@ -126,7 +126,7 @@ class Typo3DbBackend implements BackendInterface, SingletonInterface ...@@ -126,7 +126,7 @@ class Typo3DbBackend implements BackendInterface, SingletonInterface
$platform = $connection->getDatabasePlatform(); $platform = $connection->getDatabasePlatform();
if ($platform instanceof SQLServerPlatform) { if ($platform instanceof SQLServerPlatform) {
// mssql needs to set proper PARAM_LOB and others to update fields // mssql needs to set proper PARAM_LOB and others to update fields
$tableDetails = $connection->getSchemaManager()->listTableDetails($tableName); $tableDetails = $connection->createSchemaManager()->listTableDetails($tableName);
foreach ($fieldValues as $columnName => $columnValue) { foreach ($fieldValues as $columnName => $columnValue) {
$columnName = (string)$columnName; $columnName = (string)$columnName;
$types[$columnName] = $tableDetails->getColumn($columnName)->getType()->getBindingType(); $types[$columnName] = $tableDetails->getColumn($columnName)->getType()->getBindingType();
......
...@@ -140,7 +140,7 @@ class CacheService implements SingletonInterface ...@@ -140,7 +140,7 @@ class CacheService implements SingletonInterface
if (!isset($this->hasPidColumn[$tableName])) { if (!isset($this->hasPidColumn[$tableName])) {
$columns = $this->connectionPool $columns = $this->connectionPool
->getConnectionForTable($tableName) ->getConnectionForTable($tableName)
->getSchemaManager() ->createSchemaManager()
->listTableColumns($tableName); ->listTableColumns($tableName);
$this->hasPidColumn[$tableName] = array_key_exists('pid', $columns); $this->hasPidColumn[$tableName] = array_key_exists('pid', $columns);
} }
......
...@@ -1070,7 +1070,7 @@ class EnvironmentController extends AbstractController ...@@ -1070,7 +1070,7 @@ class EnvironmentController extends AbstractController
'host' => $connectionParameters['host'] ?? '', 'host' => $connectionParameters['host'] ?? '',
'port' => $connectionParameters['port'] ?? '', 'port' => $connectionParameters['port'] ?? '',
'socket' => $connectionParameters['unix_socket'] ?? '', 'socket' => $connectionParameters['unix_socket'] ?? '',
'numberOfTables' => count($connection->getSchemaManager()->listTableNames()), 'numberOfTables' => count($connection->createSchemaManager()->listTableNames()),
'numberOfMappedTables' => 0, 'numberOfMappedTables' => 0,
]; ];
if (isset($GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping']) if (isset($GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'])
......
...@@ -742,7 +742,7 @@ class InstallerController ...@@ -742,7 +742,7 @@ class InstallerController
$connection = GeneralUtility::makeInstance(ConnectionPool::class) $connection = GeneralUtility::makeInstance(ConnectionPool::class)
->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME); ->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME);
$connection $connection
->getSchemaManager() ->createSchemaManager()
->dropDatabase($connection->quoteIdentifier($databaseName)); ->dropDatabase($connection->quoteIdentifier($databaseName));
} }
...@@ -876,7 +876,7 @@ class InstallerController ...@@ -876,7 +876,7 @@ class InstallerController
{ {
$existingTables = GeneralUtility::makeInstance(ConnectionPool::class) $existingTables = GeneralUtility::makeInstance(ConnectionPool::class)
->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME) ->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME)
->getSchemaManager() ->createSchemaManager()
->listTableNames(); ->listTableNames();
return new JsonResponse([ return new JsonResponse([
'success' => !empty($existingTables), 'success' => !empty($existingTables),
...@@ -1274,6 +1274,7 @@ For each website you need a TypoScript template on the main page of your website ...@@ -1274,6 +1274,7 @@ For each website you need a TypoScript template on the main page of your website
// an invalid database name would lead to exceptions which would prevent // an invalid database name would lead to exceptions which would prevent
// changing the currently configured database. // changing the currently configured database.
$connection = DriverManager::getConnection($connectionParams); $connection = DriverManager::getConnection($connectionParams);
// @todo: migrate to createSchemaManager() with Doctrine DBAL 3.2 requirement in TYPO3 v12.0
$databaseArray = $connection->getSchemaManager()->listDatabases(); $databaseArray = $connection->getSchemaManager()->listDatabases();
$connection->close(); $connection->close();
...@@ -1292,6 +1293,7 @@ For each website you need a TypoScript template on the main page of your website ...@@ -1292,6 +1293,7 @@ For each website you need a TypoScript template on the main page of your website
$connectionParams['dbname'] = $databaseName; $connectionParams['dbname'] = $databaseName;
$connection = DriverManager::getConnection($connectionParams); $connection = DriverManager::getConnection($connectionParams);
// @todo: migrate to createSchemaManager() with Doctrine DBAL 3.2 requirement in TYPO3 v12.0
$databases[] = [ $databases[] = [
'name' => $databaseName, 'name' => $databaseName,
'tables' => count($connection->getSchemaManager()->listTableNames()), 'tables' => count($connection->getSchemaManager()->listTableNames()),
...@@ -1369,7 +1371,7 @@ For each website you need a TypoScript template on the main page of your website ...@@ -1369,7 +1371,7 @@ For each website you need a TypoScript template on the main page of your website
$connection = GeneralUtility::makeInstance(ConnectionPool::class) $connection = GeneralUtility::makeInstance(ConnectionPool::class)
->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME); ->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME);
if (!empty($connection->getSchemaManager()->listTableNames())) { if (!empty($connection->createSchemaManager()->listTableNames())) {
$result = new FlashMessage( $result = new FlashMessage(
sprintf('Cannot use database "%s"', $dbName) sprintf('Cannot use database "%s"', $dbName)
. ', because it already contains tables. Please select a different database or choose to create one!', . ', because it already contains tables. Please select a different database or choose to create one!',
......
...@@ -213,6 +213,6 @@ class PermissionsCheck ...@@ -213,6 +213,6 @@ class PermissionsCheck
private function getSchemaManager(): AbstractSchemaManager private function getSchemaManager(): AbstractSchemaManager
{ {
return $this->getConnection()->getSchemaManager(); return $this->getConnection()->createSchemaManager();
} }
} }
...@@ -71,7 +71,7 @@ class ClearTableService ...@@ -71,7 +71,7 @@ class ClearTableService
$tableStatistics = []; $tableStatistics = [];
foreach ($this->tableList as $table) { foreach ($this->tableList as $table) {
$connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table['name']); $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table['name']);
if ($connection->getSchemaManager()->tablesExist([$table['name']])) { if ($connection->createSchemaManager()->tablesExist([$table['name']])) {
$table['rowCount'] = $connection->count( $table['rowCount'] = $connection->count(
'*', '*',
$table['name'], $table['name'],
......
...@@ -110,7 +110,7 @@ class CollectionsExtractionUpdate extends AbstractDownloadExtensionUpdate ...@@ -110,7 +110,7 @@ class CollectionsExtractionUpdate extends AbstractDownloadExtensionUpdate
// Check if database table exist // Check if database table exist
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class); $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
$connection = $connectionPool->getConnectionByName('Default'); $connection = $connectionPool->getConnectionByName('Default');
$tableNames = $connection->getSchemaManager()->listTableNames(); $tableNames = $connection->createSchemaManager()->listTableNames();
if (in_array('sys_collection', $tableNames, true)) { if (in_array('sys_collection', $tableNames, true)) {
// table is available, now check if there are entries in it // table is available, now check if there are entries in it
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
......
...@@ -102,7 +102,7 @@ class ShortcutRecordsMigration implements UpgradeWizardInterface ...@@ -102,7 +102,7 @@ class ShortcutRecordsMigration implements UpgradeWizardInterface
protected function columnsExistInTable(): bool protected function columnsExistInTable(): bool
{ {
$schemaManager = $this->getConnectionPool()->getConnectionForTable(self::TABLE_NAME)->getSchemaManager(); $schemaManager = $this->getConnectionPool()->getConnectionForTable(self::TABLE_NAME)->createSchemaManager();
if ($schemaManager === null) { if ($schemaManager === null) {
return false; return false;
......
...@@ -72,7 +72,7 @@ END; ...@@ -72,7 +72,7 @@ END;
} }
// Ensure the level field is a varchar, otherwise we are in trouble when logging into TYPO3 Backend. // Ensure the level field is a varchar, otherwise we are in trouble when logging into TYPO3 Backend.
$schema = $this->sysLogTable->getSchemaManager(); $schema = $this->sysLogTable->createSchemaManager();
$table = $schema->listTableDetails('sys_log'); $table = $schema->listTableDetails('sys_log');
if (!$table->getColumn('level')->getType() instanceof StringType) { if (!$table->getColumn('level')->getType() instanceof StringType) {
$schema->alterTable(new TableDiff( $schema->alterTable(new TableDiff(
......
...@@ -50,7 +50,7 @@ class ShortcutRecordsMigrationTest extends FunctionalTestCase ...@@ -50,7 +50,7 @@ class ShortcutRecordsMigrationTest extends FunctionalTestCase
$schemaManager = GeneralUtility::makeInstance(ConnectionPool::class) $schemaManager = GeneralUtility::makeInstance(ConnectionPool::class)
->getConnectionForTable(self::TABLE_NAME) ->getConnectionForTable(self::TABLE_NAME)
->getSchemaManager(); ->createSchemaManager();
$schemaManager->alterTable( $schemaManager->alterTable(
new TableDiff( new TableDiff(
......
...@@ -409,7 +409,7 @@ class QueryGenerator ...@@ -409,7 +409,7 @@ class QueryGenerator
continue; continue;
} }
$connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table); $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
$tableColumns = $connection->getSchemaManager()->listTableColumns($table); $tableColumns = $connection->createSchemaManager()->listTableColumns($table);
$fieldsInDatabase = []; $fieldsInDatabase = [];
foreach ($tableColumns as $column) { foreach ($tableColumns as $column) {
$fieldsInDatabase[] = $column->getName(); $fieldsInDatabase[] = $column->getName();
......
...@@ -389,7 +389,7 @@ class DatabaseIntegrityCheck ...@@ -389,7 +389,7 @@ class DatabaseIntegrityCheck
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class); $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
foreach ($fkey_arrays as $table => $fields) { foreach ($fkey_arrays as $table => $fields) {
$connection = $connectionPool->getConnectionForTable($table); $connection = $connectionPool->getConnectionForTable($table);
$schemaManager = $connection->getSchemaManager(); $schemaManager = $connection->createSchemaManager();
$tableColumns = $schemaManager->listTableColumns($table); $tableColumns = $schemaManager->listTableColumns($table);
$queryBuilder = $connectionPool->getQueryBuilderForTable($table); $queryBuilder = $connectionPool->getQueryBuilderForTable($table);
......
...@@ -675,7 +675,7 @@ class DataHandlerHook ...@@ -675,7 +675,7 @@ class DataHandlerHook
$tableDetails = null; $tableDetails = null;
if ($platform instanceof SQLServerPlatform) { if ($platform instanceof SQLServerPlatform) {
// mssql needs to set proper PARAM_LOB and others to update fields // mssql needs to set proper PARAM_LOB and others to update fields
$tableDetails = $connection->getSchemaManager()->listTableDetails($table); $tableDetails = $connection->createSchemaManager()->listTableDetails($table);
} }
try { try {
......
Supports Markdown
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