Fix limits in queries
Summary: I think this is simpler? Includes test cases. Test Plan: Ran tests. Loaded /paste/. Reviewers: vrana, nh Reviewed By: vrana CC: aran Differential Revision: https://secure.phabricator.com/D3209
This commit is contained in:
@@ -136,6 +136,36 @@ final class PhabricatorPolicyTestCase extends PhabricatorTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test limits.
|
||||||
|
*/
|
||||||
|
public function testLimits() {
|
||||||
|
$results = array(
|
||||||
|
$this->buildObject(PhabricatorPolicies::POLICY_USER),
|
||||||
|
$this->buildObject(PhabricatorPolicies::POLICY_USER),
|
||||||
|
$this->buildObject(PhabricatorPolicies::POLICY_USER),
|
||||||
|
$this->buildObject(PhabricatorPolicies::POLICY_USER),
|
||||||
|
$this->buildObject(PhabricatorPolicies::POLICY_USER),
|
||||||
|
$this->buildObject(PhabricatorPolicies::POLICY_USER),
|
||||||
|
);
|
||||||
|
|
||||||
|
$query = new PhabricatorPolicyTestQuery();
|
||||||
|
$query->setResults($results);
|
||||||
|
$query->setViewer($this->buildUser('user'));
|
||||||
|
|
||||||
|
$this->assertEqual(
|
||||||
|
3,
|
||||||
|
count($query->setLimit(3)->setOffset(0)->execute()),
|
||||||
|
'Limits work.');
|
||||||
|
|
||||||
|
$this->assertEqual(
|
||||||
|
2,
|
||||||
|
count($query->setLimit(3)->setOffset(4)->execute()),
|
||||||
|
'Limit + offset work.');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test an object for visibility across multiple user specifications.
|
* Test an object for visibility across multiple user specifications.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -153,34 +153,16 @@ abstract class PhabricatorPolicyQuery extends PhabricatorOffsetPagedQuery {
|
|||||||
$limit = (int)$this->getLimit();
|
$limit = (int)$this->getLimit();
|
||||||
$count = 0;
|
$count = 0;
|
||||||
|
|
||||||
$need = null;
|
$need = $offset + $limit;
|
||||||
if ($offset) {
|
|
||||||
$need = $offset + $limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->willExecute();
|
$this->willExecute();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
if ($need) {
|
||||||
// Figure out how many results to load. "0" means "all results".
|
$this->rawResultLimit = min($need - $count, 1024);
|
||||||
$load = 0;
|
} else {
|
||||||
if ($need && ($count < $offset)) {
|
$this->rawResultLimit = 0;
|
||||||
// This cap is just an arbitrary limit to keep memory usage from going
|
|
||||||
// crazy for large offsets; we can't execute them efficiently, but
|
|
||||||
// it should be possible to execute them without crashing.
|
|
||||||
$load = min($need, 1024);
|
|
||||||
} else if ($limit) {
|
|
||||||
// Otherwise, just load the number of rows we're after. Note that it
|
|
||||||
// might be more efficient to load more rows than this (if we expect
|
|
||||||
// about 5% of objects to be filtered, loading 105% of the limit might
|
|
||||||
// be better) or fewer rows than this (if we already have 95 rows and
|
|
||||||
// only need 100, loading only 5 rows might be better), but we currently
|
|
||||||
// just use the simplest heuristic since we don't have enough data
|
|
||||||
// about policy queries in the real world to tweak it.
|
|
||||||
$load = $limit;
|
|
||||||
}
|
}
|
||||||
$this->rawResultLimit = $load;
|
|
||||||
|
|
||||||
|
|
||||||
$page = $this->loadPage();
|
$page = $this->loadPage();
|
||||||
|
|
||||||
@@ -202,13 +184,13 @@ abstract class PhabricatorPolicyQuery extends PhabricatorOffsetPagedQuery {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$load) {
|
if (!$this->rawResultLimit) {
|
||||||
// If we don't have a load count, we loaded all the results. We do
|
// If we don't have a load count, we loaded all the results. We do
|
||||||
// not need to load another page.
|
// not need to load another page.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($page) < $load) {
|
if (count($page) < $this->rawResultLimit) {
|
||||||
// If we have a load count but the unfiltered results contained fewer
|
// If we have a load count but the unfiltered results contained fewer
|
||||||
// objects, we know this was the last page of objects; we do not need
|
// objects, we know this was the last page of objects; we do not need
|
||||||
// to load another page because we can deduce it would be empty.
|
// to load another page because we can deduce it would be empty.
|
||||||
|
|||||||
Reference in New Issue
Block a user