1
0
mirror of synced 2025-01-27 18:41:46 +03:00

Fixed behavior of PersistentCollection#clear(). Fixed single-valued association path expression support in DQL UpdateItems.

This commit is contained in:
Roman S. Borschel 2010-07-08 17:30:39 +02:00
parent 4212b88edc
commit a1c13b58d3
9 changed files with 71 additions and 54 deletions

View File

@ -560,15 +560,20 @@ final class PersistentCollection implements Collection
*/
public function clear()
{
$this->initialize(); // TODO: not needed!?
$result = $this->coll->clear();
if ($this->initialized && $this->isEmpty()) {
return;
}
if ($this->association->isOneToMany() && $this->association->orphanRemoval) {
foreach ($this->coll as $element) {
$this->em->getUnitOfWork()->scheduleOrphanRemoval($element);
}
}
$this->coll->clear();
if ($this->association->isOwningSide) {
$this->changed();
$this->em->getUnitOfWork()->scheduleCollectionDeletion($this);
$this->takeSnapshot();
}
return $result;
}
/**

View File

@ -242,6 +242,7 @@ final class Query extends AbstractQuery
}
if (is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(get_class($value))) {
//TODO: Check that $value is MANAGED?
$values = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
$sqlPositions = $paramMappings[$key];
$sqlParams += array_combine((array)$sqlPositions, $values);

View File

@ -36,13 +36,12 @@ namespace Doctrine\ORM\Query\AST;
*/
class UpdateItem extends Node
{
public $identificationVariable;
public $field;
public $pathExpression;
public $newValue;
public function __construct($field, $newValue)
public function __construct($pathExpression, $newValue)
{
$this->field = $field;
$this->pathExpression = $pathExpression;
$this->newValue = $newValue;
}

View File

@ -84,8 +84,9 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
$updateSql = 'UPDATE ' . $class->getQuotedTableName($platform) . ' SET ';
foreach ($updateItems as $updateItem) {
$field = $updateItem->field;
if (isset($class->fieldMappings[$field]) && ! isset($class->fieldMappings[$field]['inherited'])) {
$field = $updateItem->pathExpression->parts[0];
if (isset($class->fieldMappings[$field]) && ! isset($class->fieldMappings[$field]['inherited']) ||
isset($class->associationMappings[$field]) && ! $class->associationMappings[$field]->inherited) {
$newValue = $updateItem->newValue;
if ( ! $affected) {

View File

@ -1291,28 +1291,9 @@ class Parser
*/
public function UpdateItem()
{
$token = $this->_lexer->lookahead;
$identVariable = $this->IdentificationVariable();
$this->match(Lexer::T_DOT);
$this->match(Lexer::T_IDENTIFIER);
$field = $this->_lexer->token['value'];
// Check if field exists
$class = $this->_queryComponents[$identVariable]['metadata'];
if ( ! isset($class->associationMappings[$field]) && ! isset($class->fieldMappings[$field])) {
$this->semanticalError(
'Class ' . $class->name . ' has no field named ' . $field, $token
);
}
$pathExpr = $this->PathExpression(AST\PathExpression::TYPE_STATE_FIELD | AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION);
$this->match(Lexer::T_EQUALS);
$newValue = $this->NewValue();
$updateItem = new AST\UpdateItem($field, $newValue);
$updateItem->identificationVariable = $identVariable;
$updateItem = new AST\UpdateItem($pathExpr, $this->NewValue());
return $updateItem;
}

View File

@ -1202,27 +1202,17 @@ class SqlWalker implements TreeWalker
$useTableAliasesBefore = $this->_useSqlTableAliases;
$this->_useSqlTableAliases = false;
$sql = '';
$dqlAlias = $updateItem->identificationVariable;
$qComp = $this->_queryComponents[$dqlAlias];
if ($this->_useSqlTableAliases) {
$sql .= $this->getSqlTableAlias($qComp['metadata']->getTableName()) . '.';
}
$sql .= $qComp['metadata']->getQuotedColumnName($updateItem->field, $this->_platform) . ' = ';
$sql = $this->walkPathExpression($updateItem->pathExpression) . ' = ';
$newValue = $updateItem->newValue;
if ($newValue instanceof AST\Node) {
$sql .= $newValue->dispatch($this);
} else if (is_string($newValue)) {
if (strcasecmp($newValue, 'NULL') === 0) {
if ($newValue === null) {
$sql .= 'NULL';
} else if ($newValue instanceof AST\Node) {
$sql .= $newValue->dispatch($this);
} else {
$sql .= $this->_conn->quote($newValue);
}
}
$this->_useSqlTableAliases = $useTableAliasesBefore;

View File

@ -161,10 +161,13 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->flush();
// Check that there are just 2 phonenumbers left
$count = $this->_em->getConnection()->executeQuery(
"SELECT COUNT(*) FROM cms_phonenumbers", array()
)->fetchColumn();
$count = $this->_em->getConnection()->fetchColumn("SELECT COUNT(*) FROM cms_phonenumbers");
$this->assertEquals(2, $count); // only 2 remaining
// check that clear() removes the others via orphan removal
$user->getPhonenumbers()->clear();
$this->_em->flush();
$this->assertEquals(0, $this->_em->getConnection()->fetchColumn("select count(*) from cms_phonenumbers"));
}
public function testBasicQuery()
@ -664,9 +667,6 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
} catch (\InvalidArgumentException $expected) {}
}
/**
* @group orphan
*/
public function testOneToOneOrphanRemoval()
{
//$this->_em->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger);
@ -714,6 +714,36 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals(0, $this->_em->getConnection()->fetchColumn("select count(*) from cms_addresses where id=".$addressId.""));
}
public function testClearingCollectionDoesNotInitialize()
{
$user = new CmsUser();
$user->username = "beberlei";
$user->name = "Benjamin E.";
$user->status = 'active';
$grp = new CmsGroup();
$grp->setName("The Dudes");
$grp->addUser($user);
$user->addGroup($grp);
$this->_em->persist($user);
$this->_em->persist($grp);
$this->_em->flush();
$this->_em->clear();
$this->assertEquals(1, $this->_em->getConnection()->fetchColumn("select count(*) from cms_users_groups"));
$user2 = $this->_em->find(get_class($user), $user->id);
$this->assertFalse($user2->groups->isInitialized());
$user2->groups->clear();
$this->assertFalse($user2->groups->isInitialized());
$this->_em->flush();
$this->assertFalse($user2->groups->isInitialized());
$this->assertEquals(0, $this->_em->getConnection()->fetchColumn("select count(*) from cms_users_groups"));
}
//DRAFT OF EXPECTED/DESIRED BEHAVIOR
/*public function testPersistentCollectionContainsDoesNeverInitialize()
{

View File

@ -167,4 +167,12 @@ class UpdateSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
"UPDATE cms_phonenumbers SET phonenumber = 1234 WHERE user_id = ?"
);
}
public function testSingleValuedAssociationFieldInSetClause()
{
$this->assertSqlGeneration(
"update Doctrine\Tests\Models\CMS\CmsComment c set c.article = null where c.article=?1",
"UPDATE cms_comments SET article_id = NULL WHERE article_id = ?"
);
}
}

View File

@ -45,7 +45,8 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
'Doctrine\Tests\Models\CMS\CmsPhonenumber',
'Doctrine\Tests\Models\CMS\CmsAddress',
'Doctrine\Tests\Models\CMS\CmsGroup',
'Doctrine\Tests\Models\CMS\CmsArticle'
'Doctrine\Tests\Models\CMS\CmsArticle',
'Doctrine\Tests\Models\CMS\CmsComment',
),
'forum' => array(),
'company' => array(
@ -106,6 +107,7 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
$conn->executeUpdate('DELETE FROM cms_groups');
$conn->executeUpdate('DELETE FROM cms_addresses');
$conn->executeUpdate('DELETE FROM cms_phonenumbers');
$conn->executeUpdate('DELETE FROM cms_comments');
$conn->executeUpdate('DELETE FROM cms_articles');
$conn->executeUpdate('DELETE FROM cms_users');
}