-
-
Notifications
You must be signed in to change notification settings - Fork 893
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use same table join code for both read and list functions #3663
Changes from 20 commits
3da5f83
178bd43
b9f9a23
ccd498d
a1fa3ee
47000ff
2aec4d6
d3d309c
69afed0
b43e830
60dddd7
078385d
4e00652
d472aee
d2d08dd
5874aec
56fd2d7
80bbd11
e6dca52
02ca335
f6f392c
c1fec40
460e532
4cd95af
d98f541
bcadb9c
44ffd91
b3ced19
cc29a42
c2706e2
dc49a67
ce13c9c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
use crate::schema::person; | ||
|
||
diesel::alias!(person as person1: Person1, person as person2: Person2); | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ use crate::{ | |
diesel::Connection, | ||
diesel_migrations::MigrationHarness, | ||
newtypes::DbUrl, | ||
traits::JoinView, | ||
CommentSortType, | ||
SortType, | ||
}; | ||
|
@@ -25,7 +26,7 @@ use diesel_async::{ | |
}, | ||
}; | ||
use diesel_migrations::EmbeddedMigrations; | ||
use futures_util::{future::BoxFuture, FutureExt}; | ||
use futures_util::{future::BoxFuture, Future, FutureExt}; | ||
use lemmy_utils::{ | ||
error::{LemmyError, LemmyErrorExt, LemmyErrorType}, | ||
settings::structs::Settings, | ||
|
@@ -404,6 +405,94 @@ where | |
} | ||
} | ||
|
||
pub type ResultFuture<'a, T> = BoxFuture<'a, Result<T, DieselError>>; | ||
|
||
pub trait ReadFn<'a, T: JoinView, Args>: | ||
Fn(DbConn<'a>, Args) -> ResultFuture<'a, <T as JoinView>::JoinTuple> | ||
{ | ||
} | ||
|
||
impl< | ||
'a, | ||
T: JoinView, | ||
Args, | ||
F: Fn(DbConn<'a>, Args) -> ResultFuture<'a, <T as JoinView>::JoinTuple>, | ||
> ReadFn<'a, T, Args> for F | ||
{ | ||
} | ||
|
||
pub trait ListFn<'a, T: JoinView, Args>: | ||
Fn(DbConn<'a>, Args) -> ResultFuture<'a, Vec<<T as JoinView>::JoinTuple>> | ||
{ | ||
} | ||
|
||
impl< | ||
'a, | ||
T: JoinView, | ||
Args, | ||
F: Fn(DbConn<'a>, Args) -> ResultFuture<'a, Vec<<T as JoinView>::JoinTuple>>, | ||
> ListFn<'a, T, Args> for F | ||
{ | ||
} | ||
|
||
/// Allows read and list functions to capture a shared closure that has an inferred return type, which is useful for join logic | ||
pub struct Queries<RF, LF> { | ||
pub read_fn: RF, | ||
pub list_fn: LF, | ||
} | ||
|
||
// `()` is used to prevent type inference error | ||
impl Queries<(), ()> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really do wish there was a better way to handle this, but oh well. Seems like such a common case, but because our type is so complicated, its near impossible to reverse. We'll still merge, but if you get some time, ask @weiznich on matrix or here if there really is no better alternative for what we need. |
||
pub fn new<'a, RFut, LFut, RT, LT, RA, LA, RF2, LF2>( | ||
read_fn: RF2, | ||
list_fn: LF2, | ||
) -> Queries<impl ReadFn<'a, RT, RA>, impl ListFn<'a, LT, LA>> | ||
where | ||
RFut: Future<Output = Result<<RT as JoinView>::JoinTuple, DieselError>> + Sized + Send + 'a, | ||
LFut: | ||
Future<Output = Result<Vec<<LT as JoinView>::JoinTuple>, DieselError>> + Sized + Send + 'a, | ||
RT: JoinView, | ||
LT: JoinView, | ||
RF2: Fn(DbConn<'a>, RA) -> RFut, | ||
LF2: Fn(DbConn<'a>, LA) -> LFut, | ||
{ | ||
Queries { | ||
read_fn: move |conn, args| read_fn(conn, args).boxed(), | ||
list_fn: move |conn, args| list_fn(conn, args).boxed(), | ||
} | ||
} | ||
} | ||
|
||
impl<RF, LF> Queries<RF, LF> { | ||
pub async fn read<'a, T, Args>( | ||
self, | ||
pool: &'a mut DbPool<'_>, | ||
args: Args, | ||
) -> Result<T, DieselError> | ||
where | ||
T: JoinView, | ||
RF: ReadFn<'a, T, Args>, | ||
{ | ||
let conn = get_conn(pool).await?; | ||
let res = (self.read_fn)(conn, args).await?; | ||
Ok(T::from_tuple(res)) | ||
} | ||
|
||
pub async fn list<'a, T, Args>( | ||
self, | ||
pool: &'a mut DbPool<'_>, | ||
args: Args, | ||
) -> Result<Vec<T>, DieselError> | ||
where | ||
T: JoinView, | ||
LF: ListFn<'a, T, Args>, | ||
{ | ||
let conn = get_conn(pool).await?; | ||
let res = (self.list_fn)(conn, args).await?; | ||
Ok(res.into_iter().map(T::from_tuple).collect()) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
#![allow(clippy::unwrap_used)] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for a separate file, you should be able to put the cfg attribute directly on the macro. Or otherwise put a
mod {}
declaration in lib.rs