1
0
mirror of synced 2025-02-03 13:59:27 +03:00
doctrine2/tests/Doctrine/Tests/ORM/Tools/SchemaToolTest.php
Tyler Romeo bb8970286d
Allow association mappings as IDs for joined-table inherited entity
SchemaTool has custom logic for creating the primary key of a
joined-table inherited entity. This logic overlooked association maps
as a possible source for identity columns, resulting in a fatal error
when fetching the primary key list for child entities.

Removed any custom logic for generating primary keys for root entities
in joined-table inheritance, deferring to the common logic used for
other entities.

Also adjusted the child entity logic, scanning association maps for
identity columns, and including the column as appropriate. It also
ensures that the primary key columns are in the correct order.
2017-12-19 17:58:31 +01:00

325 lines
10 KiB
PHP

<?php
namespace Doctrine\Tests\ORM\Tools;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
use Doctrine\ORM\Tools\Event\GenerateSchemaTableEventArgs;
use Doctrine\ORM\Tools\SchemaTool;
use Doctrine\ORM\Tools\ToolEvents;
use Doctrine\Tests\Models\CMS\CmsAddress;
use Doctrine\Tests\Models\CMS\CmsArticle;
use Doctrine\Tests\Models\CMS\CmsComment;
use Doctrine\Tests\Models\CMS\CmsEmployee;
use Doctrine\Tests\Models\CMS\CmsGroup;
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\Models\CompositeKeyInheritance\JoinedDerivedChildClass;
use Doctrine\Tests\Models\CompositeKeyInheritance\JoinedDerivedIdentityClass;
use Doctrine\Tests\Models\CompositeKeyInheritance\JoinedDerivedRootClass;
use Doctrine\Tests\Models\Forum\ForumAvatar;
use Doctrine\Tests\Models\Forum\ForumUser;
use Doctrine\Tests\Models\NullDefault\NullDefaultColumn;
use Doctrine\Tests\OrmTestCase;
class SchemaToolTest extends OrmTestCase
{
public function testAddUniqueIndexForUniqueFieldAnnotation()
{
$em = $this->_getTestEntityManager();
$schemaTool = new SchemaTool($em);
$classes = [
$em->getClassMetadata(CmsAddress::class),
$em->getClassMetadata(CmsArticle::class),
$em->getClassMetadata(CmsComment::class),
$em->getClassMetadata(CmsEmployee::class),
$em->getClassMetadata(CmsGroup::class),
$em->getClassMetadata(CmsPhonenumber::class),
$em->getClassMetadata(CmsUser::class),
];
$schema = $schemaTool->getSchemaFromMetadata($classes);
$this->assertTrue($schema->hasTable('cms_users'), "Table cms_users should exist.");
$this->assertTrue($schema->getTable('cms_users')->columnsAreIndexed(['username']), "username column should be indexed.");
}
public function testAnnotationOptionsAttribute()
{
$em = $this->_getTestEntityManager();
$schemaTool = new SchemaTool($em);
$classes = [
$em->getClassMetadata(TestEntityWithAnnotationOptionsAttribute::class),
];
$schema = $schemaTool->getSchemaFromMetadata($classes);
$expected = ['foo' => 'bar', 'baz' => ['key' => 'val']];
$this->assertEquals($expected, $schema->getTable('TestEntityWithAnnotationOptionsAttribute')->getOptions(), "options annotation are passed to the tables options");
$this->assertEquals($expected, $schema->getTable('TestEntityWithAnnotationOptionsAttribute')->getColumn('test')->getCustomSchemaOptions(), "options annotation are passed to the columns customSchemaOptions");
}
/**
* @group DDC-200
*/
public function testPassColumnDefinitionToJoinColumn()
{
$customColumnDef = "MEDIUMINT(6) UNSIGNED NOT NULL";
$em = $this->_getTestEntityManager();
$schemaTool = new SchemaTool($em);
$avatar = $em->getClassMetadata(ForumAvatar::class);
$avatar->fieldMappings['id']['columnDefinition'] = $customColumnDef;
$user = $em->getClassMetadata(ForumUser::class);
$classes = [$avatar, $user];
$schema = $schemaTool->getSchemaFromMetadata($classes);
$this->assertTrue($schema->hasTable('forum_users'));
$table = $schema->getTable("forum_users");
$this->assertTrue($table->hasColumn('avatar_id'));
$this->assertEquals($customColumnDef, $table->getColumn('avatar_id')->getColumnDefinition());
}
/**
* @group DDC-283
*/
public function testPostGenerateEvents()
{
$listener = new GenerateSchemaEventListener();
$em = $this->_getTestEntityManager();
$em->getEventManager()->addEventListener(
[ToolEvents::postGenerateSchemaTable, ToolEvents::postGenerateSchema], $listener
);
$schemaTool = new SchemaTool($em);
$classes = [
$em->getClassMetadata(CmsAddress::class),
$em->getClassMetadata(CmsArticle::class),
$em->getClassMetadata(CmsComment::class),
$em->getClassMetadata(CmsEmployee::class),
$em->getClassMetadata(CmsGroup::class),
$em->getClassMetadata(CmsPhonenumber::class),
$em->getClassMetadata(CmsUser::class),
];
$schema = $schemaTool->getSchemaFromMetadata($classes);
$this->assertEquals(count($classes), $listener->tableCalls);
$this->assertTrue($listener->schemaCalled);
}
public function testNullDefaultNotAddedToCustomSchemaOptions()
{
$em = $this->_getTestEntityManager();
$schemaTool = new SchemaTool($em);
$customSchemaOptions = $schemaTool->getSchemaFromMetadata([$em->getClassMetadata(NullDefaultColumn::class)])
->getTable('NullDefaultColumn')
->getColumn('nullDefault')
->getCustomSchemaOptions();
$this->assertSame([], $customSchemaOptions);
}
/**
* @group DDC-3671
*/
public function testSchemaHasProperIndexesFromUniqueConstraintAnnotation()
{
$em = $this->_getTestEntityManager();
$schemaTool = new SchemaTool($em);
$classes = [
$em->getClassMetadata(UniqueConstraintAnnotationModel::class),
];
$schema = $schemaTool->getSchemaFromMetadata($classes);
$this->assertTrue($schema->hasTable('unique_constraint_annotation_table'));
$table = $schema->getTable('unique_constraint_annotation_table');
$this->assertEquals(2, count($table->getIndexes()));
$this->assertTrue($table->hasIndex('primary'));
$this->assertTrue($table->hasIndex('uniq_hash'));
}
public function testRemoveUniqueIndexOverruledByPrimaryKey()
{
$em = $this->_getTestEntityManager();
$schemaTool = new SchemaTool($em);
$classes = [
$em->getClassMetadata(FirstEntity::class),
$em->getClassMetadata(SecondEntity::class)
];
$schema = $schemaTool->getSchemaFromMetadata($classes);
$this->assertTrue($schema->hasTable('first_entity'), "Table first_entity should exist.");
$indexes = $schema->getTable('first_entity')->getIndexes();
$this->assertCount(1, $indexes, "there should be only one index");
$this->assertTrue(current($indexes)->isPrimary(), "index should be primary");
}
public function testSetDiscriminatorColumnWithoutLength() : void
{
$em = $this->_getTestEntityManager();
$schemaTool = new SchemaTool($em);
$metadata = $em->getClassMetadata(FirstEntity::class);
$metadata->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE);
$metadata->setDiscriminatorColumn(['name' => 'discriminator', 'type' => 'string']);
$schema = $schemaTool->getSchemaFromMetadata([$metadata]);
$this->assertTrue($schema->hasTable('first_entity'));
$table = $schema->getTable('first_entity');
$this->assertTrue($table->hasColumn('discriminator'));
$column = $table->getColumn('discriminator');
$this->assertEquals(255, $column->getLength());
}
public function testDerivedCompositeKey() : void
{
$em = $this->_getTestEntityManager();
$schemaTool = new SchemaTool($em);
$schema = $schemaTool->getSchemaFromMetadata(
[
$em->getClassMetadata(JoinedDerivedIdentityClass::class),
$em->getClassMetadata(JoinedDerivedRootClass::class),
$em->getClassMetadata(JoinedDerivedChildClass::class),
]
);
self::assertTrue($schema->hasTable('joined_derived_identity'));
self::assertTrue($schema->hasTable('joined_derived_root'));
self::assertTrue($schema->hasTable('joined_derived_child'));
$rootTable = $schema->getTable('joined_derived_root');
self::assertNotNull($rootTable->getPrimaryKey());
self::assertSame(['keyPart1_id', 'keyPart2'], $rootTable->getPrimaryKey()->getColumns());
$childTable = $schema->getTable('joined_derived_child');
self::assertNotNull($childTable->getPrimaryKey());
self::assertSame(['keyPart1_id', 'keyPart2'], $childTable->getPrimaryKey()->getColumns());
$childTableForeignKeys = $childTable->getForeignKeys();
self::assertCount(2, $childTableForeignKeys);
$expectedColumns = [
'joined_derived_identity' => [['keyPart1_id'], ['id']],
'joined_derived_root' => [['keyPart1_id', 'keyPart2'], ['keyPart1_id', 'keyPart2']],
];
foreach ($childTableForeignKeys as $foreignKey) {
self::assertArrayHasKey($foreignKey->getForeignTableName(), $expectedColumns);
[$localColumns, $foreignColumns] = $expectedColumns[$foreignKey->getForeignTableName()];
self::assertSame($localColumns, $foreignKey->getLocalColumns());
self::assertSame($foreignColumns, $foreignKey->getForeignColumns());
}
}
}
/**
* @Entity
* @Table(options={"foo": "bar", "baz": {"key": "val"}})
*/
class TestEntityWithAnnotationOptionsAttribute
{
/** @Id @Column */
private $id;
/**
* @Column(type="string", options={"foo": "bar", "baz": {"key": "val"}})
*/
private $test;
}
class GenerateSchemaEventListener
{
public $tableCalls = 0;
public $schemaCalled = false;
public function postGenerateSchemaTable(GenerateSchemaTableEventArgs $eventArgs)
{
$this->tableCalls++;
}
public function postGenerateSchema(GenerateSchemaEventArgs $eventArgs)
{
$this->schemaCalled = true;
}
}
/**
* @Entity
* @Table(name="unique_constraint_annotation_table", uniqueConstraints={
* @UniqueConstraint(name="uniq_hash", columns={"hash"})
* })
*/
class UniqueConstraintAnnotationModel
{
/** @Id @Column */
private $id;
/**
* @Column(name="hash", type="string", length=8, nullable=false, unique=true)
*/
private $hash;
}
/**
* @Entity
* @Table(name="first_entity")
*/
class FirstEntity
{
/**
* @Id
* @Column(name="id")
*/
public $id;
/**
* @OneToOne(targetEntity="SecondEntity")
* @JoinColumn(name="id", referencedColumnName="fist_entity_id")
*/
public $secondEntity;
/**
* @Column(name="name")
*/
public $name;
}
/**
* @Entity
* @Table(name="second_entity")
*/
class SecondEntity
{
/**
* @Id
* @Column(name="fist_entity_id")
*/
public $fist_entity_id;
/**
* @Column(name="name")
*/
public $name;
}