Skip to content

Commit

Permalink
Merge pull request #24 from roxblnfk/hotfix/23
Browse files Browse the repository at this point in the history
Embedded entity's fields conflict with the parent ones even using columnPrefix
  • Loading branch information
wolfy-j committed Mar 25, 2021
2 parents 8b3c088 + 22dfcdc commit ed8df4d
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 3 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"description": "Cycle ORM Schema Builder",
"require": {
"php": ">=7.2",
"cycle/orm": "^1.0"
"cycle/orm": "^1.0",
"yiisoft/friendly-exception": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "~8.0",
Expand Down
4 changes: 2 additions & 2 deletions src/Definition/Map/FieldMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public function has(string $name): bool
public function get(string $name): Field
{
if (!$this->has($name)) {
throw new FieldException("Undefined field `{$name}`");
throw new FieldException("Undefined field `{$name}`.");
}

return $this->fields[$name];
Expand All @@ -70,7 +70,7 @@ public function get(string $name): Field
public function set(string $name, Field $field): self
{
if ($this->has($name)) {
throw new FieldException("Field `{$name}` already exists");
throw new FieldException("Field `{$name}` already exists.");
}

$this->fields[$name] = $field;
Expand Down
33 changes: 33 additions & 0 deletions src/Exception/FieldException/EmbeddedPrimaryKeyException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Cycle\Schema\Exception\FieldException;

use Cycle\Schema\Definition\Entity;
use Cycle\Schema\Exception\FieldException;
use Yiisoft\FriendlyException\FriendlyExceptionInterface;

final class EmbeddedPrimaryKeyException extends FieldException implements FriendlyExceptionInterface
{

public function __construct(Entity $embed, string $fieldName)
{
parent::__construct("Entity `{$embed->getRole()}` has conflicted field `{$fieldName}`.");
}

public function getName(): string
{
return 'Embedded entity primary key collision';
}

public function getSolution(): ?string
{
return "The primary key of the composite entity must be projected onto the embedded entity.\n"
. "However, the embedded entity already has a field with the same name.\n\n"
. "Possible solutions:\n"
. "- If the conflicting field applies only to an embedded entity, then rename it.\n"
. '- If you want to receive the primary key value of a composite entity in this field,'
. ' then remove its definition from the column list in the schema.';
}
}
4 changes: 4 additions & 0 deletions src/Relation/Embedded.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Cycle\Schema\Relation;

use Cycle\ORM\Relation;
use Cycle\Schema\Exception\FieldException\EmbeddedPrimaryKeyException;
use Cycle\Schema\Registry;
use Cycle\Schema\Relation\Traits\ForeignKeyTrait;

Expand Down Expand Up @@ -49,6 +50,9 @@ public function compute(Registry $registry): void
foreach ($source->getFields() as $name => $field) {
if ($field->isPrimary()) {
// sync primary keys
if ($target->getFields()->has($name)) {
throw new EmbeddedPrimaryKeyException($target, $name);
}
$target->getFields()->set($name, $field);
}
}
Expand Down
17 changes: 17 additions & 0 deletions tests/Schema/Driver/MySQL/EmbeddedTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

/**
* Spiral Framework.
*
* @license MIT
* @author Anton Titov (Wolfy-J)
*/

declare(strict_types=1);

namespace Cycle\Schema\Tests\Driver\MySQL;

class EmbeddedTest extends \Cycle\Schema\Tests\Relation\EmbeddedTest
{
public const DRIVER = 'mysql';
}
17 changes: 17 additions & 0 deletions tests/Schema/Driver/Postgres/EmbeddedTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

/**
* Spiral Framework.
*
* @license MIT
* @author Anton Titov (Wolfy-J)
*/

declare(strict_types=1);

namespace Cycle\Schema\Tests\Driver\Postgres;

class EmbeddedTest extends \Cycle\Schema\Tests\Relation\EmbeddedTest
{
public const DRIVER = 'postgres';
}
10 changes: 10 additions & 0 deletions tests/Schema/Driver/SQLServer/EmbeddedTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Cycle\Schema\Tests\Driver\SQLServer;

class EmbeddedTest extends \Cycle\Schema\Tests\Relation\EmbeddedTest
{
public const DRIVER = 'sqlserver';
}
17 changes: 17 additions & 0 deletions tests/Schema/Driver/SQLite/EmbeddedTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

/**
* Spiral Framework.
*
* @license MIT
* @author Anton Titov (Wolfy-J)
*/

declare(strict_types=1);

namespace Cycle\Schema\Tests\Driver\SQLite;

class EmbeddedTest extends \Cycle\Schema\Tests\Relation\EmbeddedTest
{
public const DRIVER = 'sqlite';
}
31 changes: 31 additions & 0 deletions tests/Schema/Relation/EmbeddedTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@

use Cycle\ORM\Schema;
use Cycle\Schema\Compiler;
use Cycle\Schema\Definition\Field;
use Cycle\Schema\Definition\Relation;
use Cycle\Schema\Exception\FieldException\EmbeddedPrimaryKeyException;
use Cycle\Schema\Generator\GenerateRelations;
use Cycle\Schema\Generator\RenderRelations;
use Cycle\Schema\Generator\RenderTables;
Expand Down Expand Up @@ -160,4 +162,33 @@ public function testRenderTable(): void
$this->assertTrue($table->hasColumn('id'));
$this->assertTrue($table->hasColumn('embedded_column'));
}

public function testEmbedIdFieldWithPrefix(): void
{
$c = Composite::define();
$e = EmbeddedEntity::define();

$e->getFields()->set('id', (new Field())->setColumn('embedded_id')->setType('int'));

$c->getRelations()->set(
'embedded',
(new Relation())->setTarget('embedded')->setType('embedded')
);

$r = new Registry($this->dbal);
$r->register($c)->linkTable($c, 'default', 'composite');
$r->register($e);

$this->expectException(EmbeddedPrimaryKeyException::class);
$this->expectExceptionMessage('Entity `composite:embedded` has conflicted field `id`.');

(new Compiler())->compile(
$r,
[
new GenerateRelations(['embedded' => new Embedded()]),
$t = new RenderTables(),
new RenderRelations()
]
);
}
}

0 comments on commit ed8df4d

Please sign in to comment.