fix(search): pass FTS5 boolean operators through unquoted
FTS5 boolean operators (AND, OR, NOT, NEAR) are case-sensitive uppercase keywords that must appear unquoted in the query string. Previously, the user-friendly query builder would double-quote every token, causing queries like "switch AND health" to search for the literal word "AND" instead of using it as a boolean conjunction. Adds a FTS5_OPERATORS constant and checks each token against it before quoting, allowing natural boolean search syntax to work as expected. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -52,12 +52,18 @@ pub fn to_fts_query(raw: &str, mode: FtsQueryMode) -> String {
|
|||||||
return String::new();
|
return String::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FTS5 boolean operators are case-sensitive uppercase keywords.
|
||||||
|
// Pass them through unquoted so users can write "switch AND health".
|
||||||
|
const FTS5_OPERATORS: &[&str] = &["AND", "OR", "NOT", "NEAR"];
|
||||||
|
|
||||||
let mut result = String::with_capacity(trimmed.len() + 20);
|
let mut result = String::with_capacity(trimmed.len() + 20);
|
||||||
for (i, token) in trimmed.split_whitespace().enumerate() {
|
for (i, token) in trimmed.split_whitespace().enumerate() {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
result.push(' ');
|
result.push(' ');
|
||||||
}
|
}
|
||||||
if let Some(stem) = token.strip_suffix('*')
|
if FTS5_OPERATORS.contains(&token) {
|
||||||
|
result.push_str(token);
|
||||||
|
} else if let Some(stem) = token.strip_suffix('*')
|
||||||
&& !stem.is_empty()
|
&& !stem.is_empty()
|
||||||
&& stem.chars().all(|c| c.is_alphanumeric() || c == '_')
|
&& stem.chars().all(|c| c.is_alphanumeric() || c == '_')
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user