Browse Source
Queries for multiple specific articles are limited in size because of limits on the number of bound query parameters. Currently this limit is somewhat arbitrarily set at 50, but it may increase. Historically controllers would be responsible for chunking input, but this will present problems when the expected output is a result set, and of course the maintenance burden increases as the number of controllers increases. This commit transfers the burden to the data model, and consequently introduces a ResultAggregate class which collects chunked result sets (currently only for articleList). In the course of making these changes the mock Result class was also largely rewritten, fixing many bugs with it. This commit does not modify the controllers nor their tests; this will be done in a subsequent commit.microsub
J. King
7 years ago
9 changed files with 310 additions and 99 deletions
@ -0,0 +1,46 @@ |
|||||
|
<?php |
||||
|
declare(strict_types=1); |
||||
|
namespace JKingWeb\Arsse\Db; |
||||
|
|
||||
|
use JKingWeb\Arsse\Db\Exception; |
||||
|
|
||||
|
class ResultAggregate extends AbstractResult { |
||||
|
protected $data; |
||||
|
protected $index = 0; |
||||
|
protected $cur = null; |
||||
|
|
||||
|
// actual public methods |
||||
|
|
||||
|
public function changes() { |
||||
|
return array_reduce($this->data, function($sum, $value) {return $sum + $value->changes();}, 0); |
||||
|
} |
||||
|
|
||||
|
public function lastId() { |
||||
|
return $this->data[sizeof($this->data) - 1]->lastId(); |
||||
|
} |
||||
|
|
||||
|
// constructor/destructor |
||||
|
|
||||
|
public function __construct(Result ...$result) { |
||||
|
$this->data = $result; |
||||
|
} |
||||
|
|
||||
|
public function __destruct() { |
||||
|
$max = sizeof($this->data); |
||||
|
for ($a = 0; $a < $max; $a++) { |
||||
|
unset($this->data[$a]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// PHP iterator methods |
||||
|
|
||||
|
public function valid() { |
||||
|
while (!$this->cur && isset($this->data[$this->index])) { |
||||
|
$this->cur = $this->data[$this->index]->getRow(); |
||||
|
if (!$this->cur) { |
||||
|
$this->index++; |
||||
|
} |
||||
|
} |
||||
|
return (bool) $this->cur; |
||||
|
} |
||||
|
} |
@ -0,0 +1,101 @@ |
|||||
|
<?php |
||||
|
declare(strict_types=1); |
||||
|
namespace JKingWeb\Arsse; |
||||
|
|
||||
|
use JKingWeb\Arsse\Test\Result; |
||||
|
|
||||
|
/** @covers \JKingWeb\Arsse\Db\ResultAggregate<extended> */ |
||||
|
class TestResultAggregate extends Test\AbstractTest { |
||||
|
|
||||
|
public function testGetChangeCountAndLastInsertId() { |
||||
|
$in = [ |
||||
|
new Result([], 3, 4), |
||||
|
new Result([], 27, 10), |
||||
|
new Result([], 12, 2112), |
||||
|
]; |
||||
|
$r = new Db\ResultAggregate(...$in); |
||||
|
$this->assertEquals(42, $r->changes()); |
||||
|
$this->assertEquals(2112, $r->lastId()); |
||||
|
} |
||||
|
|
||||
|
public function testIterateOverResults() { |
||||
|
$in = [ |
||||
|
new Result([['col' => 1]]), |
||||
|
new Result([['col' => 2]]), |
||||
|
new Result([['col' => 3]]), |
||||
|
]; |
||||
|
$rows = []; |
||||
|
foreach (new Db\ResultAggregate(...$in) as $index => $row) { |
||||
|
$rows[$index] = $row['col']; |
||||
|
} |
||||
|
$this->assertEquals([0 => 1, 1 => 2, 2 => 3], $rows); |
||||
|
} |
||||
|
|
||||
|
public function testIterateOverResultsTwice() { |
||||
|
$in = [ |
||||
|
new Result([['col' => 1]]), |
||||
|
new Result([['col' => 2]]), |
||||
|
new Result([['col' => 3]]), |
||||
|
]; |
||||
|
$rows = []; |
||||
|
$test = new Db\ResultAggregate(...$in); |
||||
|
foreach ($test as $row) { |
||||
|
$rows[] = $row['col']; |
||||
|
} |
||||
|
$this->assertEquals([1,2,3], $rows); |
||||
|
$this->assertException("resultReused", "Db"); |
||||
|
foreach ($test as $row) { |
||||
|
$rows[] = $row['col']; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public function testGetSingleValues() { |
||||
|
$test = new Db\ResultAggregate(...[ |
||||
|
new Result([['year' => 1867]]), |
||||
|
new Result([['year' => 1970]]), |
||||
|
new Result([['year' => 2112]]), |
||||
|
]); |
||||
|
$this->assertEquals(1867, $test->getValue()); |
||||
|
$this->assertEquals(1970, $test->getValue()); |
||||
|
$this->assertEquals(2112, $test->getValue()); |
||||
|
$this->assertSame(null, $test->getValue()); |
||||
|
} |
||||
|
|
||||
|
public function testGetFirstValuesOnly() { |
||||
|
$test = new Db\ResultAggregate(...[ |
||||
|
new Result([['year' => 1867, 'century' => 19]]), |
||||
|
new Result([['year' => 1970, 'century' => 20]]), |
||||
|
new Result([['year' => 2112, 'century' => 22]]), |
||||
|
]); |
||||
|
$this->assertEquals(1867, $test->getValue()); |
||||
|
$this->assertEquals(1970, $test->getValue()); |
||||
|
$this->assertEquals(2112, $test->getValue()); |
||||
|
$this->assertSame(null, $test->getValue()); |
||||
|
} |
||||
|
|
||||
|
public function testGetRows() { |
||||
|
$test = new Db\ResultAggregate(...[ |
||||
|
new Result([['album' => '2112', 'track' => '2112']]), |
||||
|
new Result([['album' => 'Clockwork Angels', 'track' => 'The Wreckers']]), |
||||
|
]); |
||||
|
$rows = [ |
||||
|
['album' => '2112', 'track' => '2112'], |
||||
|
['album' => 'Clockwork Angels', 'track' => 'The Wreckers'], |
||||
|
]; |
||||
|
$this->assertEquals($rows[0], $test->getRow()); |
||||
|
$this->assertEquals($rows[1], $test->getRow()); |
||||
|
$this->assertSame(null, $test->getRow()); |
||||
|
} |
||||
|
|
||||
|
public function testGetAllRows() { |
||||
|
$test = new Db\ResultAggregate(...[ |
||||
|
new Result([['album' => '2112', 'track' => '2112']]), |
||||
|
new Result([['album' => 'Clockwork Angels', 'track' => 'The Wreckers']]), |
||||
|
]); |
||||
|
$rows = [ |
||||
|
['album' => '2112', 'track' => '2112'], |
||||
|
['album' => 'Clockwork Angels', 'track' => 'The Wreckers'], |
||||
|
]; |
||||
|
$this->assertEquals($rows, $test->getAll()); |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue