feat(db): Restaure support for non-nullable boolean column

We disabled them because they are not supported on Oracle DB and it is
still the case for OCI < 23. But instead of disabling the support
completely for every database types, mark non-nullable boolean column as
actually nullable when using Oracle.

This allow to use some slighly lighter schema on normal databases who
support natively booleans wheen we don't need to store 3 states
true|false|null.

Signed-off-by: Carl Schwan <carl.schwan@nextcloud.com>
pull/55156/head
Carl Schwan 3 weeks ago
parent 7a2e25124c
commit 837fe3586d
  1. 8
      lib/private/DB/MigrationService.php
  2. 18
      tests/lib/DB/MigrationsTest.php

@ -7,6 +7,7 @@
*/
namespace OC\DB;
use Doctrine\DBAL\Platforms\OraclePlatform;
use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\SchemaException;
@ -576,8 +577,11 @@ class MigrationService {
throw new \InvalidArgumentException('Column "' . $table->getName() . '"."' . $thing->getName() . '" is NotNull, but has empty string or null as default.');
}
if ($thing->getNotnull() && $thing->getType()->getName() === Types::BOOLEAN) {
throw new \InvalidArgumentException('Column "' . $table->getName() . '"."' . $thing->getName() . '" is type Bool and also NotNull, so it can not store "false".');
if ($this->connection->getDatabasePlatform() instanceof OraclePlatform) {
// Oracle doesn't support boolean column with non-null value
if ($thing->getNotnull() && $thing->getType()->getName() === Types::BOOLEAN) {
$thing->setNotnull(false);
}
}
$sourceColumn = null;

@ -8,6 +8,7 @@
namespace Test\DB;
use Doctrine\DBAL\Platforms\OraclePlatform;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
use Doctrine\DBAL\Schema\Index;
@ -34,6 +35,7 @@ use OCP\Migration\Attributes\IndexType;
use OCP\Migration\Attributes\ModifyColumn;
use OCP\Migration\IMigrationStep;
use OCP\Server;
use PHPUnit\Framework\Attributes\TestWith;
use PHPUnit\Framework\MockObject\MockObject;
/**
@ -703,8 +705,11 @@ class MigrationsTest extends \Test\TestCase {
}
public function testEnsureOracleConstraintsBooleanNotNull(): void {
$this->expectException(\InvalidArgumentException::class);
#[TestWith([true])]
#[TestWith([false])]
public function testEnsureOracleConstraintsBooleanNotNull(bool $isOracle): void {
$this->db->method('getDatabasePlatform')
->willReturn($isOracle ? $this->createMock(OraclePlatform::class) : null);
$column = $this->createMock(Column::class);
$column->expects($this->any())
@ -739,6 +744,15 @@ class MigrationsTest extends \Test\TestCase {
->method('hasSequence')
->willReturn(false);
if ($isOracle) {
$column->expects($this->once())
->method('setNotnull')
->with(false);
} else {
$column->expects($this->never())
->method('setNotnull');
}
self::invokePrivate($this->migrationService, 'ensureOracleConstraints', [$sourceSchema, $schema, 3]);
}

Loading…
Cancel
Save