Merge branch 'master' into fix-flake

This commit is contained in:
Sam Rose 2024-07-11 15:08:59 +01:00 committed by GitHub
commit e70e7eeb1d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 46 additions and 54 deletions

View File

@ -1,6 +1,6 @@
{ {
"$schema": "node_modules/lerna/schemas/lerna-schema.json", "$schema": "node_modules/lerna/schemas/lerna-schema.json",
"version": "2.29.17", "version": "2.29.18",
"npmClient": "yarn", "npmClient": "yarn",
"packages": [ "packages": [
"packages/*", "packages/*",

View File

@ -1,6 +1,6 @@
import env from "../environment" import env from "../environment"
import { DEFAULT_TENANT_ID, SEPARATOR, DocumentType } from "../constants" import { DEFAULT_TENANT_ID, SEPARATOR, DocumentType } from "../constants"
import { getTenantId, getGlobalDBName } from "../context" import { getTenantId, getGlobalDBName, isMultiTenant } from "../context"
import { doWithDB, directCouchAllDbs } from "./db" import { doWithDB, directCouchAllDbs } from "./db"
import { AppState, DeletedApp, getAppMetadata } from "../cache/appMetadata" import { AppState, DeletedApp, getAppMetadata } from "../cache/appMetadata"
import { isDevApp, isDevAppID, getProdAppID } from "../docIds/conversions" import { isDevApp, isDevAppID, getProdAppID } from "../docIds/conversions"
@ -213,6 +213,11 @@ export function isSqsEnabledForTenant(): boolean {
return false return false
} }
// single tenant (self host and dev) always enabled if flag set
if (!isMultiTenant()) {
return true
}
// This is to guard against the situation in tests where tests pass because // This is to guard against the situation in tests where tests pass because
// we're not actually using SQS, we're using Lucene and the tests pass due to // we're not actually using SQS, we're using Lucene and the tests pass due to
// parity. // parity.

View File

@ -809,6 +809,20 @@ describe.each([
}, },
}).toContainExactly([{ name: "foo" }, { name: "bar" }]) }).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", () => { describe("fuzzy", () => {

View File

@ -24,16 +24,6 @@ export enum FilterTypes {
ONE_OF = "oneOf", 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 = [ export const CanSwitchTypes = [
[FieldType.JSON, FieldType.ARRAY], [FieldType.JSON, FieldType.ARRAY],
[ [

View File

@ -2,14 +2,12 @@ import {
EmptyFilterOption, EmptyFilterOption,
Row, Row,
RowSearchParams, RowSearchParams,
SearchFilters,
SearchResponse, SearchResponse,
SortOrder, SortOrder,
} from "@budibase/types" } from "@budibase/types"
import { isExternalTableID } from "../../../integrations/utils" import { isExternalTableID } from "../../../integrations/utils"
import * as internal from "./search/internal" import * as internal from "./search/internal"
import * as external from "./search/external" import * as external from "./search/external"
import { NoEmptyFilterStrings } from "../../../constants"
import * as sqs from "./search/sqs" import * as sqs from "./search/sqs"
import { ExportRowsParams, ExportRowsResult } from "./search/types" import { ExportRowsParams, ExportRowsResult } from "./search/types"
import { dataFilters } from "@budibase/shared-core" import { dataFilters } from "@budibase/shared-core"
@ -32,44 +30,11 @@ function pickApi(tableId: any) {
return internal 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( export async function search(
options: RowSearchParams options: RowSearchParams
): Promise<SearchResponse<Row>> { ): Promise<SearchResponse<Row>> {
const isExternalTable = isExternalTableID(options.tableId) const isExternalTable = isExternalTableID(options.tableId)
options.query = removeEmptyFilters(options.query || {}) options.query = dataFilters.cleanupQuery(options.query || {})
options.query = dataFilters.fixupFilterArrays(options.query) options.query = dataFilters.fixupFilterArrays(options.query)
if ( if (
!dataFilters.hasFilters(options.query) && !dataFilters.hasFilters(options.query) &&

View File

@ -106,31 +106,49 @@ export const NoEmptyFilterStrings = [
OperatorOptions.NotEquals.value, OperatorOptions.NotEquals.value,
OperatorOptions.Contains.value, OperatorOptions.Contains.value,
OperatorOptions.NotContains.value, OperatorOptions.NotContains.value,
OperatorOptions.ContainsAny.value,
OperatorOptions.In.value,
] as (keyof SearchQueryFields)[] ] as (keyof SearchQueryFields)[]
/** /**
* Removes any fields that contain empty strings that would cause inconsistent * Removes any fields that contain empty strings that would cause inconsistent
* behaviour with how backend tables are filtered (no value means no filter). * 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) { if (!query) {
return query return query
} }
for (let filterField of NoEmptyFilterStrings) { for (let filterField of NoEmptyFilterStrings) {
const operator = filterField as SearchFilterOperator if (!query[filterField]) {
if (!query[operator]) {
continue continue
} }
for (let [key, value] of Object.entries(query[operator]!)) { for (let filterType of Object.keys(query)) {
if (value == null || value === "") { if (filterType !== filterField) {
delete query[operator]![key] 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 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 * Removes a numeric prefix on field names designed to give fields uniqueness
*/ */