Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-2524

Wrong commit order with cascade remove and double association

    Details

    • Type: Bug Bug
    • Status: Reopened
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: None
    • Security Level: All
    • Labels:
      None

      Description

      We have stumbled upon a bug in a situation where a class A has the following associations to a class B:

      • A has one B (oneToOne unidirectional)
      • A has many B (oneToMany bidirectional)

      Associations are with cascade remove.

      We will submit a PR soon with a failing test case.

      The failure is a MySQL foreign key violation exception when removing A (removals for B are executed after removals for A).

        Activity

        Hide
        Benjamin Eberlei added a comment -

        Matthieu Napoli is this fixed with your DDC-2775 PR?

        Show
        Benjamin Eberlei added a comment - Matthieu Napoli is this fixed with your DDC-2775 PR?
        Hide
        Matthieu Napoli added a comment -

        Just for clarity (I answered this question in the pull request): no this is not fixed (see https://github.com/doctrine/doctrine2/pull/707#issuecomment-31564035).

        Show
        Matthieu Napoli added a comment - Just for clarity (I answered this question in the pull request): no this is not fixed (see https://github.com/doctrine/doctrine2/pull/707#issuecomment-31564035 ).
        Hide
        Benjamin Morel added a comment -

        Just encountered what I believe to be the same bug, without any kind of circular dependency:

        class A {
            /**
             * @ORM\OneToMany(targetEntity="B", mappedBy="a", indexBy="x", cascade={"all"}, orphanRemoval=true)
             */
            private $b;
        
            ...
        }
        
        class B {
            /*
             * @ORM\ManyToOne(targetEntity="A", inversedBy="b")
             * @ORM\JoinColumn(name="aid", referencedColumnName="id", nullable=false, onDelete="CASCADE")
             */
            private $a;
        
            ...
        }
        

        The following operations in A:

        $this->b->clear();
        $this->b->add(new B());
        

        Result in the following SQL commands:

        INSERT INTO B ...
        DELETE FROM B ...
        

        This is always the wrong commit order, and is doomed to fail when you have unique constraints in the B table.

        Show
        Benjamin Morel added a comment - Just encountered what I believe to be the same bug, without any kind of circular dependency: class A { /** * @ORM\OneToMany(targetEntity= "B" , mappedBy= "a" , indexBy= "x" , cascade={ "all" }, orphanRemoval= true ) */ private $b; ... } class B { /* * @ORM\ManyToOne(targetEntity= "A" , inversedBy= "b" ) * @ORM\JoinColumn(name= "aid" , referencedColumnName= "id" , nullable= false , onDelete= "CASCADE" ) */ private $a; ... } The following operations in A : $ this ->b->clear(); $ this ->b->add( new B()); Result in the following SQL commands: INSERT INTO B ... DELETE FROM B ... This is always the wrong commit order, and is doomed to fail when you have unique constraints in the B table.
        Hide
        Maxim Kapkaev added a comment - - edited

        Another situation without circular dependency:

        class Entity
        {
            /**
             * @ORM\OneToMany(targetEntity="Picture", mappedBy="entity", fetch="EXTRA_LAZY", cascade={"all"}, orphanRemoval=true)
             * @ORM\OrderBy({"position" = "ASC"})
             */
            protected $pictures = array();
        } 
        
        class Pictures {
            /**
             * @ORM\Column(type="string", length=1024, unique = true)
             */
            protected $file;
        }
        
        $hotel->setPictures($picturesArray);
        $em->flush();
        $hotel->getPictures()->clear();
        $hotel->setPictures($somePictureUpdatedArray);
        $em->flush();
        Unique violation: 7 ERROR:  duplicate key value violates unique constraint "uniq_8f7c2fc08c9f3610"
        

        Why we can't invoke entity deletions method (executeDeletions, UnitOfWork#commit) before executeInserts?
        https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/UnitOfWork.php#L385-L388
        There is another way?

        Show
        Maxim Kapkaev added a comment - - edited Another situation without circular dependency: class Entity { /** * @ORM\OneToMany(targetEntity= "Picture" , mappedBy= "entity" , fetch= "EXTRA_LAZY" , cascade={ "all" }, orphanRemoval= true ) * @ORM\OrderBy({ "position" = "ASC" }) */ protected $pictures = array(); } class Pictures { /** * @ORM\Column(type= "string" , length=1024, unique = true ) */ protected $file; } $hotel->setPictures($picturesArray); $em->flush(); $hotel->getPictures()->clear(); $hotel->setPictures($somePictureUpdatedArray); $em->flush(); Unique violation: 7 ERROR: duplicate key value violates unique constraint "uniq_8f7c2fc08c9f3610" Why we can't invoke entity deletions method (executeDeletions, UnitOfWork#commit) before executeInserts? https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/UnitOfWork.php#L385-L388 There is another way?
        Hide
        Doctrine Bot added a comment -

        A related Github Pull-Request [GH-707] was labeled:
        https://github.com/doctrine/doctrine2/pull/707

        Show
        Doctrine Bot added a comment - A related Github Pull-Request [GH-707] was labeled: https://github.com/doctrine/doctrine2/pull/707

          People

          • Assignee:
            Benjamin Eberlei
            Reporter:
            Matthieu Napoli
          • Votes:
            2 Vote for this issue
            Watchers:
            7 Start watching this issue

            Dates

            • Created:
              Updated: