Skip to content

Commit

Permalink
FIX Trigger eagerloading for first() and last() (#10875)
Browse files Browse the repository at this point in the history
  • Loading branch information
GuySartorelli committed Jul 20, 2023
1 parent 60d65dd commit 642321d
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 4 deletions.
19 changes: 15 additions & 4 deletions src/ORM/DataList.php
Expand Up @@ -1408,8 +1408,13 @@ public function sum($fieldName)
*/
public function first()
{
foreach ($this->dataQuery->firstRow()->execute() as $row) {
return $this->createDataObject($row);
// We need to trigger eager loading by iterating over the list, rather than just fetching
// the first row from the dataQuery.
// This limit and offset logic mimics that $this->dataQuery->firstRow() would ultimately do.
$limitOffset = $this->dataQuery->query()->getLimit() ?? [];
$offset = array_key_exists('start', $limitOffset) ? $limitOffset['start'] : 0;
foreach ($this->limit(1, $offset) as $record) {
return $record;
}
return null;
}
Expand All @@ -1423,8 +1428,14 @@ public function first()
*/
public function last()
{
foreach ($this->dataQuery->lastRow()->execute() as $row) {
return $this->createDataObject($row);
// We need to trigger eager loading by iterating over the list, rather than just fetching
// the last row from the dataQuery.
// This limit and offset logic mimics that $this->dataQuery->lastRow() would ultimately do.
$limitOffset = $this->dataQuery->query()->getLimit() ?? [];
$offset = array_key_exists('start', $limitOffset) ? $limitOffset['start'] : 0;
$index = max($this->count() + $offset - 1, 0);
foreach ($this->limit(1, $index) as $record) {
return $record;
}
return null;
}
Expand Down
19 changes: 19 additions & 0 deletions tests/php/ORM/DataListEagerLoadingTest.php
Expand Up @@ -4,6 +4,7 @@

use InvalidArgumentException;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataList;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DB;
Expand Down Expand Up @@ -1115,4 +1116,22 @@ public function provideEagerLoadingEmptyRelationLists(): array
],
];
}

public function testFirstHasEagerloadedRelation()
{
$record = EagerLoadObject::create(['Title' => 'My obj']);
$record->write();
$record->HasManyEagerLoadObjects()->add(HasManyEagerLoadObject::create(['Title' => 'My related obj']));
$obj = EagerLoadObject::get()->eagerLoad('HasManyEagerLoadObjects')->first();
$this->assertInstanceOf(ArrayList::class, $obj->HasManyEagerLoadObjects());
}

public function testLastHasEagerloadedRelation()
{
$record = EagerLoadObject::create(['Title' => 'My obj']);
$record->write();
$record->HasManyEagerLoadObjects()->add(HasManyEagerLoadObject::create(['Title' => 'My related obj']));
$obj = EagerLoadObject::get()->eagerLoad('HasManyEagerLoadObjects')->last();
$this->assertInstanceOf(ArrayList::class, $obj->HasManyEagerLoadObjects());
}
}
22 changes: 22 additions & 0 deletions tests/php/ORM/DataListTest.php
Expand Up @@ -2081,6 +2081,28 @@ public function testColumnFromRelatedTable()
], $productTitles);
}

public function testFirst()
{
$list = Sortable::get()->sort('Sort');
$this->assertGreaterThanOrEqual(
3,
$list->count(),
'We must have at least 3 items for this test to be valid'
);
$this->assertSame('Steve', $list->first()->Name);
}

public function testLast()
{
$list = Sortable::get()->sort('Sort');
$this->assertGreaterThanOrEqual(
3,
$list->count(),
'We must have at least 3 items for this test to be valid'
);
$this->assertSame('John', $list->last()->Name);
}

public function testChunkedFetch()
{
$expectedIDs = Team::get()->map('ID', 'ID')->toArray();
Expand Down

0 comments on commit 642321d

Please sign in to comment.