Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-671

Table aliases wrongly computed with YAML + mappedsuperclasses and joins

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0-BETA2
    • Fix Version/s: 2.0-RC1
    • Component/s: Mapping Drivers
    • Security Level: All
    • Labels:
      None

      Description

      Affects only YAML. (Maybe also XML? But works with Annotations!)

      If there's a relation specified in a mappedSuperclass (manyToOne, towards entity B) and two Entities A and B using this mappedSuperclass, an error occurs within generating the SQL-Query when using a query a la SELECT * FROM A JOIN B ON A.relation = B.id:

      This is due to no table name being specified for the mappedSuperclass. (But this tableName is accessed in SqlWalker.php ll. 718. Be aware that there's the mappedSuperclass in use, NOT the class B!)

      I'm not quite sure how this should be handled. At least, not specifying the relation in the mappedSuperclass but moving it to each of the yml-files of A and B solves this problem. (But unneccessarily complicates things?)

      I will push a test case to my repo.

        Issue Links

          Activity

          Hide
          Christian Heinrich added a comment -

          A testcase is now available in my repo: http://github.com/Shurakai/doctrine2/tree/DDC-671

          Show
          Christian Heinrich added a comment - A testcase is now available in my repo: http://github.com/Shurakai/doctrine2/tree/DDC-671
          Hide
          Jonathan H. Wage added a comment -

          According to the docs: http://www.doctrine-project.org/projects/orm/2.0/docs/reference/inheritance-mapping/en#inheritance-mapping

          "A mapped superclass cannot be an entity, it is not queryable and persistent relationships defined by a mapped superclass must be unidirectional. For further support of inheritance, the single or joined table inheritance features have to be used."

          Show
          Jonathan H. Wage added a comment - According to the docs: http://www.doctrine-project.org/projects/orm/2.0/docs/reference/inheritance-mapping/en#inheritance-mapping "A mapped superclass cannot be an entity, it is not queryable and persistent relationships defined by a mapped superclass must be unidirectional. For further support of inheritance, the single or joined table inheritance features have to be used."
          Hide
          Benjamin Eberlei added a comment -

          I agree with Jon, this is not an issue.

          I dont understand at all what this has to do with XML, YAML or Annotations?

          Show
          Benjamin Eberlei added a comment - I agree with Jon, this is not an issue. I dont understand at all what this has to do with XML, YAML or Annotations?
          Hide
          Christian Heinrich added a comment -

          Jonathan: Thanks for your comment, but that does not seem to fit the problem. As you can see within my testcase, the mapped superclass defines a relationship (manyToOne) which is unidirectional.

          Benjamin: The problem is, that this specific feature works with annotations, but not with YAML.

          Show
          Christian Heinrich added a comment - Jonathan: Thanks for your comment, but that does not seem to fit the problem. As you can see within my testcase, the mapped superclass defines a relationship (manyToOne) which is unidirectional. Benjamin: The problem is, that this specific feature works with annotations, but not with YAML.
          Hide
          Jonathan H. Wage added a comment -

          When I look at your test I see you have association on the mapper super class side as well as on Directory side. That looks bidirectional, no?

          Show
          Jonathan H. Wage added a comment - When I look at your test I see you have association on the mapper super class side as well as on Directory side. That looks bidirectional, no?
          Hide
          Benjamin Eberlei added a comment -

          @jwage he is specifiying a directory or page on the OneToMany side, so this looks ok.

          @Christian: Why do you specified a table attribute on the mapped superclass? That doesnt make sense. The mapping looks correct, can you please show the error message? ADditionally can you link the correct line in SQL Walker again? The lines moved, so i cant verify what 718 is anymore, it changed.

          Show
          Benjamin Eberlei added a comment - @jwage he is specifiying a directory or page on the OneToMany side, so this looks ok. @Christian: Why do you specified a table attribute on the mapped superclass? That doesnt make sense. The mapping looks correct, can you please show the error message? ADditionally can you link the correct line in SQL Walker again? The lines moved, so i cant verify what 718 is anymore, it changed.
          Hide
          Christian Heinrich added a comment - - edited

          Benjamin: I removed the table attribute on the mapped superclass. I don't know why it was in there.

          Some more information:

          The parentDirectory is currently in the mappedSuperclass. However, if you try to join it this way, the source entity used in SqlWalker::walkJoinVariableDeclarationwill look like this:

            ["sourceEntity"]=>
            string(46) "Doctrine\Tests\ORM\Mapping\AbstractContentItem"
          

          Which is actually the mappingSuperclass.

          That said, Doctrine will try to get an alias for AbstractContentItem (l. 730 SqlWalker), which does not exist at that point. Thus, it will create a new one (in my case: a2).

          You can see the result in the query below. Note that a2 is only used, but never declared.

          SELECT c0_.id AS id0, c0_.extension AS extension1, c0_.parent_directory_id AS parent_directory_id2 FROM core_content_pages c0_ INNER JOIN core_content_directories c1_ ON a2_.parent_directory_id = c1_.id WHERE (c1_.url = ?) AND (c0_.extension = ?)

          It might be that l. 730 currently passes a wrong argument (mappedSuperclass instead of entity-in-use) or that there is some error in the yaml driver? As I'm unfortunately not too familiar with this process, I need your oppinions to fix this issue. It would be interesting to know where the

          $this->_queryComponents[$joinedDqlAlias]['relation']

          array is getting filled.

          Show
          Christian Heinrich added a comment - - edited Benjamin: I removed the table attribute on the mapped superclass. I don't know why it was in there. Some more information: The parentDirectory is currently in the mappedSuperclass. However, if you try to join it this way, the source entity used in SqlWalker::walkJoinVariableDeclarationwill look like this: [ "sourceEntity" ]=> string(46) "Doctrine\Tests\ORM\Mapping\AbstractContentItem" Which is actually the mappingSuperclass. That said, Doctrine will try to get an alias for AbstractContentItem (l. 730 SqlWalker), which does not exist at that point. Thus, it will create a new one (in my case: a2). You can see the result in the query below. Note that a2 is only used, but never declared. SELECT c0_.id AS id0, c0_.extension AS extension1, c0_.parent_directory_id AS parent_directory_id2 FROM core_content_pages c0_ INNER JOIN core_content_directories c1_ ON a2_.parent_directory_id = c1_.id WHERE (c1_.url = ?) AND (c0_.extension = ?) It might be that l. 730 currently passes a wrong argument (mappedSuperclass instead of entity-in-use) or that there is some error in the yaml driver? As I'm unfortunately not too familiar with this process, I need your oppinions to fix this issue. It would be interesting to know where the $ this ->_queryComponents[$joinedDqlAlias]['relation'] array is getting filled.
          Hide
          Benjamin Eberlei added a comment -

          This is actually wrong for Annotations and XML Driver also, the problem is shown by this assertions and test-failures in combination with your test:

                  $classPage = $em->getClassMetadata('Doctrine\Tests\ORM\Mapping\Page');
                  $this->assertEquals('Doctrine\Tests\ORM\Mapping\Directory', $classPage->associationMappings['parentDirectory']['sourceEntity']);
                  $classDirectory = $em->getClassMetadata('Doctrine\Tests\ORM\Mapping\Page');
                  $this->assertEquals('Doctrine\Tests\ORM\Mapping\Directory', $classDirectory->associationMappings['parentDirectory']['sourceEntity']);
          

          Failure.

          1) Doctrine\Tests\ORM\Mapping\YamlMappingDriverTest::testJoinTablesWithMappedSuperclassForYamlDriver
          Failed asserting that two strings are equal.
          --- Expected
          +++ Actual
          @@ @@
          -Doctrine\Tests\ORM\Mapping\Directory
          +Doctrine\Tests\ORM\Mapping\AbstractContentItem
          
          /home/benny/code/php/wsnetbeans/doctrine2/tests/Doctrine/Tests/ORM/Mapping/YamlMappingDriverTest.php:33
          
          2) Doctrine\Tests\ORM\Mapping\AnnotationDriverTest::testJoinTablesWithMappedSuperclassForAnnotationDriver
          Failed asserting that two strings are equal.
          --- Expected
          +++ Actual
          @@ @@
          -Doctrine\Tests\ORM\Mapping\Directory
          +Doctrine\Tests\ORM\Mapping\AbstractContentItem
          
          Show
          Benjamin Eberlei added a comment - This is actually wrong for Annotations and XML Driver also, the problem is shown by this assertions and test-failures in combination with your test: $classPage = $em->getClassMetadata('Doctrine\Tests\ORM\Mapping\Page'); $ this ->assertEquals('Doctrine\Tests\ORM\Mapping\Directory', $classPage->associationMappings['parentDirectory']['sourceEntity']); $classDirectory = $em->getClassMetadata('Doctrine\Tests\ORM\Mapping\Page'); $ this ->assertEquals('Doctrine\Tests\ORM\Mapping\Directory', $classDirectory->associationMappings['parentDirectory']['sourceEntity']); Failure. 1) Doctrine\Tests\ORM\Mapping\YamlMappingDriverTest::testJoinTablesWithMappedSuperclassForYamlDriver Failed asserting that two strings are equal. --- Expected +++ Actual @@ @@ -Doctrine\Tests\ORM\Mapping\Directory +Doctrine\Tests\ORM\Mapping\AbstractContentItem /home/benny/code/php/wsnetbeans/doctrine2/tests/Doctrine/Tests/ORM/Mapping/YamlMappingDriverTest.php:33 2) Doctrine\Tests\ORM\Mapping\AnnotationDriverTest::testJoinTablesWithMappedSuperclassForAnnotationDriver Failed asserting that two strings are equal. --- Expected +++ Actual @@ @@ -Doctrine\Tests\ORM\Mapping\Directory +Doctrine\Tests\ORM\Mapping\AbstractContentItem
          Hide
          Benjamin Eberlei added a comment -

          This works with annotations because the annotation reader also reads properties from parent classes.

          For YAML and XML this did not work and required a little change in the ClassMetadataFactory method that copied over inherited metadata.

          Show
          Benjamin Eberlei added a comment - This works with annotations because the annotation reader also reads properties from parent classes. For YAML and XML this did not work and required a little change in the ClassMetadataFactory method that copied over inherited metadata.

            People

            • Assignee:
              Benjamin Eberlei
              Reporter:
              Christian Heinrich
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: