Merge pull request #14763 from Budibase/view-calculation-sort-by-calculations

Allow sorting by calculation fields.
This commit is contained in:
Sam Rose 2024-10-11 16:17:27 +01:00 committed by GitHub
commit 58f3f31ecc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 156 additions and 13 deletions

View File

@ -273,6 +273,7 @@ class InternalBuilder {
const col = parts.pop()!
const schema = this.table.schema[col]
let identifier = this.quotedIdentifier(field)
if (
schema.type === FieldType.STRING ||
schema.type === FieldType.LONGFORM ||
@ -957,6 +958,13 @@ class InternalBuilder {
return query
}
isAggregateField(field: string): boolean {
const found = this.query.resource?.aggregations?.find(
aggregation => aggregation.name === field
)
return !!found
}
addSorting(query: Knex.QueryBuilder): Knex.QueryBuilder {
let { sort, resource } = this.query
const primaryKey = this.table.primary
@ -979,13 +987,17 @@ class InternalBuilder {
nulls = value.direction === SortOrder.ASCENDING ? "first" : "last"
}
let composite = `${aliased}.${key}`
if (this.client === SqlClient.ORACLE) {
query = query.orderByRaw(
`${this.convertClobs(composite)} ${direction} nulls ${nulls}`
)
if (this.isAggregateField(key)) {
query = query.orderBy(key, direction, nulls)
} else {
query = query.orderBy(composite, direction, nulls)
let composite = `${aliased}.${key}`
if (this.client === SqlClient.ORACLE) {
query = query.orderByRaw(
`${this.convertClobs(composite)} ${direction} nulls ${nulls}`
)
} else {
query = query.orderBy(composite, direction, nulls)
}
}
}
}

View File

@ -3381,6 +3381,124 @@ describe.each([
expect(rows).toHaveLength(1)
expect(rows[0].sum).toEqual(3)
})
it("should be able to sort by group by field", async () => {
const table = await config.api.table.save(
saveTableRequest({
schema: {
quantity: {
type: FieldType.NUMBER,
name: "quantity",
},
price: {
type: FieldType.NUMBER,
name: "price",
},
},
})
)
const view = await config.api.viewV2.create({
tableId: table._id!,
name: generator.guid(),
type: ViewV2Type.CALCULATION,
schema: {
quantity: { visible: true },
sum: {
visible: true,
calculationType: CalculationType.SUM,
field: "price",
},
},
})
await config.api.row.bulkImport(table._id!, {
rows: [
{
quantity: 1,
price: 1,
},
{
quantity: 1,
price: 2,
},
{
quantity: 2,
price: 10,
},
],
})
const { rows } = await config.api.viewV2.search(view.id, {
query: {},
sort: "quantity",
sortOrder: SortOrder.DESCENDING,
})
expect(rows).toEqual([
expect.objectContaining({ quantity: 2, sum: 10 }),
expect.objectContaining({ quantity: 1, sum: 3 }),
])
})
it("should be able to sort by a calculation", async () => {
const table = await config.api.table.save(
saveTableRequest({
schema: {
quantity: {
type: FieldType.NUMBER,
name: "quantity",
},
price: {
type: FieldType.NUMBER,
name: "price",
},
},
})
)
await config.api.row.bulkImport(table._id!, {
rows: [
{
quantity: 1,
price: 1,
},
{
quantity: 1,
price: 2,
},
{
quantity: 2,
price: 10,
},
],
})
const view = await config.api.viewV2.create({
tableId: table._id!,
name: generator.guid(),
type: ViewV2Type.CALCULATION,
schema: {
quantity: { visible: true },
sum: {
visible: true,
calculationType: CalculationType.SUM,
field: "price",
},
},
})
const { rows } = await config.api.viewV2.search(view.id, {
query: {},
sort: "sum",
sortOrder: SortOrder.DESCENDING,
})
expect(rows).toEqual([
expect.objectContaining({ quantity: 2, sum: 10 }),
expect.objectContaining({ quantity: 1, sum: 3 }),
])
})
})
!isLucene &&

View File

@ -418,13 +418,26 @@ export async function search(
if (params.sort) {
const sortField = table.schema[params.sort]
const sortType =
sortField.type === FieldType.NUMBER ? SortType.NUMBER : SortType.STRING
request.sort = {
[mapToUserColumn(sortField.name)]: {
direction: params.sortOrder || SortOrder.ASCENDING,
type: sortType as SortType,
},
const isAggregateField = aggregations.some(agg => agg.name === params.sort)
if (isAggregateField) {
request.sort = {
[params.sort]: {
direction: params.sortOrder || SortOrder.ASCENDING,
type: SortType.NUMBER,
},
}
} else if (sortField) {
const sortType =
sortField.type === FieldType.NUMBER ? SortType.NUMBER : SortType.STRING
request.sort = {
[mapToUserColumn(sortField.name)]: {
direction: params.sortOrder || SortOrder.ASCENDING,
type: sortType as SortType,
},
}
} else {
throw new Error(`Unable to sort by ${params.sort}`)
}
}