( table: TableDefinition, options: QueryOptions, requestId: string )
| 949 | } |
| 950 | |
| 951 | export async function queryRows( |
| 952 | table: TableDefinition, |
| 953 | options: QueryOptions, |
| 954 | requestId: string |
| 955 | ): Promise<QueryResult> { |
| 956 | const { |
| 957 | filter, |
| 958 | sort, |
| 959 | limit = TABLE_LIMITS.DEFAULT_QUERY_LIMIT, |
| 960 | offset = 0, |
| 961 | after, |
| 962 | includeTotal = true, |
| 963 | withExecutions = true, |
| 964 | } = options |
| 965 | |
| 966 | const tableName = USER_TABLE_ROWS_SQL_NAME |
| 967 | const columns = table.schema.columns |
| 968 | |
| 969 | // Hide rows a running delete job is about to remove — both the page and the count below share |
| 970 | // this clause, so totals stay consistent with the visible rows. |
| 971 | const [deleteMask, fractionalOrdering] = await Promise.all([ |
| 972 | pendingDeleteMask(table), |
| 973 | isFeatureEnabled('tables-fractional-ordering'), |
| 974 | ]) |
| 975 | |
| 976 | const baseConditions = and( |
| 977 | eq(userTableRows.tableId, table.id), |
| 978 | eq(userTableRows.workspaceId, table.workspaceId), |
| 979 | deleteMask |
| 980 | ) |
| 981 | |
| 982 | let whereClause = baseConditions |
| 983 | if (filter && Object.keys(filter).length > 0) { |
| 984 | const filterClause = buildFilterClause(filter, tableName, columns) |
| 985 | if (filterClause) { |
| 986 | whereClause = and(baseConditions, filterClause) |
| 987 | } |
| 988 | } |
| 989 | |
| 990 | // Keyset page: seek past the cursor on the default `(order_key, id)` order instead of paying |
| 991 | // OFFSET's scan-and-discard of every prior row (O(N²) across a deep scroll / full drain). Only |
| 992 | // valid without a custom sort — the contract rejects `after` + `sort` together. The count below |
| 993 | // deliberately excludes the cursor: totals cover the whole view, not the remaining pages. |
| 994 | const pageWhere = |
| 995 | after && !sort |
| 996 | ? and( |
| 997 | whereClause, |
| 998 | sql`(${userTableRows.orderKey}, ${userTableRows.id}) > (${after.orderKey}, ${after.id})` |
| 999 | ) |
| 1000 | : whereClause |
| 1001 | |
| 1002 | const buildPageQuery = (executor: DbExecutor) => { |
| 1003 | const query = executor |
| 1004 | .select() |
| 1005 | .from(userTableRows) |
| 1006 | .where(pageWhere ?? baseConditions) |
| 1007 | .orderBy(buildRowOrderBySql(sort, tableName, columns, fractionalOrdering)) |
| 1008 | return after ? query.limit(limit) : query.limit(limit).offset(offset) |
no test coverage detected