(params: {
tableId: string
workspaceId: string
cutoff: Date
filterClause?: SQL
afterId?: string
limit: number
})
| 497 | * fully-excluded page. |
| 498 | */ |
| 499 | export async function selectRowIdPage(params: { |
| 500 | tableId: string |
| 501 | workspaceId: string |
| 502 | cutoff: Date |
| 503 | filterClause?: SQL |
| 504 | afterId?: string |
| 505 | limit: number |
| 506 | }): Promise<string[]> { |
| 507 | const { tableId, workspaceId, cutoff, filterClause, afterId, limit } = params |
| 508 | const selectPage = (executor: DbExecutor) => |
| 509 | executor |
| 510 | .select({ id: userTableRows.id }) |
| 511 | .from(userTableRows) |
| 512 | .where( |
| 513 | and( |
| 514 | eq(userTableRows.tableId, tableId), |
| 515 | eq(userTableRows.workspaceId, workspaceId), |
| 516 | lte(userTableRows.createdAt, cutoff), |
| 517 | afterId ? gt(userTableRows.id, afterId) : undefined, |
| 518 | filterClause |
| 519 | ) |
| 520 | ) |
| 521 | .orderBy(asc(userTableRows.id)) |
| 522 | .limit(limit) |
| 523 | // A jsonb filter is unestimatable, so the planner would seq-scan the whole shared relation |
| 524 | // per page (12.6s measured) — keep it on the tenant's (table_id, id) index. |
| 525 | const rows = filterClause |
| 526 | ? await withSeqscanOff(async (trx) => selectPage(trx)) |
| 527 | : await selectPage(db) |
| 528 | return rows.map((r) => r.id) |
| 529 | } |
| 530 | |
| 531 | /** |
| 532 | * Like {@link selectRowIdPage} but returns each row's `data` too, for the bulk-update worker which |
no test coverage detected