Repository navigation
feat(database): keyset (cursor) pagination helper - #108
Merged
Merged
Conversation
paginate(query, { orderBy, after, limit }, params?) adds a seek on the sort
key, ORDER BY and LIMIT n + 1, and returns { rows, nextCursor }. One
direction seeks with a row comparison; mixed directions use the expanded OR
form, bounded on the first key. A bad or foreign cursor is InvalidCursor.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 47 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
…te and D1 Resolves the docs/reference.md conflict with afterCommit. paginate now also refuses a nullable key at run time (the type check is bypassable, and dialects disagree on where NULLs sort), and gains SQLite and D1 tests for the row comparison, the mixed-direction seek and timestamp cursors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
|
Merge-readiness pass (46e517f):
Verified locally: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Prisma-style
cursor/takepages andOFFSETpages have no typed helper in effect-orm. OFFSET reads and drops every earlier row, and on D1 that costs billed rows read.Closes #86.
Part of #52.
Changes
/databaseaddspaginate(query, { orderBy, after, limit }, params?). It returns{ rows, nextCursor: Option<string> }.ORDER BYandLIMIT limit + 1. The extra row only tells if there is a next page. The query keeps its ownwhere, so the tenant filter and params still apply.("at", "id") < ($2, $3). Postgres serves it from an index on(at, id); ClickHouse compares it as a tuple.a >= x AND (a > x OR (a = x AND b < y)). The leading bound keeps the seek on the first index column.{ k, v }:knames the sort key,vholds the key values encoded throughSchema.toCodecJsonof the key columns' types. ADateTime.Utckey comes back as the same instant.InvalidCursor(in the error channel): the cursor does not decode, or it was written for anotherorderBy.limitthat is not a positive integer is aQueryBuilderError. A query withoffset,groupBy,havingordistinctOn, or a key with no type, is aQueryBuilderDefect.operandOf(expr, value)inch/expr.tswrites a value as the column's comparisons do, for the row comparison.selectExprsOfandselectRecordOfinch/compile.tsare now exported (internal, not on an entry).docs/database.md, the reference rows, and the cursor note indocs/recipes.md. Oneminorchangeset.Left out
groupBy/having): the seek would have to go inHAVING. Refused for now.before) and a total count: not needed for a first version.where, so a changed cursor cannot cross the tenant filter. The docs say not to put secret values in the key.Query.paginate: the pipe API is in feat(query): a pipeable, data-last Query API next to the fluent builder #102.paginateis a function over theDatabasein context, not aDatabaseApimethod, to keep the change small.Validation
bun run build: ok.bun run typecheck: ok.bunx vitest run --testTimeout=60000 --hookTimeout=60000withEFFECT_ORM_CLICKHOUSE_URLset (ClickHouse 26.8.2.7): 62 files, 1046 tests passed, 0 skipped. New:src/database/paginate.test.ts(10, PGlite),src/database/paginate.test-d.ts,tests/paginate.clickhouse.test.ts(2, live ClickHouse).node scripts/check-doc-citations.mjs,node scripts/check-doc-examples.mjs,node scripts/check-exports-documented.mjs: ok.bun scripts/check-package.ts: ok.Need help on this PR? Tag
@codesmith-botwith what you need.