File: GH10531Test.php

package info (click to toggle)
doctrine 3.5.2%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 11,556 kB
  • sloc: php: 108,620; xml: 1,340; makefile: 35; sh: 14
file content (142 lines) | stat: -rw-r--r-- 4,446 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<?php

declare(strict_types=1);

namespace Doctrine\Tests\ORM\Functional\Ticket;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Tests\OrmFunctionalTestCase;

class GH10531Test extends OrmFunctionalTestCase
{
    protected function setUp(): void
    {
        parent::setUp();

        $this->createSchemaForModels(
            GH10531A::class,
            GH10531B::class,
        );
    }

    public function tearDown(): void
    {
        $conn = static::$sharedConn;
        $conn->executeStatement('DELETE FROM gh10531_b');
        $conn->executeStatement('DELETE FROM gh10531_a');
    }

    public function testInserts(): void
    {
        $a  = new GH10531A();
        $b1 = new GH10531B();
        $b2 = new GH10531B();
        $b3 = new GH10531B();

        $b1->parent = $b2;
        $b3->parent = $b2;
        $b2->parent = $a;

        /*
         * The following would force a working commit order, but that's not what
         * we want (the ORM shall sort this out internally).
         *
         * $this->_em->persist($a);
         * $this->_em->persist($b2);
         * $this->_em->flush();
         * $this->_em->persist($b1);
         * $this->_em->persist($b3);
         * $this->_em->flush();
         */

        // Pass $b2 to persist() between $b1 and $b3, so that any potential reliance upon the
        // order of persist() calls is spotted: No matter if it is in the order that persist()
        // was called or the other way round, in both cases there is an entity that will come
        // "before" $b2 but depend on its primary key, so the ORM must re-order the inserts.

        $this->_em->persist($a);
        $this->_em->persist($b1);
        $this->_em->persist($b2);
        $this->_em->persist($b3);
        $this->_em->flush();

        self::assertNotNull($a->id);
        self::assertNotNull($b1->id);
        self::assertNotNull($b2->id);
        self::assertNotNull($b3->id);
    }

    public function testDeletes(): void
    {
        $this->expectNotToPerformAssertions();
        $con = $this->_em->getConnection();

        // The "a" entity
        $con->insert('gh10531_a', ['id' => 1, 'discr' => 'A']);
        $a = $this->_em->find(GH10531A::class, 1);

        // The "b2" entity
        $con->insert('gh10531_a', ['id' => 2, 'discr' => 'B']);
        $con->insert('gh10531_b', ['id' => 2, 'parent_id' => 1]);
        $b2 = $this->_em->find(GH10531B::class, 2);

        // The "b1" entity
        $con->insert('gh10531_a', ['id' => 3, 'discr' => 'B']);
        $con->insert('gh10531_b', ['id' => 3, 'parent_id' => 2]);
        $b1 = $this->_em->find(GH10531B::class, 3);

        // The "b3" entity
        $con->insert('gh10531_a', ['id' => 4, 'discr' => 'B']);
        $con->insert('gh10531_b', ['id' => 4, 'parent_id' => 2]);
        $b3 = $this->_em->find(GH10531B::class, 4);

        /*
         * The following would make the deletions happen in an order
         * where the not-nullable foreign key constraints would not be
         * violated. But, we want the ORM to be able to sort this out
         * internally.
         *
         * $this->_em->remove($b1);
         * $this->_em->remove($b3);
         * $this->_em->remove($b2);
         */

        // As before, put $b2 in between $b1 and $b3 so that the order of the
        // remove() calls alone (in either direction) does not solve the problem.
        // The ORM will have to sort $b2 to be deleted last, after $b1 and $b3.
        $this->_em->remove($b1);
        $this->_em->remove($b2);
        $this->_em->remove($b3);

        $this->_em->flush();
    }
}

/**
 * We are using JTI here, since STI would relax the not-nullable constraint for the "parent"
 * column (it has to be NULL when the row contains a GH10531A instance). Causes another error,
 * but not the constraint violation I'd like to point out.
 */
#[ORM\Entity]
#[ORM\Table(name: 'gh10531_a')]
#[ORM\DiscriminatorColumn(name: 'discr', type: 'string')]
#[ORM\DiscriminatorMap(['A' => GH10531A::class, 'B' => GH10531B::class])]
#[ORM\InheritanceType('JOINED')]
class GH10531A
{
    /** @var int */
    #[ORM\Id]
    #[ORM\GeneratedValue(strategy: 'AUTO')]
    #[ORM\Column(type: 'integer')]
    public $id;
}

#[ORM\Entity]
#[ORM\Table(name: 'gh10531_b')]
class GH10531B extends GH10531A
{
    /** @var GH10531A */
    #[ORM\ManyToOne(targetEntity: GH10531A::class)]
    #[ORM\JoinColumn(nullable: false, name: 'parent_id')]
    public $parent;
}