diff --git a/lib/Doctrine/DBAL/Configuration.php b/lib/Doctrine/DBAL/Configuration.php index 1ef539b90..76ce1c4f0 100644 --- a/lib/Doctrine/DBAL/Configuration.php +++ b/lib/Doctrine/DBAL/Configuration.php @@ -24,10 +24,7 @@ use Doctrine\DBAL\Logging\SQLLogger; /** * Configuration container for the Doctrine DBAL. * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org * @since 2.0 - * @version $Revision: 3938 $ * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel diff --git a/lib/Doctrine/ORM/Persisters/SingleTablePersister.php b/lib/Doctrine/ORM/Persisters/SingleTablePersister.php index a0adbea67..5f5a8a4d7 100644 --- a/lib/Doctrine/ORM/Persisters/SingleTablePersister.php +++ b/lib/Doctrine/ORM/Persisters/SingleTablePersister.php @@ -26,7 +26,6 @@ use Doctrine\ORM\Mapping\ClassMetadata; * SINGLE_TABLE strategy. * * @author Roman Borschel - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @since 2.0 * @link http://martinfowler.com/eaaCatalog/singleTableInheritance.html */ diff --git a/lib/Doctrine/ORM/Query/AST/PathExpression.php b/lib/Doctrine/ORM/Query/AST/PathExpression.php index 4f8d0e277..ed856f679 100644 --- a/lib/Doctrine/ORM/Query/AST/PathExpression.php +++ b/lib/Doctrine/ORM/Query/AST/PathExpression.php @@ -1,7 +1,5 @@ * @author Jonathan Wage * @author Roman Borschel diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php index 5d9766262..645cb5ae0 100644 --- a/lib/Doctrine/ORM/Query/Parser.php +++ b/lib/Doctrine/ORM/Query/Parser.php @@ -1,7 +1,5 @@ * @author Jonathan Wage * @author Roman Borschel diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index f624798fd..0b71b82bf 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -1,7 +1,5 @@ getSqlTableAlias($class->table['name'], $dqlAlias); + $baseTableAlias = $this->getSQLTableAlias($class->table['name'], $dqlAlias); // INNER JOIN parent class tables foreach ($class->parentClasses as $parentClassName) { $parentClass = $this->_em->getClassMetadata($parentClassName); - $tableAlias = $this->getSqlTableAlias($parentClass->table['name'], $dqlAlias); - $sql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform) + $tableAlias = $this->getSQLTableAlias($parentClass->table['name'], $dqlAlias); + // If this is a joined association we must use left joins to preserve the correct result. + $sql .= isset($this->_queryComponents[$dqlAlias]['relation']) ? ' LEFT ' : ' INNER '; + $sql .= 'JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON '; $first = true; - foreach ($class->identifier as $idField) { if ($first) $first = false; else $sql .= ' AND '; @@ -260,14 +259,13 @@ class SqlWalker implements TreeWalker } } - // LEFT JOIN subclass tables, if partial objects disallowed + // LEFT JOIN subclass tables, if partial objects disallowed. if ( ! $this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) { foreach ($class->subClasses as $subClassName) { $subClass = $this->_em->getClassMetadata($subClassName); - $tableAlias = $this->getSqlTableAlias($subClass->table['name'], $dqlAlias); + $tableAlias = $this->getSQLTableAlias($subClass->table['name'], $dqlAlias); $sql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON '; - $first = true; foreach ($class->identifier as $idField) { if ($first) $first = false; else $sql .= ' AND '; diff --git a/tests/Doctrine/Tests/Models/Company/CompanyEvent.php b/tests/Doctrine/Tests/Models/Company/CompanyEvent.php index f0bb730cf..2db4986ae 100644 --- a/tests/Doctrine/Tests/Models/Company/CompanyEvent.php +++ b/tests/Doctrine/Tests/Models/Company/CompanyEvent.php @@ -6,9 +6,9 @@ namespace Doctrine\Tests\Models\Company; * @Entity @Table(name="company_events") * @InheritanceType("JOINED") * @DiscriminatorColumn(name="event_type", type="string") - * @DiscriminatorMap({"auction" = "CompanyAuction", "raffle" = "CompanyRaffle"}) + * @DiscriminatorMap({"auction"="CompanyAuction", "raffle"="CompanyRaffle"}) */ -class CompanyEvent { +abstract class CompanyEvent { /** * @Id @Column(type="integer") * @GeneratedValue diff --git a/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php b/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php index 206a567b6..ea1ad15d8 100644 --- a/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php @@ -294,5 +294,4 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase ->getResult()) > 0); } - } diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC512Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC512Test.php new file mode 100644 index 000000000..72b11aaab --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC512Test.php @@ -0,0 +1,94 @@ +_schemaTool->createSchema(array( + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC512Customer'), + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC512OfferItem'), + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC512Item'), + )); + } + + public function testIssue() + { + $customer1 = new DDC512Customer(); + $item = new DDC512OfferItem(); + $customer1->item = $item; + $this->_em->persist($customer1); + + $customer2 = new DDC512Customer(); + $this->_em->persist($customer2); + + $this->_em->flush(); + $this->_em->clear(); + + $q = $this->_em->createQuery("select u,i from ".__NAMESPACE__."\\DDC512Customer u left join u.item i"); + $result = $q->getResult(); + + $this->assertEquals(2, count($result)); + $this->assertTrue($result[0] instanceof DDC512Customer); + $this->assertTrue($result[1] instanceof DDC512Customer); + if ($result[0]->id == $customer1->id) { + $this->assertTrue($result[0]->item instanceof DDC512OfferItem); + $this->assertEquals($item->id, $result[0]->item->id); + $this->assertNull($result[1]->item); + } else { + $this->assertTrue($result[1]->item instanceof DDC512OfferItem); + $this->assertNull($result[0]->item); + } + } +} + +/** + * @Entity + */ +class DDC512Customer { + /** + * @Id + * @Column(type="integer") + * @GeneratedValue(strategy="AUTO") + */ + public $id; + + /** + * NOTE that we can currently not name the join column the same as the field + * (item = item), this currently confuses Doctrine. + * + * @OneToOne(targetEntity="DDC512OfferItem", cascade={"remove","persist"}) + * @JoinColumn(name="item_id", referencedColumnName="id") + */ + public $item; +} + +/** + * @Entity + */ +class DDC512OfferItem extends DDC512Item +{ +} + +/** + * @Entity + * @InheritanceType("JOINED") + * @DiscriminatorColumn(name="discr", type="string") + * @DiscriminatorMap({"item" = "DDC512Item", "offerItem" = "DDC512OfferItem"}) + */ +class DDC512Item +{ + /** + * @Id + * @Column(type="integer") + * @GeneratedValue(strategy="AUTO") + */ + public $id; +} + + + +