Updating underlying sql to not use ilike unless in postgres client.

This commit is contained in:
mike12345567 2021-11-05 13:48:13 +00:00
parent 5ec0d803af
commit 3474f3ae8e
3 changed files with 220 additions and 207 deletions

View File

@ -342,7 +342,7 @@ module External {
table: Table, table: Table,
relationships: RelationshipsJson[] relationships: RelationshipsJson[]
) { ) {
if (rows[0].read === true) { if (!rows || rows.length === 0 || rows[0].read === true) {
return [] return []
} }
let finalRows: { [key: string]: Row } = {} let finalRows: { [key: string]: Row } = {}

View File

@ -29,12 +29,19 @@ function parseBody(body: any) {
return body return body
} }
// right now we only do filters on the specific table being queried class InternalBuilder {
function addFilters( private readonly client: string
constructor(client: string) {
this.client = client
}
// right now we only do filters on the specific table being queried
addFilters(
tableName: string, tableName: string,
query: KnexQuery, query: KnexQuery,
filters: SearchFilters | undefined filters: SearchFilters | undefined
): KnexQuery { ): KnexQuery {
function iterate( function iterate(
structure: { [key: string]: any }, structure: { [key: string]: any },
fn: (key: string, value: any) => void fn: (key: string, value: any) => void
@ -57,13 +64,27 @@ function addFilters(
if (filters.string) { if (filters.string) {
iterate(filters.string, (key, value) => { iterate(filters.string, (key, value) => {
const fnc = allOr ? "orWhere" : "where" const fnc = allOr ? "orWhere" : "where"
// postgres supports ilike, nothing else does
if (this.client === "pg") {
query = query[fnc](key, "ilike", `${value}%`) query = query[fnc](key, "ilike", `${value}%`)
} else {
const rawFnc = `${fnc}Raw`
// @ts-ignore
query = query[rawFnc](`LOWER(${key}) LIKE ?`, [`${value}%`])
}
}) })
} }
if (filters.fuzzy) { if (filters.fuzzy) {
iterate(filters.fuzzy, (key, value) => { iterate(filters.fuzzy, (key, value) => {
const fnc = allOr ? "orWhere" : "where" const fnc = allOr ? "orWhere" : "where"
// postgres supports ilike, nothing else does
if (this.client === "pg") {
query = query[fnc](key, "ilike", `%${value}%`) query = query[fnc](key, "ilike", `%${value}%`)
} else {
const rawFnc = `${fnc}Raw`
// @ts-ignore
query = query[rawFnc](`LOWER(${key}) LIKE ?`, [`%${value}%`])
}
}) })
} }
if (filters.range) { if (filters.range) {
@ -100,15 +121,15 @@ function addFilters(
}) })
} }
return query return query
} }
function addRelationships( addRelationships(
knex: Knex, knex: Knex,
query: KnexQuery, query: KnexQuery,
fields: string | string[], fields: string | string[],
fromTable: string, fromTable: string,
relationships: RelationshipsJson[] | undefined relationships: RelationshipsJson[] | undefined
): KnexQuery { ): KnexQuery {
if (!relationships) { if (!relationships) {
return query return query
} }
@ -138,13 +159,9 @@ function addRelationships(
} }
} }
return query.limit(BASE_LIMIT) return query.limit(BASE_LIMIT)
} }
function buildCreate( create(knex: Knex, json: QueryJson, opts: QueryOptions): KnexQuery {
knex: Knex,
json: QueryJson,
opts: QueryOptions
): KnexQuery {
const { endpoint, body } = json const { endpoint, body } = json
let query: KnexQuery = knex(endpoint.entityId) let query: KnexQuery = knex(endpoint.entityId)
const parsedBody = parseBody(body) const parsedBody = parseBody(body)
@ -160,9 +177,9 @@ function buildCreate(
} else { } else {
return query.insert(parsedBody).returning("*") return query.insert(parsedBody).returning("*")
} }
} }
function buildRead(knex: Knex, json: QueryJson, limit: number): KnexQuery { read(knex: Knex, json: QueryJson, limit: number): KnexQuery {
let { endpoint, resource, filters, sort, paginate, relationships } = json let { endpoint, resource, filters, sort, paginate, relationships } = json
const tableName = endpoint.entityId const tableName = endpoint.entityId
// select all if not specified // select all if not specified
@ -199,53 +216,46 @@ function buildRead(knex: Knex, json: QueryJson, limit: number): KnexQuery {
query = query.orderBy(key, direction) query = query.orderBy(key, direction)
} }
} }
query = addFilters(tableName, query, filters) query = this.addFilters(tableName, query, filters)
// @ts-ignore // @ts-ignore
let preQuery: KnexQuery = knex({ let preQuery: KnexQuery = knex({
// @ts-ignore // @ts-ignore
[tableName]: query, [tableName]: query,
}).select(selectStatement) }).select(selectStatement)
// handle joins // handle joins
return addRelationships( return this.addRelationships(
knex, knex,
preQuery, preQuery,
selectStatement, selectStatement,
tableName, tableName,
relationships relationships
) )
} }
function buildUpdate( update(knex: Knex, json: QueryJson, opts: QueryOptions): KnexQuery {
knex: Knex,
json: QueryJson,
opts: QueryOptions
): KnexQuery {
const { endpoint, body, filters } = json const { endpoint, body, filters } = json
let query: KnexQuery = knex(endpoint.entityId) let query: KnexQuery = knex(endpoint.entityId)
const parsedBody = parseBody(body) const parsedBody = parseBody(body)
query = addFilters(endpoint.entityId, query, filters) query = this.addFilters(endpoint.entityId, query, filters)
// mysql can't use returning // mysql can't use returning
if (opts.disableReturning) { if (opts.disableReturning) {
return query.update(parsedBody) return query.update(parsedBody)
} else { } else {
return query.update(parsedBody).returning("*") return query.update(parsedBody).returning("*")
} }
} }
function buildDelete( delete(knex: Knex, json: QueryJson, opts: QueryOptions): KnexQuery {
knex: Knex,
json: QueryJson,
opts: QueryOptions
): KnexQuery {
const { endpoint, filters } = json const { endpoint, filters } = json
let query: KnexQuery = knex(endpoint.entityId) let query: KnexQuery = knex(endpoint.entityId)
query = addFilters(endpoint.entityId, query, filters) query = this.addFilters(endpoint.entityId, query, filters)
// mysql can't use returning // mysql can't use returning
if (opts.disableReturning) { if (opts.disableReturning) {
return query.delete() return query.delete()
} else { } else {
return query.delete().returning("*") return query.delete().returning("*")
} }
}
} }
class SqlQueryBuilder extends SqlTableQueryBuilder { class SqlQueryBuilder extends SqlTableQueryBuilder {
@ -266,18 +276,19 @@ class SqlQueryBuilder extends SqlTableQueryBuilder {
const sqlClient = this.getSqlClient() const sqlClient = this.getSqlClient()
const client = knex({ client: sqlClient }) const client = knex({ client: sqlClient })
let query let query
const builder = new InternalBuilder(sqlClient)
switch (this._operation(json)) { switch (this._operation(json)) {
case Operation.CREATE: case Operation.CREATE:
query = buildCreate(client, json, opts) query = builder.create(client, json, opts)
break break
case Operation.READ: case Operation.READ:
query = buildRead(client, json, this.limit) query = builder.read(client, json, this.limit)
break break
case Operation.UPDATE: case Operation.UPDATE:
query = buildUpdate(client, json, opts) query = builder.update(client, json, opts)
break break
case Operation.DELETE: case Operation.DELETE:
query = buildDelete(client, json, opts) query = builder.delete(client, json, opts)
break break
case Operation.CREATE_TABLE: case Operation.CREATE_TABLE:
case Operation.UPDATE_TABLE: case Operation.UPDATE_TABLE:

View File

@ -245,7 +245,9 @@ module MSSQLModule {
schema, schema,
} }
} }
this.tables = tables const final = finaliseExternalTables(tables)
this.tables = final.tables
this.schemaErrors = final.errors
} }
async read(query: SqlQuery | string) { async read(query: SqlQuery | string) {