Value of each ordered field from the cursor row, in
orderBy order — the i-th element is the value of
Object.entries(orderBy)[i]
Primary-key column values in key-column order; a key
column absent from orderBy is indexed by its position here
The resolved sort specification (field → direction)
The primary-key columns, appended as ascending
tiebreakers when orderBy does not already carry them
The keyset comparison, conjoinable with the caller's own filter
Build the "row after this one" keyset comparison as a portable
FilterExpression.The comparison is the lexicographic expansion of
(resolved sort) > (cursor values): oneorleg 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 isor(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 descwith anid asctiebreaker, exactlyor(lt(createdAt), and(eq(createdAt), gt(id))). A flatorof 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
orderByfollowed by every key column not already ordered (each asasc): 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 inorderByis a sort position already and is never appended twice.Cursor values layout:
orderedValuescarries the value of eachorderByfield, in order, from the row the cursor was minted against;keyValuescarries the primary-key column values in key-column order. AnorderByfield is indexed by itsorderByposition; a pure-tiebreaker key column by its own key-column position — never a sharedorderedValues[0], which may belong to a non-key field.