Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-130

Cascading and @ManyToMany associations is broken

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.0-BETA3
    • Component/s: None
    • Security Level: All
    • Labels:
      None

      Description

      I have two Entities: Users and Alerts. They are associated with @ManyToMany, the assiciation table should be "user_alert".

      Entities:
      http://pastebin.com/m7bca724a

      Sample code:
      http://pastebin.com/m4e530f42

      The "remove" command in the sample code deletes the user entry and alert entry, but not the user_alert entry (which was automatically created though). This leaves an orphan entry (or the DBMS will complain because of FK constraints).

      INSERT INTO users (name) VALUES (?)
      array(1) {
        [1]=>
        string(3) "Bob"
      }
      INSERT INTO alert (name) VALUES (?)
      array(1) {
        [1]=>
        string(9) "Testalert"
      }
      INSERT INTO user_alert (userId, alertId) VALUES (?, ?)
      array(2) {
        [0]=>
        int(1)
        [1]=>
        int(1)
      }
      DELETE FROM users WHERE id = ?
      array(1) {
        [0]=>
        int(1)
      }
      DELETE FROM alert WHERE id = ?
      array(1) {
        [0]=>
        int(1)
      }
      

      The user_alert table should be automatically updated (on creation and removal)...

        Issue Links

          Activity

          Hide
          Benjamin Eberlei added a comment -

          I pushed my proposed changes to a feature branch: http://github.com/doctrine/doctrine2/tree/DDC-130

          There are definatly refactorings that need to be done, however in that state its currently doing its job very well.

          Show
          Benjamin Eberlei added a comment - I pushed my proposed changes to a feature branch: http://github.com/doctrine/doctrine2/tree/DDC-130 There are definatly refactorings that need to be done, however in that state its currently doing its job very well.
          Hide
          Benjamin Eberlei added a comment -

          What about DQL DELETE?

          DELETE FROM Boo WHERE bar
          

          For each join table:

          DELETE FROM join_foo WHERE (SELECT id FROM foo WHERE bar)
          

          Can this be done determinstically?

          Show
          Benjamin Eberlei added a comment - What about DQL DELETE? DELETE FROM Boo WHERE bar For each join table: DELETE FROM join_foo WHERE (SELECT id FROM foo WHERE bar) Can this be done determinstically?
          Hide
          Benjamin Eberlei added a comment -

          The DQL stuff is just way to much to add. Foreign Key constraints should fail in these cases imho

          Show
          Benjamin Eberlei added a comment - The DQL stuff is just way to much to add. Foreign Key constraints should fail in these cases imho
          Hide
          Roman S. Borschel added a comment -

          I think we have to do this on bulk deletion then, too.

          Examples from EclipseLink:

          em.createQuery("delete from User2 u where u.id=1").executeUpdate();
          =>
          DELETE FROM USER2_GROUP2 WHERE EXISTS(SELECT ID FROM USER2 WHERE (ID = ?) AND ID = USER2_GROUP2.User2_ID)
          DELETE FROM USER2 WHERE (ID = ?)
          
          em.createQuery("delete from User2 u").executeUpdate();
          =>
          DELETE FROM USER2_GROUP2
          DELETE FROM USER2
          
          Show
          Roman S. Borschel added a comment - I think we have to do this on bulk deletion then, too. Examples from EclipseLink: em.createQuery( "delete from User2 u where u.id=1" ).executeUpdate(); => DELETE FROM USER2_GROUP2 WHERE EXISTS(SELECT ID FROM USER2 WHERE (ID = ?) AND ID = USER2_GROUP2.User2_ID) DELETE FROM USER2 WHERE (ID = ?) em.createQuery( "delete from User2 u" ).executeUpdate(); => DELETE FROM USER2_GROUP2 DELETE FROM USER2
          Hide
          Benjamin Eberlei added a comment -

          Fixed in master using the following semantics:

          • If a many-to-many join table is to be found not using onDelete="CASCADE" execute this manually
          • In self-referential relationships delete both possible pairs.
          • Use Database onDelete="CASCADE" if present on both foreign keys of the join table.

          Tested against normal entities, self-referential, CTI and STI, from the owning and the inverse side.

          Show
          Benjamin Eberlei added a comment - Fixed in master using the following semantics: If a many-to-many join table is to be found not using onDelete="CASCADE" execute this manually In self-referential relationships delete both possible pairs. Use Database onDelete="CASCADE" if present on both foreign keys of the join table. Tested against normal entities, self-referential, CTI and STI, from the owning and the inverse side.

            People

            • Assignee:
              Benjamin Eberlei
              Reporter:
              Nico Kaiser
            • Votes:
              1 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: