From d274f3af1e73a40e3e57265294a1f1c9632c6c37 Mon Sep 17 00:00:00 2001 From: melohagan <101575380+melohagan@users.noreply.github.com> Date: Fri, 20 Jan 2023 14:03:14 +0000 Subject: [PATCH] SQL filtering: Always escape key in LIKE statements (#9278) * Always escape key in like statements * lint --- packages/server/src/integrations/base/sql.ts | 7 ++-- .../server/src/integrations/tests/sql.spec.ts | 42 +++++++++++++++++-- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/packages/server/src/integrations/base/sql.ts b/packages/server/src/integrations/base/sql.ts index a2318eff12..1d3c57414c 100644 --- a/packages/server/src/integrations/base/sql.ts +++ b/packages/server/src/integrations/base/sql.ts @@ -23,9 +23,6 @@ const MIN_ISO_DATE = "0000-00-00T00:00:00.000Z" const MAX_ISO_DATE = "9999-00-00T00:00:00.000Z" function likeKey(client: string, key: string): string { - if (!key.includes(" ")) { - return key - } let start: string, end: string switch (client) { case SqlClient.MY_SQL: @@ -235,7 +232,9 @@ class InternalBuilder { } else { const rawFnc = `${fnc}Raw` // @ts-ignore - query = query[rawFnc](`LOWER(${key}) LIKE ?`, [`${value}%`]) + query = query[rawFnc](`LOWER(${likeKey(this.client, key)}) LIKE ?`, [ + `${value}%`, + ]) } }) } diff --git a/packages/server/src/integrations/tests/sql.spec.ts b/packages/server/src/integrations/tests/sql.spec.ts index 2e45f0754b..b05a761b54 100644 --- a/packages/server/src/integrations/tests/sql.spec.ts +++ b/packages/server/src/integrations/tests/sql.spec.ts @@ -352,7 +352,7 @@ describe("SQL query builder", () => { ) 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}.age) LIKE @p2) and (LOWER(${TABLE_NAME}.name) LIKE @p3 AND LOWER(${TABLE_NAME}.name) LIKE @p4)) as [${TABLE_NAME}]`, + sql: `select * from (select top (@p0) * from [${TABLE_NAME}] where (LOWER([${TABLE_NAME}].[age]) LIKE @p1 AND LOWER([${TABLE_NAME}].[age]) LIKE @p2) and (LOWER([${TABLE_NAME}].[name]) LIKE @p3 AND LOWER([${TABLE_NAME}].[name]) LIKE @p4)) as [${TABLE_NAME}]`, }) }) @@ -403,7 +403,7 @@ describe("SQL query builder", () => { ) expect(query).toEqual({ bindings: [10, "%20%", `%"John"%`], - sql: `select * from (select top (@p0) * from [${TABLE_NAME}] where NOT (LOWER(${TABLE_NAME}.age) LIKE @p1) and NOT (LOWER(${TABLE_NAME}.name) LIKE @p2)) as [${TABLE_NAME}]`, + sql: `select * from (select top (@p0) * from [${TABLE_NAME}] where NOT (LOWER([${TABLE_NAME}].[age]) LIKE @p1) and NOT (LOWER([${TABLE_NAME}].[name]) LIKE @p2)) as [${TABLE_NAME}]`, }) }) @@ -454,7 +454,7 @@ describe("SQL query builder", () => { ) 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 OR LOWER(${TABLE_NAME}.age) LIKE @p2) and (LOWER(${TABLE_NAME}.name) LIKE @p3 OR LOWER(${TABLE_NAME}.name) LIKE @p4)) as [${TABLE_NAME}]`, + sql: `select * from (select top (@p0) * from [${TABLE_NAME}] where (LOWER([${TABLE_NAME}].[age]) LIKE @p1 OR LOWER([${TABLE_NAME}].[age]) LIKE @p2) and (LOWER([${TABLE_NAME}].[name]) LIKE @p3 OR LOWER([${TABLE_NAME}].[name]) LIKE @p4)) as [${TABLE_NAME}]`, }) }) @@ -517,4 +517,40 @@ describe("SQL query builder", () => { sql: `select "stores"."store_id" as "stores.store_id", "stores"."store_name" as "stores.store_name", "products"."product_id" as "products.product_id", "products"."product_name" as "products.product_name" from (select * from "production"."stores" limit $1) as "stores" left join "production"."stocks" on "stores"."store_id" = "stocks"."store_id" left join "production"."products" on "products"."product_id" = "stocks"."product_id" limit $2`, }) }) + + it("should handle table names with dashes when performing a LIKE in MySQL", () => { + const tableName = "Table-Name-With-Dashes" + const query = new Sql(SqlClient.MY_SQL, limit)._query( + generateReadJson({ + table: tableName, + filters: { + string: { + name: "John", + }, + }, + }) + ) + expect(query).toEqual({ + bindings: ["John%", limit], + sql: `select * from (select * from \`${tableName}\` where LOWER(\`${tableName}\`.\`name\`) LIKE ? limit ?) as \`${tableName}\``, + }) + }) + + it("should handle table names with dashes when performing a LIKE in SQL Server", () => { + const tableName = "Table-Name-With-Dashes" + const query = new Sql(SqlClient.MS_SQL, limit)._query( + generateReadJson({ + table: tableName, + filters: { + string: { + name: "John", + }, + }, + }) + ) + expect(query).toEqual({ + bindings: [limit, "John%"], + sql: `select * from (select top (@p0) * from [${tableName}] where LOWER([${tableName}].[name]) LIKE @p1) as [${tableName}]`, + }) + }) })