From c7cee11eb6eb4a4b1ad92dc32db5d4f556807703 Mon Sep 17 00:00:00 2001 From: Julien Bandelier Date: Tue, 21 Nov 2017 11:36:12 +0100 Subject: [PATCH 1/3] Test case for GH-6776 : unique constraint violation on collection --- .../ORM/Functional/Ticket/GH6776Test.php | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/GH6776Test.php diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/GH6776Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/GH6776Test.php new file mode 100644 index 00000000000..dd06137f53d --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/GH6776Test.php @@ -0,0 +1,120 @@ +setUpEntitySchema([GH6776WheelDimension::class, GH6776Vehicle::class]); + } + + /** + * Verifies that removing and then inserting an element in a collection using a unique constraint does not + * make this constraint fail. + */ + public function testIssue() : void + { + // create some vehicle with dimensions + $vehicle = new GH6776Vehicle(); + $vehicle->name = 'SuperCar'; + + $dimension1 = new GH6776WheelDimension(); + $dimension1->width = 6; + $dimension1->diameter = 17; + $dimension1->offset = 32; + $dimension1->tirePressure = 2.75; + $dimension1->vehicle = $vehicle; + + $dimension1bis = clone $dimension1; + $dimension1bis->tirePressure = 3.10; + + $dimension2 = new GH6776WheelDimension(); + $dimension2->type = 'rear'; + $dimension2->width = 6; + $dimension2->diameter = 17; + $dimension2->offset = 39; + $dimension2->tirePressure = 2.75; + $dimension2->vehicle = $vehicle; + + $vehicle->compatibleDimensions = new ArrayCollection(); + $vehicle->compatibleDimensions->add($dimension1); + $vehicle->compatibleDimensions->add($dimension2); + + // persist and flush vehicle and the 2 original dimensions + $this->_em->persist($vehicle); + $this->_em->persist($dimension1); + $this->_em->persist($dimension2); + $this->_em->flush(); + + self::assertCount(2, $vehicle->compatibleDimensions); + + // remove dimension1 and add its clone; when flushing it should crash because of unique constraint violation + $vehicle->compatibleDimensions->removeElement($dimension1); + $this->_em->remove($dimension1); + + self::assertCount(1, $vehicle->compatibleDimensions); + + $this->_em->persist($dimension1bis); + $vehicle->compatibleDimensions->add($dimension1bis); + + $this->_em->flush(); + + // still the same count + self::assertCount(2, $vehicle->compatibleDimensions); + } +} + +/** + * @Entity + */ +class GH6776Vehicle +{ + /** @Id @Column(type="integer") @GeneratedValue */ + public $id; + + /** @Column(type="string") */ + public $name; + + /** @oneToMany(targetEntity="GH6776WheelDimension", mappedBy="vehicle") */ + public $compatibleDimensions; +} + +/** + * @Entity + * @Table(uniqueConstraints={@UniqueConstraint(name="wheel_size", columns={"offset", "width", "diameter"})}) + */ +class GH6776WheelDimension +{ + /** @Id @Column(type="integer") @GeneratedValue */ + public $id; + + /** @ManyToOne(targetEntity="GH6776Vehicle", inversedBy="compatibleDimensions") */ + public $vehicle; + + /** @Column(type="integer") */ + public $offset; + + /** @Column(type="integer") */ + public $width; + + /** @Column(type="integer") */ + public $diameter; + + /** @Column(type="float") */ + public $tirePressure; + + /** @Column(type="string") */ + public $type = 'front'; +} From 077124efa07f43997b66297fb4c05e340f2d3f12 Mon Sep 17 00:00:00 2001 From: Toby Griffiths Date: Wed, 31 Oct 2018 10:31:38 +0000 Subject: [PATCH 2/3] Added test for OneToOne version of the issue --- .../Ticket/GH6776_OneToOne_Test.php | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/GH6776_OneToOne_Test.php diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/GH6776_OneToOne_Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/GH6776_OneToOne_Test.php new file mode 100644 index 00000000000..dcafc7e0f6b --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/GH6776_OneToOne_Test.php @@ -0,0 +1,98 @@ +setUpEntitySchema([GH6776Cost::class, GH6776Vehicle::class]); + } + + + /** + * Verifies that removing and then inserting an element in a collection using a unique constraint does not + * make this constraint fail. + */ + public function testIssue(): void + { + // create some vehicle with dimensions + $vehicle = new GH6776Vehicle(); + $vehicle->name = 'SuperCar'; + + $cost1 = new GH6776Cost(); + $cost1->currency = 'GBP'; + $cost1->amount = 12000000; + $cost1->vehicle = $vehicle; + + $vehicle->cost = $cost1; + + // persist and flush vehicle and the 2 original dimensions + $this->_em->persist($vehicle); + $this->_em->persist($cost1); + $this->_em->flush(); + + self::assertEquals($cost1, $vehicle->cost); + + // remove cost1 and add its clone; when flushing it should crash because of unique constraint violation + $vehicle->cost = null; + $this->_em->remove($cost1); + + self::assertEquals(null, $vehicle->cost); + + $cost2 = clone $cost1; + $cost2->amount = 15000000; + + $this->_em->persist($cost2); + $vehicle->cost = $cost2; + + $this->_em->flush(); + + // still the same count + self::assertEquals($cost2, $vehicle->cost); + } +} + +/** + * @Entity + */ +class GH6776Vehicle +{ + /** @Id @Column(type="integer") @GeneratedValue */ + public $id; + + /** @Column(type="string") */ + public $name; + + /** @OneToOne(targetEntity="GH6776Cost", mappedBy="vehicle") */ + public $cost; +} + +/** + * @Entity() + * @Table(uniqueConstraints={@UniqueConstraint(name="cost", columns={"vehicle_id"})}) + */ +class GH6776Cost +{ + /** @Id @Column(type="integer") @GeneratedValue */ + public $id; + + /** @OneToOne(targetEntity="GH6776Vehicle", inversedBy="code") */ + public $vehicle; + + /** @Column(type="string", length=3) */ + public $currency; + + /** @Column(type="integer") */ + public $amount; +} From b01f863fe5696eb5c040096d8f02ddb2936ea0a3 Mon Sep 17 00:00:00 2001 From: Toby Griffiths Date: Wed, 31 Oct 2018 10:32:42 +0000 Subject: [PATCH 3/3] I think that should really be capitalised --- tests/Doctrine/Tests/ORM/Functional/Ticket/GH6776Test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/GH6776Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/GH6776Test.php index dd06137f53d..56a7f793bd7 100644 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/GH6776Test.php +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/GH6776Test.php @@ -87,7 +87,7 @@ class GH6776Vehicle /** @Column(type="string") */ public $name; - /** @oneToMany(targetEntity="GH6776WheelDimension", mappedBy="vehicle") */ + /** @OneToMany(targetEntity="GH6776WheelDimension", mappedBy="vehicle") */ public $compatibleDimensions; }