Browse Source

Has any of MySQL filter

master
Mel O'Hagan 4 years ago
parent
commit
804d1ef8f6
  1. 2
      packages/frontend-core/src/constants.js
  2. 3
      packages/server/src/definitions/datasource.ts
  3. 8
      packages/server/src/integrations/base/sql.ts
  4. 45
      packages/server/src/integrations/tests/sql.spec.js

2
packages/frontend-core/src/constants.js

@ -48,7 +48,7 @@ export const OperatorOptions = {
},
ContainsAny: {
value: "containsAny",
label: "Has any"
label: "Has any",
},
}

3
packages/server/src/definitions/datasource.ts

@ -137,6 +137,9 @@ export interface SearchFilters {
notContains?: {
[key: string]: any[]
}
containsAny?: {
[key: string]: any[]
}
}
export interface SortJson {

8
packages/server/src/integrations/base/sql.ts

@ -157,7 +157,7 @@ class InternalBuilder {
}
}
const contains = (mode: object) => {
const contains = (mode: object, any: boolean = false) => {
const fnc = allOr ? "orWhere" : "where"
const rawFnc = `${fnc}Raw`
const not = mode === filters?.notContains ? "NOT " : ""
@ -182,10 +182,11 @@ class InternalBuilder {
)
})
} else if (this.client === SqlClients.MY_SQL) {
const jsonFnc = any ? "JSON_OVERLAPS" : "JSON_CONTAINS"
iterate(mode, (key: string, value: Array<any>) => {
// @ts-ignore
query = query[rawFnc](
`${not}JSON_CONTAINS(${key}, ${stringifyArray(value)})`
`${not}${jsonFnc}(${key}, ${stringifyArray(value)})`
)
})
} else {
@ -282,6 +283,9 @@ class InternalBuilder {
if (filters.notContains) {
contains(filters.notContains)
}
if (filters.containsAny) {
contains(filters.containsAny, true)
}
return query
}

45
packages/server/src/integrations/tests/sql.spec.js

@ -329,4 +329,49 @@ describe("SQL query builder", () => {
sql: `select * from (select * from \"${TABLE_NAME}\" where NOT \"${TABLE_NAME}\".\"age\"::jsonb @> '[20]' and NOT \"${TABLE_NAME}\".\"name\"::jsonb @> '["John"]' limit $1) as \"${TABLE_NAME}\"`
})
})
it("should use OR like expression for MS-SQL when filter is containsAny", () => {
const query = new Sql(SqlClients.MS_SQL, 10)._query(generateReadJson({
filters: {
containsAny: {
age: [20, 25],
name: ["John", "Mary"]
}
}
}))
expect(query).toEqual({
bindings: [10, "%20%", "%25%", `%"John"%`, `%"Mary"%`],
sql: `select * from (select top (@p0) * from [${TABLE_NAME}] where LOWER(${TABLE_NAME}.age) LIKE @p1 and LOWER(${TABLE_NAME}.name) LIKE @p2) as [${TABLE_NAME}]`
})
})
it("should use JSON_OVERLAPS expression for MySQL when filter is containsAny", () => {
const query = new Sql(SqlClients.MY_SQL, 10)._query(generateReadJson({
filters: {
containsAny: {
age: [20, 25],
name: ["John", "Mary"]
}
}
}))
expect(query).toEqual({
bindings: [10],
sql: `select * from (select * from \`${TABLE_NAME}\` where JSON_OVERLAPS(${TABLE_NAME}.age, '[20,25]') and JSON_OVERLAPS(${TABLE_NAME}.name, '["John","Mary"]') limit ?) as \`${TABLE_NAME}\``
})
})
it("should use OR jsonb operator expression for PostgreSQL when filter is containsAny", () => {
const query = new Sql(SqlClients.POSTGRES, 10)._query(generateReadJson({
filters: {
containsAny: {
age: [20],
name: ["John"]
}
}
}))
expect(query).toEqual({
bindings: [10],
sql: `select * from (select * from \"${TABLE_NAME}\" where \"${TABLE_NAME}\".\"age\"::jsonb @> '[20]' and \"${TABLE_NAME}\".\"name\"::jsonb @> '["John"]' limit $1) as \"${TABLE_NAME}\"`
})
})
})

Loading…
Cancel
Save