Checkpoint, more raws converted.

This commit is contained in:
Sam Rose 2024-10-22 11:48:38 +01:00
parent 44bd00a0d7
commit 4545493cd5
No known key found for this signature in database
2 changed files with 42 additions and 34 deletions

View File

@ -258,7 +258,9 @@ class InternalBuilder {
const columnSchema = schema[column] const columnSchema = schema[column]
if (this.SPECIAL_SELECT_CASES.POSTGRES_MONEY(columnSchema)) { if (this.SPECIAL_SELECT_CASES.POSTGRES_MONEY(columnSchema)) {
return this.knex.raw("??::money::numeric as ??", [ // TODO: figure out how to express this safely without string
// interpolation.
return this.knex.raw(`??::money::numeric as "${field}"`, [
[table, column].join("."), [table, column].join("."),
field, field,
]) ])
@ -632,18 +634,16 @@ class InternalBuilder {
} }
const like = (q: Knex.QueryBuilder, key: string, value: any) => { const like = (q: Knex.QueryBuilder, key: string, value: any) => {
const fuzzyOr = filters?.fuzzyOr if (filters?.fuzzyOr || allOr) {
const fnc = fuzzyOr || allOr ? "orWhere" : "where" q = q.or
// postgres supports ilike, nothing else does
if (this.client === SqlClient.POSTGRES) {
return q[fnc](key, "ilike", `%${value}%`)
} else {
const rawFnc = `${fnc}Raw`
// @ts-ignore
return q[rawFnc](`LOWER(${this.quotedIdentifier(key)}) LIKE ?`, [
`%${value.toLowerCase()}%`,
])
} }
if (
this.client === SqlClient.ORACLE ||
this.client === SqlClient.SQL_LITE
) {
return q.whereRaw(`LOWER(??) LIKE ?`, [key, `%${value.toLowerCase()}%`])
}
return q.whereILike(key, this.knex.raw("?", [`%${value}%`]))
} }
const contains = (mode: AnySearchFilter, any: boolean = false) => { const contains = (mode: AnySearchFilter, any: boolean = false) => {
@ -1069,17 +1069,20 @@ class InternalBuilder {
private buildJsonField(field: string): string { private buildJsonField(field: string): string {
const parts = field.split(".") const parts = field.split(".")
let tableField: string, unaliased: string let unaliased: string
let tableField: string
if (parts.length > 1) { if (parts.length > 1) {
const alias = parts.shift()! const alias = parts.shift()!
unaliased = parts.join(".") unaliased = parts.join(".")
tableField = `${this.quote(alias)}.${this.quote(unaliased)}` tableField = `${alias}.${unaliased}`
} else { } else {
unaliased = parts.join(".") unaliased = parts.join(".")
tableField = this.quote(unaliased) tableField = unaliased
} }
const separator = this.client === SqlClient.ORACLE ? " VALUE " : "," const separator = this.client === SqlClient.ORACLE ? " VALUE " : ","
return `'${unaliased}'${separator}${tableField}` return this.knex.raw(`?${separator}??`, [unaliased, tableField]).toString()
} }
maxFunctionParameters() { maxFunctionParameters() {
@ -1175,13 +1178,13 @@ class InternalBuilder {
subQuery = subQuery.where( subQuery = subQuery.where(
correlatedTo, correlatedTo,
"=", "=",
knex.raw(this.quotedIdentifier(correlatedFrom)) knex.raw("??", [correlatedFrom])
) )
const standardWrap = (select: string): Knex.QueryBuilder => { const standardWrap = (select: Knex.Raw): Knex.QueryBuilder => {
subQuery = subQuery.select(`${toAlias}.*`).limit(getRelationshipLimit()) subQuery = subQuery.select(`${toAlias}.*`).limit(getRelationshipLimit())
// @ts-ignore - the from alias syntax isn't in Knex typing // @ts-ignore - the from alias syntax isn't in Knex typing
return knex.select(knex.raw(select)).from({ return knex.select(select).from({
[toAlias]: subQuery, [toAlias]: subQuery,
}) })
} }
@ -1191,12 +1194,12 @@ class InternalBuilder {
// need to check the junction table document is to the right column, this is just for SQS // need to check the junction table document is to the right column, this is just for SQS
subQuery = this.addJoinFieldCheck(subQuery, relationship) subQuery = this.addJoinFieldCheck(subQuery, relationship)
wrapperQuery = standardWrap( wrapperQuery = standardWrap(
`json_group_array(json_object(${fieldList}))` this.knex.raw(`json_group_array(json_object(${fieldList}))`)
) )
break break
case SqlClient.POSTGRES: case SqlClient.POSTGRES:
wrapperQuery = standardWrap( wrapperQuery = standardWrap(
`json_agg(json_build_object(${fieldList}))` this.knex.raw(`json_agg(json_build_object(${fieldList}))`)
) )
break break
case SqlClient.MARIADB: case SqlClient.MARIADB:
@ -1210,21 +1213,25 @@ class InternalBuilder {
case SqlClient.MY_SQL: case SqlClient.MY_SQL:
case SqlClient.ORACLE: case SqlClient.ORACLE:
wrapperQuery = standardWrap( wrapperQuery = standardWrap(
`json_arrayagg(json_object(${fieldList}))` this.knex.raw(`json_arrayagg(json_object(${fieldList}))`)
) )
break break
case SqlClient.MS_SQL: case SqlClient.MS_SQL: {
const comparatorQuery = knex
.select(`${fromAlias}.*`)
// @ts-ignore - from alias syntax not TS supported
.from({
[fromAlias]: subQuery
.select(`${toAlias}.*`)
.limit(getRelationshipLimit()),
})
wrapperQuery = knex.raw( wrapperQuery = knex.raw(
`(SELECT ${this.quote(toAlias)} = (${knex `(SELECT ?? = (${comparatorQuery} FOR JSON PATH))`,
.select(`${fromAlias}.*`) [toAlias]
// @ts-ignore - from alias syntax not TS supported
.from({
[fromAlias]: subQuery
.select(`${toAlias}.*`)
.limit(getRelationshipLimit()),
})} FOR JSON PATH))`
) )
break break
}
default: default:
throw new Error(`JSON relationships not implement for ${sqlClient}`) throw new Error(`JSON relationships not implement for ${sqlClient}`)
} }

View File

@ -792,10 +792,11 @@ describe.each([
}) })
}) })
describe.only.each([FieldType.STRING, FieldType.LONGFORM])("%s", () => { const stringTypes = [FieldType.STRING, FieldType.LONGFORM] as const
describe.only.each(stringTypes)("%s", type => {
beforeAll(async () => { beforeAll(async () => {
tableOrViewId = await createTableOrView({ tableOrViewId = await createTableOrView({
name: { name: "name", type: FieldType.STRING }, name: { name: "name", type },
}) })
await createRows([{ name: "foo" }, { name: "bar" }]) await createRows([{ name: "foo" }, { name: "bar" }])
}) })
@ -1602,7 +1603,7 @@ describe.each([
}) })
}) })
describe.each([FieldType.ARRAY, FieldType.OPTIONS])("%s", () => { describe("arrays", () => {
beforeAll(async () => { beforeAll(async () => {
tableOrViewId = await createTableOrView({ tableOrViewId = await createTableOrView({
numbers: { numbers: {