feat: support raw SQL expression cursors (v0.7.0)#36
Conversation
Allow Drizzle `sql` expressions (not just table columns) as cursor
values, enabling pagination by computed fields like upper(name),
concatenated strings, or any DB-evaluable expression.
- `Cursor` is now a discriminated union of `TableCursor` (schema) and
`SQLCursor` (sql) — both exported as named types
- `CursorConfig<C>` is generic so call-site types are inferred without
manual annotations
- `generateCursor` uses `<C extends CursorConfig>` so TypeScript infers
the exact config literal; no column-type unification issues
- `cursor.orderBy` and `cursor.where()` branch on `"sql" in cursor` at
runtime for both table and SQL cursors
- `cursor.relations.orderBy` returns `() => SQL[]` when any cursor uses
`sql`, and `Record<string, "asc"|"desc">` otherwise — resolved via
`ConfigHasSqlCursor<C>` conditional type with no manual annotations
- `cursor.relations.where()` builds `{ RAW: () => SQL }` entries for SQL
cursors alongside plain field conditions for table cursors
- Compat fixtures (drizzle-v0, drizzle-v1) extended with `items` table
and SQL expression cursor pagination tests
- README documents SQL cursor usage, RQB v2 behaviour, and the
table-alias limitation for `relations.where()` with SQL expressions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (9)
📝 WalkthroughWalkthroughThis PR introduces SQL-expression-based cursors as a new feature. The type system is updated to define cursors as a union of table-based ( Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Review rate limit: 9/10 reviews remaining, refill in 6 minutes. Comment |
Summary
SQLCursortype alongsideTableCursor—Cursoris now a discriminated union of both, both exported as named typesCursorConfig<C>generic so cursor types are fully inferred at call sites without manual annotationscursor.orderByandcursor.where()branch on"sql" in cursorat runtime, supporting both table columns and SQL expressionscursor.relations.orderByreturns() => SQL[]when any cursor usessql(auto-inferred viaConfigHasSqlCursor<C>conditional type),Record<string, "asc"|"desc">otherwise — no manual type annotation neededcursor.relations.where()builds{ RAW: () => SQL }entries for SQL cursors alongside plain field conditions for table cursorsdrizzle-v0,drizzle-v1) extended with SQL expression cursor pagination tests usingrank::text || '-' || upper(firstName)relations.where()with SQL expressionsTest plan
pnpm exec vitest run— 193 tests passpnpm exec tsc --noEmit— no type errorspnpm run test:compat— both drizzle-v0 and drizzle-v1 fixtures pass🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
Chores