use rusqlite::types::Value;
use crate::rusqlite::ToRusqliteSingleField;
use crate::sql::Field;
use crate::NumberCriterium;
use crate::StringCriterium;
impl<F: Field> ToRusqliteSingleField<F> for StringCriterium {
fn get_sql_where(&self, field_name: &str) -> String {
match self {
Self::Equals(_) => format!("{field_name} = ?"),
Self::HasPrefix(_) | Self::HasSuffix(_) | Self::Contains(_) => {
format!("{field_name} LIKE ? ESCAPE '\\'")
}
Self::Length(c) => <NumberCriterium<usize> as ToRusqliteSingleField<F>>::get_sql_where(
c,
&format!("length({})", field_name),
),
Self::IsNone => format!("{field_name} is NULL"),
}
.to_string()
}
fn get_inverted_sql_where(&self, field_name: &str) -> Option<String> {
Some(match self {
Self::Equals(_) => format!("{field_name} != ?"),
Self::HasPrefix(_)|
Self::HasSuffix(_)|
Self::Contains(_) =>
format!("{field_name} NOT LIKE ? ESCAPE '\\'"),
Self::Length(c) =>
return <NumberCriterium<usize> as ToRusqliteSingleField<F>>::get_inverted_sql_where(c, &format!("length({})", field_name)),
Self::IsNone => format!("{field_name} is not NULL"),
}.to_string())
}
fn get_where_values(&self, is_inverted: bool) -> Vec<Value> {
vec![Value::Text(match self {
Self::Equals(s) => s.clone(),
Self::HasPrefix(s) => escape_like_with_backslash(s) + "%",
Self::HasSuffix(s) => "%".to_owned() + &escape_like_with_backslash(s),
Self::Contains(s) => "%".to_owned() + &escape_like_with_backslash(s) + "%",
Self::Length(c) => {
return <NumberCriterium<usize> as ToRusqliteSingleField<F>>::get_where_values(
c,
is_inverted,
);
}
Self::IsNone => {
return Vec::new();
}
})]
}
}
fn escape_like_with_backslash(text: &str) -> String {
text.replace("\\", "\\\\")
.replace("%", "\\%")
.replace("_", "\\_")
}