diff --git a/packages/core/src/utils/__tests__/query-transformer.test.ts b/packages/core/src/utils/__tests__/query-transformer.test.ts index 6fcafe54b..6c02f3702 100644 --- a/packages/core/src/utils/__tests__/query-transformer.test.ts +++ b/packages/core/src/utils/__tests__/query-transformer.test.ts @@ -21,7 +21,7 @@ import { expect, test } from "vitest"; import { transformQuery } from "../query-transformer.js"; function lt2(str: string) { - return `(">${str}" OR ${str} OR "${str}<")`; + return `(">${str}" OR "${str}" OR "${str}<")`; } const TRANSFORM_QUERY_TESTS = [ @@ -65,14 +65,14 @@ const TRANSFORM_QUERY_TESTS = [ ["foo + OR", `foo AND ${lt2("+")}`], ['"special -phrase*"', '"special -phrase*"'], ["foo* + bar*", `"foo*" AND ${lt2("+")} AND "bar*"`], - ["(foo + bar) -baz", `(foo AND ${lt2("+")} AND bar) AND "-baz"`], + ["(foo + bar) -baz", `"(foo" AND ${lt2("+")} AND "bar)" AND "-baz"`], ['"phrase with "quotes""', '"phrase with ""quotes"""'], [ 'foo + "bar -baz" OR "qux*"', `foo AND ${lt2("+")} AND "bar -baz" OR "qux*"` ], ["foo + bar + ", `foo AND ${lt2("+")} AND bar AND ${lt2("+")}`], - ["+foo bar", `+foo AND bar`], + ["+foo bar", `"+foo" AND bar`], ["foo*bar*", `"foo*bar*"`], ['"escaped "quotes""', '"escaped ""quotes"""'], ["-hello-world", `"-hello-world"`], diff --git a/packages/core/src/utils/query-transformer.ts b/packages/core/src/utils/query-transformer.ts index 1be3b0bb9..82a28ce30 100644 --- a/packages/core/src/utils/query-transformer.ts +++ b/packages/core/src/utils/query-transformer.ts @@ -33,19 +33,20 @@ type OperatorNode = { type: "AND" | "OR" | "NOT"; }; +const INVALID_CHARS = /[:<>./\\()$&=#!\-+~§@^?,;'"[\]{}|]/; function escapeSQLString(str: string): string { if (str.startsWith('"') && str.endsWith('"')) { const innerStr = str.slice(1, -1).replace(/"/g, '""'); return `"${innerStr}"`; } - const maybeColspec = /[:<>./\\()$&=#!\-\+\~§@^?,;'"\[\]{}|]/.test(str); + const isInvalidChar = INVALID_CHARS.test(str); const isWildcard = str.startsWith("*") || str.endsWith("*") || str.startsWith("%") || str.endsWith("%"); - if (maybeColspec || isWildcard) { + if (isInvalidChar || isWildcard) { return `"${str}"`; } @@ -155,6 +156,21 @@ function generateSQL(ast: QueryNode): string { result.push(`(">${value}"`, "OR", value, "OR", `"${value}<")`); result.push("AND"); continue; + } else if ( + value.length === 3 && + value[0] === '"' && + value[2] === '"' && + !["<", ">"].includes(value[1]) + ) { + result.push( + `(">${value[1]}"`, + "OR", + value, + "OR", + `"${value[1]}<")` + ); + result.push("AND"); + continue; } result.push(value);