diff --git a/packages/server/src/integrations/base/sql.ts b/packages/server/src/integrations/base/sql.ts index c0e74bfb06..2a7d0262ad 100644 --- a/packages/server/src/integrations/base/sql.ts +++ b/packages/server/src/integrations/base/sql.ts @@ -161,24 +161,25 @@ class InternalBuilder { const fnc = allOr ? "orWhere" : "where" const rawFnc = `${fnc}Raw` const not = mode === filters?.notContains ? "NOT " : "" - function stringifyArray(value: Array): string { + function stringifyArray(value: Array, quoteStyle = '"'): string { for (let i in value) { if (typeof value[i] === "string") { - value[i] = `"${value[i]}"` + value[i] = `${quoteStyle}${value[i]}${quoteStyle}` } } - return `'[${value.join(",")}]'` + return `[${value.join(",")}]` } if (this.client === SqlClients.POSTGRES) { iterate(mode, (key: string, value: Array) => { + const wrap = any ? "" : "'" + const containsOp = any ? "\\?| array" : "@>" const fieldNames = key.split(/\./g) const tableName = fieldNames[0] const columnName = fieldNames[1] // @ts-ignore - query = query[rawFnc]( - `${not}"${tableName}"."${columnName}"::jsonb @> ${stringifyArray( - value - )}` + query = query[rawFnc](`${not}"${tableName}"."${columnName}"::jsonb ${containsOp} ${wrap}${stringifyArray( + value, any ? "'" : '"' + )}${wrap}` ) }) } else if (this.client === SqlClients.MY_SQL) { @@ -186,7 +187,7 @@ class InternalBuilder { iterate(mode, (key: string, value: Array) => { // @ts-ignore query = query[rawFnc]( - `${not}${jsonFnc}(${key}, ${stringifyArray(value)})` + `${not}${jsonFnc}(${key}, '${stringifyArray(value)}')` ) }) } else { diff --git a/packages/server/src/integrations/tests/sql.spec.js b/packages/server/src/integrations/tests/sql.spec.js index 66606516ea..121403174c 100644 --- a/packages/server/src/integrations/tests/sql.spec.js +++ b/packages/server/src/integrations/tests/sql.spec.js @@ -251,7 +251,7 @@ describe("SQL query builder", () => { })) expect(query).toEqual({ bindings: [10, "%20%", `%"John"%`], - 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}]` + 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}]` }) }) @@ -360,18 +360,18 @@ describe("SQL query builder", () => { }) }) - it("should use OR jsonb operator expression for PostgreSQL when filter is containsAny", () => { + it("should use ?| operator expression for PostgreSQL when filter is containsAny", () => { const query = new Sql(SqlClients.POSTGRES, 10)._query(generateReadJson({ filters: { containsAny: { - age: [20], - name: ["John"] + age: [20, 25], + name: ["John", "Mary"] } } })) 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}\"` + sql: `select * from (select * from \"${TABLE_NAME}\" where \"${TABLE_NAME}\".\"age\"::jsonb ?| array [20,25] and \"${TABLE_NAME}\".\"name\"::jsonb ?| array ['John','Mary'] limit $1) as \"${TABLE_NAME}\"` }) }) })