ArrayDatasource: Sort result first and then apply limit+offset

This commit is contained in:
Johannes Meyer 2021-04-12 15:17:55 +02:00
parent e5d1cb7fb6
commit 384d9535a9
2 changed files with 114 additions and 28 deletions

View File

@ -196,11 +196,16 @@ class ArrayDatasource implements Selectable
$filter = $query->getFilter(); $filter = $query->getFilter();
$offset = $query->hasOffset() ? $query->getOffset() : 0; $offset = $query->hasOffset() ? $query->getOffset() : 0;
$limit = $query->hasLimit() ? $query->getLimit() : 0; $limit = $query->hasLimit() ? $query->getLimit() : 0;
$data = $this->data;
if ($query->hasOrder()) {
uasort($data, [$query, 'compare']);
}
$foundStringKey = false; $foundStringKey = false;
$result = array(); $result = [];
$skipped = 0; $skipped = 0;
foreach ($this->data as $key => $row) { foreach ($data as $key => $row) {
if ($this->keyColumn !== null && !isset($row->{$this->keyColumn})) { if ($this->keyColumn !== null && !isset($row->{$this->keyColumn})) {
$row = clone $row; // Make sure that this won't affect the actual data $row = clone $row; // Make sure that this won't affect the actual data
$row->{$this->keyColumn} = $key; $row->{$this->keyColumn} = $key;
@ -239,14 +244,7 @@ class ArrayDatasource implements Selectable
} }
} }
// Sort the result if (! $foundStringKey) {
if ($query->hasOrder()) {
if ($foundStringKey) {
uasort($result, array($query, 'compare'));
} else {
usort($result, array($query, 'compare'));
}
} elseif (! $foundStringKey) {
$result = array_values($result); $result = array_values($result);
} }

View File

@ -8,40 +8,128 @@ use Icinga\Data\DataArray\ArrayDatasource;
class ArrayDatasourceTest extends BaseTestCase class ArrayDatasourceTest extends BaseTestCase
{ {
private $sampleData; private $query;
public function setUp(): void public function setUp(): void
{ {
parent::setUp(); parent::setUp();
$this->sampleData = array( $this->query = (new ArrayDatasource([
(object) array( (object) [
'host' => 'localhost', 'host' => 'a host',
'problem' => '1', 'problem' => '1',
'service' => 'ping',
'state' => '2', 'state' => '2',
'handled' => '1' 'handled' => '1'
), ],
(object) array( (object) [
'host' => 'localhost', 'host' => 'b host',
'problem' => '1', 'problem' => '1',
'service' => 'www.icinga.com',
'state' => '0', 'state' => '0',
'handled' => '0' 'handled' => '0'
), ],
(object) array( (object) [
'host' => 'localhost', 'host' => 'c host',
'problem' => '1', 'problem' => '1',
'service' => 'www.icinga.com',
'state' => '1', 'state' => '1',
'handled' => '0' 'handled' => '0'
) ]
); ]))->select();
} }
public function testSelectFactory() public function testSelectFactory()
{ {
$ds = new ArrayDatasource($this->sampleData); $this->assertInstanceOf('Icinga\\Data\\SimpleQuery', $this->query);
$query = $ds->select(); }
$this->assertInstanceOf('Icinga\\Data\\SimpleQuery', $query);
public function testOrderWithOneRuleIsCorrect()
{
$result = $this->query
->order('host', 'desc')
->fetchAll();
$this->assertEquals(
[
(object) [
'host' => 'c host',
'problem' => '1',
'state' => '1',
'handled' => '0'
],
(object) [
'host' => 'b host',
'problem' => '1',
'state' => '0',
'handled' => '0'
],
(object) [
'host' => 'a host',
'problem' => '1',
'state' => '2',
'handled' => '1'
]
],
$result,
'ArrayDatasource does not sort queries correctly'
);
}
public function testOrderWithTwoRulesIsCorrect()
{
$result = $this->query
->order('handled', 'asc')
->order('host', 'asc')
->fetchAll();
$this->assertEquals(
[
(object) [
'host' => 'b host',
'problem' => '1',
'state' => '0',
'handled' => '0'
],
(object) [
'host' => 'c host',
'problem' => '1',
'state' => '1',
'handled' => '0'
],
(object) [
'host' => 'a host',
'problem' => '1',
'state' => '2',
'handled' => '1'
]
],
$result,
'ArrayDatasource does not sort queries correctly'
);
}
public function testOrderIsCorrectWithLimitAndOffset()
{
$result = $this->query
->order('handled', 'asc')
->order('host', 'asc')
->limit(2)
->fetchAll();
$this->assertEquals(
[
(object) [
'host' => 'b host',
'problem' => '1',
'state' => '0',
'handled' => '0'
],
(object) [
'host' => 'c host',
'problem' => '1',
'state' => '1',
'handled' => '0'
]
],
$result,
'ArrayDatasource does not sort limited queries correctly'
);
} }
} }