Skip to content
Extraits de code Groupes Projets
Vérifiée Valider 139d6152 rédigé par Kubat's avatar Kubat
Parcourir les fichiers

DB: Add the search with the rust URI type

parent 3fdfa008
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
use crate::{models::*, *}; use crate::{models::*, uri::LktUri, *};
use kurisu_api::v1 as api_v1; use kurisu_api::v1 as api_v1;
use lektor_c_compat::rs::LktCUri;
/// Create a connexion to a database and run automatically the migrations. /// Create a connexion to a database and run automatically the migrations.
fn establish_connection(path: impl AsRef<str>) -> Result<SqliteConnection, String> { fn establish_connection(path: impl AsRef<str>) -> Result<SqliteConnection, String> {
...@@ -17,50 +16,6 @@ pub struct LktDatabaseConnection { ...@@ -17,50 +16,6 @@ pub struct LktDatabaseConnection {
sqlite: SqliteConnection, sqlite: SqliteConnection,
} }
/// Get the value of a [LktCUri] and returns Err(String) in case of invalid
/// value.
macro_rules! uri_val {
($uri: literal :/ $expr: expr) => {
$expr.get_value().ok_or_else(|| {
LktDatabaseError::String(format!("the value of the {}:// uri is invalid", $uri))
})?
};
($expr: expr) => {
$expr
.get_value()
.ok_or_else(|| LktDatabaseError::Str("the value of the uri is invalid"))?
};
}
/// Do the same thing as [uri_val], but we ensure that the value is a string and
/// then return such string.
macro_rules! uri_str {
($what: literal :/ $uri: expr) => {{
let LktUriValue::String(str) = uri_val!($what :/ $uri) else {
return Err(LktDatabaseError::String(format!("try to pass integer `{}` as {} in uri", String::from($uri), $what)))
};
str
}};
}
/// Do the same thing as [uri_val], but we ensure that the value is an integer
/// and then return integer. If the value is a string, we try to convert it into
/// an integer.
macro_rules! uri_as_int {
($what: literal :/ $uri: expr) => {
match uri_val!($what :/ $uri) {
LktUriValue::Integer(int) => int,
LktUriValue::String(str) => {
let str = str.parse::<i64>().map_err(|err| {
LktDatabaseError::String(format!("the {} `{str}` is not a correct integer: {err}", $what))
})?;
i64::try_from(str).map_err(|err| LktDatabaseError::String(format!("the {} `{str}` {err}", $what)))?
}
}
};
}
/// Load the diesel DSL for a given table. With the loaded dsl execute the /// Load the diesel DSL for a given table. With the loaded dsl execute the
/// expression... /// expression...
macro_rules! with_dsl { macro_rules! with_dsl {
...@@ -73,6 +28,15 @@ macro_rules! with_dsl { ...@@ -73,6 +28,15 @@ macro_rules! with_dsl {
}}; }};
} }
/// A simple and stupid way of doing the fuzzy search
macro_rules! fuzzy {
($($xs:ident)+) => { fuzzy!(@inner $($xs)+ $($xs)+) };
(@inner $x:ident) => { $x };
(@inner $x:ident $y:ident) => { $x.concat(" ").concat($y) };
(@inner $x:ident $y:ident $($xs:ident)+) => { fuzzy!(@inner $x $y).concat(fuzzy!(@inner $($xs)+)) };
}
impl LktDatabaseConnection { impl LktDatabaseConnection {
/// Create a new database connexion. /// Create a new database connexion.
pub fn try_new(path: impl AsRef<Path>) -> LktDatabaseResult<Self> { pub fn try_new(path: impl AsRef<Path>) -> LktDatabaseResult<Self> {
...@@ -230,7 +194,7 @@ impl LktDatabaseConnection { ...@@ -230,7 +194,7 @@ impl LktDatabaseConnection {
} }
/// Search the history by URIs. We return the local ids. /// Search the history by URIs. We return the local ids.
pub fn search_history(&mut self, _uri: LktCUri) -> LktDatabaseResult<Vec<i64>> { pub fn search_history(&mut self, _uri: LktUri) -> LktDatabaseResult<Vec<i64>> {
todo!() todo!()
} }
...@@ -238,63 +202,75 @@ impl LktDatabaseConnection { ...@@ -238,63 +202,75 @@ impl LktDatabaseConnection {
pub fn search_playlist<S: AsRef<str>>( pub fn search_playlist<S: AsRef<str>>(
&mut self, &mut self,
_playlist: S, _playlist: S,
_uri: LktCUri, _uri: LktUri,
) -> LktDatabaseResult<Vec<i64>> { ) -> LktDatabaseResult<Vec<i64>> {
todo!() todo!()
} }
/// Search karas by URIs. We return the local ids. /// Search karas by URIs. We return the local ids.
pub fn search_database(&mut self, uri: LktCUri) -> LktDatabaseResult<Vec<i64>> { pub fn search_database(&mut self, uri: LktUri) -> LktDatabaseResult<Vec<i64>> {
use lektor_c_compat::rs::{LktUriField, LktUriValue}; match uri {
let uri_type = uri.get_type().ok_or(LktDatabaseError::Str( LktUri::Id(uri_id) => Ok(vec![with_dsl! { kara => kara
"passed an URI which has no valid type...", .filter(id.is(uri_id))
))?;
match uri_type {
LktUriField::Id => Ok(vec![with_dsl!(kara => kara
.filter(id.is(uri_as_int!("id" :/ uri)))
.filter(is_virtual.is(false)) .filter(is_virtual.is(false))
.select(id) .select(id)
.first::<i64>(&mut self.sqlite)? .first::<i64>(&mut self.sqlite)?
)]), }]),
LktUriField::KaraMaker => Ok(with_dsl!(kara_maker => kara_maker LktUri::KaraMaker(uri_kara_maker) => Ok(with_dsl! { kara_maker => kara_maker
.filter(name.like(uri_str!("author" :/ uri))) .filter(name.like(uri_kara_maker.as_str()))
.inner_join(schema::kara::table) .inner_join(schema::kara::table)
.filter(schema::kara::is_virtual.is(false)) .filter(schema::kara::is_virtual.is(false))
.select(id) .select(id)
.load::<i64>(&mut self.sqlite)? .load::<i64>(&mut self.sqlite)?
)), }),
LktUriField::Origin => Ok(with_dsl!(kara => kara LktUri::Origin(uri_origin) => Ok(with_dsl! { kara => kara
.filter(song_origin.like(uri_str!("origin" :/ uri))) .filter(song_origin.is(uri_origin.as_str()))
.filter(is_virtual.is(false)) .filter(is_virtual.is(false))
.select(id).load::<i64>(&mut self.sqlite)? .select(id)
)), .load::<i64>(&mut self.sqlite)?
}),
LktUriField::Type => Ok(with_dsl!(kara => kara LktUri::Type(uri_type) => Ok(with_dsl!(kara => kara
.filter(song_type.is(uri_str!("type" :/ uri))) .filter(song_type.is(uri_type.as_str()))
.filter(is_virtual.is(false)) .filter(is_virtual.is(false))
.select(id).load::<i64>(&mut self.sqlite)? .select(id)
.load::<i64>(&mut self.sqlite)?
)), )),
LktUriField::Language => Ok(with_dsl!(kara_lang => kara_lang LktUri::Language(uri_lang) => Ok(with_dsl!(kara_lang => kara_lang
.filter(code.like(uri_str!("language" :/ uri))) .filter(code.is(uri_lang.as_str()))
.inner_join(schema::kara::table) .inner_join(schema::kara::table)
.filter(schema::kara::is_virtual.is(false)) .filter(schema::kara::is_virtual.is(false))
.select(id) .select(id)
.load::<i64>(&mut self.sqlite)? .load::<i64>(&mut self.sqlite)?
)), )),
LktUriField::Search | LktUriField::FuzzySearch => { LktUri::FuzzySearch(uri_search) | LktUri::Search(uri_search) => {
let _ = uri_str!("query" :/ uri); let uri_search = uri_search.join("%");
todo!() let uri_search = uri_search.as_str();
Ok(with_dsl! { kara => {
use schema::kara_lang::code as code;
let fuzzy = fuzzy!( song_title source_name song_origin song_type code );
kara.inner_join(schema::kara_lang::table)
.filter(fuzzy.like(uri_search))
.select(id)
.load::<i64>(&mut self.sqlite)?
}})
} }
LktUriField::Playlist => { LktUri::Playlist(uri_playlist) => Ok(with_dsl!(playlist_kara => playlist_kara
let _ = uri_str!("playlist" :/ uri); .inner_join(schema::playlist::table)
todo!() .filter(schema::playlist::name.like(uri_playlist.as_str()))
} .select(kara_id)
.load::<i64>(&mut self.sqlite)?
)),
LktUri::Any => Ok(with_dsl! { kara => kara
.select(id)
.load::<i64>(&mut self.sqlite)?
}),
} }
} }
......
...@@ -9,10 +9,16 @@ use std::{ ...@@ -9,10 +9,16 @@ use std::{
// TODO: FromIterator without having to allocate a String // TODO: FromIterator without having to allocate a String
#[derive(Clone, Default, serde::Serialize, serde::Deserialize)] #[derive(Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct SmallString<B: Array<Item = u8> = [u8; 8]> { pub struct SmallString<B: Array<Item = u8> = [u8; 16]> {
buffer: SmallVec<B>, buffer: SmallVec<B>,
} }
impl SmallString {
pub fn as_str(&self) -> &str {
self.as_ref()
}
}
impl<B: Array<Item = u8>> std::hash::Hash for SmallString<B> { impl<B: Array<Item = u8>> std::hash::Hash for SmallString<B> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
let s: &str = self; let s: &str = self;
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter