commit
27885bee72
|
@ -10,6 +10,7 @@ use Icinga\Application\Icinga;
|
||||||
use Icinga\Application\Benchmark;
|
use Icinga\Application\Benchmark;
|
||||||
use Icinga\Data\Filter\Filter;
|
use Icinga\Data\Filter\Filter;
|
||||||
use Icinga\Exception\IcingaException;
|
use Icinga\Exception\IcingaException;
|
||||||
|
use Icinga\Exception\ProgrammingError;
|
||||||
use Icinga\Web\Paginator\Adapter\QueryAdapter;
|
use Icinga\Web\Paginator\Adapter\QueryAdapter;
|
||||||
|
|
||||||
class SimpleQuery implements QueryInterface, Queryable, Iterator
|
class SimpleQuery implements QueryInterface, Queryable, Iterator
|
||||||
|
@ -28,6 +29,13 @@ class SimpleQuery implements QueryInterface, Queryable, Iterator
|
||||||
*/
|
*/
|
||||||
protected $iterator;
|
protected $iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current position of this query's iterator
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $iteratorPosition;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The target you are going to query
|
* The target you are going to query
|
||||||
*
|
*
|
||||||
|
@ -83,6 +91,20 @@ class SimpleQuery implements QueryInterface, Queryable, Iterator
|
||||||
*/
|
*/
|
||||||
protected $limitOffset;
|
protected $limitOffset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to peek ahead for more results
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $peekAhead;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the query did not yield all available results
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $hasMore;
|
||||||
|
|
||||||
protected $filter;
|
protected $filter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -136,6 +158,7 @@ class SimpleQuery implements QueryInterface, Queryable, Iterator
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->iterator->rewind();
|
$this->iterator->rewind();
|
||||||
|
$this->iteratorPosition = 0;
|
||||||
Benchmark::measure('Query result iteration started');
|
Benchmark::measure('Query result iteration started');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +179,15 @@ class SimpleQuery implements QueryInterface, Queryable, Iterator
|
||||||
*/
|
*/
|
||||||
public function valid()
|
public function valid()
|
||||||
{
|
{
|
||||||
if (! $this->iterator->valid()) {
|
$valid = $this->iterator->valid();
|
||||||
|
if ($valid && $this->peekAhead && $this->hasLimit() && $this->iteratorPosition + 1 === $this->getLimit()) {
|
||||||
|
$this->hasMore = true;
|
||||||
|
$valid = false; // We arrived at the last result, which is the requested extra row, so stop the iteration
|
||||||
|
} elseif (! $valid) {
|
||||||
|
$this->hasMore = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $valid) {
|
||||||
Benchmark::measure('Query result iteration finished');
|
Benchmark::measure('Query result iteration finished');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -180,6 +211,7 @@ class SimpleQuery implements QueryInterface, Queryable, Iterator
|
||||||
public function next()
|
public function next()
|
||||||
{
|
{
|
||||||
$this->iterator->next();
|
$this->iterator->next();
|
||||||
|
$this->iteratorPosition += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -358,6 +390,36 @@ class SimpleQuery implements QueryInterface, Queryable, Iterator
|
||||||
return $this->order;
|
return $this->order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether this query should peek ahead for more results
|
||||||
|
*
|
||||||
|
* Enabling this causes the current query limit to be increased by one. The potential extra row being yielded will
|
||||||
|
* be removed from the result set. Note that this only applies when fetching multiple results of limited queries.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function peekAhead($state = true)
|
||||||
|
{
|
||||||
|
$this->peekAhead = (bool) $state;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether this query did not yield all available results
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*
|
||||||
|
* @throws ProgrammingError In case the query did not run yet
|
||||||
|
*/
|
||||||
|
public function hasMore()
|
||||||
|
{
|
||||||
|
if ($this->hasMore === null) {
|
||||||
|
throw new ProgrammingError('Query did not run. Cannot determine whether there are more results.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->hasMore;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a limit count and offset to the query
|
* Set a limit count and offset to the query
|
||||||
*
|
*
|
||||||
|
@ -390,7 +452,7 @@ class SimpleQuery implements QueryInterface, Queryable, Iterator
|
||||||
*/
|
*/
|
||||||
public function getLimit()
|
public function getLimit()
|
||||||
{
|
{
|
||||||
return $this->limitCount;
|
return $this->peekAhead && $this->hasLimit() ? $this->limitCount + 1 : $this->limitCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -460,6 +522,14 @@ class SimpleQuery implements QueryInterface, Queryable, Iterator
|
||||||
Benchmark::measure('Fetching all results started');
|
Benchmark::measure('Fetching all results started');
|
||||||
$results = $this->ds->fetchAll($this);
|
$results = $this->ds->fetchAll($this);
|
||||||
Benchmark::measure('Fetching all results finished');
|
Benchmark::measure('Fetching all results finished');
|
||||||
|
|
||||||
|
if ($this->peekAhead && $this->hasLimit() && count($results) === $this->getLimit()) {
|
||||||
|
$this->hasMore = true;
|
||||||
|
array_pop($results);
|
||||||
|
} else {
|
||||||
|
$this->hasMore = false;
|
||||||
|
}
|
||||||
|
|
||||||
return $results;
|
return $results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,6 +556,14 @@ class SimpleQuery implements QueryInterface, Queryable, Iterator
|
||||||
Benchmark::measure('Fetching one column started');
|
Benchmark::measure('Fetching one column started');
|
||||||
$values = $this->ds->fetchColumn($this);
|
$values = $this->ds->fetchColumn($this);
|
||||||
Benchmark::measure('Fetching one column finished');
|
Benchmark::measure('Fetching one column finished');
|
||||||
|
|
||||||
|
if ($this->peekAhead && $this->hasLimit() && count($values) === $this->getLimit()) {
|
||||||
|
$this->hasMore = true;
|
||||||
|
array_pop($values);
|
||||||
|
} else {
|
||||||
|
$this->hasMore = false;
|
||||||
|
}
|
||||||
|
|
||||||
return $values;
|
return $values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,6 +592,14 @@ class SimpleQuery implements QueryInterface, Queryable, Iterator
|
||||||
Benchmark::measure('Fetching pairs started');
|
Benchmark::measure('Fetching pairs started');
|
||||||
$pairs = $this->ds->fetchPairs($this);
|
$pairs = $this->ds->fetchPairs($this);
|
||||||
Benchmark::measure('Fetching pairs finished');
|
Benchmark::measure('Fetching pairs finished');
|
||||||
|
|
||||||
|
if ($this->peekAhead && $this->hasLimit() && count($pairs) === $this->getLimit()) {
|
||||||
|
$this->hasMore = true;
|
||||||
|
array_pop($pairs);
|
||||||
|
} else {
|
||||||
|
$this->hasMore = false;
|
||||||
|
}
|
||||||
|
|
||||||
return $pairs;
|
return $pairs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ namespace Icinga\Repository;
|
||||||
|
|
||||||
use Iterator;
|
use Iterator;
|
||||||
use IteratorAggregate;
|
use IteratorAggregate;
|
||||||
|
use Traversable;
|
||||||
use Icinga\Application\Benchmark;
|
use Icinga\Application\Benchmark;
|
||||||
use Icinga\Application\Logger;
|
use Icinga\Application\Logger;
|
||||||
use Icinga\Data\QueryInterface;
|
use Icinga\Data\QueryInterface;
|
||||||
|
@ -343,6 +344,29 @@ class RepositoryQuery implements QueryInterface, SortRules, Iterator
|
||||||
return $this->query->getOrder();
|
return $this->query->getOrder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether this query should peek ahead for more results
|
||||||
|
*
|
||||||
|
* Enabling this causes the current query limit to be increased by one. The potential extra row being yielded will
|
||||||
|
* be removed from the result set. Note that this only applies when fetching multiple results of limited queries.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function peekAhead($state = true)
|
||||||
|
{
|
||||||
|
return $this->query->peekAhead($state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether this query did not yield all available results
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasMore()
|
||||||
|
{
|
||||||
|
return $this->query->hasMore();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Limit this query's results
|
* Limit this query's results
|
||||||
*
|
*
|
||||||
|
@ -581,7 +605,12 @@ class RepositoryQuery implements QueryInterface, SortRules, Iterator
|
||||||
$this->order();
|
$this->order();
|
||||||
}
|
}
|
||||||
|
|
||||||
$iterator = $this->repository->getDataSource()->query($this->query);
|
if ($this->query instanceof Traversable) {
|
||||||
|
$iterator = $this->query;
|
||||||
|
} else {
|
||||||
|
$iterator = $this->repository->getDataSource()->query($this->query);
|
||||||
|
}
|
||||||
|
|
||||||
if ($iterator instanceof IteratorAggregate) {
|
if ($iterator instanceof IteratorAggregate) {
|
||||||
$this->iterator = $iterator->getIterator();
|
$this->iterator = $iterator->getIterator();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -410,6 +410,29 @@ abstract class DataView implements QueryInterface, SortRules, IteratorAggregate
|
||||||
return $this->query->count();
|
return $this->query->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether the query should peek ahead for more results
|
||||||
|
*
|
||||||
|
* Enabling this causes the current query limit to be increased by one. The potential extra row being yielded will
|
||||||
|
* be removed from the result set. Note that this only applies when fetching multiple results of limited queries.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function peekAhead($state = true)
|
||||||
|
{
|
||||||
|
return $this->query->peekAhead($state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether the query did not yield all available results
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasMore()
|
||||||
|
{
|
||||||
|
return $this->query->hasMore();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a limit count and offset
|
* Set a limit count and offset
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue