From 55c72c715063cbcf69626fe5a7bca18f917f90ec Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Thu, 11 Jul 2024 14:12:43 +0200 Subject: [PATCH 1/3] Add tests --- .../server/src/api/routes/tests/search.spec.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/server/src/api/routes/tests/search.spec.ts b/packages/server/src/api/routes/tests/search.spec.ts index 8d3722300f..e2335cb71c 100644 --- a/packages/server/src/api/routes/tests/search.spec.ts +++ b/packages/server/src/api/routes/tests/search.spec.ts @@ -809,6 +809,20 @@ describe.each([ }, }).toContainExactly([{ name: "foo" }, { name: "bar" }]) }) + + it("empty arrays returns all when onEmptyFilter is set to return 'all'", async () => { + await expectQuery({ + onEmptyFilter: EmptyFilterOption.RETURN_ALL, + oneOf: { name: [] }, + }).toContainExactly([{ name: "foo" }, { name: "bar" }]) + }) + + it("empty arrays returns all when onEmptyFilter is set to return 'none'", async () => { + await expectQuery({ + onEmptyFilter: EmptyFilterOption.RETURN_NONE, + oneOf: { name: [] }, + }).toContainExactly([]) + }) }) describe("fuzzy", () => { From 9fb9c08aabdf14b07de734d41da9027c438ec390 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Thu, 11 Jul 2024 14:36:51 +0200 Subject: [PATCH 2/3] Merge duplicated code --- packages/server/src/constants/index.ts | 10 ------ packages/server/src/sdk/app/rows/search.ts | 37 +--------------------- packages/shared-core/src/filters.ts | 30 ++++++++++++++---- 3 files changed, 25 insertions(+), 52 deletions(-) diff --git a/packages/server/src/constants/index.ts b/packages/server/src/constants/index.ts index 4fcc9c5d06..316d27b3fc 100644 --- a/packages/server/src/constants/index.ts +++ b/packages/server/src/constants/index.ts @@ -24,16 +24,6 @@ export enum FilterTypes { ONE_OF = "oneOf", } -export const NoEmptyFilterStrings = [ - FilterTypes.STRING, - FilterTypes.FUZZY, - FilterTypes.EQUAL, - FilterTypes.NOT_EQUAL, - FilterTypes.CONTAINS, - FilterTypes.NOT_CONTAINS, - FilterTypes.CONTAINS_ANY, -] - export const CanSwitchTypes = [ [FieldType.JSON, FieldType.ARRAY], [ diff --git a/packages/server/src/sdk/app/rows/search.ts b/packages/server/src/sdk/app/rows/search.ts index 763fbb46ef..d074e8e2ac 100644 --- a/packages/server/src/sdk/app/rows/search.ts +++ b/packages/server/src/sdk/app/rows/search.ts @@ -2,14 +2,12 @@ import { EmptyFilterOption, Row, RowSearchParams, - SearchFilters, SearchResponse, SortOrder, } from "@budibase/types" import { isExternalTableID } from "../../../integrations/utils" import * as internal from "./search/internal" import * as external from "./search/external" -import { NoEmptyFilterStrings } from "../../../constants" import * as sqs from "./search/sqs" import { ExportRowsParams, ExportRowsResult } from "./search/types" import { dataFilters } from "@budibase/shared-core" @@ -32,44 +30,11 @@ function pickApi(tableId: any) { return internal } -function isEmptyArray(value: any) { - return Array.isArray(value) && value.length === 0 -} - -// don't do a pure falsy check, as 0 is included -// https://github.com/Budibase/budibase/issues/10118 -export function removeEmptyFilters(filters: SearchFilters) { - for (let filterField of NoEmptyFilterStrings) { - if (!filters[filterField]) { - continue - } - - for (let filterType of Object.keys(filters)) { - if (filterType !== filterField) { - continue - } - // don't know which one we're checking, type could be anything - const value = filters[filterType] as unknown - if (typeof value === "object") { - for (let [key, value] of Object.entries( - filters[filterType] as object - )) { - if (value == null || value === "" || isEmptyArray(value)) { - // @ts-ignore - delete filters[filterField][key] - } - } - } - } - } - return filters -} - export async function search( options: RowSearchParams ): Promise> { const isExternalTable = isExternalTableID(options.tableId) - options.query = removeEmptyFilters(options.query || {}) + options.query = dataFilters.cleanupQuery(options.query || {}) options.query = dataFilters.fixupFilterArrays(options.query) if ( !dataFilters.hasFilters(options.query) && diff --git a/packages/shared-core/src/filters.ts b/packages/shared-core/src/filters.ts index d3fcae11e2..3369b5a3d1 100644 --- a/packages/shared-core/src/filters.ts +++ b/packages/shared-core/src/filters.ts @@ -106,31 +106,49 @@ export const NoEmptyFilterStrings = [ OperatorOptions.NotEquals.value, OperatorOptions.Contains.value, OperatorOptions.NotContains.value, + OperatorOptions.NotContains.value, + OperatorOptions.In.value, ] as (keyof SearchQueryFields)[] /** * Removes any fields that contain empty strings that would cause inconsistent * behaviour with how backend tables are filtered (no value means no filter). + * + * don't do a pure falsy check, as 0 is included + * https://github.com/Budibase/budibase/issues/10118 */ -const cleanupQuery = (query: SearchFilters) => { +export const cleanupQuery = (query: SearchFilters) => { if (!query) { return query } for (let filterField of NoEmptyFilterStrings) { - const operator = filterField as SearchFilterOperator - if (!query[operator]) { + if (!query[filterField]) { continue } - for (let [key, value] of Object.entries(query[operator]!)) { - if (value == null || value === "") { - delete query[operator]![key] + for (let filterType of Object.keys(query)) { + if (filterType !== filterField) { + continue + } + // don't know which one we're checking, type could be anything + const value = query[filterType] as unknown + if (typeof value === "object") { + for (let [key, value] of Object.entries(query[filterType] as object)) { + if (value == null || value === "" || isEmptyArray(value)) { + // @ts-ignore + delete query[filterField][key] + } + } } } } return query } +function isEmptyArray(value: any) { + return Array.isArray(value) && value.length === 0 +} + /** * Removes a numeric prefix on field names designed to give fields uniqueness */ From 2ff11d1a12e433154379e8e140ba3cb1d8ef2550 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Thu, 11 Jul 2024 15:02:32 +0200 Subject: [PATCH 3/3] Fix NoEmptyFilterStrings --- packages/shared-core/src/filters.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared-core/src/filters.ts b/packages/shared-core/src/filters.ts index 3369b5a3d1..6db89dd2f3 100644 --- a/packages/shared-core/src/filters.ts +++ b/packages/shared-core/src/filters.ts @@ -106,7 +106,7 @@ export const NoEmptyFilterStrings = [ OperatorOptions.NotEquals.value, OperatorOptions.Contains.value, OperatorOptions.NotContains.value, - OperatorOptions.NotContains.value, + OperatorOptions.ContainsAny.value, OperatorOptions.In.value, ] as (keyof SearchQueryFields)[]