diff --git a/packages/server/src/api/routes/tests/search.spec.ts b/packages/server/src/api/routes/tests/search.spec.ts index 090514250d..1ec5ca792a 100644 --- a/packages/server/src/api/routes/tests/search.spec.ts +++ b/packages/server/src/api/routes/tests/search.spec.ts @@ -408,7 +408,6 @@ describe.each([ }) }) - // We've decided not to try and support binding for in-memory search just now. !isInMemory && describe("bindings", () => { let globalUsers: any = [] @@ -528,6 +527,20 @@ describe.each([ ]) }) + !isLucene && + it("should return all rows matching the session user firstname when logical operator used", async () => { + await expectQuery({ + $and: { + conditions: [{ equal: { name: "{{ [user].firstName }}" } }], + }, + }).toContainExactly([ + { + name: config.getUser().firstName, + appointment: future.toISOString(), + }, + ]) + }) + it("should parse the date binding and return all rows after the resolved value", async () => { await tk.withFreeze(serverTime, async () => { await expectQuery({ diff --git a/packages/server/src/sdk/app/rows/search/utils.ts b/packages/server/src/sdk/app/rows/search/utils.ts index 6548f963b8..1dba420a28 100644 --- a/packages/server/src/sdk/app/rows/search/utils.ts +++ b/packages/server/src/sdk/app/rows/search/utils.ts @@ -11,7 +11,7 @@ import { RowSearchParams, } from "@budibase/types" import { db as dbCore, context } from "@budibase/backend-core" -import { utils } from "@budibase/shared-core" +import { utils, dataFilters } from "@budibase/shared-core" export async function paginatedSearch( query: SearchFilters, @@ -31,13 +31,13 @@ export async function fullSearch( function findColumnInQueries( column: string, - options: RowSearchParams, + filters: SearchFilters, callback: (filter: any) => any ) { - if (!options.query) { + if (!filters) { return } - for (let filterBlock of Object.values(options.query)) { + for (let filterBlock of Object.values(filters)) { if (typeof filterBlock !== "object") { continue } @@ -49,8 +49,8 @@ function findColumnInQueries( } } -function userColumnMapping(column: string, options: RowSearchParams) { - findColumnInQueries(column, options, (filterValue: any): any => { +function userColumnMapping(column: string, filters: SearchFilters) { + findColumnInQueries(column, filters, (filterValue: any): any => { const isArray = Array.isArray(filterValue), isString = typeof filterValue === "string" if (!isString && !isArray) { @@ -83,26 +83,31 @@ function userColumnMapping(column: string, options: RowSearchParams) { // maps through the search parameters to check if any of the inputs are invalid // based on the table schema, converts them to something that is valid. export function searchInputMapping(table: Table, options: RowSearchParams) { - for (let [key, column] of Object.entries(table.schema || {})) { - switch (column.type) { - case FieldType.BB_REFERENCE_SINGLE: { - const subtype = column.subtype - switch (subtype) { - case BBReferenceFieldSubType.USER: - userColumnMapping(key, options) - break + // need an internal function to loop over filters, because this takes the full options + function checkFilters(filters: SearchFilters) { + for (let [key, column] of Object.entries(table.schema || {})) { + switch (column.type) { + case FieldType.BB_REFERENCE_SINGLE: { + const subtype = column.subtype + switch (subtype) { + case BBReferenceFieldSubType.USER: + userColumnMapping(key, filters) + break - default: - utils.unreachable(subtype) + default: + utils.unreachable(subtype) + } + break + } + case FieldType.BB_REFERENCE: { + userColumnMapping(key, filters) + break } - break - } - case FieldType.BB_REFERENCE: { - userColumnMapping(key, options) - break } } + return dataFilters.recurseLogicalOperators(filters, checkFilters) } + options.query = checkFilters(options.query) return options } diff --git a/packages/shared-core/src/filters.ts b/packages/shared-core/src/filters.ts index 45e9a7c6d0..ef0500b01a 100644 --- a/packages/shared-core/src/filters.ts +++ b/packages/shared-core/src/filters.ts @@ -124,7 +124,7 @@ export function recurseLogicalOperators( fn: (f: SearchFilters) => SearchFilters ) { for (const logical of LOGICAL_OPERATORS) { - if (filters[logical]) { + if (filters?.[logical]) { filters[logical]!.conditions = filters[logical]!.conditions.map( condition => fn(condition) )