mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
BUG: Fix ManyManyList->removeAll() when filters are applied to the query
In order to be cross-database compatible and support filters, the IDs to delete must be retrieved in a sub-query.
This commit is contained in:
parent
365e8021ba
commit
b537ee28a2
@ -168,11 +168,27 @@ class ManyManyList extends RelationList {
|
|||||||
* Remove all items from this many-many join. To remove a subset of items, filter it first.
|
* Remove all items from this many-many join. To remove a subset of items, filter it first.
|
||||||
*/
|
*/
|
||||||
public function removeAll() {
|
public function removeAll() {
|
||||||
$query = $this->dataQuery()->query();
|
$base = ClassInfo::baseDataClass($this->dataClass());
|
||||||
$query->setDelete(true);
|
|
||||||
$query->setSelect(array('*'));
|
// Remove the join to the join table to avoid MySQL row locking issues.
|
||||||
$query->setFrom("\"$this->joinTable\"");
|
$query = $this->dataQuery();
|
||||||
$query->execute();
|
$query->removeFilterOn($query->getQueryParam('Foreign.Filter'));
|
||||||
|
|
||||||
|
$query = $query->query();
|
||||||
|
$query->setSelect("\"$base\".\"ID\"");
|
||||||
|
|
||||||
|
$from = $query->getFrom();
|
||||||
|
unset($from[$this->joinTable]);
|
||||||
|
$query->setFrom($from);
|
||||||
|
|
||||||
|
// Use a sub-query as SQLite does not support setting delete targets in
|
||||||
|
// joined queries.
|
||||||
|
$delete = new SQLQuery();
|
||||||
|
$delete->setDelete(true);
|
||||||
|
$delete->setFrom("\"$this->joinTable\"");
|
||||||
|
$delete->addWhere($this->foreignIDFilter());
|
||||||
|
$delete->addWhere("\"$this->joinTable\".\"$this->localKey\" IN ({$query->sql()})");
|
||||||
|
$delete->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -161,4 +161,53 @@ class ManyManyListTest extends SapphireTest {
|
|||||||
$this->assertEquals($teamTwoID, $teamsWithoutTheCaptain->first()->ID,
|
$this->assertEquals($teamTwoID, $teamsWithoutTheCaptain->first()->ID,
|
||||||
'The ManyManyList contains the wrong team');
|
'The ManyManyList contains the wrong team');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testRemoveAll() {
|
||||||
|
$first = new DataObjectTest_Team();
|
||||||
|
$first->write();
|
||||||
|
|
||||||
|
$second = new DataObjectTest_Team();
|
||||||
|
$second->write();
|
||||||
|
|
||||||
|
$firstPlayers = $first->Players();
|
||||||
|
$secondPlayers = $second->Players();
|
||||||
|
|
||||||
|
$a = new DataObjectTest_Player();
|
||||||
|
$a->ShirtNumber = 'a';
|
||||||
|
$a->write();
|
||||||
|
|
||||||
|
$b = new DataObjectTest_Player();
|
||||||
|
$b->ShirtNumber = 'b';
|
||||||
|
$b->write();
|
||||||
|
|
||||||
|
$firstPlayers->add($a);
|
||||||
|
$firstPlayers->add($b);
|
||||||
|
|
||||||
|
$secondPlayers->add($a);
|
||||||
|
$secondPlayers->add($b);
|
||||||
|
|
||||||
|
$this->assertEquals(array('a', 'b'), $firstPlayers->sort('ShirtNumber')->column('ShirtNumber'));
|
||||||
|
$this->assertEquals(array('a', 'b'), $secondPlayers->sort('ShirtNumber')->column('ShirtNumber'));
|
||||||
|
|
||||||
|
$firstPlayers->removeAll();
|
||||||
|
|
||||||
|
$this->assertEquals(0, count($firstPlayers));
|
||||||
|
$this->assertEquals(2, count($secondPlayers));
|
||||||
|
|
||||||
|
$firstPlayers->removeAll();
|
||||||
|
|
||||||
|
$firstPlayers->add($a);
|
||||||
|
$firstPlayers->add($b);
|
||||||
|
|
||||||
|
$this->assertEquals(array('a', 'b'), $firstPlayers->sort('ShirtNumber')->column('ShirtNumber'));
|
||||||
|
|
||||||
|
$firstPlayers->filter('ShirtNumber', 'b')->removeAll();
|
||||||
|
|
||||||
|
$this->assertEquals(array('a'), $firstPlayers->column('ShirtNumber'));
|
||||||
|
$this->assertEquals(array('a', 'b'), $secondPlayers->sort('ShirtNumber')->column('ShirtNumber'));
|
||||||
|
|
||||||
|
$this->assertNotNull(DataObjectTest_Player::get()->byID($a->ID));
|
||||||
|
$this->assertNotNull(DataObjectTest_Player::get()->byID($b->ID));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user