From: Coleman Watts Date: Mon, 13 Apr 2020 02:34:32 +0000 (-0400) Subject: APIv4 - Fix setting offset with no limit X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=f8bf8e26df5ffb21ef99346cf7efda3d848cff0e;p=civicrm-core.git APIv4 - Fix setting offset with no limit The API treats 0 as "no limit" but mysql does not. This allows setting an offset with no limit but applying the maximum possible row count, as mysql does not allow LIMIT NULL. See https://stackoverflow.com/questions/255517/mysql-offset-infinite-rows --- diff --git a/Civi/Api4/Query/Api4SelectQuery.php b/Civi/Api4/Query/Api4SelectQuery.php index 34c27ee671..75dd6d1487 100644 --- a/Civi/Api4/Query/Api4SelectQuery.php +++ b/Civi/Api4/Query/Api4SelectQuery.php @@ -241,7 +241,8 @@ class Api4SelectQuery extends SelectQuery { */ protected function buildLimit() { if (!empty($this->limit) || !empty($this->offset)) { - $this->query->limit($this->limit, $this->offset); + // If limit is 0, mysql will actually return 0 results. Instead set to maximum possible. + $this->query->limit($this->limit ?: '18446744073709551615', $this->offset); } } diff --git a/tests/phpunit/api/v4/Action/ContactGetTest.php b/tests/phpunit/api/v4/Action/ContactGetTest.php index 78d78eb375..e1be3ca566 100644 --- a/tests/phpunit/api/v4/Action/ContactGetTest.php +++ b/tests/phpunit/api/v4/Action/ContactGetTest.php @@ -58,4 +58,25 @@ class ContactGetTest extends \api\v4\UnitTestCase { $this->assertContains($del['id'], $contacts->column('id')); } + public function testGetWithLimit() { + $last_name = uniqid('getWithLimitTest'); + + $bob = Contact::create() + ->setValues(['first_name' => 'Bob', 'last_name' => $last_name]) + ->execute()->first(); + + $jan = Contact::create() + ->setValues(['first_name' => 'Jan', 'last_name' => $last_name]) + ->execute()->first(); + + $dan = Contact::create() + ->setValues(['first_name' => 'Dan', 'last_name' => $last_name]) + ->execute()->first(); + + $num = Contact::get()->setCheckPermissions(FALSE)->selectRowCount()->execute()->count(); + $this->assertCount($num - 1, Contact::get()->setCheckPermissions(FALSE)->setLimit(0)->setOffset(1)->execute()); + $this->assertCount($num - 2, Contact::get()->setCheckPermissions(FALSE)->setLimit(0)->setOffset(2)->execute()); + $this->assertCount(2, Contact::get()->setCheckPermissions(FALSE)->setLimit(2)->setOffset(0)->execute()); + } + }