feat(database): add simplePaginate() to SelectQueryBuilder - #2250
feat(database): add simplePaginate() to SelectQueryBuilder#2250Lanser0614 wants to merge 4 commits into
Conversation
Benchmark ResultsComparison of Open to see the benchmark results
Generated by phpbench against commit 8b57fed |
|
@brendt @innocenzi What is the average review time for a pull request ? |
| if ($this->itemsPerPage <= 0) { | ||
| throw new ArgumentWasInvalid('Items per page must be positive'); | ||
| } | ||
|
|
||
| if ($this->currentPage <= 0) { | ||
| throw new ArgumentWasInvalid('Current page must be positive'); | ||
| } |
There was a problem hiding this comment.
Let's set an upper-bound as well. Though edge-case, a big enough argument (e.g. PHP_INT_MAX) can cause an overflow, coercing the type to float and causing a TypeError.
| if ($this->itemsPerPage <= 0) { | ||
| throw new ArgumentWasInvalid('Items per page must be positive'); | ||
| } | ||
|
|
||
| if ($this->currentPage <= 0) { | ||
| throw new ArgumentWasInvalid('Current page must be positive'); | ||
| } |
There was a problem hiding this comment.
Let's also create named, past tense exceptions for these, see other exceptions in the codebase. The old paginator follows the currently implemented patterns, but I'd consider it legacy and move towards named exceptions. Only fix these exceptions for now, if you wish, you can open a followup PR for the original paginator exceptions. Though I'd wait for @brendt's approval with this.
Summary
Adds simple pagination without executing an additional
COUNT(*)query.The query requests one additional item:
If the additional item exists, it is removed from the returned data and
hasNextis set totrue.Changes
SelectQueryBuilder::simplePaginate().SimplePaginator.SimplePaginatedDatawithout synthetictotalItemsortotalPages.hasNext,hasPrevious,nextPage, andpreviousPage.map(), array serialization, and JSON serialization.itemsPerPageandcurrentPage.paginate()API never returns more thanitemsPerPageitems.Tests
Added unit and integration coverage for:
itemsPerPageresults;itemsPerPage + 1;map(),toArray(), and JSON serialization;SelectQueryBuilder::simplePaginate();SELECTquery withoutCOUNT(*).Local verification:
Notes
This is still offset-based pagination. It avoids the potentially expensive count query, but large offsets may remain costly, and concurrent inserts or deletes can shift results between pages. Cursor/keyset pagination remains preferable for very large or frequently changing datasets.