From decea21ae67e05c2e358b74261a6ca037cc4867a Mon Sep 17 00:00:00 2001
From: Markus Klein <markus.klein@typo3.org>
Date: Fri, 13 Mar 2020 20:12:53 +0100
Subject: [PATCH] [BUGFIX] Make SQL schema migrations working on SQLite

This patch fixes three things:

1) SQLite can handle a primary key, the special handling
   can be removed. The field names must be quoted though.
   A lot of duplicate tests can be removed here.

2) The handcrafted arrays passed on to the TableDiff class
   need to be indexed by the column or index name, otherwise
   the SQLite driver fails to identify them correctly.

3) Allow only one column operation per table.
   Having multiple column adjustments (rename, removal)
   within one run generates wrong migration SQL.
   This is due to the possibility of the Install Tool
   to be able to select on a "per column" level.
   (Keep in mind that in SQLite one operation needs at
   least 5 SQL statements, contrary to other DMBS)

Resolves: #90758
Resolves: #90754
Resolves: #90751
Releases: master, 9.5
Change-Id: I972346fae3cc97b877e20033b466345fa1c0a83d
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/63702
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Daniel Siepmann <coding@daniel-siepmann.de>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Reviewed-by: Benni Mack <benni@typo3.org>
---
 .../Database/Schema/ConnectionMigrator.php    |  57 +-
 .../Database/Schema/DefaultTcaSchema.php      |  24 +-
 .../Schema/DefaultTcaSchemaSqliteTest.php     | 820 ------------------
 .../Database/Schema/DefaultTcaSchemaTest.php  |   9 +-
 4 files changed, 48 insertions(+), 862 deletions(-)
 delete mode 100644 typo3/sysext/core/Tests/Unit/Database/Schema/DefaultTcaSchemaSqliteTest.php

diff --git a/typo3/sysext/core/Classes/Database/Schema/ConnectionMigrator.php b/typo3/sysext/core/Classes/Database/Schema/ConnectionMigrator.php
index 78916c2383bf..58f996c1f1c1 100644
--- a/typo3/sysext/core/Classes/Database/Schema/ConnectionMigrator.php
+++ b/typo3/sysext/core/Classes/Database/Schema/ConnectionMigrator.php
@@ -361,11 +361,11 @@ class ConnectionMigrator
             if (count($changedTable->addedColumns) !== 0) {
                 // Treat each added column with a new diff to get a dedicated suggestions
                 // just for this single column.
-                foreach ($changedTable->addedColumns as $addedColumn) {
+                foreach ($changedTable->addedColumns as $columnName => $addedColumn) {
                     $changedTables[$index . ':tbl_' . $addedColumn->getName()] = GeneralUtility::makeInstance(
                         TableDiff::class,
                         $changedTable->name,
-                        [$addedColumn],
+                        [$columnName => $addedColumn],
                         [],
                         [],
                         [],
@@ -379,14 +379,14 @@ class ConnectionMigrator
             if (count($changedTable->addedIndexes) !== 0) {
                 // Treat each added index with a new diff to get a dedicated suggestions
                 // just for this index.
-                foreach ($changedTable->addedIndexes as $addedIndex) {
+                foreach ($changedTable->addedIndexes as $indexName => $addedIndex) {
                     $changedTables[$index . ':idx_' . $addedIndex->getName()] = GeneralUtility::makeInstance(
                         TableDiff::class,
                         $changedTable->name,
                         [],
                         [],
                         [],
-                        [$this->buildQuotedIndex($addedIndex)],
+                        [$indexName => $this->buildQuotedIndex($addedIndex)],
                         [],
                         [],
                         $fromTable
@@ -497,7 +497,7 @@ class ConnectionMigrator
             // Treat each changed index with a new diff to get a dedicated suggestions
             // just for this index.
             if (count($changedTable->changedIndexes) !== 0) {
-                foreach ($changedTable->changedIndexes as $key => $changedIndex) {
+                foreach ($changedTable->changedIndexes as $indexName => $changedIndex) {
                     $indexDiff = GeneralUtility::makeInstance(
                         TableDiff::class,
                         $changedTable->name,
@@ -505,7 +505,7 @@ class ConnectionMigrator
                         [],
                         [],
                         [],
-                        [$changedIndex],
+                        [$indexName => $changedIndex],
                         [],
                         $schemaDiff->fromSchema->getTable($changedTable->name)
                     );
@@ -567,7 +567,7 @@ class ConnectionMigrator
                 // just for this single column.
                 $fromTable = $this->buildQuotedTable($schemaDiff->fromSchema->getTable($changedTable->name));
 
-                foreach ($changedTable->changedColumns as $changedColumn) {
+                foreach ($changedTable->changedColumns as $columnName => $changedColumn) {
                     // Field has been renamed and will be handled separately
                     if ($changedColumn->getOldColumnName()->getName() !== $changedColumn->column->getName()) {
                         continue;
@@ -587,7 +587,7 @@ class ConnectionMigrator
                         TableDiff::class,
                         $changedTable->name,
                         [],
-                        [$changedColumn],
+                        [$columnName => $changedColumn],
                         [],
                         [],
                         [],
@@ -711,9 +711,11 @@ class ConnectionMigrator
                 continue;
             }
 
+            $isSqlite = $this->tableRunsOnSqlite($index);
+
             // Treat each changed column with a new diff to get a dedicated suggestions
             // just for this single column.
-            foreach ($changedTable->changedColumns as $changedColumn) {
+            foreach ($changedTable->changedColumns as $oldFieldName => $changedColumn) {
                 // Field has not been renamed
                 if ($changedColumn->getOldColumnName()->getName() === $changedColumn->column->getName()) {
                     continue;
@@ -723,13 +725,16 @@ class ConnectionMigrator
                     TableDiff::class,
                     $changedTable->name,
                     [],
-                    [$changedColumn],
+                    [$oldFieldName => $changedColumn],
                     [],
                     [],
                     [],
                     [],
                     $this->buildQuotedTable($schemaDiff->fromSchema->getTable($changedTable->name))
                 );
+                if ($isSqlite) {
+                    break;
+                }
             }
         }
 
@@ -765,28 +770,35 @@ class ConnectionMigrator
         foreach ($schemaDiff->changedTables as $index => $changedTable) {
             $fromTable = $this->buildQuotedTable($schemaDiff->fromSchema->getTable($changedTable->name));
 
+            $isSqlite = $this->tableRunsOnSqlite($index);
+            $addMoreOperations = true;
+
             if (count($changedTable->removedColumns) !== 0) {
                 // Treat each changed column with a new diff to get a dedicated suggestions
                 // just for this single column.
-                foreach ($changedTable->removedColumns as $removedColumn) {
+                foreach ($changedTable->removedColumns as $columnName => $removedColumn) {
                     $changedTables[$index . ':tbl_' . $removedColumn->getName()] = GeneralUtility::makeInstance(
                         TableDiff::class,
                         $changedTable->name,
                         [],
                         [],
-                        [$this->buildQuotedColumn($removedColumn)],
+                        [$columnName => $this->buildQuotedColumn($removedColumn)],
                         [],
                         [],
                         [],
                         $fromTable
                     );
+                    if ($isSqlite) {
+                        $addMoreOperations = false;
+                        break;
+                    }
                 }
             }
 
-            if (count($changedTable->removedIndexes) !== 0) {
+            if ($addMoreOperations && count($changedTable->removedIndexes) !== 0) {
                 // Treat each removed index with a new diff to get a dedicated suggestions
                 // just for this index.
-                foreach ($changedTable->removedIndexes as $removedIndex) {
+                foreach ($changedTable->removedIndexes as $indexName => $removedIndex) {
                     $changedTables[$index . ':idx_' . $removedIndex->getName()] = GeneralUtility::makeInstance(
                         TableDiff::class,
                         $changedTable->name,
@@ -795,13 +807,17 @@ class ConnectionMigrator
                         [],
                         [],
                         [],
-                        [$this->buildQuotedIndex($removedIndex)],
+                        [$indexName => $this->buildQuotedIndex($removedIndex)],
                         $fromTable
                     );
+                    if ($isSqlite) {
+                        $addMoreOperations = false;
+                        break;
+                    }
                 }
             }
 
-            if (count($changedTable->removedForeignKeys) !== 0) {
+            if ($addMoreOperations && count($changedTable->removedForeignKeys) !== 0) {
                 // Treat each removed foreign key with a new diff to get a dedicated suggestions
                 // just for this foreign key.
                 foreach ($changedTable->removedForeignKeys as $removedForeignKey) {
@@ -818,6 +834,9 @@ class ConnectionMigrator
                         $fromTable
                     );
                     $changedTables[$fkIndex]->removedForeignKeys = [$this->buildQuotedForeignKey($removedForeignKey)];
+                    if ($isSqlite) {
+                        break;
+                    }
                 }
             }
         }
@@ -1302,4 +1321,10 @@ class ConnectionMigrator
             $index->getOptions()
         );
     }
+
+    protected function tableRunsOnSqlite(string $tableName): bool
+    {
+        $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($tableName);
+        return $connection->getDatabasePlatform() instanceof SqlitePlatform;
+    }
 }
diff --git a/typo3/sysext/core/Classes/Database/Schema/DefaultTcaSchema.php b/typo3/sysext/core/Classes/Database/Schema/DefaultTcaSchema.php
index a4b3cabb7fae..5bbe6d349d71 100644
--- a/typo3/sysext/core/Classes/Database/Schema/DefaultTcaSchema.php
+++ b/typo3/sysext/core/Classes/Database/Schema/DefaultTcaSchema.php
@@ -16,10 +16,7 @@ namespace TYPO3\CMS\Core\Database\Schema;
  * The TYPO3 project - inspiring people to share!
  */
 
-use Doctrine\DBAL\Platforms\SqlitePlatform;
 use Doctrine\DBAL\Schema\Table;
-use TYPO3\CMS\Core\Database\ConnectionPool;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * This class is called by the SchemaMigrator after all extension's ext_tables.sql
@@ -63,7 +60,7 @@ class DefaultTcaSchema
             // uid column and primary key if uid is not defined
             if (!$this->isColumnDefinedForTable($tables, $tableName, 'uid')) {
                 $tables[$tablePosition]->addColumn(
-                    'uid',
+                    $this->quote('uid'),
                     'integer',
                     [
                         'notnull' => true,
@@ -71,10 +68,7 @@ class DefaultTcaSchema
                         'autoincrement' => true,
                     ]
                 );
-                // SQLite does not need primary key, only needs autoincrement on integer fields
-                if (!$this->tableRunsOnSqlite($tableName)) {
-                    $tables[$tablePosition]->setPrimaryKey(['uid']);
-                }
+                $tables[$tablePosition]->setPrimaryKey(['uid']);
             }
 
             // pid column and prepare parent key if pid is not defined
@@ -89,7 +83,7 @@ class DefaultTcaSchema
                     // We need negative pid's (-1) if table is workspace aware
                     $options['unsigned'] = true;
                 }
-                $tables[$tablePosition]->addColumn('pid', 'integer', $options);
+                $tables[$tablePosition]->addColumn($this->quote('pid'), 'integer', $options);
                 $pidColumnAdded = true;
             }
 
@@ -666,16 +660,4 @@ class DefaultTcaSchema
     {
         return '`' . $identifier . '`';
     }
-
-    /**
-     * SQLite does not need primary key, only needs autoincrement on integer fields
-     * See https://github.com/doctrine/dbal/pull/3141
-     * @param string $tableName
-     * @return bool
-     */
-    protected function tableRunsOnSqlite(string $tableName): bool
-    {
-        $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($tableName);
-        return $connection->getDatabasePlatform() instanceof SqlitePlatform;
-    }
 }
diff --git a/typo3/sysext/core/Tests/Unit/Database/Schema/DefaultTcaSchemaSqliteTest.php b/typo3/sysext/core/Tests/Unit/Database/Schema/DefaultTcaSchemaSqliteTest.php
deleted file mode 100644
index 1eed3258bfcb..000000000000
--- a/typo3/sysext/core/Tests/Unit/Database/Schema/DefaultTcaSchemaSqliteTest.php
+++ /dev/null
@@ -1,820 +0,0 @@
-<?php
-declare(strict_types = 1);
-
-namespace TYPO3\CMS\Core\Tests\Unit\Database\Schema;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use Doctrine\DBAL\Schema\Column;
-use Doctrine\DBAL\Schema\Index;
-use Doctrine\DBAL\Schema\SchemaException;
-use Doctrine\DBAL\Schema\Table;
-use Doctrine\DBAL\Types\Type;
-use TYPO3\CMS\Core\Database\Schema\DefaultTcaSchema;
-use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
-
-/**
- * Test case
- */
-class DefaultTcaSchemaSqliteTest extends UnitTestCase
-{
-    /**
-     * @var DefaultTcaSchema
-     */
-    protected $subject;
-
-    /**
-     * @var Table
-     */
-    protected $defaultTable;
-
-    public function setUp(): void
-    {
-        parent::setUp();
-        $this->subject = $this->getAccessibleMock(DefaultTcaSchema::class, ['tableRunsOnSqlite']);
-        $this->subject->method('tableRunsOnSqlite')->willReturn(true);
-        $this->defaultTable = new Table('aTable');
-    }
-
-    /**
-     * @test
-     */
-    public function enrichKeepsGivenTablesArrayWithEmptyTca()
-    {
-        $GLOBALS['TCA'] = [];
-        self::assertEquals([], $this->subject->enrich([]));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichDoesNotAddColumnIfExists()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [];
-
-        $table = new Table('aTable');
-        $table->addColumn('uid', 'integer');
-        $table->addColumn('pid', 'integer');
-        $input = [];
-        $input[] = $table;
-
-        $table = new Table('aTable');
-        $table->addColumn('uid', 'integer');
-        $table->addColumn('pid', 'integer');
-        $expected = [];
-        $expected[] = $table;
-
-        self::assertEquals($expected, $this->subject->enrich($input));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichDoesNotAddColumnIfTableExistsMultipleTimesAndUidExists()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [];
-
-        $table = new Table('aTable');
-        $table->addColumn('foo', 'integer');
-        $input = [];
-        $input[] = $table;
-        $table = new Table('aTable');
-        $table->addColumn('uid', 'integer');
-        $table->addColumn('pid', 'integer');
-        $input[] = $table;
-
-        $table = new Table('aTable');
-        $table->addColumn('foo', 'integer');
-        $expected = [];
-        $expected[] = $table;
-        $table = new Table('aTable');
-        $table->addColumn('uid', 'integer');
-        $table->addColumn('pid', 'integer');
-        $expected[] = $table;
-
-        self::assertEquals($expected, $this->subject->enrich($input));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsFieldToFirstTableDefinitionOfThatName()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [];
-
-        $table = new Table('aTable');
-        $table->addColumn('foo', 'integer');
-        $input = [];
-        $input[] = $table;
-        $table = new Table('aTable');
-        $table->addColumn('bar', 'integer');
-        $input[] = $table;
-
-        $result = $this->subject->enrich($input);
-
-        self::assertInstanceOf(Column::class, $result[0]->getColumn('uid'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsUidAndNoPrimaryKey()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedUidColumn = new Column(
-            'uid',
-            Type::getType('integer'),
-            [
-                'notnull' => true,
-                'unsigned' => true,
-                'autoincrement' => true,
-            ]
-        );
-        self::assertEquals($expectedUidColumn, $result[0]->getColumn('uid'));
-        self::assertNull($result[0]->getPrimaryKey());
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsPid()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedPidColumn = new Column(
-            'pid',
-            Type::getType('integer'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => true,
-            ]
-        );
-        self::assertEquals($expectedPidColumn, $result[0]->getColumn('pid'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsSignedPidWithEnabledWorkspace()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'versioningWS' => true,
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedPidColumn = new Column(
-            'pid',
-            Type::getType('integer'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => false,
-            ]
-        );
-        self::assertEquals($expectedPidColumn, $result[0]->getColumn('pid'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsTstamp()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'tstamp' => 'updatedon',
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`updatedon`',
-            Type::getType('integer'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => true,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('updatedon'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsCrdate()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'crdate' => 'createdon',
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`createdon`',
-            Type::getType('integer'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => true,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('createdon'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsCruserid()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'cruser_id' => 'createdby',
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`createdby`',
-            Type::getType('integer'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => true,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('createdby'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsDeleted()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'delete' => 'deleted',
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`deleted`',
-            Type::getType('smallint'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => true,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('deleted'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsDisabled()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'enablecolumns' => [
-                'disabled' => 'disabled',
-            ]
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`disabled`',
-            Type::getType('smallint'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => true,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('disabled'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsStarttime()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'enablecolumns' => [
-                'starttime' => 'starttime',
-            ]
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`starttime`',
-            Type::getType('integer'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => true,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('starttime'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsEndtime()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'enablecolumns' => [
-                'endtime' => 'endtime',
-            ]
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`endtime`',
-            Type::getType('integer'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => true,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('endtime'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsFegroup()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'enablecolumns' => [
-                'fe_group' => 'fe_group',
-            ]
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`fe_group`',
-            Type::getType('string'),
-            [
-                'default' => '0',
-                'notnull' => true,
-                'length' => 255,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('fe_group'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsSorting()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'sortby' => 'sorting',
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`sorting`',
-            Type::getType('integer'),
-            [
-                'default' => '0',
-                'notnull' => true,
-                'unsigned' => false,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('sorting'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsParentKey()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedIndex = new Index('parent', ['pid']);
-        self::assertEquals($expectedIndex, $result[0]->getIndex('parent'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsParentKeyWithDelete()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'delete' => 'deleted',
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedIndex = new Index('parent', ['pid', 'deleted']);
-        self::assertEquals($expectedIndex, $result[0]->getIndex('parent'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsParentKeyWithDisabled()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'enablecolumns' => [
-                'disabled' => 'disabled',
-            ],
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedIndex = new Index('parent', ['pid', 'disabled']);
-        self::assertEquals($expectedIndex, $result[0]->getIndex('parent'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsParentKeyInCorrectOrder()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'delete' => 'deleted',
-            'enablecolumns' => [
-                'disabled' => 'disabled',
-            ],
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedIndex = new Index('parent', ['pid', 'deleted', 'disabled']);
-        self::assertEquals($expectedIndex, $result[0]->getIndex('parent'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsSysLanguageUid()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'languageField' => 'sys_language_uid',
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`sys_language_uid`',
-            Type::getType('integer'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => false,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('sys_language_uid'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsL10nParent()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'languageField' => 'sys_language_uid',
-            'transOrigPointerField' => 'l10n_parent',
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`l10n_parent`',
-            Type::getType('integer'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => true,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('l10n_parent'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichDoesNotAddL10nParentIfLanguageFieldIsNotDefined()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'transOrigPointerField' => 'l10n_parent',
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $this->expectException(SchemaException::class);
-        $result[0]->getColumn('l10n_parent');
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsDescription()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'descriptionColumn' => 'rowDescription',
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`rowDescription`',
-            Type::getType('text'),
-            [
-                'notnull' => false,
-                'length' => 65535,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('rowDescription'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsEditlock()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'editlock' => 'editlock'
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`editlock`',
-            Type::getType('smallint'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => true,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('editlock'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsL10nSource()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'languageField' => 'sys_language_uid',
-            'translationSource' => 'l10n_source',
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`l10n_source`',
-            Type::getType('integer'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => true,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('l10n_source'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichDoesNotAddL10nSourceIfLanguageFieldIsNotDefined()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'translationSource' => 'l10n_source',
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $this->expectException(SchemaException::class);
-        $result[0]->getColumn('l10n_source');
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsL10nState()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'languageField' => 'sys_language_uid',
-            'transOrigPointerField' => 'l10n_parent',
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`l10n_state`',
-            Type::getType('text'),
-            [
-                'notnull' => false,
-                'length' => 65535,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('l10n_state'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichDoesNotAddL10nStateIfLanguageFieldIsNotDefined()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'transOrigPointerField' => 'l10n_parent',
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $this->expectException(SchemaException::class);
-        $result[0]->getColumn('l10n_state');
-    }
-
-    /**
-     * @test
-     */
-    public function enrichDoesNotAddL10nStateIfTransOrigPointerFieldIsNotDefined()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'languageField' => 'sys_language_uid',
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $this->expectException(SchemaException::class);
-        $result[0]->getColumn('l10n_state');
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsT3origUid()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'origUid' => 't3_origuid',
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`t3_origuid`',
-            Type::getType('integer'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => true,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('t3_origuid'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsL10nDiffsource()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'transOrigDiffSourceField' => 'l18n_diffsource',
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`l18n_diffsource`',
-            Type::getType('blob'),
-            [
-                'length' => 16777215,
-                'notnull' => false,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('l18n_diffsource'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsT3verOid()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'versioningWS' => true,
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`t3ver_oid`',
-            Type::getType('integer'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => true,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('t3ver_oid'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsT3verWsid()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'versioningWS' => true,
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`t3ver_wsid`',
-            Type::getType('integer'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => true,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('t3ver_wsid'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsT3verState()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'versioningWS' => true,
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`t3ver_state`',
-            Type::getType('smallint'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => false,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('t3ver_state'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsT3verStage()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'versioningWS' => true,
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`t3ver_stage`',
-            Type::getType('integer'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => false,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('t3ver_stage'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsT3verCount()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'versioningWS' => true,
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`t3ver_count`',
-            Type::getType('integer'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => true,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('t3ver_count'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsT3verTstamp()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'versioningWS' => true,
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`t3ver_tstamp`',
-            Type::getType('integer'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => true,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('t3ver_tstamp'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsT3verMoveId()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'versioningWS' => true,
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedColumn = new Column(
-            '`t3ver_move_id`',
-            Type::getType('integer'),
-            [
-                'default' => 0,
-                'notnull' => true,
-                'unsigned' => true,
-            ]
-        );
-        self::assertEquals($expectedColumn, $result[0]->getColumn('t3ver_move_id'));
-    }
-
-    /**
-     * @test
-     */
-    public function enrichAddsT3verOidIndex()
-    {
-        $GLOBALS['TCA']['aTable']['ctrl'] = [
-            'versioningWS' => true,
-        ];
-        $result = $this->subject->enrich([$this->defaultTable]);
-        $expectedIndex = new Index('t3ver_oid', ['t3ver_oid', 't3ver_wsid']);
-        self::assertEquals($expectedIndex, $result[0]->getIndex('t3ver_oid'));
-    }
-}
diff --git a/typo3/sysext/core/Tests/Unit/Database/Schema/DefaultTcaSchemaTest.php b/typo3/sysext/core/Tests/Unit/Database/Schema/DefaultTcaSchemaTest.php
index 2256e296a248..23ca1bf36cfd 100644
--- a/typo3/sysext/core/Tests/Unit/Database/Schema/DefaultTcaSchemaTest.php
+++ b/typo3/sysext/core/Tests/Unit/Database/Schema/DefaultTcaSchemaTest.php
@@ -42,8 +42,7 @@ class DefaultTcaSchemaTest extends UnitTestCase
     public function setUp(): void
     {
         parent::setUp();
-        $this->subject = $this->getAccessibleMock(DefaultTcaSchema::class, ['tableRunsOnSqlite']);
-        $this->subject->method('tableRunsOnSqlite')->willReturn(false);
+        $this->subject = new DefaultTcaSchema();
         $this->defaultTable = new Table('aTable');
     }
 
@@ -134,7 +133,7 @@ class DefaultTcaSchemaTest extends UnitTestCase
         $GLOBALS['TCA']['aTable']['ctrl'] = [];
         $result = $this->subject->enrich([$this->defaultTable]);
         $expectedUidColumn = new Column(
-            'uid',
+            '`uid`',
             Type::getType('integer'),
             [
                 'notnull' => true,
@@ -155,7 +154,7 @@ class DefaultTcaSchemaTest extends UnitTestCase
         $GLOBALS['TCA']['aTable']['ctrl'] = [];
         $result = $this->subject->enrich([$this->defaultTable]);
         $expectedPidColumn = new Column(
-            'pid',
+            '`pid`',
             Type::getType('integer'),
             [
                 'default' => 0,
@@ -176,7 +175,7 @@ class DefaultTcaSchemaTest extends UnitTestCase
         ];
         $result = $this->subject->enrich([$this->defaultTable]);
         $expectedPidColumn = new Column(
-            'pid',
+            '`pid`',
             Type::getType('integer'),
             [
                 'default' => 0,
-- 
GitLab