Fixing issue #2788 - making client side queries and SQL queries consistent with internal table ones.

This commit is contained in:
mike12345567 2021-10-06 17:38:32 +01:00
parent 2d9a087efe
commit 3cea3dd510
5 changed files with 77 additions and 0 deletions

View File

@ -44,6 +44,15 @@ export const OperatorOptions = {
},
}
export const NoEmptyFilterStrings = [
OperatorOptions.StartsWith.value,
OperatorOptions.Like.value,
OperatorOptions.Equals.value,
OperatorOptions.NotEquals.value,
OperatorOptions.Contains.value,
OperatorOptions.NotContains.value,
]
/**
* Returns the valid operator options for a certain data type
* @param type the data type

View File

@ -1,3 +1,26 @@
import { NoEmptyFilterStrings } from "../constants/lucene"
/**
* Removes any fields that contain empty strings that would cause inconsistent
* behaviour with how backend tables are filtered (no value means no filter).
*/
function cleanupQuery(query) {
if (!query) {
return query
}
for (let filterField of NoEmptyFilterStrings) {
if (!query[filterField]) {
continue
}
for (let [key, value] of Object.entries(query[filterField])) {
if (!value || value === "") {
delete query[filterField][key]
}
}
}
return query
}
/**
* Builds a lucene JSON query from the filter structure generated in the builder
* @param filter the builder filter structure
@ -76,6 +99,8 @@ export const luceneQuery = (docs, query) => {
if (!query) {
return docs
}
// make query consistent first
query = cleanupQuery(query)
// Iterates over a set of filters and evaluates a fail function against a doc
const match = (type, failFn) => doc => {

View File

@ -2,6 +2,7 @@ const {
DataSourceOperation,
SortDirection,
FieldTypes,
NoEmptyFilterStrings,
} = require("../../../constants")
const {
breakExternalTableId,
@ -11,6 +12,19 @@ const ExternalRequest = require("./ExternalRequest")
const CouchDB = require("../../../db")
async function handleRequest(appId, operation, tableId, opts = {}) {
// make sure the filters are cleaned up, no empty strings for equals, fuzzy or string
if (opts && opts.filters) {
for (let filterField of NoEmptyFilterStrings) {
if (!opts.filters[filterField]) {
continue
}
for (let [key, value] of Object.entries(opts.filters[filterField])) {
if (!value || value === "") {
delete opts.filters[filterField][key]
}
}
}
}
return new ExternalRequest(appId, operation, tableId, opts.datasource).run(
opts
)

View File

@ -6,6 +6,29 @@ exports.JobQueues = {
AUTOMATIONS: "automationQueue",
}
const FilterTypes = {
STRING: "string",
FUZZY: "fuzzy",
RANGE: "range",
EQUAL: "equal",
NOT_EQUAL: "notEqual",
EMPTY: "empty",
NOT_EMPTY: "notEmpty",
CONTAINS: "contains",
NOT_CONTAINS: "notContains",
ONE_OF: "oneOf",
}
exports.FilterTypes = FilterTypes
exports.NoEmptyFilterStrings = [
FilterTypes.STRING,
FilterTypes.FUZZY,
FilterTypes.EQUAL,
FilterTypes.NOT_EQUAL,
FilterTypes.CONTAINS,
FilterTypes.NOT_CONTAINS,
]
exports.FieldTypes = {
STRING: "string",
LONGFORM: "longform",

View File

@ -55,6 +55,12 @@ function addFilters(
query = query[fnc](key, "ilike", `${value}%`)
})
}
if (filters.fuzzy) {
iterate(filters.fuzzy, (key, value) => {
const fnc = allOr ? "orWhere" : "where"
query = query[fnc](key, "ilike", `%${value}%`)
})
}
if (filters.range) {
iterate(filters.range, (key, value) => {
if (!value.high || !value.low) {