diff --git a/packages/backend-core/src/sql/sql.ts b/packages/backend-core/src/sql/sql.ts index 7ab3e8ca80..9bc2092b83 100644 --- a/packages/backend-core/src/sql/sql.ts +++ b/packages/backend-core/src/sql/sql.ts @@ -596,6 +596,9 @@ class InternalBuilder { const offset = page * paginate.limit foundLimit = paginate.limit foundOffset = offset + } else if (paginate && paginate.offset && paginate.limit) { + foundLimit = paginate.limit + foundOffset = paginate.offset } else if (paginate && paginate.limit) { foundLimit = paginate.limit } diff --git a/packages/server/src/api/routes/tests/search.spec.ts b/packages/server/src/api/routes/tests/search.spec.ts index 22971c9c1f..f651908c01 100644 --- a/packages/server/src/api/routes/tests/search.spec.ts +++ b/packages/server/src/api/routes/tests/search.spec.ts @@ -512,75 +512,63 @@ describe.each([ ]) }) - // TODO(samwho): fix for SQS - !isSqs && - it("should match the session user id in a multi user field", async () => { - const allUsers = [...globalUsers, config.getUser()].map( - (user: any) => { + it("should match the session user id in a multi user field", async () => { + const allUsers = [...globalUsers, config.getUser()].map((user: any) => { + return { _id: user._id } + }) + + await expectQuery({ + contains: { multi_user: ["{{ [user]._id }}"] }, + }).toContainExactly([ + { + name: "multi user with session user", + multi_user: allUsers, + }, + ]) + }) + + it("should match the session user id in a deprecated multi user field", async () => { + const allUsers = [...globalUsers, config.getUser()].map((user: any) => { + return { _id: user._id } + }) + + await expectQuery({ + contains: { deprecated_multi_user: ["{{ [user]._id }}"] }, + }).toContainExactly([ + { + name: "deprecated multi user with session user", + deprecated_multi_user: allUsers, + }, + ]) + }) + + it("should not match the session user id in a multi user field", async () => { + await expectQuery({ + notContains: { multi_user: ["{{ [user]._id }}"] }, + notEmpty: { multi_user: true }, + }).toContainExactly([ + { + name: "multi user", + multi_user: globalUsers.map((user: any) => { return { _id: user._id } - } - ) + }), + }, + ]) + }) - await expectQuery({ - contains: { multi_user: ["{{ [user]._id }}"] }, - }).toContainExactly([ - { - name: "multi user with session user", - multi_user: allUsers, - }, - ]) - }) - - // TODO(samwho): fix for SQS - !isSqs && - it("should match the session user id in a deprecated multi user field", async () => { - const allUsers = [...globalUsers, config.getUser()].map( - (user: any) => { + it("should not match the session user id in a deprecated multi user field", async () => { + await expectQuery({ + notContains: { deprecated_multi_user: ["{{ [user]._id }}"] }, + notEmpty: { deprecated_multi_user: true }, + }).toContainExactly([ + { + name: "deprecated multi user", + deprecated_multi_user: globalUsers.map((user: any) => { return { _id: user._id } - } - ) - - await expectQuery({ - contains: { deprecated_multi_user: ["{{ [user]._id }}"] }, - }).toContainExactly([ - { - name: "deprecated multi user with session user", - deprecated_multi_user: allUsers, - }, - ]) - }) - - // TODO(samwho): fix for SQS - !isSqs && - it("should not match the session user id in a multi user field", async () => { - await expectQuery({ - notContains: { multi_user: ["{{ [user]._id }}"] }, - notEmpty: { multi_user: true }, - }).toContainExactly([ - { - name: "multi user", - multi_user: globalUsers.map((user: any) => { - return { _id: user._id } - }), - }, - ]) - }) - - // TODO(samwho): fix for SQS - !isSqs && - it("should not match the session user id in a deprecated multi user field", async () => { - await expectQuery({ - notContains: { deprecated_multi_user: ["{{ [user]._id }}"] }, - notEmpty: { deprecated_multi_user: true }, - }).toContainExactly([ - { - name: "deprecated multi user", - deprecated_multi_user: globalUsers.map((user: any) => { - return { _id: user._id } - }), - }, - ]) - }) + }), + }, + ]) + }) it("should match the session user id and a user table row id using helpers, user binding and a static user id.", async () => { await expectQuery({ @@ -1552,38 +1540,34 @@ describe.each([ }) }) - // TODO(samwho): fix for SQS - !isSqs && - describe("pagination", () => { - it("should paginate through all rows", async () => { - // @ts-ignore - let bookmark: string | number = undefined - let rows: Row[] = [] + describe("pagination", () => { + it("should paginate through all rows", async () => { + // @ts-ignore + let bookmark: string | number = undefined + let rows: Row[] = [] - // eslint-disable-next-line no-constant-condition - while (true) { - const response = await config.api.row.search(table._id!, { - tableId: table._id!, - limit: 3, - query: {}, - bookmark, - paginate: true, - }) + // eslint-disable-next-line no-constant-condition + while (true) { + const response = await config.api.row.search(table._id!, { + tableId: table._id!, + limit: 3, + query: {}, + bookmark, + paginate: true, + }) - rows.push(...response.rows) + rows.push(...response.rows) - if (!response.bookmark || !response.hasNextPage) { - break - } - bookmark = response.bookmark + if (!response.bookmark || !response.hasNextPage) { + break } + bookmark = response.bookmark + } - expect(rows).toHaveLength(10) - expect(rows.map(row => row.auto)).toEqual( - expect.arrayContaining([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) - ) - }) + const autoValues = rows.map(row => row.auto).sort((a, b) => a - b) + expect(autoValues).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) }) + }) }) describe("field name 1:name", () => { diff --git a/packages/server/src/sdk/app/rows/search/sqs.ts b/packages/server/src/sdk/app/rows/search/sqs.ts index 59a0afc0a4..98b4053931 100644 --- a/packages/server/src/sdk/app/rows/search/sqs.ts +++ b/packages/server/src/sdk/app/rows/search/sqs.ts @@ -167,13 +167,9 @@ export async function search( const sortField = table.schema[params.sort] const sortType = sortField.type === FieldType.NUMBER ? SortType.NUMBER : SortType.STRING - const sortDirection = - params.sortOrder === SortOrder.ASCENDING - ? SortOrder.ASCENDING - : SortOrder.DESCENDING request.sort = { [sortField.name]: { - direction: sortDirection, + direction: params.sortOrder || SortOrder.DESCENDING, type: sortType as SortType, }, } @@ -182,14 +178,15 @@ export async function search( if (params.bookmark && typeof params.bookmark !== "number") { throw new Error("Unable to paginate with string based bookmarks") } - const bookmark: number = (params.bookmark as number) || 1 - const limit = params.limit + + const bookmark: number = (params.bookmark as number) || 0 if (paginate && params.limit) { request.paginate = { limit: params.limit + 1, - page: bookmark, + offset: bookmark * params.limit, } } + try { const rows = await runSqlQuery(request, allTables) @@ -221,18 +218,12 @@ export async function search( } // check for pagination - if (paginate && limit) { + if (paginate) { const response: SearchResponse = { rows: finalRows, } - const prevLimit = request.paginate!.limit - request.paginate = { - limit: 1, - page: bookmark * prevLimit + 1, - } - const hasNextPage = !!nextRow - response.hasNextPage = hasNextPage - if (hasNextPage) { + if (nextRow) { + response.hasNextPage = true response.bookmark = bookmark + 1 } return response diff --git a/packages/types/src/sdk/search.ts b/packages/types/src/sdk/search.ts index 00bb6e267d..e5cbccf5c1 100644 --- a/packages/types/src/sdk/search.ts +++ b/packages/types/src/sdk/search.ts @@ -85,6 +85,7 @@ export interface SortJson { export interface PaginationJson { limit: number page?: string | number + offset?: number } export interface RenameColumn {