From 076663fe3ae09667e1b7b0edf76ad3def9f367b9 Mon Sep 17 00:00:00 2001 From: "Fabio B. Silva" Date: Wed, 27 Jun 2012 00:14:29 -0300 Subject: [PATCH] fix DDC-1885 in persisters --- .../ORM/Persisters/BasicEntityPersister.php | 63 +++++++------ .../ORM/Persisters/ManyToManyPersister.php | 10 +- tests/Doctrine/Tests/Models/Quote/User.php | 2 +- .../ORM/Functional/Ticket/DDC1885Test.php | 92 +++++++++++++++++++ 4 files changed, 136 insertions(+), 31 deletions(-) create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1885Test.php diff --git a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php index 7ccc7e663..eeeb89dd8 100644 --- a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php +++ b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php @@ -846,7 +846,11 @@ class BasicEntityPersister if ($assoc['isOwningSide']) { $quotedJoinTable = $this->quoteStrategy->getJoinTableName($assoc, $sourceClass, $this->_platform); - foreach ($assoc['relationToSourceKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) { + foreach ($assoc['joinTable']['joinColumns'] as $joinColumn) { + $relationKeyColumn = $joinColumn['name']; + $sourceKeyColumn = $joinColumn['referencedColumnName']; + $quotedKeyColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $sourceClass, $this->_platform); + if ($sourceClass->containsForeignIdentifier) { $field = $sourceClass->getFieldForColumn($sourceKeyColumn); $value = $sourceClass->reflFields[$field]->getValue($sourceEntity); @@ -856,9 +860,9 @@ class BasicEntityPersister $value = $value[$this->_em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]]; } - $criteria[$quotedJoinTable . "." . $relationKeyColumn] = $value; + $criteria[$quotedJoinTable . "." . $quotedKeyColumn] = $value; } else if (isset($sourceClass->fieldNames[$sourceKeyColumn])) { - $criteria[$quotedJoinTable . "." . $relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity); + $criteria[$quotedJoinTable . "." . $quotedKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity); } else { throw MappingException::joinColumnMustPointToMappedField( $sourceClass->name, $sourceKeyColumn @@ -870,7 +874,11 @@ class BasicEntityPersister $quotedJoinTable = $this->quoteStrategy->getJoinTableName($owningAssoc, $sourceClass, $this->_platform); // TRICKY: since the association is inverted source and target are flipped - foreach ($owningAssoc['relationToTargetKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) { + foreach ($owningAssoc['joinTable']['inverseJoinColumns'] as $joinColumn) { + $relationKeyColumn = $joinColumn['name']; + $sourceKeyColumn = $joinColumn['referencedColumnName']; + $quotedKeyColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $sourceClass, $this->_platform); + if ($sourceClass->containsForeignIdentifier) { $field = $sourceClass->getFieldForColumn($sourceKeyColumn); $value = $sourceClass->reflFields[$field]->getValue($sourceEntity); @@ -880,9 +888,9 @@ class BasicEntityPersister $value = $value[$this->_em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]]; } - $criteria[$quotedJoinTable . "." . $relationKeyColumn] = $value; + $criteria[$quotedJoinTable . "." . $quotedKeyColumn] = $value; } else if (isset($sourceClass->fieldNames[$sourceKeyColumn])) { - $criteria[$quotedJoinTable . "." . $relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity); + $criteria[$quotedJoinTable . "." . $quotedKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity); } else { throw MappingException::joinColumnMustPointToMappedField( $sourceClass->name, $sourceKeyColumn @@ -1132,31 +1140,28 @@ class BasicEntityPersister */ protected function _getSelectManyToManyJoinSQL(array $manyToMany) { - if ($manyToMany['isOwningSide']) { - $owningAssoc = $manyToMany; - $joinClauses = $manyToMany['relationToTargetKeyColumns']; - } else { - $owningAssoc = $this->_em->getClassMetadata($manyToMany['targetEntity'])->associationMappings[$manyToMany['mappedBy']]; - $joinClauses = $owningAssoc['relationToSourceKeyColumns']; + + $conditions = array(); + $sourceTableAlias = $this->_getSQLTableAlias($this->_class->name); + + $association = ($manyToMany['isOwningSide']) + ? $manyToMany + : $this->_em->getClassMetadata($manyToMany['targetEntity']) + ->associationMappings[$manyToMany['mappedBy']]; + + $relationColumns = ($manyToMany['isOwningSide']) + ? $association['joinTable']['inverseJoinColumns'] + : $association['joinTable']['joinColumns']; + + $joinTableName = $this->quoteStrategy->getJoinTableName($association, $this->_class, $this->_platform); + foreach ($relationColumns as $joinColumn) { + $quotedSourceColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->_class, $this->_platform); + $quotedTargetColumn = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $this->_class, $this->_platform); + + $conditions[] = $sourceTableAlias . '.' . $quotedTargetColumn . ' = ' . $joinTableName . '.' . $quotedSourceColumn; } - $joinTableName = $this->quoteStrategy->getJoinTableName($owningAssoc, $this->_class, $this->_platform); - $joinSql = ''; - - foreach ($joinClauses as $joinTableColumn => $sourceColumn) { - if ($joinSql != '') $joinSql .= ' AND '; - - if ($this->_class->containsForeignIdentifier && ! isset($this->_class->fieldNames[$sourceColumn])) { - $quotedColumn = $sourceColumn; // join columns cannot be quoted - } else { - $quotedColumn = $this->quoteStrategy->getColumnName($this->_class->fieldNames[$sourceColumn], $this->_class, $this->_platform); - } - - $joinSql .= $this->_getSQLTableAlias($this->_class->name) . '.' . $quotedColumn . ' = ' - . $joinTableName . '.' . $joinTableColumn; - } - - return ' INNER JOIN ' . $joinTableName . ' ON ' . $joinSql; + return ' INNER JOIN ' . $joinTableName . ' ON ' . implode(' AND ', $conditions); } /** diff --git a/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php b/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php index 153482693..7e017f530 100644 --- a/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php +++ b/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php @@ -76,11 +76,19 @@ class ManyToManyPersister extends AbstractCollectionPersister */ protected function _getInsertRowSQL(PersistentCollection $coll) { + $columns = array(); $mapping = $coll->getMapping(); - $columns = $mapping['joinTableColumns']; $class = $this->_em->getClassMetadata(get_class($coll->getOwner())); $joinTable = $this->quoteStrategy->getJoinTableName($mapping, $class, $this->platform); + foreach ($mapping['joinTable']['joinColumns'] as $joinColumn) { + $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); + } + + foreach ($mapping['joinTable']['inverseJoinColumns'] as $joinColumn) { + $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); + } + return 'INSERT INTO ' . $joinTable . ' (' . implode(', ', $columns) . ')' . ' VALUES (' . implode(', ', array_fill(0, count($columns), '?')) . ')'; } diff --git a/tests/Doctrine/Tests/Models/Quote/User.php b/tests/Doctrine/Tests/Models/Quote/User.php index 72715d783..fe700c09c 100644 --- a/tests/Doctrine/Tests/Models/Quote/User.php +++ b/tests/Doctrine/Tests/Models/Quote/User.php @@ -34,7 +34,7 @@ class User public $address; /** - * @ManyToMany(targetEntity="Group", inversedBy="users", cascade={"persist"}) + * @ManyToMany(targetEntity="Group", inversedBy="users", cascade={"all"}) * @JoinTable(name="`quote-users-groups`", * joinColumns={ * @JoinColumn( diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1885Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1885Test.php new file mode 100644 index 000000000..8818e2776 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1885Test.php @@ -0,0 +1,92 @@ +_schemaTool->createSchema(array( + $this->_em->getClassMetadata('Doctrine\Tests\Models\Quote\User'), + $this->_em->getClassMetadata('Doctrine\Tests\Models\Quote\Group'), + $this->_em->getClassMetadata('Doctrine\Tests\Models\Quote\Address'), + )); + } catch(\Exception $e) { + } + } + + public function testCreateRetreaveUpdateDelete() + { + + $g1 = new Group('G 1'); + $g2 = new Group('G 2'); + $user = new User(); + + $user->name = "FabioBatSilva"; + $user->email = "fabio.bat.silva@gmail.com"; + $user->groups[] = $g1; + $user->groups[] = $g2; + + // Create + $this->_em->persist($user); + $this->_em->flush(); + $this->_em->clear(); + + $u1Id = $user->id; + $g1Id = $g1->id; + $g2Id = $g2->id; + + // Retreave + $user = $this->_em->find('Doctrine\Tests\Models\Quote\User', $u1Id); + + $this->assertInstanceOf('Doctrine\Tests\Models\Quote\User', $user); + $this->assertEquals('FabioBatSilva', $user->name); + $this->assertEquals($u1Id, $user->id); + + $this->assertCount(2, $user->groups); + + $g1 = $user->getGroups()->get(0); + $g2 = $user->getGroups()->get(1); + + $this->assertInstanceOf('Doctrine\Tests\Models\Quote\Group', $g1); + $this->assertInstanceOf('Doctrine\Tests\Models\Quote\Group', $g2); + + $g1->name = 'Bar 11'; + $g2->name = 'Foo 22'; + + // Update + $this->_em->persist($user); + $this->_em->flush(); + $this->_em->clear(); + + $user = $this->_em->find('Doctrine\Tests\Models\Quote\User', $u1Id); + + $this->assertInstanceOf('Doctrine\Tests\Models\Quote\User', $user); + $this->assertEquals('FabioBatSilva', $user->name); + $this->assertEquals($u1Id, $user->id); + + // Delete + $this->_em->remove($user); + + $this->_em->flush(); + $this->_em->clear(); + + $this->assertNull($this->_em->find('Doctrine\Tests\Models\Quote\User', $u1Id)); + $this->assertNull($this->_em->find('Doctrine\Tests\Models\Quote\Group', $g1Id)); + $this->assertNull($this->_em->find('Doctrine\Tests\Models\Quote\Group', $g2Id)); + } + +} \ No newline at end of file