Adding test cases for counting as well as some small fixes.
This commit is contained in:
parent
0caff1a404
commit
e0d8a66fd8
|
@ -12,21 +12,21 @@ import {
|
|||
BBReferenceFieldMetadata,
|
||||
FieldSchema,
|
||||
FieldType,
|
||||
INTERNAL_TABLE_SOURCE_ID,
|
||||
JsonFieldMetadata,
|
||||
JsonTypes,
|
||||
Operation,
|
||||
prefixed,
|
||||
QueryJson,
|
||||
QueryOptions,
|
||||
RelationshipsJson,
|
||||
SearchFilters,
|
||||
SortOrder,
|
||||
SqlClient,
|
||||
SqlQuery,
|
||||
SqlQueryBinding,
|
||||
Table,
|
||||
TableSourceType,
|
||||
INTERNAL_TABLE_SOURCE_ID,
|
||||
QueryOptions,
|
||||
JsonTypes,
|
||||
prefixed,
|
||||
SortOrder,
|
||||
} from "@budibase/types"
|
||||
import environment from "../environment"
|
||||
import { helpers } from "@budibase/shared-core"
|
||||
|
@ -824,6 +824,9 @@ class SqlQueryBuilder extends SqlTableQueryBuilder {
|
|||
await this.getReturningRow(queryFn, this.checkLookupKeys(id, json))
|
||||
)
|
||||
}
|
||||
if (operation === Operation.COUNT) {
|
||||
return results
|
||||
}
|
||||
if (operation !== Operation.READ) {
|
||||
return row
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
User,
|
||||
Row,
|
||||
RelationshipType,
|
||||
SearchResponse,
|
||||
} from "@budibase/types"
|
||||
import _ from "lodash"
|
||||
import tk from "timekeeper"
|
||||
|
@ -105,6 +106,17 @@ describe.each([
|
|||
}
|
||||
}
|
||||
|
||||
private async performSearchFullResponse(): Promise<SearchResponse<Row>> {
|
||||
if (isInMemory) {
|
||||
return { rows: dataFilters.search(_.cloneDeep(rows), this.query) }
|
||||
} else {
|
||||
return config.api.row.search(table._id!, {
|
||||
...this.query,
|
||||
tableId: table._id!,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// We originally used _.isMatch to compare rows, but found that when
|
||||
// comparing arrays it would return true if the source array was a subset of
|
||||
// the target array. This would sometimes create false matches. This
|
||||
|
@ -205,6 +217,34 @@ describe.each([
|
|||
)
|
||||
}
|
||||
|
||||
// Asserts that the query returns some property values - this cannot be used
|
||||
// to check row values, however this shouldn't be important for checking properties
|
||||
async toHaveProperty(
|
||||
properties: {
|
||||
key: keyof SearchResponse<Row>
|
||||
value?: any
|
||||
}[]
|
||||
) {
|
||||
const response = await this.performSearchFullResponse()
|
||||
for (let property of properties) {
|
||||
// eslint-disable-next-line jest/no-standalone-expect
|
||||
expect(response[property.key]).toBeDefined()
|
||||
if (property.value) {
|
||||
// eslint-disable-next-line jest/no-standalone-expect
|
||||
expect(response[property.key]).toEqual(property.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Asserts that the query doesn't return a property, e.g. pagination parameters.
|
||||
async toNotHaveProperty(properties: (keyof SearchResponse<Row>)[]) {
|
||||
const response = await this.performSearchFullResponse()
|
||||
for (let property of properties) {
|
||||
// eslint-disable-next-line jest/no-standalone-expect
|
||||
expect(response[property]).toBeUndefined()
|
||||
}
|
||||
}
|
||||
|
||||
// Asserts that the query returns rows matching the set of rows passed in.
|
||||
// The order of the rows is not important. Extra rows will not cause the
|
||||
// assertion to fail.
|
||||
|
@ -1797,4 +1837,40 @@ describe.each([
|
|||
{ two: "foo", other: [{ _id: otherRows[0]._id }] },
|
||||
]))
|
||||
})
|
||||
|
||||
// lucene can't count, and in memory there is no point
|
||||
!isLucene &&
|
||||
!isInMemory &&
|
||||
describe("row counting", () => {
|
||||
beforeAll(async () => {
|
||||
table = await createTable({
|
||||
name: {
|
||||
name: "name",
|
||||
type: FieldType.STRING,
|
||||
},
|
||||
})
|
||||
await createRows([{ name: "a" }, { name: "b" }])
|
||||
})
|
||||
|
||||
it("should be able to count rows when option set", () =>
|
||||
expectSearch({
|
||||
countRows: true,
|
||||
query: {
|
||||
notEmpty: {
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
}).toHaveProperty([{ key: "totalRows", value: 2 }, { key: "rows" }]))
|
||||
|
||||
it("shouldn't count rows when option is not set", () => {
|
||||
expectSearch({
|
||||
countRows: false,
|
||||
query: {
|
||||
notEmpty: {
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
}).toNotHaveProperty(["totalRows"])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -230,10 +230,12 @@ export async function search(
|
|||
nextRow = processed.pop()
|
||||
}
|
||||
|
||||
let rowCount: number | undefined
|
||||
let totalRows: number | undefined
|
||||
if (options.countRows) {
|
||||
// get the total count of rows
|
||||
rowCount = await runSqlQuery(request, allTables, { countTotalRows: true })
|
||||
totalRows = await runSqlQuery(request, allTables, {
|
||||
countTotalRows: true,
|
||||
})
|
||||
}
|
||||
|
||||
// get the rows
|
||||
|
@ -248,24 +250,18 @@ export async function search(
|
|||
finalRows = finalRows.map((r: any) => pick(r, fields))
|
||||
}
|
||||
|
||||
// check for pagination
|
||||
if (paginate) {
|
||||
const response: SearchResponse<Row> = {
|
||||
rows: finalRows,
|
||||
}
|
||||
if (nextRow) {
|
||||
response.hasNextPage = true
|
||||
response.bookmark = bookmark + 1
|
||||
}
|
||||
if (rowCount != null) {
|
||||
response.totalRows = rowCount
|
||||
}
|
||||
return response
|
||||
} else {
|
||||
return {
|
||||
rows: finalRows,
|
||||
}
|
||||
const response: SearchResponse<Row> = {
|
||||
rows: finalRows,
|
||||
}
|
||||
if (totalRows) {
|
||||
response.totalRows = totalRows
|
||||
}
|
||||
// check for pagination
|
||||
if (paginate && nextRow) {
|
||||
response.hasNextPage = true
|
||||
response.bookmark = bookmark + 1
|
||||
}
|
||||
return response
|
||||
} catch (err: any) {
|
||||
const msg = typeof err === "string" ? err : err.message
|
||||
if (err.status === 404 && msg?.includes(SQLITE_DESIGN_DOC_ID)) {
|
||||
|
|
Loading…
Reference in New Issue