diff --git a/src/rust/lektor_db/src/connexion.rs b/src/rust/lektor_db/src/connexion.rs index 6021a8a1d341535e2e0f296adb85d9abdbcfd631..03f8ca4e60f73e0390e01f0beaf65da46b2fae5c 100644 --- a/src/rust/lektor_db/src/connexion.rs +++ b/src/rust/lektor_db/src/connexion.rs @@ -1,6 +1,7 @@ use crate::{models::*, types::*, uri::LktUri, *}; use hashbrown::HashMap; use kurisu_api::v1 as api_v1; +use smallstring::SmallString; /// Create a connexion to a database and run automatically the migrations. fn establish_connection(path: impl AsRef<str>) -> Result<SqliteConnection, String> { @@ -17,6 +18,24 @@ pub struct LktDatabaseConnection { sqlite: SqliteConnection, } +/// Builder to realize a search operation in the database. +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct LktDatabaseSearch { + search_type: LktDatabaseSearchType, + uri: LktUri, + range: Option<Range<usize>>, +} + +/// A searcg type, to determine which table we are search. +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub enum LktDatabaseSearchType { + Playlist(SmallString), + History, + + #[default] + Database, +} + /// Load the diesel DSL for a given table. With the loaded dsl execute the /// expression... macro_rules! with_dsl { @@ -38,6 +57,30 @@ macro_rules! fuzzy { (@inner $x:ident $y:ident $($xs:ident)+) => { fuzzy!(@inner $x $y).concat(fuzzy!(@inner $($xs)+)) }; } +impl LktDatabaseSearch { + pub fn new(search_type: LktDatabaseSearchType) -> Self { + Self { + search_type, + ..Default::default() + } + } + + pub fn search_type(mut self, ty: LktDatabaseSearchType) -> Self { + self.search_type = ty; + self + } + + pub fn range(mut self, range: Range<usize>) -> Self { + self.range = Some(range); + self + } + + pub fn uri(mut self, uri: LktUri) -> Self { + self.uri = uri; + self + } +} + impl LktDatabaseConnection { /// Create a new database connexion. pub fn try_new(path: impl AsRef<Path>) -> LktDatabaseResult<Self> { @@ -201,17 +244,43 @@ impl LktDatabaseConnection { }} } - /// Search the history by URIs. We return the local ids. - pub fn search_history(&mut self, _uri: LktUri) -> LktDatabaseResult<Vec<i64>> { - todo!() - } + /// Search the database with the built search. We return the local ids. + pub fn search(&mut self, search: LktDatabaseSearch) -> LktDatabaseResult<Vec<i64>> { + // We begin by filtering the database, for KaraMaker, Language, Search + // and Playlist we get all non virtual karas, because we are joining + // other tables we can't use [into_boxed]... + + let karas = match search.uri { + LktUri::Id(uri_id) => with_dsl! { kara => kara + .filter(id.is(uri_id)) + .filter(is_virtual.is(false)) + .into_boxed() + }, + + LktUri::Origin(ref uri_origin) => with_dsl! { kara => kara + .filter(song_origin.is(uri_origin.as_str())) + .filter(is_virtual.is(false)) + .into_boxed() + }, + + LktUri::Type(ref uri_type) => with_dsl!(kara => kara + .filter(song_type.is(uri_type.as_str())) + .filter(is_virtual.is(false)) + .into_boxed() + ), + + LktUri::FuzzySearch(_) => with_dsl! { kara => kara.into_boxed() }, + + LktUri::KaraMaker(_) + | LktUri::Language(_) + | LktUri::Search(_) + | LktUri::Playlist(_) + | LktUri::Any => with_dsl! { kara => kara + .filter(is_virtual.is(false)) + .into_boxed() + }, + }; - /// Search the given playlist by URIs. We return the local ids. - pub fn search_playlist<S: AsRef<str>>( - &mut self, - _playlist: S, - _uri: LktUri, - ) -> LktDatabaseResult<Vec<i64>> { todo!() } diff --git a/src/rust/lektor_db/src/uri.rs b/src/rust/lektor_db/src/uri.rs index dd5e0b17b66f9574925703963ed4a6d6ae3d83ed..dd0fee774d9dff5b553a6ff838980c784e07ab57 100644 --- a/src/rust/lektor_db/src/uri.rs +++ b/src/rust/lektor_db/src/uri.rs @@ -1,7 +1,7 @@ use lektor_c_compat::rs::{LktCUri, LktUriField}; use smallstring::SmallString; -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, PartialEq, Eq)] pub enum LktUri { /// The id of the kara must match the URI. Id(i64),