Merge branch 'master' into budi-8730-views-filter-by-current-user_id-does-not-work

This commit is contained in:
Sam Rose 2024-10-11 16:42:37 +01:00 committed by GitHub
commit 13424218eb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 191 additions and 15 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

@ -14,6 +14,7 @@ import {
InternalTable,
tenancy,
features,
utils,
} from "@budibase/backend-core"
import { quotas } from "@budibase/pro"
import {
@ -757,6 +758,37 @@ describe.each([
})
})
describe("user column", () => {
beforeAll(async () => {
table = await config.api.table.save(
saveTableRequest({
schema: {
user: {
name: "user",
type: FieldType.BB_REFERENCE_SINGLE,
subtype: BBReferenceFieldSubType.USER,
default: "{{ [Current User]._id }}",
},
},
})
)
})
it("creates a new row with a default value successfully", async () => {
const row = await config.api.row.save(table._id!, {})
expect(row.user._id).toEqual(config.getUser()._id)
})
it("does not use default value if value specified", async () => {
const id = `us_${utils.newid()}`
await config.createUser({ _id: id })
const row = await config.api.row.save(table._id!, {
user: id,
})
expect(row.user._id).toEqual(id)
})
})
describe("bindings", () => {
describe("string column", () => {
beforeAll(async () => {

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}`)
}
}

View File

@ -67,7 +67,7 @@ const allowDefaultColumnByType: Record<FieldType, boolean> = {
[FieldType.SIGNATURE_SINGLE]: false,
[FieldType.LINK]: false,
[FieldType.BB_REFERENCE]: false,
[FieldType.BB_REFERENCE_SINGLE]: false,
[FieldType.BB_REFERENCE_SINGLE]: true,
}
export function canBeDisplayColumn(type: FieldType): boolean {

View File

@ -172,7 +172,7 @@ export const processSearchFilters = (
.sort((a, b) => {
return a.localeCompare(b)
})
.filter(key => key in filter)
.filter(key => filter[key])
if (filterPropertyKeys.length == 1) {
const key = filterPropertyKeys[0],

View File

@ -126,6 +126,7 @@ export interface BBReferenceSingleFieldMetadata
extends Omit<BaseFieldSchema, "subtype"> {
type: FieldType.BB_REFERENCE_SINGLE
subtype: Exclude<BBReferenceFieldSubType, BBReferenceFieldSubType.USERS>
default?: string
}
export interface AttachmentFieldMetadata extends BaseFieldSchema {