Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-2995

Joined Inheritance Mapping and Filters

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 2.4.2
    • Fix Version/s: None
    • Component/s: ORM
    • Labels:

      Description

      Is there any reason why Inheritance Mapping IS LEFT JOINED not INNER JOINED?

      When there is a filter and it's left joined it happens a record might not have parent table record. For example

      Class B extends Class A.
      Class A have column is_active | and filter activated with is_active = 1 condition.

      Final query: LEFT JOIN parent_table s1_ ON p2_.id = s1_.id AND (s1_.is_active = '1')

      Record 1 have is_active = false, so result set looks like this:

      table_b | table_a
      id | id is_active discriminatorColumn
      1 | null null null

      and occurs exception: The discriminator column ... is missing for ....

        Activity

        Hide
        Marco Pivetta added a comment -

        JTI MUST be left-joined, since not every subclass of the root of the inheritance causes inserts on all of the inheritance tables.

        What is the DQL query that is causing the problem?

        Show
        Marco Pivetta added a comment - JTI MUST be left-joined, since not every subclass of the root of the inheritance causes inserts on all of the inheritance tables. What is the DQL query that is causing the problem?
        Hide
        Bojidar Hristov added a comment - - edited

        Hello Marco, I don't query from parent table, but from child. No sense to be LEFT JOINED.

        DQL is something like that:

        SELECT class1, class2 FROM Class1 class1 JOIN class1.class2 class2;

        (Class2 extends Class3)
        Class3 have is_active column.

        And following filter:

        public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias) {
        if (!$targetEntity->reflClass->implementsInterface('ActivateableInterface'))

        { return ""; }

        return $targetTableAlias . '.is_active = ' . $this->getParameter('isActive');
        }

        Filter condition is added in LEFT JOINED parent_table. Full example SQL:
        SELECT ....
        FROM class1 c1
        INNER JOIN class2 c2 ON c1.c2_id = c2.id
        LEFT JOIN table3 c3 ON c2.id = c3.id AND (c3.is_active = '1')

        Show
        Bojidar Hristov added a comment - - edited Hello Marco, I don't query from parent table, but from child. No sense to be LEFT JOINED. DQL is something like that: SELECT class1, class2 FROM Class1 class1 JOIN class1.class2 class2; (Class2 extends Class3) Class3 have is_active column. And following filter: public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias) { if (!$targetEntity->reflClass->implementsInterface('ActivateableInterface')) { return ""; } return $targetTableAlias . '.is_active = ' . $this->getParameter('isActive'); } Filter condition is added in LEFT JOINED parent_table. Full example SQL: SELECT .... FROM class1 c1 INNER JOIN class2 c2 ON c1.c2_id = c2.id LEFT JOIN table3 c3 ON c2.id = c3.id AND (c3.is_active = '1')
        Hide
        Marco Pivetta added a comment -

        There are two possible solutions here:

        • verify if the selected entity is a leaf of a JTI, and use INNER JOIN on that if possible (probably not optimal, since the selection may be part of a LEFT JOIN itself)
        • add filtering on the discriminator column

        Bojidar Hristov can you provide a failing test case to make it easier to work on this?

        Show
        Marco Pivetta added a comment - There are two possible solutions here: verify if the selected entity is a leaf of a JTI, and use INNER JOIN on that if possible (probably not optimal, since the selection may be part of a LEFT JOIN itself) add filtering on the discriminator column Bojidar Hristov can you provide a failing test case to make it easier to work on this?
        Hide
        Bojidar Hristov added a comment -

        Yes. Here is it sample failing test.

        http://pastebin.com/xi8uUNX5 - Parent Class
        http://pastebin.com/XRZLbyGX - Child Class
        http://pastebin.com/HuPFb98u - Assoc Class
        http://pastebin.com/hGqRk74e - TestCase

        Here it should found 0 records because ot JOIN and is_active = true filter.

        Show
        Bojidar Hristov added a comment - Yes. Here is it sample failing test. http://pastebin.com/xi8uUNX5 - Parent Class http://pastebin.com/XRZLbyGX - Child Class http://pastebin.com/HuPFb98u - Assoc Class http://pastebin.com/hGqRk74e - TestCase Here it should found 0 records because ot JOIN and is_active = true filter.
        Hide
        Benjamin Eberlei added a comment -

        Since filters are only available on the root, i guess inner join is really necessary here.

        Show
        Benjamin Eberlei added a comment - Since filters are only available on the root, i guess inner join is really necessary here.
        Hide
        Bojidar Hristov added a comment -

        Do you need something more? The bug is status Feedback?

        Show
        Bojidar Hristov added a comment - Do you need something more? The bug is status Feedback?

          People

          • Assignee:
            Marco Pivetta
            Reporter:
            Bojidar Hristov
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated: