Updating how between/less than/greater than are handled for sqlite.
This commit is contained in:
parent
94fb8b748a
commit
60ed4d8443
|
@ -6,6 +6,7 @@ import {
|
||||||
SqlClient,
|
SqlClient,
|
||||||
isValidFilter,
|
isValidFilter,
|
||||||
getNativeSql,
|
getNativeSql,
|
||||||
|
SqlStatements,
|
||||||
} from "../utils"
|
} from "../utils"
|
||||||
import SqlTableQueryBuilder from "./sqlTable"
|
import SqlTableQueryBuilder from "./sqlTable"
|
||||||
import {
|
import {
|
||||||
|
@ -163,6 +164,13 @@ class InternalBuilder {
|
||||||
table: Table,
|
table: Table,
|
||||||
opts: { aliases?: Record<string, string>; relationship?: boolean }
|
opts: { aliases?: Record<string, string>; relationship?: boolean }
|
||||||
): Knex.QueryBuilder {
|
): Knex.QueryBuilder {
|
||||||
|
if (!filters) {
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
filters = parseFilters(filters)
|
||||||
|
// if all or specified in filters, then everything is an or
|
||||||
|
const allOr = filters.allOr
|
||||||
|
const sqlStatements = new SqlStatements(this.client, table, { allOr })
|
||||||
const tableName =
|
const tableName =
|
||||||
this.client === SqlClient.SQL_LITE ? table._id! : table.name
|
this.client === SqlClient.SQL_LITE ? table._id! : table.name
|
||||||
|
|
||||||
|
@ -261,12 +269,6 @@ class InternalBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!filters) {
|
|
||||||
return query
|
|
||||||
}
|
|
||||||
filters = parseFilters(filters)
|
|
||||||
// if all or specified in filters, then everything is an or
|
|
||||||
const allOr = filters.allOr
|
|
||||||
if (filters.oneOf) {
|
if (filters.oneOf) {
|
||||||
iterate(filters.oneOf, (key, array) => {
|
iterate(filters.oneOf, (key, array) => {
|
||||||
const fnc = allOr ? "orWhereIn" : "whereIn"
|
const fnc = allOr ? "orWhereIn" : "whereIn"
|
||||||
|
@ -293,9 +295,6 @@ class InternalBuilder {
|
||||||
}
|
}
|
||||||
if (filters.range) {
|
if (filters.range) {
|
||||||
iterate(filters.range, (key, value) => {
|
iterate(filters.range, (key, value) => {
|
||||||
const fieldName = key.split(".")[1]
|
|
||||||
const field = table.schema[fieldName]
|
|
||||||
|
|
||||||
const isEmptyObject = (val: any) => {
|
const isEmptyObject = (val: any) => {
|
||||||
return (
|
return (
|
||||||
val &&
|
val &&
|
||||||
|
@ -312,47 +311,11 @@ class InternalBuilder {
|
||||||
const lowValid = isValidFilter(value.low),
|
const lowValid = isValidFilter(value.low),
|
||||||
highValid = isValidFilter(value.high)
|
highValid = isValidFilter(value.high)
|
||||||
if (lowValid && highValid) {
|
if (lowValid && highValid) {
|
||||||
// Use a between operator if we have 2 valid range values
|
query = sqlStatements.between(query, 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) {
|
} else if (lowValid) {
|
||||||
// Use just a single greater than operator if we only have a low
|
query = sqlStatements.lower(query, 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) {
|
} else if (highValid) {
|
||||||
// Use just a single less than operator if we only have a high
|
query = sqlStatements.higher(query, 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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { SqlClient } from "../utils"
|
import { SqlClient } from "../utils"
|
||||||
import Sql from "../base/sql"
|
import Sql from "../base/sql"
|
||||||
import {
|
import {
|
||||||
|
FieldType,
|
||||||
Operation,
|
Operation,
|
||||||
QueryJson,
|
QueryJson,
|
||||||
TableSourceType,
|
|
||||||
Table,
|
Table,
|
||||||
FieldType,
|
TableSourceType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
const TABLE_NAME = "test"
|
const TABLE_NAME = "test"
|
||||||
|
@ -13,7 +13,12 @@ const TABLE: Table = {
|
||||||
type: "table",
|
type: "table",
|
||||||
sourceType: TableSourceType.EXTERNAL,
|
sourceType: TableSourceType.EXTERNAL,
|
||||||
sourceId: "SOURCE_ID",
|
sourceId: "SOURCE_ID",
|
||||||
schema: {},
|
schema: {
|
||||||
|
id: {
|
||||||
|
name: "id",
|
||||||
|
type: FieldType.NUMBER,
|
||||||
|
},
|
||||||
|
},
|
||||||
name: TABLE_NAME,
|
name: TABLE_NAME,
|
||||||
primary: ["id"],
|
primary: ["id"],
|
||||||
}
|
}
|
||||||
|
@ -73,7 +78,7 @@ function generateUpdateJson({
|
||||||
meta?: any
|
meta?: any
|
||||||
}): QueryJson {
|
}): QueryJson {
|
||||||
if (!meta.table) {
|
if (!meta.table) {
|
||||||
meta.table = table
|
meta.table = TABLE
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
endpoint: endpoint(table, "UPDATE"),
|
endpoint: endpoint(table, "UPDATE"),
|
||||||
|
@ -158,6 +163,9 @@ function generateManyRelationshipJson(config: { schema?: string } = {}) {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
extra: { idFilter: {} },
|
extra: { idFilter: {} },
|
||||||
|
meta: {
|
||||||
|
table: TABLE,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,7 +349,7 @@ describe("SQL query builder", () => {
|
||||||
)
|
)
|
||||||
expect(query).toEqual({
|
expect(query).toEqual({
|
||||||
bindings: [date, limit],
|
bindings: [date, limit],
|
||||||
sql: `select * from (select * from "${TABLE_NAME}" where "${TABLE_NAME}"."property" > $1 limit $2) as "${TABLE_NAME}"`,
|
sql: `select * from (select * from "${TABLE_NAME}" where "${TABLE_NAME}"."property" >= $1 limit $2) as "${TABLE_NAME}"`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -360,7 +368,7 @@ describe("SQL query builder", () => {
|
||||||
)
|
)
|
||||||
expect(query).toEqual({
|
expect(query).toEqual({
|
||||||
bindings: [date, limit],
|
bindings: [date, limit],
|
||||||
sql: `select * from (select * from "${TABLE_NAME}" where "${TABLE_NAME}"."property" < $1 limit $2) as "${TABLE_NAME}"`,
|
sql: `select * from (select * from "${TABLE_NAME}" where "${TABLE_NAME}"."property" <= $1 limit $2) as "${TABLE_NAME}"`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -594,7 +602,7 @@ describe("SQL query builder", () => {
|
||||||
)
|
)
|
||||||
expect(query).toEqual({
|
expect(query).toEqual({
|
||||||
bindings: ["2000-01-01 00:00:00", 500],
|
bindings: ["2000-01-01 00:00:00", 500],
|
||||||
sql: `select * from (select * from "${TABLE_NAME}" where "${TABLE_NAME}"."dob" > $1 limit $2) as "${TABLE_NAME}"`,
|
sql: `select * from (select * from "${TABLE_NAME}" where "${TABLE_NAME}"."dob" >= $1 limit $2) as "${TABLE_NAME}"`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -613,7 +621,7 @@ describe("SQL query builder", () => {
|
||||||
)
|
)
|
||||||
expect(query).toEqual({
|
expect(query).toEqual({
|
||||||
bindings: ["2010-01-01 00:00:00", 500],
|
bindings: ["2010-01-01 00:00:00", 500],
|
||||||
sql: `select * from (select * from "${TABLE_NAME}" where "${TABLE_NAME}"."dob" < $1 limit $2) as "${TABLE_NAME}"`,
|
sql: `select * from (select * from "${TABLE_NAME}" where "${TABLE_NAME}"."dob" <= $1 limit $2) as "${TABLE_NAME}"`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./utils"
|
||||||
|
export { SqlStatements } from "./sqlStatements"
|
|
@ -0,0 +1,80 @@
|
||||||
|
import { FieldType, Table, FieldSchema } from "@budibase/types"
|
||||||
|
import { SqlClient } from "./utils"
|
||||||
|
import { Knex } from "knex"
|
||||||
|
|
||||||
|
export class SqlStatements {
|
||||||
|
client: string
|
||||||
|
table: Table
|
||||||
|
allOr: boolean | undefined
|
||||||
|
constructor(
|
||||||
|
client: string,
|
||||||
|
table: Table,
|
||||||
|
{ allOr }: { allOr?: boolean } = {}
|
||||||
|
) {
|
||||||
|
this.client = client
|
||||||
|
this.table = table
|
||||||
|
this.allOr = allOr
|
||||||
|
}
|
||||||
|
|
||||||
|
getField(key: string): FieldSchema | undefined {
|
||||||
|
const fieldName = key.split(".")[1]
|
||||||
|
return this.table.schema[fieldName]
|
||||||
|
}
|
||||||
|
|
||||||
|
between(
|
||||||
|
query: Knex.QueryBuilder,
|
||||||
|
key: string,
|
||||||
|
low: number | string,
|
||||||
|
high: number | string
|
||||||
|
) {
|
||||||
|
// Use a between operator if we have 2 valid range values
|
||||||
|
const field = this.getField(key)
|
||||||
|
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)`,
|
||||||
|
[low, high]
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
const fnc = this.allOr ? "orWhereBetween" : "whereBetween"
|
||||||
|
query = query[fnc](key, [low, high])
|
||||||
|
}
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
lower(query: Knex.QueryBuilder, key: string, low: number | string) {
|
||||||
|
// Use just a single greater than operator if we only have a low
|
||||||
|
const field = this.getField(key)
|
||||||
|
if (
|
||||||
|
field?.type === FieldType.BIGINT &&
|
||||||
|
this.client === SqlClient.SQL_LITE
|
||||||
|
) {
|
||||||
|
query = query.whereRaw(`CAST(${key} AS INTEGER) >= CAST(? AS INTEGER)`, [
|
||||||
|
low,
|
||||||
|
])
|
||||||
|
} else {
|
||||||
|
const fnc = this.allOr ? "orWhere" : "where"
|
||||||
|
query = query[fnc](key, ">=", low)
|
||||||
|
}
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
higher(query: Knex.QueryBuilder, key: string, high: number | string) {
|
||||||
|
const field = this.getField(key)
|
||||||
|
// Use just a single less than operator if we only have a high
|
||||||
|
if (
|
||||||
|
field?.type === FieldType.BIGINT &&
|
||||||
|
this.client === SqlClient.SQL_LITE
|
||||||
|
) {
|
||||||
|
query = query.whereRaw(`CAST(${key} AS INTEGER) <= CAST(? AS INTEGER)`, [
|
||||||
|
high,
|
||||||
|
])
|
||||||
|
} else {
|
||||||
|
const fnc = this.allOr ? "orWhere" : "where"
|
||||||
|
query = query[fnc](key, "<=", high)
|
||||||
|
}
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,10 +5,10 @@ import {
|
||||||
FieldType,
|
FieldType,
|
||||||
TableSourceType,
|
TableSourceType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { DocumentType, SEPARATOR } from "../db/utils"
|
import { DocumentType, SEPARATOR } from "../../db/utils"
|
||||||
import { InvalidColumns, DEFAULT_BB_DATASOURCE_ID } from "../constants"
|
import { InvalidColumns, DEFAULT_BB_DATASOURCE_ID } from "../../constants"
|
||||||
import { helpers } from "@budibase/shared-core"
|
import { helpers } from "@budibase/shared-core"
|
||||||
import env from "../environment"
|
import env from "../../environment"
|
||||||
import { Knex } from "knex"
|
import { Knex } from "knex"
|
||||||
|
|
||||||
const DOUBLE_SEPARATOR = `${SEPARATOR}${SEPARATOR}`
|
const DOUBLE_SEPARATOR = `${SEPARATOR}${SEPARATOR}`
|
Loading…
Reference in New Issue