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

View File

@ -8,40 +8,128 @@ use Icinga\Data\DataArray\ArrayDatasource;
class ArrayDatasourceTest extends BaseTestCase
{
private $sampleData;
private $query;
public function setUp(): void
{
parent::setUp();
$this->sampleData = array(
(object) array(
'host' => 'localhost',
$this->query = (new ArrayDatasource([
(object) [
'host' => 'a host',
'problem' => '1',
'service' => 'ping',
'state' => '2',
'handled' => '1'
),
(object) array(
'host' => 'localhost',
],
(object) [
'host' => 'b host',
'problem' => '1',
'service' => 'www.icinga.com',
'state' => '0',
'handled' => '0'
),
(object) array(
'host' => 'localhost',
],
(object) [
'host' => 'c host',
'problem' => '1',
'service' => 'www.icinga.com',
'state' => '1',
'handled' => '0'
)
);
]
]))->select();
}
public function testSelectFactory()
{
$ds = new ArrayDatasource($this->sampleData);
$query = $ds->select();
$this->assertInstanceOf('Icinga\\Data\\SimpleQuery', $query);
$this->assertInstanceOf('Icinga\\Data\\SimpleQuery', $this->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'
);
}
}