mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-12-12 13:56:46 +00:00
Combined tables try 2
This commit is contained in:
parent
7304ef3261
commit
39b3ec2473
|
@ -179,6 +179,12 @@ pub struct LtreeDef(pub String);
|
|||
#[cfg_attr(feature = "full", ts(export))]
|
||||
pub struct DbUrl(pub(crate) Box<Url>);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[cfg_attr(feature = "full", derive(DieselNewType, TS))]
|
||||
#[cfg_attr(feature = "full", ts(export))]
|
||||
/// The report combined id
|
||||
pub struct ReportCombinedId(i32);
|
||||
|
||||
impl DbUrl {
|
||||
pub fn inner(&self) -> &Url {
|
||||
&self.0
|
||||
|
|
|
@ -856,6 +856,15 @@ diesel::table! {
|
|||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
report_combined (id) {
|
||||
id -> Int4,
|
||||
published -> Timestamptz,
|
||||
post_report_id -> Nullable<Int4>,
|
||||
comment_report_id -> Nullable<Int4>,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
secret (id) {
|
||||
id -> Int4,
|
||||
|
@ -1006,6 +1015,8 @@ diesel::joinable!(post_report -> post (post_id));
|
|||
diesel::joinable!(private_message_report -> private_message (private_message_id));
|
||||
diesel::joinable!(registration_application -> local_user (local_user_id));
|
||||
diesel::joinable!(registration_application -> person (admin_id));
|
||||
diesel::joinable!(report_combined -> comment_report (comment_report_id));
|
||||
diesel::joinable!(report_combined -> post_report (post_report_id));
|
||||
diesel::joinable!(site -> instance (instance_id));
|
||||
diesel::joinable!(site_aggregates -> site (site_id));
|
||||
diesel::joinable!(site_language -> language (language_id));
|
||||
|
@ -1072,6 +1083,7 @@ diesel::allow_tables_to_appear_in_same_query!(
|
|||
received_activity,
|
||||
registration_application,
|
||||
remote_image,
|
||||
report_combined,
|
||||
secret,
|
||||
sent_activity,
|
||||
site,
|
||||
|
|
1
crates/db_schema/src/source/combined/mod.rs
Normal file
1
crates/db_schema/src/source/combined/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod report;
|
22
crates/db_schema/src/source/combined/report.rs
Normal file
22
crates/db_schema/src/source/combined/report.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
use crate::newtypes::{CommentReportId, PostReportId, ReportCombinedId};
|
||||
#[cfg(feature = "full")]
|
||||
use crate::schema::report_combined;
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::skip_serializing_none;
|
||||
#[cfg(feature = "full")]
|
||||
use ts_rs::TS;
|
||||
|
||||
#[skip_serializing_none]
|
||||
#[derive(PartialEq, Eq, Serialize, Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Selectable, TS))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = report_combined))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
#[cfg_attr(feature = "full", ts(export))]
|
||||
/// A combined reports table.
|
||||
pub struct ReportCombined {
|
||||
pub id: ReportCombinedId,
|
||||
pub published: DateTime<Utc>,
|
||||
pub post_report_id: Option<PostReportId>,
|
||||
pub comment_report_id: Option<CommentReportId>,
|
||||
}
|
|
@ -5,6 +5,7 @@ use url::Url;
|
|||
pub mod activity;
|
||||
pub mod actor_language;
|
||||
pub mod captcha_answer;
|
||||
pub mod combined;
|
||||
pub mod comment;
|
||||
pub mod comment_reply;
|
||||
pub mod comment_report;
|
||||
|
|
|
@ -22,6 +22,8 @@ pub mod private_message_view;
|
|||
#[cfg(feature = "full")]
|
||||
pub mod registration_application_view;
|
||||
#[cfg(feature = "full")]
|
||||
pub mod report_combined_view;
|
||||
#[cfg(feature = "full")]
|
||||
pub mod site_view;
|
||||
pub mod structs;
|
||||
#[cfg(feature = "full")]
|
||||
|
|
|
@ -136,15 +136,15 @@ fn queries<'a>() -> Queries<
|
|||
query = query.order_by(post_report::published.desc());
|
||||
}
|
||||
|
||||
let (limit, offset) = limit_and_offset(options.page, options.limit)?;
|
||||
|
||||
query = query.limit(limit).offset(offset);
|
||||
|
||||
// If its not an admin, get only the ones you mod
|
||||
if !user.local_user.admin {
|
||||
query = query.filter(community_actions::became_moderator.is_not_null());
|
||||
}
|
||||
|
||||
let (limit, offset) = limit_and_offset(options.page, options.limit)?;
|
||||
|
||||
query = query.limit(limit).offset(offset);
|
||||
|
||||
query.load::<PostReportView>(&mut conn).await
|
||||
};
|
||||
|
||||
|
|
238
crates/db_views/src/report_combined_view.rs
Normal file
238
crates/db_views/src/report_combined_view.rs
Normal file
|
@ -0,0 +1,238 @@
|
|||
use crate::structs::{
|
||||
LocalUserView,
|
||||
PostOrCommentReportViewTemp,
|
||||
PostReportView,
|
||||
ReportCombinedView,
|
||||
};
|
||||
use diesel::{
|
||||
pg::Pg,
|
||||
result::Error,
|
||||
BoolExpressionMethods,
|
||||
ExpressionMethods,
|
||||
JoinOnDsl,
|
||||
NullableExpressionMethods,
|
||||
QueryDsl,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_db_schema::{
|
||||
aliases::{self, creator_community_actions},
|
||||
newtypes::{CommunityId, PersonId, PostReportId},
|
||||
schema::{
|
||||
comment_report,
|
||||
community,
|
||||
community_actions,
|
||||
local_user,
|
||||
person,
|
||||
person_actions,
|
||||
post,
|
||||
post_actions,
|
||||
post_aggregates,
|
||||
post_report,
|
||||
report_combined,
|
||||
},
|
||||
source::community::CommunityFollower,
|
||||
utils::{
|
||||
actions,
|
||||
actions_alias,
|
||||
functions::coalesce,
|
||||
get_conn,
|
||||
limit_and_offset,
|
||||
DbConn,
|
||||
DbPool,
|
||||
ListFn,
|
||||
Queries,
|
||||
ReadFn,
|
||||
},
|
||||
};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
impl ReportCombinedView {
|
||||
/// returns the current unresolved report count for the communities you mod
|
||||
pub async fn get_report_count(
|
||||
pool: &mut DbPool<'_>,
|
||||
my_person_id: PersonId,
|
||||
admin: bool,
|
||||
community_id: Option<CommunityId>,
|
||||
) -> Result<i64, Error> {
|
||||
use diesel::dsl::count;
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let mut query = post_report::table
|
||||
.inner_join(post::table)
|
||||
.filter(post_report::resolved.eq(false))
|
||||
.into_boxed();
|
||||
|
||||
if let Some(community_id) = community_id {
|
||||
query = query.filter(post::community_id.eq(community_id))
|
||||
}
|
||||
|
||||
// If its not an admin, get only the ones you mod
|
||||
if !admin {
|
||||
query
|
||||
.inner_join(
|
||||
community_actions::table.on(
|
||||
community_actions::community_id
|
||||
.eq(post::community_id)
|
||||
.and(community_actions::person_id.eq(my_person_id))
|
||||
.and(community_actions::became_moderator.is_not_null()),
|
||||
),
|
||||
)
|
||||
.select(count(post_report::id))
|
||||
.first::<i64>(conn)
|
||||
.await
|
||||
} else {
|
||||
query
|
||||
.select(count(post_report::id))
|
||||
.first::<i64>(conn)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ReportCombinedQuery {
|
||||
pub community_id: Option<CommunityId>,
|
||||
pub page: Option<i64>,
|
||||
pub limit: Option<i64>,
|
||||
pub unresolved_only: bool,
|
||||
}
|
||||
|
||||
impl ReportCombinedQuery {
|
||||
pub async fn list(
|
||||
self,
|
||||
pool: &mut DbPool<'_>,
|
||||
user: &LocalUserView,
|
||||
) -> LemmyResult<Vec<PostOrCommentReportViewTemp>> {
|
||||
let options = self;
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let mut query = report_combined::table
|
||||
.left_join(post_report::table)
|
||||
.left_join(comment_report::table)
|
||||
// .inner_join(post::table)
|
||||
// .inner_join(community::table.on(post::community_id.eq(community::id)))
|
||||
.left_join(
|
||||
person::table.on(
|
||||
post_report::creator_id
|
||||
.eq(person::id)
|
||||
.or(comment_report::creator_id.eq(person::id)),
|
||||
),
|
||||
)
|
||||
// .inner_join(aliases::person1.on(post::creator_id.eq(aliases::person1.field(person::id))))
|
||||
// .left_join(actions_alias(
|
||||
// creator_community_actions,
|
||||
// post::creator_id,
|
||||
// post::community_id,
|
||||
// ))
|
||||
// .left_join(actions(
|
||||
// community_actions::table,
|
||||
// Some(my_person_id),
|
||||
// post::community_id,
|
||||
// ))
|
||||
// .left_join(
|
||||
// local_user::table.on(
|
||||
// post::creator_id
|
||||
// .eq(local_user::person_id)
|
||||
// .and(local_user::admin.eq(true)),
|
||||
// ),
|
||||
// )
|
||||
// .left_join(actions(post_actions::table, Some(my_person_id), post::id))
|
||||
// .left_join(actions(
|
||||
// person_actions::table,
|
||||
// Some(my_person_id),
|
||||
// post::creator_id,
|
||||
// ))
|
||||
// .inner_join(post_aggregates::table.on(post_report::post_id.eq(post_aggregates::post_id)))
|
||||
// .left_join(
|
||||
// aliases::person2
|
||||
// .on(post_report::resolver_id.eq(aliases::person2.field(person::id).nullable())),
|
||||
// )
|
||||
.select((
|
||||
post_report::all_columns.nullable(),
|
||||
comment_report::all_columns.nullable(),
|
||||
// post::all_columns,
|
||||
// community::all_columns,
|
||||
person::all_columns.nullable(),
|
||||
// aliases::person1.fields(person::all_columns),
|
||||
// creator_community_actions
|
||||
// .field(community_actions::received_ban)
|
||||
// .nullable()
|
||||
// .is_not_null(),
|
||||
// creator_community_actions
|
||||
// .field(community_actions::became_moderator)
|
||||
// .nullable()
|
||||
// .is_not_null(),
|
||||
// local_user::admin.nullable().is_not_null(),
|
||||
// CommunityFollower::select_subscribed_type(),
|
||||
// post_actions::saved.nullable().is_not_null(),
|
||||
// post_actions::read.nullable().is_not_null(),
|
||||
// post_actions::hidden.nullable().is_not_null(),
|
||||
// person_actions::blocked.nullable().is_not_null(),
|
||||
// post_actions::like_score.nullable(),
|
||||
// coalesce(
|
||||
// post_aggregates::comments.nullable() - post_actions::read_comments_amount.nullable(),
|
||||
// post_aggregates::comments,
|
||||
// ),
|
||||
// post_aggregates::all_columns,
|
||||
// aliases::person2.fields(person::all_columns.nullable()),
|
||||
))
|
||||
.into_boxed();
|
||||
|
||||
// if let Some(community_id) = options.community_id {
|
||||
// query = query.filter(post::community_id.eq(community_id));
|
||||
// }
|
||||
|
||||
// if let Some(post_id) = options.post_id {
|
||||
// query = query.filter(post::id.eq(post_id));
|
||||
// }
|
||||
|
||||
// If viewing all reports, order by newest, but if viewing unresolved only, show the oldest
|
||||
// first (FIFO)
|
||||
// if options.unresolved_only {
|
||||
// query = query
|
||||
// .filter(post_report::resolved.eq(false))
|
||||
// .order_by(post_report::published.asc());
|
||||
// } else {
|
||||
// query = query.order_by(post_report::published.desc());
|
||||
// }
|
||||
|
||||
// If its not an admin, get only the ones you mod
|
||||
// if !user.local_user.admin {
|
||||
// query = query.filter(community_actions::became_moderator.is_not_null());
|
||||
// }
|
||||
|
||||
let (limit, offset) = limit_and_offset(options.page, options.limit)?;
|
||||
|
||||
query = query.limit(limit).offset(offset);
|
||||
|
||||
let res = query.load::<ReportCombinedView>(conn).await?;
|
||||
let out = res
|
||||
.iter()
|
||||
.filter_map(map_to_post_or_comment_view_tmp)
|
||||
.collect();
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
}
|
||||
|
||||
fn map_to_post_or_comment_view_tmp(
|
||||
view: &ReportCombinedView,
|
||||
) -> Option<PostOrCommentReportViewTemp> {
|
||||
// If it has post_report, you know the other fields are defined
|
||||
if let (Some(post_report), Some(post_creator)) = (view.post_report.clone(), view.creator.clone())
|
||||
{
|
||||
Some(PostOrCommentReportViewTemp::Post {
|
||||
post_report,
|
||||
post_creator,
|
||||
})
|
||||
} else if let (Some(comment_report), Some(comment_creator)) =
|
||||
(view.comment_report.clone(), view.creator.clone())
|
||||
{
|
||||
Some(PostOrCommentReportViewTemp::Comment {
|
||||
comment_report,
|
||||
comment_creator,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// TODO add tests
|
|
@ -237,3 +237,56 @@ pub struct LocalImageView {
|
|||
pub local_image: LocalImage,
|
||||
pub person: Person,
|
||||
}
|
||||
#[skip_serializing_none]
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
||||
#[cfg_attr(feature = "full", derive(TS, Queryable))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
// TODO TS shouldn't be necessary here, since this shouldn't be used externally
|
||||
#[cfg_attr(feature = "full", ts(export))]
|
||||
/// A combined report view
|
||||
pub struct ReportCombinedView {
|
||||
// Post-specific
|
||||
pub post_report: Option<PostReport>,
|
||||
// pub post_creator: Person,
|
||||
// pub unread_comments: i64,
|
||||
// pub post_counts: PostAggregates,
|
||||
// #[cfg_attr(feature = "full", ts(optional))]
|
||||
// pub resolver: Option<Person>,
|
||||
// Comment-specific
|
||||
pub comment_report: Option<CommentReport>,
|
||||
// pub comment_creator: Person,
|
||||
// pub comment: Comment,
|
||||
// pub comment_counts: CommentAggregates,
|
||||
// Shared
|
||||
// pub post: Post,
|
||||
// pub community: Community,
|
||||
// pub creator: Person,
|
||||
// pub creator_banned_from_community: bool,
|
||||
// pub creator_is_moderator: bool,
|
||||
// pub creator_is_admin: bool,
|
||||
// pub subscribed: SubscribedType,
|
||||
// pub saved: bool,
|
||||
// pub read: bool,
|
||||
// pub hidden: bool,
|
||||
// pub creator_blocked: bool,
|
||||
// #[cfg_attr(feature = "full", ts(optional))]
|
||||
// pub my_vote: Option<i16>,
|
||||
// ---
|
||||
pub creator: Option<Person>,
|
||||
}
|
||||
|
||||
pub enum PostOrCommentReportView {
|
||||
Post(PostReportView),
|
||||
Comment(CommentReportView),
|
||||
}
|
||||
|
||||
pub enum PostOrCommentReportViewTemp {
|
||||
Post {
|
||||
post_report: PostReport,
|
||||
post_creator: Person,
|
||||
},
|
||||
Comment {
|
||||
comment_report: CommentReport,
|
||||
comment_creator: Person,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
DROP TABLE report_combined;
|
14
migrations/2024-11-26-115042_add_combined_tables/up.sql
Normal file
14
migrations/2024-11-26-115042_add_combined_tables/up.sql
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
CREATE TABLE report_combined (
|
||||
id serial PRIMARY KEY,
|
||||
published timestamptz not null,
|
||||
post_report_id int REFERENCES post_report ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
comment_report_id int REFERENCES comment_report ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
UNIQUE (post_report_id, comment_report_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_report_combined_published on report_combined (published desc);
|
||||
|
||||
-- TODO do history update
|
||||
-- TODO do triggers in replaceable schema
|
||||
|
Loading…
Reference in a new issue