diff options
Diffstat (limited to 'tests/lib/DB/MigratorTest.php')
-rw-r--r-- | tests/lib/DB/MigratorTest.php | 214 |
1 files changed, 116 insertions, 98 deletions
diff --git a/tests/lib/DB/MigratorTest.php b/tests/lib/DB/MigratorTest.php index 6f3ebbb2b0c..9d8ee6791a9 100644 --- a/tests/lib/DB/MigratorTest.php +++ b/tests/lib/DB/MigratorTest.php @@ -1,22 +1,25 @@ <?php /** - * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. + * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\DB; use Doctrine\DBAL\Exception; -use Doctrine\DBAL\Platforms\MySQLPlatform; -use Doctrine\DBAL\Platforms\OraclePlatform; -use Doctrine\DBAL\Platforms\SqlitePlatform; +use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\SchemaConfig; -use OC\DB\SchemaWrapper; +use OC\DB\Migrator; +use OC\DB\OracleMigrator; +use OC\DB\SQLiteMigrator; +use OCP\DB\Types; +use OCP\EventDispatcher\IEventDispatcher; use OCP\IConfig; +use OCP\IDBConnection; +use OCP\Server; /** * Class MigratorTest @@ -32,11 +35,6 @@ class MigratorTest extends \Test\TestCase { private $connection; /** - * @var \OC\DB\MDB2SchemaManager - */ - private $manager; - - /** * @var IConfig **/ private $config; @@ -50,18 +48,25 @@ class MigratorTest extends \Test\TestCase { protected function setUp(): void { parent::setUp(); - $this->config = \OC::$server->getConfig(); - $this->connection = \OC::$server->get(\OC\DB\Connection::class); - if ($this->connection->getDatabasePlatform() instanceof OraclePlatform) { - $this->markTestSkipped('DB migration tests are not supported on OCI'); - } - $this->manager = new \OC\DB\MDB2SchemaManager($this->connection); + $this->config = Server::get(IConfig::class); + $this->connection = Server::get(\OC\DB\Connection::class); + $this->tableName = $this->getUniqueTableName(); $this->tableNameTmp = $this->getUniqueTableName(); } + private function getMigrator(): Migrator { + $dispatcher = Server::get(IEventDispatcher::class); + if ($this->connection->getDatabaseProvider() === IDBConnection::PLATFORM_SQLITE) { + return new SQLiteMigrator($this->connection, $this->config, $dispatcher); + } elseif ($this->connection->getDatabaseProvider() === IDBConnection::PLATFORM_ORACLE) { + return new OracleMigrator($this->connection, $this->config, $dispatcher); + } + return new Migrator($this->connection, $this->config, $dispatcher); + } + private function getUniqueTableName() { - return strtolower($this->getUniqueID($this->config->getSystemValue('dbtableprefix', 'oc_') . 'test_')); + return strtolower($this->getUniqueID($this->config->getSystemValueString('dbtableprefix', 'oc_') . 'test_')); } protected function tearDown(): void { @@ -123,69 +128,9 @@ class MigratorTest extends \Test\TestCase { return $config; } - private function isSQLite() { - return $this->connection->getDatabasePlatform() instanceof SqlitePlatform; - } - - private function isMySQL() { - return $this->connection->getDatabasePlatform() instanceof MySQLPlatform; - } - - - public function testDuplicateKeyUpgrade() { - $this->expectException(Exception\UniqueConstraintViolationException::class); - - if ($this->isSQLite()) { - $this->markTestSkipped('sqlite does not throw errors when creating a new key on existing data'); - } - list($startSchema, $endSchema) = $this->getDuplicateKeySchemas(); - $migrator = $this->manager->getMigrator(); - $migrator->migrate($startSchema); - - $this->connection->insert($this->tableName, ['id' => 1, 'name' => 'foo']); - $this->connection->insert($this->tableName, ['id' => 2, 'name' => 'bar']); - $this->connection->insert($this->tableName, ['id' => 2, 'name' => 'qwerty']); - - try { - $migrator->migrate($endSchema); - } catch (Exception\UniqueConstraintViolationException $e) { - if (!$this->isMySQL()) { - $this->connection->rollBack(); - } - throw $e; - } - } - - public function testChangeToString() { - list($startSchema, $endSchema) = $this->getChangedTypeSchema('integer', 'string'); - $migrator = $this->manager->getMigrator(); - $migrator->migrate($startSchema); - $schema = new SchemaWrapper($this->connection); - $table = $schema->getTable(substr($this->tableName, 3)); - $this->assertEquals('integer', $table->getColumn('id')->getType()->getName()); - - $this->connection->insert($this->tableName, ['id' => 1, 'name' => 'foo']); - $this->connection->insert($this->tableName, ['id' => 2, 'name' => 'bar']); - $this->connection->insert($this->tableName, ['id' => 3, 'name' => 'qwerty']); - - $migrator->migrate($endSchema); - $this->addToAssertionCount(1); - - $qb = $this->connection->getQueryBuilder(); - $result = $qb->select('*')->from(substr($this->tableName, 3))->execute(); - $this->assertEquals([ - ['id' => 1, 'name' => 'foo'], - ['id' => 2, 'name' => 'bar'], - ['id' => 3, 'name' => 'qwerty'] - ], $result->fetchAll()); - $schema = new SchemaWrapper($this->connection); - $table = $schema->getTable(substr($this->tableName, 3)); - $this->assertEquals('string', $table->getColumn('id')->getType()->getName()); - } - - public function testUpgrade() { - list($startSchema, $endSchema) = $this->getDuplicateKeySchemas(); - $migrator = $this->manager->getMigrator(); + public function testUpgrade(): void { + [$startSchema, $endSchema] = $this->getDuplicateKeySchemas(); + $migrator = $this->getMigrator(); $migrator->migrate($startSchema); $this->connection->insert($this->tableName, ['id' => 1, 'name' => 'foo']); @@ -196,14 +141,14 @@ class MigratorTest extends \Test\TestCase { $this->addToAssertionCount(1); } - public function testUpgradeDifferentPrefix() { - $oldTablePrefix = $this->config->getSystemValue('dbtableprefix', 'oc_'); + public function testUpgradeDifferentPrefix(): void { + $oldTablePrefix = $this->config->getSystemValueString('dbtableprefix', 'oc_'); $this->config->setSystemValue('dbtableprefix', 'ownc_'); - $this->tableName = strtolower($this->getUniqueID($this->config->getSystemValue('dbtableprefix') . 'test_')); + $this->tableName = strtolower($this->getUniqueID($this->config->getSystemValueString('dbtableprefix') . 'test_')); - list($startSchema, $endSchema) = $this->getDuplicateKeySchemas(); - $migrator = $this->manager->getMigrator(); + [$startSchema, $endSchema] = $this->getDuplicateKeySchemas(); + $migrator = $this->getMigrator(); $migrator->migrate($startSchema); $this->connection->insert($this->tableName, ['id' => 1, 'name' => 'foo']); @@ -216,9 +161,9 @@ class MigratorTest extends \Test\TestCase { $this->config->setSystemValue('dbtableprefix', $oldTablePrefix); } - public function testInsertAfterUpgrade() { - list($startSchema, $endSchema) = $this->getDuplicateKeySchemas(); - $migrator = $this->manager->getMigrator(); + public function testInsertAfterUpgrade(): void { + [$startSchema, $endSchema] = $this->getDuplicateKeySchemas(); + $migrator = $this->getMigrator(); $migrator->migrate($startSchema); $migrator->migrate($endSchema); @@ -233,7 +178,7 @@ class MigratorTest extends \Test\TestCase { } } - public function testAddingPrimaryKeyWithAutoIncrement() { + public function testAddingPrimaryKeyWithAutoIncrement(): void { $startSchema = new Schema([], [], $this->getSchemaConfig()); $table = $startSchema->createTable($this->tableName); $table->addColumn('id', 'integer'); @@ -245,7 +190,7 @@ class MigratorTest extends \Test\TestCase { $table->addColumn('name', 'string'); $table->setPrimaryKey(['id']); - $migrator = $this->manager->getMigrator(); + $migrator = $this->getMigrator(); $migrator->migrate($startSchema); $migrator->migrate($endSchema); @@ -253,7 +198,7 @@ class MigratorTest extends \Test\TestCase { $this->addToAssertionCount(1); } - public function testReservedKeywords() { + public function testReservedKeywords(): void { $startSchema = new Schema([], [], $this->getSchemaConfig()); $table = $startSchema->createTable($this->tableName); $table->addColumn('id', 'integer', ['autoincrement' => true]); @@ -266,7 +211,7 @@ class MigratorTest extends \Test\TestCase { $table->addColumn('user', 'string', ['length' => 64]); $table->setPrimaryKey(['id']); - $migrator = $this->manager->getMigrator(); + $migrator = $this->getMigrator(); $migrator->migrate($startSchema); $migrator->migrate($endSchema); @@ -274,23 +219,96 @@ class MigratorTest extends \Test\TestCase { $this->addToAssertionCount(1); } - public function testAddingForeignKey() { + /** + * Test for nextcloud/server#36803 + */ + public function testColumnCommentsInUpdate(): void { + $startSchema = new Schema([], [], $this->getSchemaConfig()); + $table = $startSchema->createTable($this->tableName); + $table->addColumn('id', 'integer', ['autoincrement' => true, 'comment' => 'foo']); + $table->setPrimaryKey(['id']); + + $endSchema = new Schema([], [], $this->getSchemaConfig()); + $table = $endSchema->createTable($this->tableName); + $table->addColumn('id', 'integer', ['autoincrement' => true, 'comment' => 'foo']); + // Assert adding comments on existing tables work (or at least does not throw) + $table->addColumn('time', 'integer', ['comment' => 'unix-timestamp', 'notnull' => false]); + $table->setPrimaryKey(['id']); + + $migrator = $this->getMigrator(); + $migrator->migrate($startSchema); + + $migrator->migrate($endSchema); + + $this->addToAssertionCount(1); + } + + public function testAddingForeignKey(): void { $startSchema = new Schema([], [], $this->getSchemaConfig()); $table = $startSchema->createTable($this->tableName); $table->addColumn('id', 'integer', ['autoincrement' => true]); $table->addColumn('name', 'string'); $table->setPrimaryKey(['id']); - $fkName = "fkc"; + $fkName = 'fkc'; $tableFk = $startSchema->createTable($this->tableNameTmp); $tableFk->addColumn('fk_id', 'integer'); $tableFk->addColumn('name', 'string'); $tableFk->addForeignKeyConstraint($this->tableName, ['fk_id'], ['id'], [], $fkName); - $migrator = $this->manager->getMigrator(); + $migrator = $this->getMigrator(); $migrator->migrate($startSchema); $this->assertTrue($startSchema->getTable($this->tableNameTmp)->hasForeignKey($fkName)); } + + public static function dataNotNullEmptyValuesFailOracle(): array { + return [ + [ParameterType::BOOLEAN, true, Types::BOOLEAN, false], + [ParameterType::BOOLEAN, false, Types::BOOLEAN, true], + + [ParameterType::STRING, 'foo', Types::STRING, false], + [ParameterType::STRING, '', Types::STRING, true], + + [ParameterType::INTEGER, 1234, Types::INTEGER, false], + [ParameterType::INTEGER, 0, Types::INTEGER, false], // Integer 0 is not stored as Null and therefor works + + [ParameterType::STRING, '{"a": 2}', Types::JSON, false], + ]; + } + + /** + * + * @param int $parameterType + * @param bool|int|string $value + * @param string $columnType + * @param bool $oracleThrows + */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataNotNullEmptyValuesFailOracle')] + public function testNotNullEmptyValuesFailOracle(int $parameterType, $value, string $columnType, bool $oracleThrows): void { + $startSchema = new Schema([], [], $this->getSchemaConfig()); + $table = $startSchema->createTable($this->tableName); + $table->addColumn('id', Types::BIGINT); + $table->addColumn('will_it_blend', $columnType, [ + 'notnull' => true, + ]); + $table->addIndex(['id'], $this->tableName . '_id'); + + $migrator = $this->getMigrator(); + $migrator->migrate($startSchema); + + if ($oracleThrows && $this->connection->getDatabaseProvider() === IDBConnection::PLATFORM_ORACLE) { + // Oracle can not store false|empty string in notnull columns + $this->expectException(\Doctrine\DBAL\Exception\NotNullConstraintViolationException::class); + } + + $this->connection->insert( + $this->tableName, + ['id' => 1, 'will_it_blend' => $value], + ['id' => ParameterType::INTEGER, 'will_it_blend' => $parameterType], + ); + + $this->addToAssertionCount(1); + } } |