From 3bb6184477f1ddf545c1ecd3d461d3b2ab804789 Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Mon, 12 Apr 2010 23:55:41 +0200 Subject: [PATCH 1/4] Updated UPGRADE_TO_2_0 file with recent changes --- UPGRADE_TO_2_0 | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/UPGRADE_TO_2_0 b/UPGRADE_TO_2_0 index 379d364db..edd11e965 100644 --- a/UPGRADE_TO_2_0 +++ b/UPGRADE_TO_2_0 @@ -1,6 +1,62 @@ # Upgrade from 2.0-ALPHA4 to 2.0-BETA1 +## Console migrated to Symfony Console + +The Doctrine Cli has been replaced by Symfony Console Configuration + +Instead of having to specifiy: + + [php] + $cliConfig = new CliConfiguration(); + $cliConfig->setAttribute('em', $entityManager); + +You now have to configure the script like: + + [php] + $helperSet = new \Symfony\Components\Console\Helper\HelperSet(array( + 'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()), + 'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em) + )); + +## Console: No need for Mapping Paths anymore + +In previous versions you had to specify the --from and --from-path options +to show where your mapping paths are from the console. However this information +is already known from the Mapping Driver configuration, so the requirement +for this options were dropped. + +Instead for each console command all the entities are loaded and to +restrict the operation to one or more sub-groups you can use the --filter flag. + +## AnnotationDriver is not a default mapping driver anymore + +In conjunction with the recent changes to Console we realized that the +annotations driver being a default metadata driver lead to lots of glue +code in the console components to detect where entities lie and how to load +them for batch updates like SchemaTool and other commands. However the +annotations driver being a default driver does not really help that much +anyways. + +Therefore we decided to break backwards compability in this issue and drop +the support for Annotations as Default Driver and require our users to +specify the driver explicitly (which allows us to ask for the path to all +entities). + +If you are using the annotations metadata driver as default driver, you +have to add the following lines to your bootstrap code: + + $driverImpl = $config->newDefaultAnnotationDriver(array(__DIR__."/Entities")); + $config->setMetadataDriverImpl($driverImpl); + +You have to specify the path to your entities as either string of a single +path or array of multiple paths +to your entities. This information will be used by all console commands to +access all entities. + +Xml and Yaml Drivers work as before! + + ## New inversedBy attribute It is now *mandatory* that the owning side of a bidirectional association specifies the From b6f9cd0c074b22e567b43ea7f0bddfe9b106d598 Mon Sep 17 00:00:00 2001 From: Guilherme Blanco Date: Mon, 12 Apr 2010 21:54:43 -0300 Subject: [PATCH 2/4] [2.0][DDC-503] Added missing IdGeneratorType. --- lib/Doctrine/ORM/Tools/EntityGenerator.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/Doctrine/ORM/Tools/EntityGenerator.php b/lib/Doctrine/ORM/Tools/EntityGenerator.php index 9dcc27d4b..c8957041a 100644 --- a/lib/Doctrine/ORM/Tools/EntityGenerator.php +++ b/lib/Doctrine/ORM/Tools/EntityGenerator.php @@ -933,6 +933,9 @@ public function () case ClassMetadataInfo::GENERATOR_TYPE_IDENTITY: return 'IDENTITY'; + case ClassMetadataInfo::GENERATOR_TYPE_NONE: + return 'NONE'; + default: throw new \InvalidArgumentException('Invalid provided IdGeneratorType: ' . $type); } From 56a8f5cd5353908b815607a6e089201c95e01e6c Mon Sep 17 00:00:00 2001 From: Guilherme Blanco Date: Tue, 13 Apr 2010 00:29:29 -0300 Subject: [PATCH 3/4] [2.0][DDC-448][DDC-513] Fixed issue with Joined Inheritance Type and One To One Associations. --- lib/Doctrine/ORM/Query/SqlWalker.php | 31 ++++---- .../ORM/Functional/Ticket/DDC448Test.php | 71 +++++++++++++++++ .../ORM/Functional/Ticket/DDC513Test.php | 79 +++++++++++++++++++ 3 files changed, 164 insertions(+), 17 deletions(-) create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC448Test.php create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC513Test.php diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index d16d9ff60..be583c625 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -465,6 +465,11 @@ class SqlWalker implements TreeWalker $fieldName = array_pop($parts); $dqlAlias = $pathExpr->identificationVariable; $class = $this->_queryComponents[$dqlAlias]['metadata']; + + if (isset($class->inheritedAssociationFields[$fieldName])) { + $class = $this->_em->getClassMetadata($class->inheritedAssociationFields[$fieldName]); + } + $assoc = $class->associationMappings[$fieldName]; if ($assoc->isOwningSide) { @@ -472,8 +477,8 @@ class SqlWalker implements TreeWalker if (count($assoc->sourceToTargetKeyColumns) > 1) { throw QueryException::associationPathCompositeKeyNotSupported(); } - $sql .= $this->walkIdentificationVariable($dqlAlias) . '.' - . reset($assoc->targetToSourceKeyColumns); + $sql .= $this->getSqlTableAlias($class->table['name'], $dqlAlias) . '.' + . reset($assoc->targetToSourceKeyColumns); } else { // 2- Inverse side: NOT (YET?) SUPPORTED throw QueryException::associationPathInverseSideNotSupported(); @@ -683,23 +688,15 @@ class SqlWalker implements TreeWalker $joinAssocPathExpr = $join->joinAssociationPathExpression; $joinedDqlAlias = $join->aliasIdentificationVariable; - $targetQComp = $this->_queryComponents[$joinedDqlAlias]; - $targetClass = $targetQComp['metadata']; - $relation = $targetQComp['relation']; - $sourceClass = $this->_queryComponents[$joinAssocPathExpr->identificationVariable]['metadata']; - + $relation = $this->_queryComponents[$joinedDqlAlias]['relation']; + $targetClass = $this->_em->getClassMetadata($relation->targetEntityName); + $sourceClass = $this->_em->getClassMetadata($relation->sourceEntityName); $targetTableName = $targetClass->getQuotedTableName($this->_platform); - $targetTableAlias = $this->getSqlTableAlias($targetClass->getTableName(), $joinedDqlAlias); - $sourceTableAlias = $this->getSqlTableAlias( - $sourceClass->getTableName(), $joinAssocPathExpr->identificationVariable - ); + $targetTableAlias = $this->getSqlTableAlias($targetClass->table['name'], $joinedDqlAlias); + $sourceTableAlias = $this->getSqlTableAlias($sourceClass->table['name'], $joinAssocPathExpr->identificationVariable); // Ensure we got the owning side, since it has all mapping info - if ( ! $relation->isOwningSide) { - $assoc = $targetClass->associationMappings[$relation->mappedBy]; - } else { - $assoc = $relation; - } + $assoc = ( ! $relation->isOwningSide) ? $targetClass->associationMappings[$relation->mappedBy] : $relation; if ($this->_query->getHint(Query::HINT_INTERNAL_ITERATION) == true) { if ($relation->isOneToMany() || $relation->isManyToMany()) { @@ -713,7 +710,7 @@ class SqlWalker implements TreeWalker foreach ($assoc->sourceToTargetKeyColumns as $sourceColumn => $targetColumn) { if ( ! $first) $sql .= ' AND '; else $first = false; - + if ($relation->isOwningSide) { $quotedTargetColumn = $targetClass->getQuotedColumnName($targetClass->fieldNames[$targetColumn], $this->_platform); $sql .= $sourceTableAlias . '.' . $sourceColumn diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC448Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC448Test.php new file mode 100644 index 000000000..91c9e129e --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC448Test.php @@ -0,0 +1,71 @@ +_schemaTool->createSchema(array( + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC448MainTable'), + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC448ConnectedClass'), + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC448SubTable'), + )); + } + + public function testIssue() + { + $q = $this->_em->createQuery("select b from ".__NAMESPACE__."\\DDC448SubTable b where b.connectedClassId = ?1"); + $this->assertEquals('SELECT d0_.id AS id0, d0_.discr AS discr1, d0_.connectedClassId AS connectedClassId2 FROM SubTable s1_ INNER JOIN DDC448MainTable d0_ ON s1_.id = d0_.id WHERE d0_.connectedClassId = ?', $q->getSQL()); + } +} + +/** + * @Entity + * @InheritanceType("JOINED") + * @DiscriminatorColumn(name="discr", type="smallint") + * @DiscriminatorMap({ + * "0" = "DDC448MainTable", + * "1" = "DDC448SubTable" + * }) + */ +class DDC448MainTable +{ + /** + * @Id + * @Column(name="id", type="integer") + * @GeneratedValue(strategy="AUTO") + */ + private $id; + + /** + * @ManyToOne(targetEntity="DDC448ConnectedClass", cascade={"all"}, fetch="EAGER") + * @JoinColumn(name="connectedClassId", referencedColumnName="id", onDelete="CASCADE", onUpdate="CASCADE", nullable=true) + */ + private $connectedClassId; +} + +/** + * @Entity + * @Table(name="connectedClass") + * @HasLifecycleCallbacks + */ +class DDC448ConnectedClass +{ + /** + * @Id + * @Column(name="id", type="integer") + * @GeneratedValue(strategy="AUTO") + */ + protected $id; // connected with DDC448MainTable +} + +/** + * @Entity + * @Table(name="SubTable") + */ +class DDC448SubTable extends DDC448MainTable +{ +} diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC513Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC513Test.php new file mode 100644 index 000000000..b7cee97cf --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC513Test.php @@ -0,0 +1,79 @@ +_schemaTool->createSchema(array( + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC513OfferItem'), + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC513Item'), + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC513Price'), + )); + } + + public function testIssue() + { + $item = new DDC513OfferItem(); + $this->_em->persist($item); + $this->_em->flush(); + + //$q = $this->_em->createQuery("select u from ".__NAMESPACE__."\\DDC513Item u left join u.price p"); + //$this->assertEquals('SELECT d0_.id AS id0, d0_.discr AS discr1, d0_.price AS price2 FROM DDC513Item d0_ LEFT JOIN DDC513OfferItem d1_ ON d0_.id = d1_.id LEFT JOIN DDC513Price d2_ ON d0_.price = d2_.id', $q->getSQL()); + + /* THIS QUERY CAUSE EXCEPTION */ + $q = $this->_em->createQuery("select u from ".__NAMESPACE__."\\DDC513OfferItem u left join u.price p"); + $this->assertEquals('SELECT d0_.id AS id0, d0_.discr AS discr1, d0_.price AS price2 FROM DDC513OfferItem d1_ INNER JOIN DDC513Item d0_ ON d1_.id = d0_.id LEFT JOIN DDC513Price d2_ ON d0_.price = d2_.id', $q->getSQL()); + } +} + +/** + * @Entity + */ +class DDC513OfferItem extends DDC513Item +{ +} + +/** + * @Entity + * @InheritanceType("JOINED") + * @DiscriminatorColumn(name="discr", type="string") + * @DiscriminatorMap({"item" = "DDC513Item", "offerItem" = "DDC513OfferItem"}) + */ +class DDC513Item +{ + /** + * @Id + * @Column(type="integer") + * @GeneratedValue(strategy="AUTO") + */ + public $id; + + /** + * @OneToOne(targetEntity="DDC513Price", cascade={"remove","persist"}) + * @JoinColumn(name="price", referencedColumnName="id") + */ + public $price; +} + +/** + * @Entity + */ +class DDC513Price { + /** + * @Id + * @Column(type="integer") + * @GeneratedValue(strategy="AUTO") + */ + public $id; + + /** @Column(type="string") */ + public $data; +} + + + + From dd2dd80281e2f74b8a0e53dea5bd94a765e32621 Mon Sep 17 00:00:00 2001 From: Guilherme Blanco Date: Tue, 13 Apr 2010 00:40:45 -0300 Subject: [PATCH 4/4] [2.0][DDC-493] Added coverage to DDC-493 and optimized DDC-513 unit tests. Previous commit fixed the issue. --- .../ORM/Functional/Ticket/DDC493Test.php | 69 +++++++++++++++++++ .../ORM/Functional/Ticket/DDC513Test.php | 8 --- 2 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC493Test.php diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC493Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC493Test.php new file mode 100644 index 000000000..5503d033e --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC493Test.php @@ -0,0 +1,69 @@ +_schemaTool->createSchema(array( + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC493Customer'), + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC493Distributor'), + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC493Contact') + )); + } + + public function testIssue() + { + $q = $this->_em->createQuery("select u, u.contact.data from ".__NAMESPACE__."\\DDC493Distributor u"); + $this->assertEquals('SELECT d0_.id AS id0, d1_.data AS data1, d0_.discr AS discr2, d0_.contact AS contact3 FROM DDC493Distributor d2_ INNER JOIN DDC493Customer d0_ ON d2_.id = d0_.id INNER JOIN DDC493Contact d1_ ON d0_.contact = d1_.id', $q->getSQL()); + } +} + +/** + * @Entity + * @InheritanceType("JOINED") + * @DiscriminatorColumn(name="discr", type="string") + * @DiscriminatorMap({"distributor" = "DDC493Distributor", "customer" = "DDC493Customer"}) + */ +class DDC493Customer { + /** + * @Id + * @Column(type="integer") + * @GeneratedValue(strategy="AUTO") + */ + public $id; + /** + * @OneToOne(targetEntity="DDC493Contact", cascade={"remove","persist"}) + * @JoinColumn(name="contact", referencedColumnName="id") + */ + public $contact; + +} + +/** + * @Entity + */ +class DDC493Distributor extends DDC493Customer { +} + +/** + * @Entity + */ +class DDC493Contact +{ + /** + * @Id + * @Column(type="integer") + * @GeneratedValue(strategy="AUTO") + */ + public $id; + /** @Column(type="string") */ + public $data; +} + + + + diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC513Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC513Test.php index b7cee97cf..125f297db 100644 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC513Test.php +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC513Test.php @@ -17,14 +17,6 @@ class DDC513Test extends \Doctrine\Tests\OrmFunctionalTestCase public function testIssue() { - $item = new DDC513OfferItem(); - $this->_em->persist($item); - $this->_em->flush(); - - //$q = $this->_em->createQuery("select u from ".__NAMESPACE__."\\DDC513Item u left join u.price p"); - //$this->assertEquals('SELECT d0_.id AS id0, d0_.discr AS discr1, d0_.price AS price2 FROM DDC513Item d0_ LEFT JOIN DDC513OfferItem d1_ ON d0_.id = d1_.id LEFT JOIN DDC513Price d2_ ON d0_.price = d2_.id', $q->getSQL()); - - /* THIS QUERY CAUSE EXCEPTION */ $q = $this->_em->createQuery("select u from ".__NAMESPACE__."\\DDC513OfferItem u left join u.price p"); $this->assertEquals('SELECT d0_.id AS id0, d0_.discr AS discr1, d0_.price AS price2 FROM DDC513OfferItem d1_ INNER JOIN DDC513Item d0_ ON d1_.id = d0_.id LEFT JOIN DDC513Price d2_ ON d0_.price = d2_.id', $q->getSQL()); }