mirror of
https://github.com/ankitects/anki.git
synced 2025-09-21 07:22:23 -04:00
fix escaping of * in field search
mentioned in https://github.com/ankitects/anki/pull/769
This commit is contained in:
parent
d9562a1898
commit
7e872de875
1 changed files with 28 additions and 6 deletions
|
@ -13,6 +13,8 @@ use crate::{
|
|||
text::{normalize_to_nfc, strip_html_preserving_image_filenames, without_combining},
|
||||
timestamp::TimestampSecs,
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
use std::{borrow::Cow, fmt::Write};
|
||||
|
||||
pub(crate) struct SqlWriter<'a> {
|
||||
|
@ -391,12 +393,15 @@ impl SqlWriter<'_> {
|
|||
}
|
||||
|
||||
let cmp;
|
||||
let cmp_trailer;
|
||||
if is_re {
|
||||
cmp = "regexp";
|
||||
cmp_trailer = "";
|
||||
self.args.push(format!("(?i){}", val));
|
||||
} else {
|
||||
cmp = "like";
|
||||
self.args.push(val.replace('*', "%"));
|
||||
cmp_trailer = "escape '\\'";
|
||||
self.args.push(convert_glob_char(val).into())
|
||||
}
|
||||
|
||||
let arg_idx = self.args.len();
|
||||
|
@ -404,10 +409,11 @@ impl SqlWriter<'_> {
|
|||
.iter()
|
||||
.map(|(ntid, ord)| {
|
||||
format!(
|
||||
"(n.mid = {mid} and field_at_index(n.flds, {ord}) {cmp} ?{n})",
|
||||
"(n.mid = {mid} and field_at_index(n.flds, {ord}) {cmp} ?{n} {cmp_trailer})",
|
||||
mid = ntid,
|
||||
ord = ord.unwrap_or_default(),
|
||||
cmp = cmp,
|
||||
cmp_trailer = cmp_trailer,
|
||||
n = arg_idx
|
||||
)
|
||||
})
|
||||
|
@ -455,6 +461,14 @@ impl SqlWriter<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Replace * with %, leaving \* alone.
|
||||
fn convert_glob_char(val: &str) -> Cow<str> {
|
||||
lazy_static! {
|
||||
static ref RE: Regex = Regex::new(r"(^|[^\\])\*").unwrap();
|
||||
}
|
||||
RE.replace_all(val, "${1}%")
|
||||
}
|
||||
|
||||
/// Convert a string with _, % or * characters into a regex.
|
||||
/// If string contains no globbing characters, return None.
|
||||
fn glob_to_re(glob: &str) -> Option<String> {
|
||||
|
@ -596,10 +610,10 @@ mod test {
|
|||
s(ctx, "front:te*st"),
|
||||
(
|
||||
concat!(
|
||||
"(((n.mid = 1581236385344 and field_at_index(n.flds, 0) like ?1) or ",
|
||||
"(n.mid = 1581236385345 and field_at_index(n.flds, 0) like ?1) or ",
|
||||
"(n.mid = 1581236385346 and field_at_index(n.flds, 0) like ?1) or ",
|
||||
"(n.mid = 1581236385347 and field_at_index(n.flds, 0) like ?1)))"
|
||||
"(((n.mid = 1581236385344 and field_at_index(n.flds, 0) like ?1 escape '\\') or ",
|
||||
"(n.mid = 1581236385345 and field_at_index(n.flds, 0) like ?1 escape '\\') or ",
|
||||
"(n.mid = 1581236385346 and field_at_index(n.flds, 0) like ?1 escape '\\') or ",
|
||||
"(n.mid = 1581236385347 and field_at_index(n.flds, 0) like ?1 escape '\\')))"
|
||||
)
|
||||
.into(),
|
||||
vec!["te%st".into()]
|
||||
|
@ -788,4 +802,12 @@ mod test {
|
|||
RequiredTable::Notes
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn convert_glob() {
|
||||
assert_eq!(&convert_glob_char("foo*bar"), "foo%bar");
|
||||
assert_eq!(&convert_glob_char("*bar"), "%bar");
|
||||
assert_eq!(&convert_glob_char("\n*bar"), "\n%bar");
|
||||
assert_eq!(&convert_glob_char(r"\*bar"), r"\*bar");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue