Skip to content

Commit

Permalink
Merge pull request #14140 from Budibase/BUDI-8449/when-return-all-tab…
Browse files Browse the repository at this point in the history
…le-rows-is-selected-the-is-in-filter

When `return all table rows` is selected the is in filter returns nothing instead of all rows
  • Loading branch information
adrinr authored Jul 11, 2024
2 parents d01284d + 97e6f84 commit 2558519
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 52 deletions.
14 changes: 14 additions & 0 deletions packages/server/src/api/routes/tests/search.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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", () => {
Expand Down
10 changes: 0 additions & 10 deletions packages/server/src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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],
[
Expand Down
37 changes: 1 addition & 36 deletions packages/server/src/sdk/app/rows/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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<SearchResponse<Row>> {
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) &&
Expand Down
30 changes: 24 additions & 6 deletions packages/shared-core/src/filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,31 +106,49 @@ export const NoEmptyFilterStrings = [
OperatorOptions.NotEquals.value,
OperatorOptions.Contains.value,
OperatorOptions.NotContains.value,
OperatorOptions.ContainsAny.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
*/
Expand Down

0 comments on commit 2558519

Please sign in to comment.