keysetPredicate(orderedValues: ReadonlyArray<CursorValue>,keyValues: ReadonlyArray<CursorValue>,orderBy: Readonly<Record<string, OrderDirection>>,keyColumns: ReadonlyArray<string>): FilterExpression
Build the "row after this one" keyset comparison as a portable
FilterExpression.
The comparison is the lexicographic expansion of
(resolved sort) > (cursor values): one or leg per position of the
resolved sort, where each leg pins every earlier field to its cursor value
(eq) and compares the leg's own field strictly in its own direction. For
a sort (a asc, b desc, k asc) over cursor values (a0, b0, k0) the tree
is or(gt(a, a0), and(eq(a, a0), lt(b, b0)), and(eq(a, a0), eq(b, b0), gt(k, k0))) — for the plan §3.8 case, createdAt desc with an id asc
tiebreaker, exactly or(lt(createdAt), and(eq(createdAt), gt(id))). A flat
or of per-field strict comparisons is NOT this tree: it matches rows
before the cursor whenever any single field sorts beyond its cursor value.
The resolved sort is the caller's orderBy followed by every key column
not already ordered (each as asc): the primary-key tiebreaker is a
correctness requirement, not a refinement — over rows carrying only two
distinct sort values, a walk that omitted it returned 4 of 6 and reported
success. A key column already present in orderBy is a sort position
already and is never appended twice.
Cursor values layout: orderedValues carries the value of each
orderBy field, in order, from the row the cursor was minted against;
keyValues carries the primary-key column values in key-column order. An
orderBy field is indexed by its orderBy position; a pure-tiebreaker key
column by its own key-column position — never a shared orderedValues[0],
which may belong to a non-key field.
orderedValues: ReadonlyArray<CursorValue>
Value of each ordered field from the cursor row, in
orderBy order — the i-th element is the value of
Object.entries(orderBy)[i]
keyValues: ReadonlyArray<CursorValue>
Primary-key column values in key-column order; a key
column absent from orderBy is indexed by its position here
orderBy: Readonly<Record<string, OrderDirection>>
The resolved sort specification (field → direction)
The keyset comparison, conjoinable with the caller's own filter