# 设计说明

## 为什么位置必须包含唯一键

仅以 `created_at` 分页时，同一时间戳的多条记录没有确定先后；若一页在这组记录中间结束，下一页无法知道哪些同值记录已经返回。MoonPageFlow 将唯一 ID 作为最后一个升序键，因此任意两条记录都有严格顺序，游标是一个确定位置而不是模糊过滤值。

## 内存参考实现

`paginate` 先验证排序声明、行和限制，再按同一比较器排序；解码游标并核对字段、方向、NULL 策略和快照；按排他边界筛选，正向取前 N 条，反向取后 N 条，最后为每条边生成可继续的游标。它用于小数据集和适配器行为验证，复杂度为 O(n log n)。

## 数据库下推

`build_seek_plan` 将位置 `[k1=v1, k2=v2, id=i]` 编译为：

```text
(k1 after v1)
OR (k1 = v1 AND k2 after v2)
OR (k1 = v1 AND k2 = v2 AND id after i)
```

每个分支保留类型、方向和 NULL 策略；适配器负责映射到参数化 SQL 或查询构造器。反向页反转比较和数据库 ORDER BY，取到有限结果后再恢复 API 展示顺序。生成计划的键数量通常很小，构造等值前缀的复杂度为 O(k²)。

## 快照与恢复

keyset 保证相对于边界前进，但持续修改可能改变“完整遍历”含义。库不猜测数据库隔离机制，而由宿主提供 revision。`TraversalCheckpoint` 保存 snapshot、cursor、页数、记录数和已见 ID；恢复时验证版本一致，推进时拒绝重复 ID 和不前进的游标。
