More refactoring.

This commit is contained in:
Sam Rose 2024-10-23 17:07:42 +01:00
parent aaf4022f25
commit a120ce4e14
No known key found for this signature in database
1 changed files with 51 additions and 32 deletions

View File

@ -162,6 +162,12 @@ class InternalBuilder {
return this.table.schema[column] return this.table.schema[column]
} }
private supportsILike(): boolean {
return !(
this.client === SqlClient.ORACLE || this.client === SqlClient.SQL_LITE
)
}
private quoteChars(): [string, string] { private quoteChars(): [string, string] {
const wrapped = this.knexClient.wrapIdentifier("foo", {}) const wrapped = this.knexClient.wrapIdentifier("foo", {})
return [wrapped[0], wrapped[wrapped.length - 1]] return [wrapped[0], wrapped[wrapped.length - 1]]
@ -566,7 +572,7 @@ class InternalBuilder {
filters = this.parseFilters({ ...filters }) filters = this.parseFilters({ ...filters })
const aliases = this.query.tableAliases const aliases = this.query.tableAliases
// if all or specified in filters, then everything is an or // if all or specified in filters, then everything is an or
const allOr = filters.allOr const shouldOr = filters.allOr
const isSqlite = this.client === SqlClient.SQL_LITE const isSqlite = this.client === SqlClient.SQL_LITE
const tableName = isSqlite ? this.table._id! : this.table.name const tableName = isSqlite ? this.table._id! : this.table.name
@ -630,7 +636,7 @@ class InternalBuilder {
value value
) )
} else if (shouldProcessRelationship) { } else if (shouldProcessRelationship) {
if (allOr) { if (shouldOr) {
query = query.or query = query.or
} }
query = builder.addRelationshipForFilter( query = builder.addRelationshipForFilter(
@ -646,7 +652,7 @@ class InternalBuilder {
} }
const like = (q: Knex.QueryBuilder, key: string, value: any) => { const like = (q: Knex.QueryBuilder, key: string, value: any) => {
if (filters?.fuzzyOr || allOr) { if (filters?.fuzzyOr || shouldOr) {
q = q.or q = q.or
} }
if ( if (
@ -667,7 +673,7 @@ class InternalBuilder {
const contains = (mode: ArrayFilter, any = false) => { const contains = (mode: ArrayFilter, any = false) => {
function addModifiers<T extends {}, Q>(q: Knex.QueryBuilder<T, Q>) { function addModifiers<T extends {}, Q>(q: Knex.QueryBuilder<T, Q>) {
if (allOr || mode === filters?.containsAny) { if (shouldOr || mode === filters?.containsAny) {
q = q.or q = q.or
} }
if (mode === filters?.notContains) { if (mode === filters?.notContains) {
@ -777,38 +783,46 @@ class InternalBuilder {
} }
if (filters.oneOf) { if (filters.oneOf) {
const fnc = allOr ? "orWhereIn" : "whereIn"
iterate( iterate(
filters.oneOf, filters.oneOf,
ArrayOperator.ONE_OF, ArrayOperator.ONE_OF,
(q, key: string, array) => { (q, key: string, array) => {
if (shouldOr) {
q = q.or
}
if (this.client === SqlClient.ORACLE) { if (this.client === SqlClient.ORACLE) {
// @ts-ignore // @ts-ignore
key = this.convertClobs(key) key = this.convertClobs(key)
} }
return q[fnc](key, Array.isArray(array) ? array : [array]) return q.whereIn(key, Array.isArray(array) ? array : [array])
}, },
(q, key: string[], array) => { (q, key: string[], array) => {
if (shouldOr) {
q = q.or
}
if (this.client === SqlClient.ORACLE) { if (this.client === SqlClient.ORACLE) {
// @ts-ignore // @ts-ignore
key = key.map(k => this.convertClobs(k)) key = key.map(k => this.convertClobs(k))
} }
return q[fnc](key, Array.isArray(array) ? array : [array]) return q.whereIn(key, Array.isArray(array) ? array : [array])
} }
) )
} }
if (filters.string) { if (filters.string) {
iterate(filters.string, BasicOperator.STRING, (q, key, value) => { iterate(filters.string, BasicOperator.STRING, (q, key, value) => {
// postgres supports ilike, nothing else does if (shouldOr) {
if (this.client === SqlClient.POSTGRES) { q = q.or
const fnc = allOr ? "orWhere" : "where" }
return q[fnc](key, "ilike", `${value}%`) if (
} else { this.client === SqlClient.ORACLE ||
const fnc = allOr ? "orWhereRaw" : "whereRaw" this.client === SqlClient.SQL_LITE
return q[fnc](`LOWER(??) LIKE ?`, [ ) {
return q.whereRaw(`LOWER(??) LIKE ?`, [
this.rawQuotedIdentifier(key), this.rawQuotedIdentifier(key),
`${value.toLowerCase()}%`, `${value.toLowerCase()}%`,
]) ])
} else {
return q.whereILike(key, `${value}%`)
} }
}) })
} }
@ -852,37 +866,42 @@ class InternalBuilder {
low = this.knex.raw("CAST(? AS INTEGER)", [value.low]) low = this.knex.raw("CAST(? AS INTEGER)", [value.low])
} }
if (shouldOr) {
q = q.or
}
if (lowValid && highValid) { if (lowValid && highValid) {
const fnc = allOr ? "orWhereBetween" : "whereBetween"
// @ts-ignore // @ts-ignore
return q[fnc](rawKey, [low, high]) return q.whereBetween(rawKey, [low, high])
} else if (lowValid) { } else if (lowValid) {
const fnc = allOr ? "orWhere" : "where"
// @ts-ignore // @ts-ignore
return q[fnc](rawKey, ">=", low) return q.where(rawKey, ">=", low)
} else if (highValid) { } else if (highValid) {
const fnc = allOr ? "orWhere" : "where"
// @ts-ignore // @ts-ignore
return q[fnc](rawKey, "<=", high) return q.where(rawKey, "<=", high)
} }
return q return q
}) })
} }
if (filters.equal) { if (filters.equal) {
iterate(filters.equal, BasicOperator.EQUAL, (q, key, value) => { iterate(filters.equal, BasicOperator.EQUAL, (q, key, value) => {
const fnc = allOr ? "orWhereRaw" : "whereRaw" if (shouldOr) {
q = q.or
}
if (this.client === SqlClient.MS_SQL) { if (this.client === SqlClient.MS_SQL) {
return q[fnc]( return q.whereRaw(`CASE WHEN ?? = ? THEN 1 ELSE 0 END = 1`, [
`CASE WHEN ${this.quotedIdentifier(key)} = ? THEN 1 ELSE 0 END = 1`, this.quotedIdentifier(key),
[value]
)
} else if (this.client === SqlClient.ORACLE) {
const identifier = this.convertClobs(key)
return q[fnc](`(${identifier} IS NOT NULL AND ${identifier} = ?)`, [
value, value,
]) ])
} else if (this.client === SqlClient.ORACLE) {
const identifier = this.convertClobs(key)
return q.where(subq =>
// @ts-expect-error knex types are wrong, raw is fine here
subq.whereNotNull(identifier).andWhere(identifier, value)
)
} else { } else {
return q[fnc](`COALESCE(${this.quotedIdentifier(key)} = ?, FALSE)`, [ return q.whereRaw(`COALESCE(?? = ?, FALSE)`, [
this.rawQuotedIdentifier(key),
value, value,
]) ])
} }
@ -890,7 +909,7 @@ class InternalBuilder {
} }
if (filters.notEqual) { if (filters.notEqual) {
iterate(filters.notEqual, BasicOperator.NOT_EQUAL, (q, key, value) => { iterate(filters.notEqual, BasicOperator.NOT_EQUAL, (q, key, value) => {
const fnc = allOr ? "orWhereRaw" : "whereRaw" const fnc = shouldOr ? "orWhereRaw" : "whereRaw"
if (this.client === SqlClient.MS_SQL) { if (this.client === SqlClient.MS_SQL) {
return q[fnc]( return q[fnc](
`CASE WHEN ${this.quotedIdentifier(key)} = ? THEN 1 ELSE 0 END = 0`, `CASE WHEN ${this.quotedIdentifier(key)} = ? THEN 1 ELSE 0 END = 0`,
@ -911,13 +930,13 @@ class InternalBuilder {
} }
if (filters.empty) { if (filters.empty) {
iterate(filters.empty, BasicOperator.EMPTY, (q, key) => { iterate(filters.empty, BasicOperator.EMPTY, (q, key) => {
const fnc = allOr ? "orWhereNull" : "whereNull" const fnc = shouldOr ? "orWhereNull" : "whereNull"
return q[fnc](key) return q[fnc](key)
}) })
} }
if (filters.notEmpty) { if (filters.notEmpty) {
iterate(filters.notEmpty, BasicOperator.NOT_EMPTY, (q, key) => { iterate(filters.notEmpty, BasicOperator.NOT_EMPTY, (q, key) => {
const fnc = allOr ? "orWhereNotNull" : "whereNotNull" const fnc = shouldOr ? "orWhereNotNull" : "whereNotNull"
return q[fnc](key) return q[fnc](key)
}) })
} }