Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/Doctrine/DBAL/Schema/SchemaDiff.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ protected function _toSql(AbstractPlatform $platform, $saveMode = false)
}
}

if ($platform->supportsForeignKeyConstraints() && $saveMode === false) {
if ($platform->supportsCreateDropForeignKeyConstraints() && $saveMode === false) {
foreach ($this->orphanedForeignKeys as $orphanedForeignKey) {
$sql[] = $platform->getDropForeignKeySQL($orphanedForeignKey, $orphanedForeignKey->getLocalTable());
}
Expand Down
2 changes: 1 addition & 1 deletion tests/Doctrine/Tests/DBAL/Functional/ExceptionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ public function testConnectionExceptionSqLite() : void
}

// mode 0 is considered read-only on Windows
$mode = PHP_OS === 'Linux' ? 0444 : 0000;
$mode = PHP_OS === 'Windows' ? 0000 : 0444;

$filename = sprintf('%s/%s', sys_get_temp_dir(), 'doctrine_failed_connection_' . $mode . '.db');

Expand Down
161 changes: 161 additions & 0 deletions tests/Doctrine/Tests/DBAL/Schema/SqliteSchemaDiffTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
<?php

namespace Doctrine\Tests\DBAL\Schema;

use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
use Doctrine\DBAL\Schema\SchemaDiff;
use Doctrine\DBAL\Schema\Table;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

class SqliteSchemaDiffTest extends TestCase
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the tests specific to Sqlite or could they apply to other platforms?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure. They are testing a specific use case that I encountered with SQLite, it might apply to any platform where supportsForeignKeyConstraints() is true and supportsCreateDropForeignKeyConstraints() is false.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the number of things mocked, I can barely understand what is being tested here. Would it make sense to have an integration test instead?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess so. I just copied the code that was in the SchemaDiffTest. Maybe a more generic integration test could cover both cases.

{
/**
* @return AbstractPlatform|MockObject
*/
private function getGenericPlatform()
{
$platform = $this->createMock(AbstractPlatform::class);

$platform->expects($this->exactly(1))
->method('supportsSchemas')
->will($this->returnValue(false));

$platform->expects($this->exactly(1))
->method('supportsSequences')
->will($this->returnValue(false));

$platform->expects($this->exactly(0))
->method('supportsForeignKeyConstraints')
->will($this->returnValue(true));

$platform->expects($this->exactly(1))
->method('getCreateTableSql')
->with($this->isInstanceOf(Table::class))
->will($this->returnValue(['create_table']));

return $platform;
}

/**
* @param bool $safe Whether the method should output only safe SQL code or not
*
* @return AbstractPlatform|MockObject
*/
private function getForeignKeyConstraintsOnlyPlatform(bool $safe = true)
{
$platform = $this->getGenericPlatform();

$platform->expects($this->any())
->method('supportsCreateDropForeignKeyConstraints')
->will($this->returnValue(false));

$platform->expects($this->exactly(0))
->method('getCreateForeignKeySQL')
->with($this->isInstanceOf(ForeignKeyConstraint::class))
->will($this->throwException(
new DBALException('This platform does not support alter foreign key, the table must be fully recreated using getAlterTableSQL.')
));

if (! $safe) {
$platform->expects($this->exactly(0))
->method('getDropForeignKeySql')
->with(
$this->isInstanceOf(ForeignKeyConstraint::class),
$this->isInstanceOf(Table::class)
)
->will($this->throwException(
new DBALException('This platform does not support alter foreign key, the table must be fully recreated using getAlterTableSQL.')
));
}

return $platform;
}

/**
* @param bool $safe Whether the method should output only safe SQL code or not
*
* @return AbstractPlatform|MockObject
*/
private function getCreateDropForeignKeyConstraintsPlatform(bool $safe = true)
{
$platform = $this->getGenericPlatform();

$platform->expects($this->any())
->method('supportsCreateDropForeignKeyConstraints')
->will($this->returnValue(true));

$platform->expects($this->exactly(1))
->method('getCreateForeignKeySQL')
->with($this->isInstanceOf(ForeignKeyConstraint::class))
->will($this->returnValue('create_foreign_key'));

if (! $safe) {
$platform->expects($this->exactly(1))
->method('getDropForeignKeySql')
->with(
$this->isInstanceOf(ForeignKeyConstraint::class),
$this->isInstanceOf(Table::class)
)
->will($this->returnValue('drop_orphan_fk'));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a lot of mocking… why not use the real object? A cross-platform functional test should make all this a bit shorter.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thoughts exactly. All of your above remarks apply. I just copied the SchemaDiffTest and kept the same coding style.


return $platform;
}

/**
* @return mixed[]
*/
public function provider() : array
{
$diff = $this->createSchemaDiff();

return [
'supportsForeignKeyConstraintsOnly' => [
['create_table'],
$diff->toSql($this->getForeignKeyConstraintsOnlyPlatform(false)),
],
'supportsForeignKeyConstraintsOnlySaveSql' => [
['create_table'],
$diff->toSaveSql($this->getForeignKeyConstraintsOnlyPlatform()),
],
'supportsCreateDropForeignKeyConstraints' => [
['drop_orphan_fk', 'create_table', 'create_foreign_key'],
$diff->toSql($this->getCreateDropForeignKeyConstraintsPlatform(false)),
],
'supportsCreateDropForeignKeyConstraintsSaveSql' => [
['create_table', 'create_foreign_key'],
$diff->toSaveSql($this->getCreateDropForeignKeyConstraintsPlatform()),
],
];
}

/**
* @param string[] $expectedActions An array of actions to be taken on the database
* @param string[] $sql An array of actions gnerated by the SchemaDiff
*
* @dataProvider provider
*/
public function testSchemaDiff(array $expectedActions, array $sql) : void
{
self::assertEquals($expectedActions, $sql);
}

public function createSchemaDiff() : SchemaDiff
{
$diff = new SchemaDiff();

$diff->newTables['foo_table'] = new Table('foo_table');
$diff->newTables['foo_table']->addColumn('foreign_id', 'integer');
$diff->newTables['foo_table']->addForeignKeyConstraint('foreign_table', ['foreign_id'], ['id']);

$fk = new ForeignKeyConstraint(['id'], 'foreign_table', ['id']);
$fk->setLocalTable(new Table('local_table'));

$diff->orphanedForeignKeys[] = $fk;

return $diff;
}
}