Fixing issue #2788 - making client side queries and SQL queries consistent with internal table ones.
This commit is contained in:
parent
3cc733eefd
commit
3878cf76cd
|
@ -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
|
* Returns the valid operator options for a certain data type
|
||||||
* @param type the data type
|
* @param type the data type
|
||||||
|
|
|
@ -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
|
* Builds a lucene JSON query from the filter structure generated in the builder
|
||||||
* @param filter the builder filter structure
|
* @param filter the builder filter structure
|
||||||
|
@ -76,6 +99,8 @@ export const luceneQuery = (docs, query) => {
|
||||||
if (!query) {
|
if (!query) {
|
||||||
return docs
|
return docs
|
||||||
}
|
}
|
||||||
|
// make query consistent first
|
||||||
|
query = cleanupQuery(query)
|
||||||
|
|
||||||
// Iterates over a set of filters and evaluates a fail function against a doc
|
// Iterates over a set of filters and evaluates a fail function against a doc
|
||||||
const match = (type, failFn) => doc => {
|
const match = (type, failFn) => doc => {
|
||||||
|
|
|
@ -2,6 +2,7 @@ const {
|
||||||
DataSourceOperation,
|
DataSourceOperation,
|
||||||
SortDirection,
|
SortDirection,
|
||||||
FieldTypes,
|
FieldTypes,
|
||||||
|
NoEmptyFilterStrings,
|
||||||
} = require("../../../constants")
|
} = require("../../../constants")
|
||||||
const {
|
const {
|
||||||
breakExternalTableId,
|
breakExternalTableId,
|
||||||
|
@ -11,6 +12,19 @@ const ExternalRequest = require("./ExternalRequest")
|
||||||
const CouchDB = require("../../../db")
|
const CouchDB = require("../../../db")
|
||||||
|
|
||||||
async function handleRequest(appId, operation, tableId, opts = {}) {
|
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(
|
return new ExternalRequest(appId, operation, tableId, opts.datasource).run(
|
||||||
opts
|
opts
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,6 +6,29 @@ exports.JobQueues = {
|
||||||
AUTOMATIONS: "automationQueue",
|
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 = {
|
exports.FieldTypes = {
|
||||||
STRING: "string",
|
STRING: "string",
|
||||||
LONGFORM: "longform",
|
LONGFORM: "longform",
|
||||||
|
|
|
@ -55,6 +55,12 @@ function addFilters(
|
||||||
query = query[fnc](key, "ilike", `${value}%`)
|
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) {
|
if (filters.range) {
|
||||||
iterate(filters.range, (key, value) => {
|
iterate(filters.range, (key, value) => {
|
||||||
if (!value.high || !value.low) {
|
if (!value.high || !value.low) {
|
||||||
|
|
Loading…
Reference in New Issue