Range tests passing.
This commit is contained in:
parent
253fa0def8
commit
03b1823463
|
@ -18,12 +18,12 @@ import _ from "lodash"
|
|||
jest.unmock("mssql")
|
||||
|
||||
describe.each([
|
||||
// ["internal", undefined],
|
||||
["internal", undefined],
|
||||
["internal-sqs", undefined],
|
||||
// [DatabaseName.POSTGRES, getDatasource(DatabaseName.POSTGRES)],
|
||||
// [DatabaseName.MYSQL, getDatasource(DatabaseName.MYSQL)],
|
||||
// [DatabaseName.SQL_SERVER, getDatasource(DatabaseName.SQL_SERVER)],
|
||||
// [DatabaseName.MARIADB, getDatasource(DatabaseName.MARIADB)],
|
||||
[DatabaseName.POSTGRES, getDatasource(DatabaseName.POSTGRES)],
|
||||
[DatabaseName.MYSQL, getDatasource(DatabaseName.MYSQL)],
|
||||
[DatabaseName.SQL_SERVER, getDatasource(DatabaseName.SQL_SERVER)],
|
||||
[DatabaseName.MARIADB, getDatasource(DatabaseName.MARIADB)],
|
||||
])("/api/:sourceId/search (%s)", (name, dsProvider) => {
|
||||
const isSqs = name === "internal-sqs"
|
||||
const isInternal = name === "internal"
|
||||
|
@ -337,6 +337,20 @@ describe.each([
|
|||
expectQuery({
|
||||
range: { age: { low: 5, high: 9 } },
|
||||
}).toFindNothing())
|
||||
|
||||
// We never implemented half-open ranges in Lucene.
|
||||
!isInternal &&
|
||||
it("can search using just a low value", () =>
|
||||
expectQuery({
|
||||
range: { age: { low: 5 } },
|
||||
}).toContainExactly([{ age: 10 }]))
|
||||
|
||||
// We never implemented half-open ranges in Lucene.
|
||||
!isInternal &&
|
||||
it("can search using just a high value", () =>
|
||||
expectQuery({
|
||||
range: { age: { high: 5 } },
|
||||
}).toContainExactly([{ age: 1 }]))
|
||||
})
|
||||
|
||||
describe("sort", () => {
|
||||
|
@ -441,6 +455,20 @@ describe.each([
|
|||
expectQuery({
|
||||
range: { dob: { low: JAN_5TH, high: JAN_9TH } },
|
||||
}).toFindNothing())
|
||||
|
||||
// We never implemented half-open ranges in Lucene.
|
||||
!isInternal &&
|
||||
it("can search using just a low value", () =>
|
||||
expectQuery({
|
||||
range: { dob: { low: JAN_5TH } },
|
||||
}).toContainExactly([{ dob: JAN_10TH }]))
|
||||
|
||||
// We never implemented half-open ranges in Lucene.
|
||||
!isInternal &&
|
||||
it("can search using just a high value", () =>
|
||||
expectQuery({
|
||||
range: { dob: { high: JAN_5TH } },
|
||||
}).toContainExactly([{ dob: JAN_1ST }]))
|
||||
})
|
||||
|
||||
describe("sort", () => {
|
||||
|
@ -616,7 +644,7 @@ describe.each([
|
|||
// we've decided not to spend time on it.
|
||||
!isInternal &&
|
||||
describe("range", () => {
|
||||
it.only("successfully finds a row", () =>
|
||||
it("successfully finds a row", () =>
|
||||
expectQuery({
|
||||
range: { num: { low: SMALL, high: "5" } },
|
||||
}).toContainExactly([{ num: SMALL }]))
|
||||
|
@ -635,6 +663,16 @@ describe.each([
|
|||
expectQuery({
|
||||
range: { num: { low: "5", high: "5" } },
|
||||
}).toFindNothing())
|
||||
|
||||
it("can search using just a low value", () =>
|
||||
expectQuery({
|
||||
range: { num: { low: MEDIUM } },
|
||||
}).toContainExactly([{ num: MEDIUM }, { num: BIG }]))
|
||||
|
||||
it("can search using just a high value", () =>
|
||||
expectQuery({
|
||||
range: { num: { high: MEDIUM } },
|
||||
}).toContainExactly([{ num: SMALL }, { num: MEDIUM }]))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -146,7 +146,7 @@ class InternalBuilder {
|
|||
addFilters(
|
||||
query: Knex.QueryBuilder,
|
||||
filters: SearchFilters | undefined,
|
||||
tableName: string,
|
||||
table: Table,
|
||||
opts: { aliases?: Record<string, string>; relationship?: boolean }
|
||||
): Knex.QueryBuilder {
|
||||
function getTableName(name: string) {
|
||||
|
@ -161,7 +161,7 @@ class InternalBuilder {
|
|||
const updatedKey = dbCore.removeKeyNumbering(key)
|
||||
const isRelationshipField = updatedKey.includes(".")
|
||||
if (!opts.relationship && !isRelationshipField) {
|
||||
fn(`${getTableName(tableName)}.${updatedKey}`, value)
|
||||
fn(`${getTableName(table.name)}.${updatedKey}`, value)
|
||||
}
|
||||
if (opts.relationship && isRelationshipField) {
|
||||
const [filterTableName, property] = updatedKey.split(".")
|
||||
|
@ -276,6 +276,9 @@ class InternalBuilder {
|
|||
}
|
||||
if (filters.range) {
|
||||
iterate(filters.range, (key, value) => {
|
||||
const fieldName = key.split(".")[1]
|
||||
const field = table.schema[fieldName]
|
||||
|
||||
const isEmptyObject = (val: any) => {
|
||||
return (
|
||||
val &&
|
||||
|
@ -293,16 +296,46 @@ class InternalBuilder {
|
|||
highValid = isValidFilter(value.high)
|
||||
if (lowValid && highValid) {
|
||||
// Use a between operator if we have 2 valid range values
|
||||
const fnc = allOr ? "orWhereBetween" : "whereBetween"
|
||||
query = query[fnc](key, [value.low, value.high])
|
||||
if (
|
||||
field.type === FieldType.BIGINT &&
|
||||
this.client === SqlClient.SQL_LITE
|
||||
) {
|
||||
query = query.whereRaw(
|
||||
`CAST(${key} AS INTEGER) BETWEEN CAST(? AS INTEGER) AND CAST(? AS INTEGER)`,
|
||||
[value.low, value.high]
|
||||
)
|
||||
} else {
|
||||
const fnc = allOr ? "orWhereBetween" : "whereBetween"
|
||||
query = query[fnc](key, [value.low, value.high])
|
||||
}
|
||||
} else if (lowValid) {
|
||||
// Use just a single greater than operator if we only have a low
|
||||
const fnc = allOr ? "orWhere" : "where"
|
||||
query = query[fnc](key, ">", value.low)
|
||||
if (
|
||||
field.type === FieldType.BIGINT &&
|
||||
this.client === SqlClient.SQL_LITE
|
||||
) {
|
||||
query = query.whereRaw(
|
||||
`CAST(${key} AS INTEGER) >= CAST(? AS INTEGER)`,
|
||||
[value.low]
|
||||
)
|
||||
} else {
|
||||
const fnc = allOr ? "orWhere" : "where"
|
||||
query = query[fnc](key, ">=", value.low)
|
||||
}
|
||||
} else if (highValid) {
|
||||
// Use just a single less than operator if we only have a high
|
||||
const fnc = allOr ? "orWhere" : "where"
|
||||
query = query[fnc](key, "<", value.high)
|
||||
if (
|
||||
field.type === FieldType.BIGINT &&
|
||||
this.client === SqlClient.SQL_LITE
|
||||
) {
|
||||
query = query.whereRaw(
|
||||
`CAST(${key} AS INTEGER) <= CAST(? AS INTEGER)`,
|
||||
[value.high]
|
||||
)
|
||||
} else {
|
||||
const fnc = allOr ? "orWhere" : "where"
|
||||
query = query[fnc](key, "<=", value.high)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -532,7 +565,7 @@ class InternalBuilder {
|
|||
if (foundOffset) {
|
||||
query = query.offset(foundOffset)
|
||||
}
|
||||
query = this.addFilters(query, filters, tableName, {
|
||||
query = this.addFilters(query, filters, json.meta?.table!, {
|
||||
aliases: tableAliases,
|
||||
})
|
||||
// add sorting to pre-query
|
||||
|
@ -553,7 +586,7 @@ class InternalBuilder {
|
|||
endpoint.schema,
|
||||
tableAliases
|
||||
)
|
||||
return this.addFilters(query, filters, tableName, {
|
||||
return this.addFilters(query, filters, json.meta?.table!, {
|
||||
relationship: true,
|
||||
aliases: tableAliases,
|
||||
})
|
||||
|
@ -563,7 +596,7 @@ class InternalBuilder {
|
|||
const { endpoint, body, filters, tableAliases } = json
|
||||
let query = this.knexWithAlias(knex, endpoint, tableAliases)
|
||||
const parsedBody = parseBody(body)
|
||||
query = this.addFilters(query, filters, endpoint.entityId, {
|
||||
query = this.addFilters(query, filters, json.meta?.table!, {
|
||||
aliases: tableAliases,
|
||||
})
|
||||
// mysql can't use returning
|
||||
|
@ -577,7 +610,7 @@ class InternalBuilder {
|
|||
delete(knex: Knex, json: QueryJson, opts: QueryOptions): Knex.QueryBuilder {
|
||||
const { endpoint, filters, tableAliases } = json
|
||||
let query = this.knexWithAlias(knex, endpoint, tableAliases)
|
||||
query = this.addFilters(query, filters, endpoint.entityId, {
|
||||
query = this.addFilters(query, filters, json.meta?.table!, {
|
||||
aliases: tableAliases,
|
||||
})
|
||||
// mysql can't use returning
|
||||
|
|
|
@ -185,6 +185,6 @@ export async function search(
|
|||
}
|
||||
} catch (err: any) {
|
||||
const msg = typeof err === "string" ? err : err.message
|
||||
throw new Error(`Unable to search by SQL - ${msg}`)
|
||||
throw new Error(`Unable to search by SQL - ${msg}`, { cause: err })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,10 +13,13 @@ export interface SearchFilters {
|
|||
[key: string]: string
|
||||
}
|
||||
range?: {
|
||||
[key: string]: {
|
||||
high: number | string
|
||||
low: number | string
|
||||
}
|
||||
[key: string]:
|
||||
| {
|
||||
high: number | string
|
||||
low: number | string
|
||||
}
|
||||
| { high: number | string }
|
||||
| { low: number | string }
|
||||
}
|
||||
equal?: {
|
||||
[key: string]: any
|
||||
|
|
Loading…
Reference in New Issue