From 14efd5730b84cc56e40b843b059a9328b02e45b5 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 6 Jan 2024 16:59:46 -0700 Subject: [PATCH 001/232] Post --- crates/db_schema/src/schema.rs | 31 +++++-------------------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 88d468a6f..7eac6a83e 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -661,7 +661,11 @@ diesel::table! { person_id -> Int4, post_id -> Int4, read_comments -> Int8, - published -> Timestamptz, + read_comments_published -> Nullable, + read: Nullable, + saved: Nullable, + like_score: Int2, + like_published: Nullable, } } @@ -716,23 +720,6 @@ diesel::table! { } } -diesel::table! { - post_like (person_id, post_id) { - post_id -> Int4, - person_id -> Int4, - score -> Int2, - published -> Timestamptz, - } -} - -diesel::table! { - post_read (person_id, post_id) { - post_id -> Int4, - person_id -> Int4, - published -> Timestamptz, - } -} - diesel::table! { post_report (id) { id -> Int4, @@ -750,14 +737,6 @@ diesel::table! { } } -diesel::table! { - post_saved (person_id, post_id) { - post_id -> Int4, - person_id -> Int4, - published -> Timestamptz, - } -} - diesel::table! { private_message (id) { id -> Int4, From c32f62ece2114f540d7453e94d480e955e6e7fe3 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 6 Jan 2024 17:05:02 -0700 Subject: [PATCH 002/232] comment --- crates/db_schema/src/schema.rs | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 7eac6a83e..4fecdf4e2 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -107,15 +107,14 @@ diesel::table! { } } -diesel::table! { - comment_like (person_id, comment_id) { - person_id -> Int4, - comment_id -> Int4, +person_id -> Int4, post_id -> Int4, - score -> Int2, - published -> Timestamptz, - } -} + read_comments -> Int8, + read_comments_published -> Nullable, + read: Nullable, + saved: Nullable, + like_score: Int2, + like_published: Nullable, diesel::table! { comment_reply (id) { @@ -141,14 +140,6 @@ diesel::table! { } } -diesel::table! { - comment_saved (person_id, comment_id) { - comment_id -> Int4, - person_id -> Int4, - published -> Timestamptz, - } -} - diesel::table! { community (id) { id -> Int4, @@ -656,6 +647,16 @@ diesel::table! { } } +diesel::table! { + person_comment_aggregates (person_id, comment_id) { + person_id -> Int4, + comment_id -> Int4, + saved: Nullable, + like_score: Int2, + like_published: Nullable, + } +} + diesel::table! { person_post_aggregates (person_id, post_id) { person_id -> Int4, From ba82958ed33fbeefec54c0b5f9ae9eea809c0bd3 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 6 Jan 2024 17:10:24 -0700 Subject: [PATCH 003/232] Update schema.rs --- crates/db_schema/src/schema.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 4fecdf4e2..75c75bbec 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -107,15 +107,6 @@ diesel::table! { } } -person_id -> Int4, - post_id -> Int4, - read_comments -> Int8, - read_comments_published -> Nullable, - read: Nullable, - saved: Nullable, - like_score: Int2, - like_published: Nullable, - diesel::table! { comment_reply (id) { id -> Int4, From a82f99435bee91ee355f56ce8def4aace0723447 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 6 Jan 2024 17:40:49 -0700 Subject: [PATCH 004/232] Community --- crates/db_schema/src/schema.rs | 47 ++++++++++------------------------ 1 file changed, 13 insertions(+), 34 deletions(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 75c75bbec..f5191b9fb 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -183,23 +183,6 @@ diesel::table! { } } -diesel::table! { - community_block (person_id, community_id) { - person_id -> Int4, - community_id -> Int4, - published -> Timestamptz, - } -} - -diesel::table! { - community_follower (person_id, community_id) { - community_id -> Int4, - person_id -> Int4, - published -> Timestamptz, - pending -> Bool, - } -} - diesel::table! { community_language (community_id, language_id) { community_id -> Int4, @@ -207,23 +190,6 @@ diesel::table! { } } -diesel::table! { - community_moderator (person_id, community_id) { - community_id -> Int4, - person_id -> Int4, - published -> Timestamptz, - } -} - -diesel::table! { - community_person_ban (person_id, community_id) { - community_id -> Int4, - person_id -> Int4, - published -> Timestamptz, - expires -> Nullable, - } -} - diesel::table! { custom_emoji (id) { id -> Int4, @@ -648,6 +614,19 @@ diesel::table! { } } +diesel::table! { + person_community_aggregates (person_id, community_id) { + person_id -> Int4, + community_id -> Int4, + block -> Nullable, + follow -> Nullable, + follow_pending -> Bool, + moderator -> Nullable, + ban: Nullable, + ban_expires -> Nullable, + } +} + diesel::table! { person_post_aggregates (person_id, post_id) { person_id -> Int4, From 1bf52bbcc17568de1ee090cc2a95007456a55784 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 7 Jan 2024 14:59:16 -0700 Subject: [PATCH 005/232] person --- crates/db_schema/src/schema.rs | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index f5191b9fb..cc2806565 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -577,23 +577,6 @@ diesel::table! { } } -diesel::table! { - person_block (person_id, target_id) { - person_id -> Int4, - target_id -> Int4, - published -> Timestamptz, - } -} - -diesel::table! { - person_follower (follower_id, person_id) { - person_id -> Int4, - follower_id -> Int4, - published -> Timestamptz, - pending -> Bool, - } -} - diesel::table! { person_mention (id) { id -> Int4, @@ -627,6 +610,16 @@ diesel::table! { } } +diesel::table! { + person_person_aggregates (person_id, target_id) { + person_id -> Int4, + target_id -> Int4, + block -> Nullable, + follow -> Nullable, + follow_pending -> Bool, + } +} + diesel::table! { person_post_aggregates (person_id, post_id) { person_id -> Int4, From 06fedb38427d775767b02dbc0d330856fa90a08a Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 12 Jan 2024 20:15:08 -0700 Subject: [PATCH 006/232] Update post_view.rs --- crates/db_views/src/post_view.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index f5acc3804..e687d2c97 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -222,6 +222,12 @@ fn queries<'a>() -> Queries< .inner_join(person::table) .inner_join(community::table) .inner_join(post::table) + .left_join(person_post_aggregates::table + .on( + post_aggregates::post_id + .eq(person_post_aggregates::post_id) + .and(person_post_aggregates::person_id.nullable().eq(my_person_id)), + )) .select(( post::all_columns, person::all_columns, @@ -231,12 +237,12 @@ fn queries<'a>() -> Queries< creator_is_admin, post_aggregates::all_columns, subscribed_type_selection, - is_saved_selection, - is_read_selection, + person_post_aggregates::saved.is_not_null(), + person_post_aggregates::read.is_not_null(), is_creator_blocked_selection, score_selection, coalesce( - post_aggregates::comments.nullable() - read_comments, + post_aggregates::comments.nullable() - person_post_aggregates::read_comments.nullable(), post_aggregates::comments, ), )) From a458c6e0396b991cf4409c94a8fa71b2ad6ea585 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 13 Jan 2024 09:50:58 -0700 Subject: [PATCH 007/232] Update schema.rs --- crates/db_schema/src/schema.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index cc2806565..bcb9d2001 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -592,8 +592,8 @@ diesel::table! { person_id -> Int4, comment_id -> Int4, saved: Nullable, - like_score: Int2, - like_published: Nullable, + liked: Nullable, + like_score: Nullable, } } @@ -601,11 +601,11 @@ diesel::table! { person_community_aggregates (person_id, community_id) { person_id -> Int4, community_id -> Int4, - block -> Nullable, - follow -> Nullable, - follow_pending -> Bool, + blocked -> Nullable, + followed -> Nullable, + follow_pending -> Nullable, moderator -> Nullable, - ban: Nullable, + banned: Nullable, ban_expires -> Nullable, } } @@ -614,9 +614,9 @@ diesel::table! { person_person_aggregates (person_id, target_id) { person_id -> Int4, target_id -> Int4, - block -> Nullable, - follow -> Nullable, - follow_pending -> Bool, + blocked -> Nullable, + followed -> Nullable, + follow_pending -> Nullable, } } @@ -628,8 +628,8 @@ diesel::table! { read_comments_published -> Nullable, read: Nullable, saved: Nullable, - like_score: Int2, - like_published: Nullable, + liked: Nullable, + like_score: Nullable, } } From e6e76ab1551b4dae7c1b8de736cc47c57ad2813b Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 13 Jan 2024 10:10:32 -0700 Subject: [PATCH 008/232] Update post_view.rs --- crates/db_views/src/post_view.rs | 33 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index e687d2c97..8413e048b 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -86,21 +86,6 @@ fn queries<'a>() -> Queries< impl ReadFn<'a, PostView, (PostId, Option, bool)>, impl ListFn<'a, PostView, PostQuery<'a>>, > { - let is_creator_banned_from_community = exists( - community_person_ban::table.filter( - post_aggregates::community_id - .eq(community_person_ban::community_id) - .and(community_person_ban::person_id.eq(post_aggregates::creator_id)), - ), - ); - let creator_is_moderator = exists( - community_moderator::table.filter( - post_aggregates::community_id - .eq(community_moderator::community_id) - .and(community_moderator::person_id.eq(post_aggregates::creator_id)), - ), - ); - let creator_is_admin = exists( local_user::table.filter( post_aggregates::creator_id @@ -219,15 +204,27 @@ fn queries<'a>() -> Queries< }; query - .inner_join(person::table) - .inner_join(community::table) - .inner_join(post::table) + .left_join(person_person_aggregates::table + .on( + post_aggregates::creator + .eq(person_person_aggregates::target_id) + .and(person_person_aggregates::person_id.nullable().eq(my_person_id)), + )) + .left_join(person_community_aggregates::table + .on( + post_aggregates::community_id + .eq(person_community_aggregates::community_id) + .and(person_community_aggregates::person_id.nullable().eq(my_person_id)), + )) .left_join(person_post_aggregates::table .on( post_aggregates::post_id .eq(person_post_aggregates::post_id) .and(person_post_aggregates::person_id.nullable().eq(my_person_id)), )) + .inner_join(person::table) + .inner_join(community::table) + .inner_join(post::table) .select(( post::all_columns, person::all_columns, From 4745cc34b27f6b9b9a9b47c17ccf16de889c0d8c Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 13 Jan 2024 11:06:41 -0700 Subject: [PATCH 009/232] Update schema.rs --- crates/db_schema/src/schema.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index bcb9d2001..f723b1d1d 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -588,7 +588,7 @@ diesel::table! { } diesel::table! { - person_comment_aggregates (person_id, comment_id) { + person_comment_actions (person_id, comment_id) { person_id -> Int4, comment_id -> Int4, saved: Nullable, @@ -598,20 +598,20 @@ diesel::table! { } diesel::table! { - person_community_aggregates (person_id, community_id) { + person_community_actions (person_id, community_id) { person_id -> Int4, community_id -> Int4, blocked -> Nullable, followed -> Nullable, follow_pending -> Nullable, - moderator -> Nullable, - banned: Nullable, + became_moderator -> Nullable, + received_ban: Nullable, ban_expires -> Nullable, } } diesel::table! { - person_person_aggregates (person_id, target_id) { + person_person_actions (person_id, target_id) { person_id -> Int4, target_id -> Int4, blocked -> Nullable, @@ -621,7 +621,7 @@ diesel::table! { } diesel::table! { - person_post_aggregates (person_id, post_id) { + person_post_actions (person_id, post_id) { person_id -> Int4, post_id -> Int4, read_comments -> Int8, From 56502414b359458cb0ca81bd91f1f4ffe9ce9a09 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 13 Jan 2024 11:20:05 -0700 Subject: [PATCH 010/232] Update schema.rs --- crates/db_schema/src/schema.rs | 92 +++++++++++++++++----------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index f723b1d1d..d34f49cb3 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -94,6 +94,16 @@ diesel::table! { } } +diesel::table! { + comment_actions (person_id, comment_id) { + person_id -> Int4, + comment_id -> Int4, + saved: Nullable, + liked: Nullable, + like_score: Nullable, + } +} + diesel::table! { comment_aggregates (comment_id) { comment_id -> Int4, @@ -168,6 +178,19 @@ diesel::table! { } } +diesel::table! { + community_actions (person_id, community_id) { + person_id -> Int4, + community_id -> Int4, + blocked -> Nullable, + followed -> Nullable, + follow_pending -> Nullable, + became_moderator -> Nullable, + received_ban: Nullable, + ban_expires -> Nullable, + } +} + diesel::table! { community_aggregates (community_id) { community_id -> Int4, @@ -560,6 +583,16 @@ diesel::table! { } } +diesel::table! { + person_actions (person_id, target_id) { + person_id -> Int4, + target_id -> Int4, + blocked -> Nullable, + followed -> Nullable, + follow_pending -> Nullable, + } +} + diesel::table! { person_aggregates (person_id) { person_id -> Int4, @@ -587,52 +620,6 @@ diesel::table! { } } -diesel::table! { - person_comment_actions (person_id, comment_id) { - person_id -> Int4, - comment_id -> Int4, - saved: Nullable, - liked: Nullable, - like_score: Nullable, - } -} - -diesel::table! { - person_community_actions (person_id, community_id) { - person_id -> Int4, - community_id -> Int4, - blocked -> Nullable, - followed -> Nullable, - follow_pending -> Nullable, - became_moderator -> Nullable, - received_ban: Nullable, - ban_expires -> Nullable, - } -} - -diesel::table! { - person_person_actions (person_id, target_id) { - person_id -> Int4, - target_id -> Int4, - blocked -> Nullable, - followed -> Nullable, - follow_pending -> Nullable, - } -} - -diesel::table! { - person_post_actions (person_id, post_id) { - person_id -> Int4, - post_id -> Int4, - read_comments -> Int8, - read_comments_published -> Nullable, - read: Nullable, - saved: Nullable, - liked: Nullable, - like_score: Nullable, - } -} - diesel::table! { post (id) { id -> Int4, @@ -662,6 +649,19 @@ diesel::table! { } } +diesel::table! { + post_actions (person_id, post_id) { + person_id -> Int4, + post_id -> Int4, + read_comments -> Int8, + read_comments_published -> Nullable, + read: Nullable, + saved: Nullable, + liked: Nullable, + like_score: Nullable, + } +} + diesel::table! { post_aggregates (post_id) { post_id -> Int4, From 89124c02dc733c553158732140b9cc341f27b823 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 13 Jan 2024 11:52:31 -0700 Subject: [PATCH 011/232] Update post_view.rs --- crates/db_views/src/post_view.rs | 215 ++++++------------------------- 1 file changed, 36 insertions(+), 179 deletions(-) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 8413e048b..38cdebb5c 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -18,6 +18,7 @@ use diesel::{ use diesel_async::RunQueryDsl; use lemmy_db_schema::{ aggregates::structs::PostAggregates, + aliases::creator_community_actions, newtypes::{CommunityId, LocalUserId, PersonId, PostId}, schema::{ community, @@ -94,134 +95,14 @@ fn queries<'a>() -> Queries< ), ); - let is_saved = |person_id| { - exists( - post_saved::table.filter( - post_aggregates::post_id - .eq(post_saved::post_id) - .and(post_saved::person_id.eq(person_id)), - ), - ) - }; - - let is_read = |person_id| { - exists( - post_read::table.filter( - post_aggregates::post_id - .eq(post_read::post_id) - .and(post_read::person_id.eq(person_id)), - ), - ) - }; - - let is_creator_blocked = |person_id| { - exists( - person_block::table.filter( - post_aggregates::creator_id - .eq(person_block::target_id) - .and(person_block::person_id.eq(person_id)), - ), - ) - }; - - let score = |person_id| { - post_like::table - .filter( - post_aggregates::post_id - .eq(post_like::post_id) - .and(post_like::person_id.eq(person_id)), - ) - .select(post_like::score.nullable()) - .single_value() - }; - let all_joins = move |query: post_aggregates::BoxedQuery<'a, Pg>, my_person_id: Option, saved_only: bool| { - let is_saved_selection: Box> = - if saved_only { - Box::new(true.into_sql::()) - } else if let Some(person_id) = my_person_id { - Box::new(is_saved(person_id)) - } else { - Box::new(false.into_sql::()) - }; - - let is_read_selection: Box> = - if let Some(person_id) = my_person_id { - Box::new(is_read(person_id)) - } else { - Box::new(false.into_sql::()) - }; - - let is_creator_blocked_selection: Box> = - if let Some(person_id) = my_person_id { - Box::new(is_creator_blocked(person_id)) - } else { - Box::new(false.into_sql::()) - }; - - let subscribed_type_selection: Box< - dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable>, - > = if let Some(person_id) = my_person_id { - Box::new( - community_follower::table - .filter( - post_aggregates::community_id - .eq(community_follower::community_id) - .and(community_follower::person_id.eq(person_id)), - ) - .select(community_follower::pending.nullable()) - .single_value(), - ) - } else { - Box::new(None::.into_sql::>()) - }; - - let score_selection: Box< - dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable>, - > = if let Some(person_id) = my_person_id { - Box::new(score(person_id)) - } else { - Box::new(None::.into_sql::>()) - }; - - let read_comments: Box< - dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable>, - > = if let Some(person_id) = my_person_id { - Box::new( - person_post_aggregates::table - .filter( - post_aggregates::post_id - .eq(person_post_aggregates::post_id) - .and(person_post_aggregates::person_id.eq(person_id)), - ) - .select(person_post_aggregates::read_comments.nullable()) - .single_value(), - ) - } else { - Box::new(None::.into_sql::>()) - }; - query - .left_join(person_person_aggregates::table - .on( - post_aggregates::creator - .eq(person_person_aggregates::target_id) - .and(person_person_aggregates::person_id.nullable().eq(my_person_id)), - )) - .left_join(person_community_aggregates::table - .on( - post_aggregates::community_id - .eq(person_community_aggregates::community_id) - .and(person_community_aggregates::person_id.nullable().eq(my_person_id)), - )) - .left_join(person_post_aggregates::table - .on( - post_aggregates::post_id - .eq(person_post_aggregates::post_id) - .and(person_post_aggregates::person_id.nullable().eq(my_person_id)), - )) + .left_join(actions(person_actions::table, my_person_id, post_aggregates::creator_id)) + .left_join(actions(community_actions::table, my_person_id, post_aggregates::community_id)) + .left_join(actions(creator_community_actions, post_aggregates::creator_id.nullable(), post_aggregates::community_id)) + .left_join(actions(post_actions::table, my_person_id, post_aggregates::post_id)) .inner_join(person::table) .inner_join(community::table) .inner_join(post::table) @@ -229,19 +110,16 @@ fn queries<'a>() -> Queries< post::all_columns, person::all_columns, community::all_columns, - is_creator_banned_from_community, - creator_is_moderator, + creator_community_actions::received_ban.is_not_null(), + creator_community_actions::became_moderator.is_not_null(), creator_is_admin, post_aggregates::all_columns, - subscribed_type_selection, - person_post_aggregates::saved.is_not_null(), - person_post_aggregates::read.is_not_null(), - is_creator_blocked_selection, - score_selection, - coalesce( - post_aggregates::comments.nullable() - person_post_aggregates::read_comments.nullable(), - post_aggregates::comments, - ), + community_actions::follow_pending.nullable(), + post_actions::saved.is_not_null(), + post_actions::read.is_not_null(), + person_actions::blocked.is_not_null(), + post_actions::like_score.nullable(), + post_aggregates::comments - coalesce(post_actions::read_comments.nullable(), 0), )) }; @@ -332,13 +210,7 @@ fn queries<'a>() -> Queries< if let Some(listing_type) = options.listing_type { if let Some(person_id) = my_person_id { - let is_subscribed = exists( - community_follower::table.filter( - post_aggregates::community_id - .eq(community_follower::community_id) - .and(community_follower::person_id.eq(person_id)), - ), - ); + let is_subscribed = community_actions::followed.is_not_null(); match listing_type { ListingType::Subscribed => query = query.filter(is_subscribed), ListingType::Local => { @@ -348,13 +220,7 @@ fn queries<'a>() -> Queries< } ListingType::All => query = query.filter(community::hidden.eq(false).or(is_subscribed)), ListingType::ModeratorView => { - query = query.filter(exists( - community_moderator::table.filter( - post::community_id - .eq(community_moderator::community_id) - .and(community_moderator::person_id.eq(person_id)), - ), - )); + query = query.filter(community_actions::became_moderator.is_not_null()); } } } @@ -404,8 +270,8 @@ fn queries<'a>() -> Queries< query = query.filter(person::bot_account.eq(false)); }; - if let (true, Some(person_id)) = (options.saved_only, my_person_id) { - query = query.filter(is_saved(person_id)); + if options.saved_only { + query = query.filter(post_actions::saved.is_not_null()); } // Only hide the read posts, if the saved_only is false. Otherwise ppl with the hide_read // setting wont be able to see saved posts. @@ -416,41 +282,32 @@ fn queries<'a>() -> Queries< { // Do not hide read posts when it is a user profile view // Or, only hide read posts on non-profile views - if let (None, Some(person_id)) = (options.creator_id, my_person_id) { - query = query.filter(not(is_read(person_id))); + if let None = options.creator_id { + query = query.filter(post_actions::read.is_null()); } } - if let Some(person_id) = my_person_id { - if options.liked_only { - query = query.filter(score(person_id).eq(1)); - } else if options.disliked_only { - query = query.filter(score(person_id).eq(-1)); - } - }; + if options.liked_only { + query = query.filter(post_actions::like_score.eq(1)); + } else if options.disliked_only { + query = query.filter(post_actions::like_score.eq(-1)); + } // Dont filter blocks or missing languages for moderator view type - if let (Some(person_id), false) = ( - my_person_id, - options.listing_type.unwrap_or_default() == ListingType::ModeratorView, - ) { - // Filter out the rows with missing languages - query = query.filter(exists( - local_user_language::table.filter( - post::language_id - .eq(local_user_language::language_id) - .and(local_user_language::local_user_id.eq(local_user_id_join)), - ), - )); + if let options.listing_type.unwrap_or_default() != ListingType::ModeratorView { + // Filter out the rows with missing languages if user is logged in + if my_person_id.is_some() { + query = query.filter(exists( + local_user_language::table.filter( + post::language_id + .eq(local_user_language::language_id) + .and(local_user_language::local_user_id.eq(local_user_id_join)), + ), + )); + } // Don't show blocked instances, communities or persons - query = query.filter(not(exists( - community_block::table.filter( - post_aggregates::community_id - .eq(community_block::community_id) - .and(community_block::person_id.eq(person_id_join)), - ), - ))); + query = query.filter(community_actions::blocked.is_null()); query = query.filter(not(exists( instance_block::table.filter( post_aggregates::instance_id From 04f44df280644463161f1c155d8244a36046494e Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 13 Jan 2024 13:01:47 -0700 Subject: [PATCH 012/232] Update schema.rs --- crates/db_schema/src/schema.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index d34f49cb3..99d5416a0 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -295,10 +295,10 @@ diesel::table! { } diesel::table! { - instance_block (person_id, instance_id) { + instance_actions (person_id, instance_id) { person_id -> Int4, instance_id -> Int4, - published -> Timestamptz, + blocked -> Nullable, } } From 4718efa6e9fc871a549bda8913b5e7bcc53d40d5 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 13 Jan 2024 13:14:47 -0700 Subject: [PATCH 013/232] Update post_view.rs --- crates/db_views/src/post_view.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 38cdebb5c..58ca3263c 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -99,10 +99,11 @@ fn queries<'a>() -> Queries< my_person_id: Option, saved_only: bool| { query - .left_join(actions(person_actions::table, my_person_id, post_aggregates::creator_id)) .left_join(actions(community_actions::table, my_person_id, post_aggregates::community_id)) - .left_join(actions(creator_community_actions, post_aggregates::creator_id.nullable(), post_aggregates::community_id)) + .left_join(actions(person_actions::table, my_person_id, post_aggregates::creator_id)) .left_join(actions(post_actions::table, my_person_id, post_aggregates::post_id)) + .left_join(actions(instance_actions::table, my_person_id, post_aggregates::instance_id)) + .left_join(actions(creator_community_actions, post_aggregates::creator_id.nullable(), post_aggregates::community_id)) .inner_join(person::table) .inner_join(community::table) .inner_join(post::table) @@ -308,14 +309,8 @@ fn queries<'a>() -> Queries< // Don't show blocked instances, communities or persons query = query.filter(community_actions::blocked.is_null()); - query = query.filter(not(exists( - instance_block::table.filter( - post_aggregates::instance_id - .eq(instance_block::instance_id) - .and(instance_block::person_id.eq(person_id_join)), - ), - ))); - query = query.filter(not(is_creator_blocked(person_id))); + query = query.filter(instance_actions::blocked.is_null()); + query = query.filter(person_actions::blocked.is_null()); } let featured_field = if options.community_id.is_none() || options.community_id_just_for_prefetch From 5ca3a31c3aa9e012c25986170aca4006338266ae Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 13 Jan 2024 13:58:56 -0700 Subject: [PATCH 014/232] Update schema.rs --- crates/db_schema/src/schema.rs | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 99d5416a0..ed1de97cd 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -91,6 +91,12 @@ diesel::table! { path -> Ltree, distinguished -> Bool, language_id -> Int4, + score -> Int8, + upvotes -> Int8, + downvotes -> Int8, + child_count -> Int4, + hot_rank -> Float8, + controversy_rank -> Float8, } } @@ -104,19 +110,6 @@ diesel::table! { } } -diesel::table! { - comment_aggregates (comment_id) { - comment_id -> Int4, - score -> Int8, - upvotes -> Int8, - downvotes -> Int8, - published -> Timestamptz, - child_count -> Int4, - hot_rank -> Float8, - controversy_rank -> Float8, - } -} - diesel::table! { comment_reply (id) { id -> Int4, @@ -580,6 +573,10 @@ diesel::table! { bot_account -> Bool, ban_expires -> Nullable, instance_id -> Int4, + post_count -> Int8, + post_score -> Int8, + comment_count -> Int8, + comment_score -> Int8, } } @@ -593,16 +590,6 @@ diesel::table! { } } -diesel::table! { - person_aggregates (person_id) { - person_id -> Int4, - post_count -> Int8, - post_score -> Int8, - comment_count -> Int8, - comment_score -> Int8, - } -} - diesel::table! { person_ban (person_id) { person_id -> Int4, From eff5ffdb8115e346fa56d27035d457b719a7afae Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 13 Jan 2024 19:36:41 -0700 Subject: [PATCH 015/232] Update schema.rs --- crates/db_schema/src/schema.rs | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index ed1de97cd..08a5e40f3 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -633,6 +633,14 @@ diesel::table! { language_id -> Int4, featured_community -> Bool, featured_local -> Bool, + comments -> Int8, + upvotes -> Int8, + downvotes -> Int8, + newest_comment_time_necro -> Timestamptz, + newest_comment_time -> Timestamptz, + instance_id -> Int4, + ranks_time -> Timestamptz, + community_users_active_month -> Int8, } } @@ -649,28 +657,6 @@ diesel::table! { } } -diesel::table! { - post_aggregates (post_id) { - post_id -> Int4, - comments -> Int8, - score -> Int8, - upvotes -> Int8, - downvotes -> Int8, - published -> Timestamptz, - newest_comment_time_necro -> Timestamptz, - newest_comment_time -> Timestamptz, - featured_community -> Bool, - featured_local -> Bool, - hot_rank -> Float8, - hot_rank_active -> Float8, - community_id -> Int4, - creator_id -> Int4, - controversy_rank -> Float8, - instance_id -> Int4, - scaled_rank -> Float8, - } -} - diesel::table! { post_report (id) { id -> Int4, From a8eb28076d92fcf35e3c2126a796a34568f504af Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 13 Jan 2024 19:39:06 -0700 Subject: [PATCH 016/232] Update schema.rs --- crates/db_schema/src/schema.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 08a5e40f3..65993eef6 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -186,16 +186,14 @@ diesel::table! { diesel::table! { community_aggregates (community_id) { - community_id -> Int4, subscribers -> Int8, posts -> Int8, comments -> Int8, - published -> Timestamptz, users_active_day -> Int8, users_active_week -> Int8, users_active_month -> Int8, users_active_half_year -> Int8, - hot_rank -> Float8, + ranks_time -> Timestamptz, } } From b1e7e83750e84e12cb992cfad07ac8f7892565e2 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 13 Jan 2024 19:57:16 -0700 Subject: [PATCH 017/232] Update post_view.rs --- crates/db_views/src/post_view.rs | 40 +++++++++++++------------------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 58ca3263c..5bd8074e9 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -95,33 +95,31 @@ fn queries<'a>() -> Queries< ), ); - let all_joins = move |query: post_aggregates::BoxedQuery<'a, Pg>, - my_person_id: Option, - saved_only: bool| { - query - .left_join(actions(community_actions::table, my_person_id, post_aggregates::community_id)) - .left_join(actions(person_actions::table, my_person_id, post_aggregates::creator_id)) - .left_join(actions(post_actions::table, my_person_id, post_aggregates::post_id)) - .left_join(actions(instance_actions::table, my_person_id, post_aggregates::instance_id)) - .left_join(actions(creator_community_actions, post_aggregates::creator_id.nullable(), post_aggregates::community_id)) + let all_joins = move |my_person_id: Option| { + post::table + .left_join(actions(community_actions::table, my_person_id, post::community_id)) + .left_join(actions(person_actions::table, my_person_id, post::creator_id)) + .left_join(actions(post_actions::table, my_person_id, post::post_id)) + .left_join(actions(instance_actions::table, my_person_id, post::instance_id)) + .left_join(actions(creator_community_actions, post::creator_id.nullable(), post::community_id)) .inner_join(person::table) .inner_join(community::table) - .inner_join(post::table) .select(( - post::all_columns, - person::all_columns, - community::all_columns, + Post::as_select(), + Person::as_select(), + Community::as_select(), creator_community_actions::received_ban.is_not_null(), creator_community_actions::became_moderator.is_not_null(), creator_is_admin, - post_aggregates::all_columns, + PostAggregates::as_select(), community_actions::follow_pending.nullable(), post_actions::saved.is_not_null(), post_actions::read.is_not_null(), person_actions::blocked.is_not_null(), post_actions::like_score.nullable(), - post_aggregates::comments - coalesce(post_actions::read_comments.nullable(), 0), + post::comments - coalesce(post_actions::read_comments.nullable(), 0), )) + .into_boxed() }; let read = @@ -131,12 +129,8 @@ fn queries<'a>() -> Queries< let person_id_join = my_person_id.unwrap_or(PersonId(-1)); let mut query = all_joins( - post_aggregates::table - .filter(post_aggregates::post_id.eq(post_id)) - .into_boxed(), my_person_id, - false, - ); + ).filter(post::id.eq(post_id)); // Hide deleted and removed for non-admins or mods if !is_mod_or_admin { @@ -176,9 +170,7 @@ fn queries<'a>() -> Queries< let local_user_id_join = my_local_user_id.unwrap_or(LocalUserId(-1)); let mut query = all_joins( - post_aggregates::table.into_boxed(), my_person_id, - options.saved_only, ); // hide posts from deleted communities @@ -202,11 +194,11 @@ fn queries<'a>() -> Queries< .filter(post::removed.eq(false)); } if let Some(community_id) = options.community_id { - query = query.filter(post_aggregates::community_id.eq(community_id)); + query = query.filter(post::community_id.eq(community_id)); } if let Some(creator_id) = options.creator_id { - query = query.filter(post_aggregates::creator_id.eq(creator_id)); + query = query.filter(post::creator_id.eq(creator_id)); } if let Some(listing_type) = options.listing_type { From bf9320708fdd67b7ef1e81c2038636582bdcf3d5 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 20 Jan 2024 15:08:35 -0700 Subject: [PATCH 018/232] Update schema.rs --- crates/db_schema/src/schema.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 65993eef6..5621a716c 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -91,12 +91,10 @@ diesel::table! { path -> Ltree, distinguished -> Bool, language_id -> Int4, - score -> Int8, upvotes -> Int8, downvotes -> Int8, child_count -> Int4, - hot_rank -> Float8, - controversy_rank -> Float8, + ranks_time -> Timestamptz, } } From 96a24ebfa1457f029a705b7739f76cded58ff038 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 21 Jan 2024 09:01:08 -0700 Subject: [PATCH 019/232] Update post_view.rs --- crates/db_views/src/post_view.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 5bd8074e9..db3bfae65 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -108,8 +108,8 @@ fn queries<'a>() -> Queries< Post::as_select(), Person::as_select(), Community::as_select(), - creator_community_actions::received_ban.is_not_null(), - creator_community_actions::became_moderator.is_not_null(), + creator_community_actions.field(community_actions::received_ban).is_not_null(), + creator_community_actions.field(community_actions::became_moderator).is_not_null(), creator_is_admin, PostAggregates::as_select(), community_actions::follow_pending.nullable(), From a597eb65c1bbef29401464b38f5ae3b4e5995aae Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 21 Jan 2024 09:29:51 -0700 Subject: [PATCH 020/232] Update comment_report_view.rs --- crates/db_views/src/comment_report_view.rs | 46 ++++++++++------------ 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/crates/db_views/src/comment_report_view.rs b/crates/db_views/src/comment_report_view.rs index 83ab5c063..290688fc9 100644 --- a/crates/db_views/src/comment_report_view.rs +++ b/crates/db_views/src/comment_report_view.rs @@ -32,22 +32,18 @@ fn queries<'a>() -> Queries< impl ListFn<'a, CommentReportView, (CommentReportQuery, &'a LocalUserView)>, > { let all_joins = |query: comment_report::BoxedQuery<'a, Pg>, my_person_id: PersonId| { - query + let my_vote = actions_subquery(comment_actions::table, my_person_id, comment_report::comment_id) + .select(comment_actions::like_score) + .single_value + + comment_report::table .inner_join(comment::table) .inner_join(post::table.on(comment::post_id.eq(post::id))) .inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(person::table.on(comment_report::creator_id.eq(person::id))) .inner_join(aliases::person1.on(comment::creator_id.eq(aliases::person1.field(person::id)))) - .inner_join( - comment_aggregates::table.on(comment_report::comment_id.eq(comment_aggregates::comment_id)), - ) - .left_join( - comment_like::table.on( - comment::id - .eq(comment_like::comment_id) - .and(comment_like::person_id.eq(my_person_id)), - ), - ) + .left_join(actions(comment_actions::table, my_person_id, comment::id)) + .left_join(actions(community_actions::table, comment::creator_id.nullable(), post::community_id)) .left_join( aliases::person2 .on(comment_report::resolver_id.eq(aliases::person2.field(person::id).nullable())), @@ -68,25 +64,23 @@ fn queries<'a>() -> Queries< ); let read = move |mut conn: DbConn<'a>, (report_id, my_person_id): (CommentReportId, PersonId)| async move { - all_joins( - comment_report::table.find(report_id).into_boxed(), - my_person_id, - ) - .left_join( - community_person_ban::table.on( - community::id - .eq(community_person_ban::community_id) - .and(community_person_ban::person_id.eq(comment::creator_id)), - ), - ) - .select(selection) - .first::(&mut conn) - .await + all_joins(my_person_id) + .left_join( + community_person_ban::table.on( + community::id + .eq(community_person_ban::community_id) + .and(community_person_ban::person_id.eq(comment::creator_id)), + ), + ) + .filter(comment_report::id.eq(report_id)) + .select(selection) + .first::(&mut conn) + .await }; let list = move |mut conn: DbConn<'a>, (options, user): (CommentReportQuery, &'a LocalUserView)| async move { - let mut query = all_joins(comment_report::table.into_boxed(), user.person.id) + let mut query = all_joins(user.person.id) .left_join( community_person_ban::table.on( community::id From b7f11f1b9d3dd67308a26699fa143863950e7376 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 21 Jan 2024 09:44:59 -0700 Subject: [PATCH 021/232] Update comment_report_view.rs --- crates/db_views/src/comment_report_view.rs | 62 +++++++++------------- 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/crates/db_views/src/comment_report_view.rs b/crates/db_views/src/comment_report_view.rs index 290688fc9..1ffc9b470 100644 --- a/crates/db_views/src/comment_report_view.rs +++ b/crates/db_views/src/comment_report_view.rs @@ -32,9 +32,21 @@ fn queries<'a>() -> Queries< impl ListFn<'a, CommentReportView, (CommentReportQuery, &'a LocalUserView)>, > { let all_joins = |query: comment_report::BoxedQuery<'a, Pg>, my_person_id: PersonId| { + let creator_banned_from_community = exists( + actions_subquery(community_actions::table, comment::creator_id.nullable(), post::community_id) + .filter( + community_actions::received_ban_from_community.is_not_null() + .and( + community_actions::ban_expires + .is_null() + .or(community_actions::ban_expires.gt(now)), + ) + ) + ); + let my_vote = actions_subquery(comment_actions::table, my_person_id, comment_report::comment_id) .select(comment_actions::like_score) - .single_value + .single_value(); comment_report::table .inner_join(comment::table) @@ -42,36 +54,25 @@ fn queries<'a>() -> Queries< .inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(person::table.on(comment_report::creator_id.eq(person::id))) .inner_join(aliases::person1.on(comment::creator_id.eq(aliases::person1.field(person::id)))) - .left_join(actions(comment_actions::table, my_person_id, comment::id)) - .left_join(actions(community_actions::table, comment::creator_id.nullable(), post::community_id)) .left_join( aliases::person2 .on(comment_report::resolver_id.eq(aliases::person2.field(person::id).nullable())), ) + .select(( + comment_report::all_columns, + comment::all_columns, + post::all_columns, + community::all_columns, + person::all_columns, + aliases::person1.fields(person::all_columns), + creator_banned_from_community, + my_vote, + aliases::person2.fields(person::all_columns).nullable(), + )) }; - let selection = ( - comment_report::all_columns, - comment::all_columns, - post::all_columns, - community::all_columns, - person::all_columns, - aliases::person1.fields(person::all_columns), - comment_aggregates::all_columns, - community_person_ban::community_id.nullable().is_not_null(), - comment_like::score.nullable(), - aliases::person2.fields(person::all_columns).nullable(), - ); - let read = move |mut conn: DbConn<'a>, (report_id, my_person_id): (CommentReportId, PersonId)| async move { all_joins(my_person_id) - .left_join( - community_person_ban::table.on( - community::id - .eq(community_person_ban::community_id) - .and(community_person_ban::person_id.eq(comment::creator_id)), - ), - ) .filter(comment_report::id.eq(report_id)) .select(selection) .first::(&mut conn) @@ -80,20 +81,7 @@ fn queries<'a>() -> Queries< let list = move |mut conn: DbConn<'a>, (options, user): (CommentReportQuery, &'a LocalUserView)| async move { - let mut query = all_joins(user.person.id) - .left_join( - community_person_ban::table.on( - community::id - .eq(community_person_ban::community_id) - .and(community_person_ban::person_id.eq(comment::creator_id)) - .and( - community_person_ban::expires - .is_null() - .or(community_person_ban::expires.gt(now)), - ), - ), - ) - .select(selection); + let mut query = all_joins(user.person.id).into_boxed(); if let Some(community_id) = options.community_id { query = query.filter(post::community_id.eq(community_id)); From 0f9ffa81a21870f20d8719b5a8d1b4d82c2866de Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 11 Feb 2024 10:23:57 -0700 Subject: [PATCH 022/232] Update post_view.rs --- crates/db_views/src/post_view.rs | 38 ++++++++++++++------------------ 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index db3bfae65..0fd42d964 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -87,37 +87,31 @@ fn queries<'a>() -> Queries< impl ReadFn<'a, PostView, (PostId, Option, bool)>, impl ListFn<'a, PostView, PostQuery<'a>>, > { - let creator_is_admin = exists( - local_user::table.filter( - post_aggregates::creator_id - .eq(local_user::person_id) - .and(local_user::admin.eq(true)), - ), - ); - let all_joins = move |my_person_id: Option| { - post::table - .left_join(actions(community_actions::table, my_person_id, post::community_id)) - .left_join(actions(person_actions::table, my_person_id, post::creator_id)) - .left_join(actions(post_actions::table, my_person_id, post::post_id)) - .left_join(actions(instance_actions::table, my_person_id, post::instance_id)) - .left_join(actions(creator_community_actions, post::creator_id.nullable(), post::community_id)) + post_aggregates::table .inner_join(person::table) + .left_join(local_user::table) .inner_join(community::table) + .inner_join(post::table) + .left_join(actions(community_actions::table, my_person_id, post_aggregates::community_id)) + .left_join(actions(person_actions::table, my_person_id, post_aggregates::creator_id)) + .left_join(actions(post_actions::table, my_person_id, post_aggregates::post_id)) + .left_join(actions(instance_actions::table, my_person_id, post_aggregates::instance_id)) + .left_join(actions(creator_community_actions, post_aggregates::creator_id.nullable(), post_aggregates::community_id)) .select(( - Post::as_select(), - Person::as_select(), - Community::as_select(), + post::all_columns, + person::all_columns, + community::all_columns, creator_community_actions.field(community_actions::received_ban).is_not_null(), creator_community_actions.field(community_actions::became_moderator).is_not_null(), creator_is_admin, - PostAggregates::as_select(), + post_aggregates::all_columns, community_actions::follow_pending.nullable(), post_actions::saved.is_not_null(), post_actions::read.is_not_null(), person_actions::blocked.is_not_null(), post_actions::like_score.nullable(), - post::comments - coalesce(post_actions::read_comments.nullable(), 0), + post_aggregates::comments - coalesce(post_actions::read_comments.nullable(), 0), )) .into_boxed() }; @@ -130,7 +124,7 @@ fn queries<'a>() -> Queries< let mut query = all_joins( my_person_id, - ).filter(post::id.eq(post_id)); + ).filter(post_aggregates::post_id.eq(post_id)); // Hide deleted and removed for non-admins or mods if !is_mod_or_admin { @@ -194,11 +188,11 @@ fn queries<'a>() -> Queries< .filter(post::removed.eq(false)); } if let Some(community_id) = options.community_id { - query = query.filter(post::community_id.eq(community_id)); + query = query.filter(post_aggregates::community_id.eq(community_id)); } if let Some(creator_id) = options.creator_id { - query = query.filter(post::creator_id.eq(creator_id)); + query = query.filter(post_aggregates::creator_id.eq(creator_id)); } if let Some(listing_type) = options.listing_type { From d4ffdf5de1733b16a443fa9f793559dcb7379ce4 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 11 Feb 2024 11:56:28 -0700 Subject: [PATCH 023/232] Update utils.rs --- crates/db_schema/src/utils.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index d7af17544..76e1a962f 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -396,6 +396,19 @@ pub fn now() -> AsExprOf { diesel::dsl::now.into_sql::() } +pub fn actions(actions_table: T, person_id: Option, target_id: C) -> dsl::On< + T, + dsl::And< + dsl::Eq, BindIfSome>, + dsl::Eq, + >, +> +where + T: Table, +{ + actions_table.on(K0::default().nullable().eq(BindIfSome(person_id)).and(K1::default().eq(target_id))) +} + pub type ResultFuture<'a, T> = BoxFuture<'a, Result>; pub trait ReadFn<'a, T, Args>: Fn(DbConn<'a>, Args) -> ResultFuture<'a, T> {} From aa7077f89727494ace196ac8e3176e5a78053bc0 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 11 Feb 2024 18:24:42 -0700 Subject: [PATCH 024/232] Update schema.rs --- crates/db_schema/src/schema.rs | 61 +++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 5621a716c..9a8514083 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -91,10 +91,6 @@ diesel::table! { path -> Ltree, distinguished -> Bool, language_id -> Int4, - upvotes -> Int8, - downvotes -> Int8, - child_count -> Int4, - ranks_time -> Timestamptz, } } @@ -108,6 +104,19 @@ diesel::table! { } } +diesel::table! { + comment_aggregates (comment_id) { + comment_id -> Int4, + score -> Int8, + upvotes -> Int8, + downvotes -> Int8, + published -> Timestamptz, + child_count -> Int4, + hot_rank -> Float8, + controversy_rank -> Float8, + } +} + diesel::table! { comment_reply (id) { id -> Int4, @@ -569,10 +578,6 @@ diesel::table! { bot_account -> Bool, ban_expires -> Nullable, instance_id -> Int4, - post_count -> Int8, - post_score -> Int8, - comment_count -> Int8, - comment_score -> Int8, } } @@ -586,6 +591,16 @@ diesel::table! { } } +diesel::table! { + person_aggregates (person_id) { + person_id -> Int4, + post_count -> Int8, + post_score -> Int8, + comment_count -> Int8, + comment_score -> Int8, + } +} + diesel::table! { person_ban (person_id) { person_id -> Int4, @@ -629,14 +644,6 @@ diesel::table! { language_id -> Int4, featured_community -> Bool, featured_local -> Bool, - comments -> Int8, - upvotes -> Int8, - downvotes -> Int8, - newest_comment_time_necro -> Timestamptz, - newest_comment_time -> Timestamptz, - instance_id -> Int4, - ranks_time -> Timestamptz, - community_users_active_month -> Int8, } } @@ -653,6 +660,28 @@ diesel::table! { } } +diesel::table! { + post_aggregates (post_id) { + post_id -> Int4, + comments -> Int8, + score -> Int8, + upvotes -> Int8, + downvotes -> Int8, + published -> Timestamptz, + newest_comment_time_necro -> Timestamptz, + newest_comment_time -> Timestamptz, + featured_community -> Bool, + featured_local -> Bool, + hot_rank -> Float8, + hot_rank_active -> Float8, + community_id -> Int4, + creator_id -> Int4, + controversy_rank -> Float8, + instance_id -> Int4, + scaled_rank -> Float8, + } +} + diesel::table! { post_report (id) { id -> Int4, From 9761ea8f7e2a723b7b6ea37e25b5cc5794581358 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Fri, 16 Feb 2024 17:43:59 +0000 Subject: [PATCH 025/232] stuff --- crates/db_schema/src/schema.rs | 5 +- crates/db_schema/src/utils.rs | 19 ++++---- crates/db_views/src/comment_report_view.rs | 56 ++++++++++++---------- crates/db_views/src/post_view.rs | 55 +++++++++++++++------ 4 files changed, 86 insertions(+), 49 deletions(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 4d2b0571b..84d295f9d 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -201,14 +201,17 @@ diesel::table! { diesel::table! { community_aggregates (community_id) { + community_id -> Int4, subscribers -> Int8, posts -> Int8, comments -> Int8, + published -> Timestamptz, users_active_day -> Int8, users_active_week -> Int8, users_active_month -> Int8, users_active_half_year -> Int8, - ranks_time -> Timestamptz, + hot_rank -> Float8, + subscribers_local -> Int8, } } diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index 558d6014b..40b0b7712 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -502,17 +502,20 @@ pub fn now() -> AsExprOf { diesel::dsl::now.into_sql::() } -pub fn actions(actions_table: T, person_id: Option, target_id: C) -> dsl::On< - T, - dsl::And< - dsl::Eq, BindIfSome>, - dsl::Eq, - >, -> +pub fn actions( + actions_table: T, + person_id: Option, + target_id: C, +) -> dsl::On, BindIfSome>, dsl::Eq>> where T: Table, { - actions_table.on(K0::default().nullable().eq(BindIfSome(person_id)).and(K1::default().eq(target_id))) + actions_table.on( + K0::default() + .nullable() + .eq(BindIfSome(person_id)) + .and(K1::default().eq(target_id)), + ) } pub type ResultFuture<'a, T> = BoxFuture<'a, Result>; diff --git a/crates/db_views/src/comment_report_view.rs b/crates/db_views/src/comment_report_view.rs index f2c47fefd..e1618b727 100644 --- a/crates/db_views/src/comment_report_view.rs +++ b/crates/db_views/src/comment_report_view.rs @@ -32,32 +32,29 @@ fn queries<'a>() -> Queries< impl ListFn<'a, CommentReportView, (CommentReportQuery, &'a LocalUserView)>, > { let all_joins = |query: comment_report::BoxedQuery<'a, Pg>, my_person_id: PersonId| { - let creator_banned_from_community = exists( - actions_subquery(community_actions::table, comment::creator_id.nullable(), post::community_id) - .filter( - community_actions::received_ban_from_community.is_not_null() - .and( - community_actions::ban_expires - .is_null() - .or(community_actions::ban_expires.gt(now)), - ) - ) - ); - - let my_vote = actions_subquery(comment_actions::table, my_person_id, comment_report::comment_id) - .select(comment_actions::like_score) - .single_value(); - - comment_report::table + query .inner_join(comment::table) .inner_join(post::table.on(comment::post_id.eq(post::id))) .inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(person::table.on(comment_report::creator_id.eq(person::id))) .inner_join(aliases::person1.on(comment::creator_id.eq(aliases::person1.field(person::id)))) + .inner_join( + comment_aggregates::table.on(comment_report::comment_id.eq(comment_aggregates::comment_id)), + ) + .left_join(actions( + comment_actions::table, + Some(my_person_id), + comment_report::comment_id, + )) .left_join( aliases::person2 .on(comment_report::resolver_id.eq(aliases::person2.field(person::id).nullable())), ) + .left_join(actions( + creator_community_actions, + comment::creator_id.nullable(), + post_aggregates::community_id, + )) .select(( comment_report::all_columns, comment::all_columns, @@ -65,23 +62,32 @@ fn queries<'a>() -> Queries< community::all_columns, person::all_columns, aliases::person1.fields(person::all_columns), - creator_banned_from_community, - my_vote, + comment_aggregates::all_columns, + creator_community_actions + .field(community_actions::received_ban) + .is_null() + .or( + creator_community_actions + .field(community_actions::ban_expires) + .gt(now), + ), + post_actions::like_score.nullable(), aliases::person2.fields(person::all_columns).nullable(), )) }; let read = move |mut conn: DbConn<'a>, (report_id, my_person_id): (CommentReportId, PersonId)| async move { - all_joins(my_person_id) - .filter(comment_report::id.eq(report_id)) - .select(selection) - .first::(&mut conn) - .await + all_joins( + comment_report::table.find(report_id).into_boxed(), + my_person_id, + ) + .first::(&mut conn) + .await }; let list = move |mut conn: DbConn<'a>, (options, user): (CommentReportQuery, &'a LocalUserView)| async move { - let mut query = all_joins(user.person.id).into_boxed(); + let mut query = all_joins(comment_report::table.into_boxed(), user.person.id); if let Some(community_id) = options.community_id { query = query.filter(post::community_id.eq(community_id)); diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 215f2a946..141429c7f 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -65,23 +65,48 @@ fn queries<'a>() -> Queries< impl ReadFn<'a, PostView, (PostId, Option, bool)>, impl ListFn<'a, PostView, (PostQuery<'a>, &'a Site)>, > { - let all_joins = move |my_person_id: Option| { - post_aggregates::table + let all_joins = move |query: post_aggregates::BoxedQuery<'a, Pg>, + my_person_id: Option| { + query .inner_join(person::table) .left_join(local_user::table) .inner_join(community::table) .inner_join(post::table) - .left_join(actions(community_actions::table, my_person_id, post_aggregates::community_id)) - .left_join(actions(person_actions::table, my_person_id, post_aggregates::creator_id)) - .left_join(actions(post_actions::table, my_person_id, post_aggregates::post_id)) - .left_join(actions(instance_actions::table, my_person_id, post_aggregates::instance_id)) - .left_join(actions(creator_community_actions, post_aggregates::creator_id.nullable(), post_aggregates::community_id)) + .left_join(actions( + community_actions::table, + my_person_id, + post_aggregates::community_id, + )) + .left_join(actions( + person_actions::table, + my_person_id, + post_aggregates::creator_id, + )) + .left_join(actions( + post_actions::table, + my_person_id, + post_aggregates::post_id, + )) + .left_join(actions( + instance_actions::table, + my_person_id, + post_aggregates::instance_id, + )) + .left_join(actions( + creator_community_actions, + post_aggregates::creator_id.nullable(), + post_aggregates::community_id, + )) .select(( post::all_columns, person::all_columns, community::all_columns, - creator_community_actions.field(community_actions::received_ban).is_not_null(), - creator_community_actions.field(community_actions::became_moderator).is_not_null(), + creator_community_actions + .field(community_actions::received_ban) + .is_not_null(), + creator_community_actions + .field(community_actions::became_moderator) + .is_not_null(), creator_is_admin, post_aggregates::all_columns, community_actions::follow_pending.nullable(), @@ -91,7 +116,6 @@ fn queries<'a>() -> Queries< post_actions::like_score.nullable(), post_aggregates::comments - coalesce(post_actions::read_comments.nullable(), 0), )) - .into_boxed() }; let read = @@ -101,8 +125,11 @@ fn queries<'a>() -> Queries< let person_id_join = my_person_id.unwrap_or(PersonId(-1)); let mut query = all_joins( + post_aggregates::table + .filter(post_aggregates::post_id.eq(post_id)) + .into_boxed(), my_person_id, - ).filter(post_aggregates::post_id.eq(post_id)); + ); // Hide deleted and removed for non-admins or mods if !is_mod_or_admin { @@ -149,9 +176,7 @@ fn queries<'a>() -> Queries< let person_id_join = my_person_id.unwrap_or(PersonId(-1)); let local_user_id_join = my_local_user_id.unwrap_or(LocalUserId(-1)); - let mut query = all_joins( - my_person_id, - ); + let mut query = all_joins(post_aggregates::table.into_boxed(), my_person_id); // hide posts from deleted communities query = query.filter(community::deleted.eq(false)); @@ -274,7 +299,7 @@ fn queries<'a>() -> Queries< } // Dont filter blocks or missing languages for moderator view type - if let options.listing_type.unwrap_or_default() != ListingType::ModeratorView { + if options.listing_type.unwrap_or_default() != ListingType::ModeratorView { // Filter out the rows with missing languages if user is logged in if my_person_id.is_some() { query = query.filter(exists( From 893d62a8122e53b014738af48c6f4a52e269820e Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Fri, 16 Feb 2024 17:57:59 +0000 Subject: [PATCH 026/232] stuff --- crates/db_schema/src/schema.rs | 67 ++++++++++++---------------------- crates/db_schema/src/utils.rs | 14 +------ 2 files changed, 25 insertions(+), 56 deletions(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 84d295f9d..8b34c38d7 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -102,9 +102,10 @@ diesel::table! { comment_actions (person_id, comment_id) { person_id -> Int4, comment_id -> Int4, - saved: Nullable, - liked: Nullable, - like_score: Nullable, + post_id -> Int4, + saved -> Nullable, + liked -> Nullable, + like_score -> Nullable, } } @@ -194,7 +195,7 @@ diesel::table! { followed -> Nullable, follow_pending -> Nullable, became_moderator -> Nullable, - received_ban: Nullable, + received_ban -> Nullable, ban_expires -> Nullable, } } @@ -669,10 +670,10 @@ diesel::table! { post_id -> Int4, read_comments -> Int8, read_comments_published -> Nullable, - read: Nullable, - saved: Nullable, - liked: Nullable, - like_score: Nullable, + read -> Nullable, + saved -> Nullable, + liked -> Nullable, + like_score -> Nullable, } } @@ -860,35 +861,27 @@ diesel::joinable!(admin_purge_post -> person (admin_person_id)); diesel::joinable!(comment -> language (language_id)); diesel::joinable!(comment -> person (creator_id)); diesel::joinable!(comment -> post (post_id)); +diesel::joinable!(comment_actions -> comment (comment_id)); +diesel::joinable!(comment_actions -> person (person_id)); +diesel::joinable!(comment_actions -> post (post_id)); diesel::joinable!(comment_aggregates -> comment (comment_id)); -diesel::joinable!(comment_like -> comment (comment_id)); -diesel::joinable!(comment_like -> person (person_id)); -diesel::joinable!(comment_like -> post (post_id)); diesel::joinable!(comment_reply -> comment (comment_id)); diesel::joinable!(comment_reply -> person (recipient_id)); diesel::joinable!(comment_report -> comment (comment_id)); -diesel::joinable!(comment_saved -> comment (comment_id)); -diesel::joinable!(comment_saved -> person (person_id)); diesel::joinable!(community -> instance (instance_id)); +diesel::joinable!(community_actions -> community (community_id)); +diesel::joinable!(community_actions -> person (person_id)); diesel::joinable!(community_aggregates -> community (community_id)); -diesel::joinable!(community_block -> community (community_id)); -diesel::joinable!(community_block -> person (person_id)); -diesel::joinable!(community_follower -> community (community_id)); -diesel::joinable!(community_follower -> person (person_id)); diesel::joinable!(community_language -> community (community_id)); diesel::joinable!(community_language -> language (language_id)); -diesel::joinable!(community_moderator -> community (community_id)); -diesel::joinable!(community_moderator -> person (person_id)); -diesel::joinable!(community_person_ban -> community (community_id)); -diesel::joinable!(community_person_ban -> person (person_id)); diesel::joinable!(custom_emoji -> local_site (local_site_id)); diesel::joinable!(custom_emoji_keyword -> custom_emoji (custom_emoji_id)); diesel::joinable!(email_verification -> local_user (local_user_id)); diesel::joinable!(federation_allowlist -> instance (instance_id)); diesel::joinable!(federation_blocklist -> instance (instance_id)); diesel::joinable!(federation_queue_state -> instance (instance_id)); -diesel::joinable!(instance_block -> instance (instance_id)); -diesel::joinable!(instance_block -> person (person_id)); +diesel::joinable!(instance_actions -> instance (instance_id)); +diesel::joinable!(instance_actions -> person (person_id)); diesel::joinable!(local_image -> local_user (local_user_id)); diesel::joinable!(local_site -> site (site_id)); diesel::joinable!(local_site_rate_limit -> local_site (local_site_id)); @@ -917,22 +910,16 @@ diesel::joinable!(person_aggregates -> person (person_id)); diesel::joinable!(person_ban -> person (person_id)); diesel::joinable!(person_mention -> comment (comment_id)); diesel::joinable!(person_mention -> person (recipient_id)); -diesel::joinable!(person_post_aggregates -> person (person_id)); -diesel::joinable!(person_post_aggregates -> post (post_id)); diesel::joinable!(post -> community (community_id)); diesel::joinable!(post -> language (language_id)); diesel::joinable!(post -> person (creator_id)); +diesel::joinable!(post_actions -> person (person_id)); +diesel::joinable!(post_actions -> post (post_id)); diesel::joinable!(post_aggregates -> community (community_id)); diesel::joinable!(post_aggregates -> instance (instance_id)); diesel::joinable!(post_aggregates -> person (creator_id)); diesel::joinable!(post_aggregates -> post (post_id)); -diesel::joinable!(post_like -> person (person_id)); -diesel::joinable!(post_like -> post (post_id)); -diesel::joinable!(post_read -> person (person_id)); -diesel::joinable!(post_read -> post (post_id)); diesel::joinable!(post_report -> post (post_id)); -diesel::joinable!(post_saved -> person (person_id)); -diesel::joinable!(post_saved -> 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)); @@ -949,18 +936,14 @@ diesel::allow_tables_to_appear_in_same_query!( admin_purge_post, captcha_answer, comment, + comment_actions, comment_aggregates, - comment_like, comment_reply, comment_report, - comment_saved, community, + community_actions, community_aggregates, - community_block, - community_follower, community_language, - community_moderator, - community_person_ban, custom_emoji, custom_emoji_keyword, email_verification, @@ -968,7 +951,7 @@ diesel::allow_tables_to_appear_in_same_query!( federation_blocklist, federation_queue_state, instance, - instance_block, + instance_actions, language, local_image, local_site, @@ -989,18 +972,14 @@ diesel::allow_tables_to_appear_in_same_query!( mod_transfer_community, password_reset_request, person, + person_actions, person_aggregates, person_ban, - person_block, - person_follower, person_mention, - person_post_aggregates, post, + post_actions, post_aggregates, - post_like, - post_read, post_report, - post_saved, private_message, private_message_report, received_activity, diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index 40b0b7712..c94a907ab 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -1,7 +1,7 @@ use crate::{ diesel::Connection, diesel_migrations::MigrationHarness, - newtypes::DbUrl, + newtypes::{DbUrl, PersonId}, CommentSortType, SortType, }; @@ -10,17 +10,7 @@ use anyhow::Context; use chrono::{DateTime, Utc}; use deadpool::Runtime; use diesel::{ - backend::Backend, - deserialize::FromSql, - helper_types::AsExprOf, - pg::Pg, - query_builder::{Query, QueryFragment}, - query_dsl::methods::LimitDsl, - result::{ConnectionError, ConnectionResult, Error as DieselError, Error::QueryBuilderError}, - serialize::{Output, ToSql}, - sql_types::{self, Text, Timestamptz}, - IntoSql, - PgConnection, + backend::Backend, deserialize::FromSql, dsl, helper_types::AsExprOf, pg::Pg, query_builder::{Query, QueryFragment}, query_dsl::methods::LimitDsl, result::{ConnectionError, ConnectionResult, Error::{self as DieselError, QueryBuilderError}}, serialize::{Output, ToSql}, sql_types::{self, Text, Timestamptz}, IntoSql, PgConnection, Table }; use diesel_async::{ pg::AsyncPgConnection, From 66bdc491d1c0074fa490ecc80a15dfea51299883 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Fri, 16 Feb 2024 19:53:14 +0000 Subject: [PATCH 027/232] fix actions --- crates/db_schema/src/utils.rs | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index c94a907ab..3c46bac84 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -10,7 +10,25 @@ use anyhow::Context; use chrono::{DateTime, Utc}; use deadpool::Runtime; use diesel::{ - backend::Backend, deserialize::FromSql, dsl, helper_types::AsExprOf, pg::Pg, query_builder::{Query, QueryFragment}, query_dsl::methods::LimitDsl, result::{ConnectionError, ConnectionResult, Error::{self as DieselError, QueryBuilderError}}, serialize::{Output, ToSql}, sql_types::{self, Text, Timestamptz}, IntoSql, PgConnection, Table + backend::Backend, + deserialize::FromSql, + dsl, + expression::AsExpression, + helper_types::AsExprOf, + pg::Pg, + query_builder::{Query, QueryFragment}, + query_dsl::methods::LimitDsl, + result::{ + ConnectionError, + ConnectionResult, + Error::{self as DieselError, QueryBuilderError}, + }, + serialize::{Output, ToSql}, + sql_types::{self, SqlType, Text, Timestamptz}, + Expression, + IntoSql, + PgConnection, + Table, }; use diesel_async::{ pg::AsyncPgConnection, @@ -492,18 +510,29 @@ pub fn now() -> AsExprOf { diesel::dsl::now.into_sql::() } +// TODO: BindIfSome pub fn actions( actions_table: T, person_id: Option, target_id: C, -) -> dsl::On, BindIfSome>, dsl::Eq>> +) -> dsl::On, Option>, dsl::Eq>> where T: Table, + K0: Default + Expression + Sized, + dsl::Nullable: diesel::ExpressionMethods, + as Expression>::SqlType: SqlType, + Option: AsExpression< as Expression>::SqlType>, + K1: Default + diesel::ExpressionMethods, + ::SqlType: SqlType, + C: AsExpression<::SqlType>, + dsl::Eq, Option>: + Expression>, + dsl::Eq: Expression, { actions_table.on( K0::default() .nullable() - .eq(BindIfSome(person_id)) + .eq(person_id) .and(K1::default().eq(target_id)), ) } From 8cb325bf88e596228fe38082609e49bd11269905 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Tue, 20 Feb 2024 02:24:17 +0000 Subject: [PATCH 028/232] PostLike --- crates/db_schema/src/impls/post.rs | 112 +++++++++++++++++++++------ crates/db_schema/src/source/post.rs | 12 ++- crates/db_schema/src/utils.rs | 2 + crates/db_schema/src/utils/uplete.rs | 33 ++++++++ 4 files changed, 128 insertions(+), 31 deletions(-) create mode 100644 crates/db_schema/src/utils/uplete.rs diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index f49af6226..6c356c83e 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -1,20 +1,23 @@ use crate::{ newtypes::{CommunityId, DbUrl, PersonId, PostId}, - schema::post::dsl::{ - ap_id, - body, - community_id, - creator_id, - deleted, - featured_community, - local, - name, - post, - published, - removed, - thumbnail_url, - updated, - url, + schema::{ + post::dsl::{ + ap_id, + body, + community_id, + creator_id, + deleted, + featured_community, + local, + name, + post, + published, + removed, + thumbnail_url, + updated, + url, + }, + post_actions, }, source::post::{ Post, @@ -32,6 +35,7 @@ use crate::{ functions::coalesce, get_conn, naive_now, + uplete::Uplete, DbPool, DELETED_REPLACEMENT_TEXT, FETCH_LIMIT_MAX, @@ -40,8 +44,19 @@ use crate::{ }, }; use ::url::Url; -use chrono::{Duration, Utc}; -use diesel::{dsl::insert_into, result::Error, ExpressionMethods, QueryDsl, TextExpressionMethods}; +use chrono::{DateTime, Duration, Utc}; +use diesel::{ + dsl::{self, insert_into}, + pg::Pg, + result::Error, + sql_types, + BoxableExpression, + ExpressionMethods, + IntoSql, + PgExpressionMethods, + QueryDsl, + TextExpressionMethods, +}; use diesel_async::RunQueryDsl; use std::collections::HashSet; @@ -253,18 +268,65 @@ impl Post { } } +fn uplete_actions( + person_id: PersonId, + post_id: PostId, + update_values: T, +) -> Uplete< + post_actions::table, + dsl::And, dsl::Eq>, + Box>, + T, +> { + Uplete { + target: post_actions::table, + filter: post_actions::person_id.eq(person_id).and(post_actions::post_id.eq(post_id)), + delete_condition: Box::new( + post_actions::all_columns + .into_sql::>() + .is_not_distinct_from(( + post_actions::person_id, + post_actions::post_id, + None::, + None::>, + None::>, + None::>, + None::>, + None::, + )), + ), + update_values, + } +} + +impl PostLike { + fn as_select_unwrap() -> ( + post_actions::post_id, + post_actions::person_id, + dsl::AssumeNotNull, + dsl::AssumeNotNull, + ) { + ( + post_actions::post_id, + post_actions::person_id, + post_actions::like_score.assume_not_null(), + post_actions::liked.assume_not_null(), + ) + } +} + #[async_trait] impl Likeable for PostLike { type Form = PostLikeForm; type IdType = PostId; async fn like(pool: &mut DbPool<'_>, post_like_form: &PostLikeForm) -> Result { - use crate::schema::post_like::dsl::{person_id, post_id, post_like}; let conn = &mut get_conn(pool).await?; - insert_into(post_like) + insert_into(post_actions::table) .values(post_like_form) - .on_conflict((post_id, person_id)) + .on_conflict((post_actions::post_id, post_actions::person_id)) .do_update() .set(post_like_form) + .returning(PostLike::as_select_unwrap()) .get_result::(conn) .await } @@ -273,11 +335,13 @@ impl Likeable for PostLike { person_id: PersonId, post_id: PostId, ) -> Result { - use crate::schema::post_like::dsl; let conn = &mut get_conn(pool).await?; - diesel::delete(dsl::post_like.find((person_id, post_id))) - .execute(conn) - .await + uplete_actions(person_id, post_id,( + post_actions::like_score.eq(None::), + post_actions::liked.eq(None::>), + )) + .execute(conn) + .await } } diff --git a/crates/db_schema/src/source/post.rs b/crates/db_schema/src/source/post.rs index 4ac3e2a65..2a0b4f159 100644 --- a/crates/db_schema/src/source/post.rs +++ b/crates/db_schema/src/source/post.rs @@ -1,6 +1,6 @@ use crate::newtypes::{CommunityId, DbUrl, LanguageId, PersonId, PostId}; #[cfg(feature = "full")] -use crate::schema::{post, post_like, post_read, post_saved}; +use crate::schema::{post, post_actions}; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; @@ -115,12 +115,9 @@ pub struct PostUpdateForm { } #[derive(PartialEq, Eq, Debug)] -#[cfg_attr( - feature = "full", - derive(Identifiable, Queryable, Selectable, Associations) -)] +#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::post::Post)))] -#[cfg_attr(feature = "full", diesel(table_name = post_like))] +#[cfg_attr(feature = "full", diesel(table_name = post_actions))] #[cfg_attr(feature = "full", diesel(primary_key(person_id, post_id)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] pub struct PostLike { @@ -132,10 +129,11 @@ pub struct PostLike { #[derive(Clone)] #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] -#[cfg_attr(feature = "full", diesel(table_name = post_like))] +#[cfg_attr(feature = "full", diesel(table_name = post_actions))] pub struct PostLikeForm { pub post_id: PostId, pub person_id: PersonId, + #[cfg_attr(feature = "full", diesel(column_name = like_score))] pub score: i16, } diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index 878b0e561..ad5cbc82b 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -1,3 +1,5 @@ +pub mod uplete; + use crate::{ diesel::Connection, diesel_migrations::MigrationHarness, diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs new file mode 100644 index 000000000..638006b93 --- /dev/null +++ b/crates/db_schema/src/utils/uplete.rs @@ -0,0 +1,33 @@ +use diesel::{ + pg::Pg, + query_builder::{AstPass, QueryFragment}, + QueryResult, +}; + +// TODO: use trait bounds to validate fields + +#[derive(QueryId)] +pub struct Uplete { + pub target: T, + /// Must only match 1 row + pub filter: F, + pub delete_condition: D, + pub update_values: U, +} + +impl, F: QueryFragment, D: QueryFragment, U: QueryFragment> QueryFragment + for Uplete +{ + fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> { + out.push_sql("MERGE INTO "); + self.target.walk_ast(out.reborrow())?; + out.push_sql("USING (VALUES (1)) AS uplete_source ON ("); + self.filter.walk_ast(out.reborrow())?; + out.push_sql(") WHEN MATCHED AND ("); + self.delete_condition.walk_ast(out.reborrow())?; + out.push_sql(") THEN DELETE WHEN MATCHED THEN UPDATE SET "); + self.update_values.walk_ast(out.reborrow())?; + + Ok(()) + } +} From e12e2c2529a3105a71f57f83104a57fd6ab1d98c Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Tue, 20 Feb 2024 02:26:43 +0000 Subject: [PATCH 029/232] fmt --- crates/db_schema/src/impls/post.rs | 16 +++++++++++----- crates/db_schema/src/utils/uplete.rs | 4 ++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index 6c356c83e..e96700997 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -280,7 +280,9 @@ fn uplete_actions( > { Uplete { target: post_actions::table, - filter: post_actions::person_id.eq(person_id).and(post_actions::post_id.eq(post_id)), + filter: post_actions::person_id + .eq(person_id) + .and(post_actions::post_id.eq(post_id)), delete_condition: Box::new( post_actions::all_columns .into_sql::>() @@ -336,10 +338,14 @@ impl Likeable for PostLike { post_id: PostId, ) -> Result { let conn = &mut get_conn(pool).await?; - uplete_actions(person_id, post_id,( - post_actions::like_score.eq(None::), - post_actions::liked.eq(None::>), - )) + uplete_actions( + person_id, + post_id, + ( + post_actions::like_score.eq(None::), + post_actions::liked.eq(None::>), + ), + ) .execute(conn) .await } diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 638006b93..f39a4706d 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -15,8 +15,8 @@ pub struct Uplete { pub update_values: U, } -impl, F: QueryFragment, D: QueryFragment, U: QueryFragment> QueryFragment - for Uplete +impl, F: QueryFragment, D: QueryFragment, U: QueryFragment> + QueryFragment for Uplete { fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> { out.push_sql("MERGE INTO "); From d3f57ba14dd416781745a27ca6e50bde679c0cba Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sat, 24 Feb 2024 03:33:35 +0000 Subject: [PATCH 030/232] more post stuff (partial) --- crates/db_schema/src/impls/post.rs | 55 ++++++++++++---------------- crates/db_schema/src/source/post.rs | 6 +-- crates/db_schema/src/utils/uplete.rs | 35 +++++++++++++----- 3 files changed, 53 insertions(+), 43 deletions(-) diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index e96700997..23edc9813 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -32,15 +32,7 @@ use crate::{ }, traits::{Crud, Likeable, Saveable}, utils::{ - functions::coalesce, - get_conn, - naive_now, - uplete::Uplete, - DbPool, - DELETED_REPLACEMENT_TEXT, - FETCH_LIMIT_MAX, - SITEMAP_DAYS, - SITEMAP_LIMIT, + functions::coalesce, get_conn, naive_now, now, uplete::Uplete, DbPool, DELETED_REPLACEMENT_TEXT, FETCH_LIMIT_MAX, SITEMAP_DAYS, SITEMAP_LIMIT }, }; use ::url::Url; @@ -56,6 +48,7 @@ use diesel::{ PgExpressionMethods, QueryDsl, TextExpressionMethods, + NullableExpressionMethods, }; use diesel_async::RunQueryDsl; use std::collections::HashSet; @@ -269,20 +262,17 @@ impl Post { } fn uplete_actions( - person_id: PersonId, - post_id: PostId, + keys: impl IntoIterator, update_values: T, ) -> Uplete< post_actions::table, - dsl::And, dsl::Eq>, + Vec<(dsl::AsExprOf, dsl::AsExprOf)>, Box>, T, > { Uplete { target: post_actions::table, - filter: post_actions::person_id - .eq(person_id) - .and(post_actions::post_id.eq(post_id)), + keys: keys.into_iter().map(|(a, b)| (a.into_sql::(), b.into_sql::())).collect::>(), delete_condition: Box::new( post_actions::all_columns .into_sql::>() @@ -323,6 +313,7 @@ impl Likeable for PostLike { type IdType = PostId; async fn like(pool: &mut DbPool<'_>, post_like_form: &PostLikeForm) -> Result { let conn = &mut get_conn(pool).await?; + let post_like_form = (post_like_form.clone(), post_actions::liked.eq(now()), "a"); insert_into(post_actions::table) .values(post_like_form) .on_conflict((post_actions::post_id, post_actions::person_id)) @@ -339,8 +330,8 @@ impl Likeable for PostLike { ) -> Result { let conn = &mut get_conn(pool).await?; uplete_actions( - person_id, - post_id, + [(person_id, + post_id,)], ( post_actions::like_score.eq(None::), post_actions::liked.eq(None::>), @@ -355,20 +346,19 @@ impl Likeable for PostLike { impl Saveable for PostSaved { type Form = PostSavedForm; async fn save(pool: &mut DbPool<'_>, post_saved_form: &PostSavedForm) -> Result { - use crate::schema::post_saved::dsl::{person_id, post_id, post_saved}; let conn = &mut get_conn(pool).await?; - insert_into(post_saved) + let post_saved_form = (post_saved_form.clone(), post_actions::saved.eq(now())); + insert_into(post_actions::table) .values(post_saved_form) - .on_conflict((post_id, person_id)) + .on_conflict((post_actions::post_id, post_actions::person_id)) .do_update() .set(post_saved_form) .get_result::(conn) .await } async fn unsave(pool: &mut DbPool<'_>, post_saved_form: &PostSavedForm) -> Result { - use crate::schema::post_saved::dsl::post_saved; let conn = &mut get_conn(pool).await?; - diesel::delete(post_saved.find((post_saved_form.person_id, post_saved_form.post_id))) + uplete_actions([(post_saved_form.person_id, post_saved_form.post_id)], post_actions::saved.eq(None::>)) .execute(conn) .await } @@ -380,16 +370,20 @@ impl PostRead { post_ids: HashSet, person_id: PersonId, ) -> Result { - use crate::schema::post_read::dsl::post_read; let conn = &mut get_conn(pool).await?; let forms = post_ids .into_iter() - .map(|post_id| PostReadForm { post_id, person_id }) - .collect::>(); - insert_into(post_read) + .map(|post_id| ( + PostReadForm{post_id,person_id}, + post_actions::read.eq(now().nullable()) + )) + .collect::>(); + insert_into(post_actions::table) .values(forms) - .on_conflict_do_nothing() + .on_conflict((post_actions::person_id, post_actions::post_id)) + .do_update() + .set(post_actions::read.eq(now().nullable())) .execute(conn) .await } @@ -399,13 +393,12 @@ impl PostRead { post_id_: HashSet, person_id_: PersonId, ) -> Result { - use crate::schema::post_read::dsl::{person_id, post_id, post_read}; let conn = &mut get_conn(pool).await?; diesel::delete( - post_read - .filter(post_id.eq_any(post_id_)) - .filter(person_id.eq(person_id_)), + post_actions::table + .filter(post_actions::post_id.eq_any(post_id_)) + .filter(post_actions::person_id.eq(person_id_)), ) .execute(conn) .await diff --git a/crates/db_schema/src/source/post.rs b/crates/db_schema/src/source/post.rs index 2a0b4f159..5448b4d60 100644 --- a/crates/db_schema/src/source/post.rs +++ b/crates/db_schema/src/source/post.rs @@ -162,10 +162,10 @@ pub struct PostSavedForm { #[derive(PartialEq, Eq, Debug)] #[cfg_attr( feature = "full", - derive(Identifiable, Queryable, Selectable, Associations) + derive(Identifiable, Queryable, Associations) )] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::post::Post)))] -#[cfg_attr(feature = "full", diesel(table_name = post_read))] +#[cfg_attr(feature = "full", diesel(table_name = post_actions))] #[cfg_attr(feature = "full", diesel(primary_key(post_id, person_id)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] pub struct PostRead { @@ -175,7 +175,7 @@ pub struct PostRead { } #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] -#[cfg_attr(feature = "full", diesel(table_name = post_read))] +#[cfg_attr(feature = "full", diesel(table_name = post_actions))] pub(crate) struct PostReadForm { pub post_id: PostId, pub person_id: PersonId, diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index f39a4706d..f9dbd121d 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -1,29 +1,46 @@ use diesel::{ pg::Pg, query_builder::{AstPass, QueryFragment}, - QueryResult, + QueryResult, Table, }; // TODO: use trait bounds to validate fields +/// Find each row in `target` that has its primary key listed in `keys`, and +/// if `delete_condition` is true, then delete the row, otherwise update it with `update_values` #[derive(QueryId)] -pub struct Uplete { +pub struct Uplete { pub target: T, - /// Must only match 1 row - pub filter: F, + pub keys: K, pub delete_condition: D, pub update_values: U, } -impl, F: QueryFragment, D: QueryFragment, U: QueryFragment> - QueryFragment for Uplete +impl + Table, K, D: QueryFragment, U: QueryFragment> + QueryFragment for Uplete + where + for<'a> &'a K: IntoIterator, + for<'a> <&'a K as IntoIterator>::Item: QueryFragment, + T::PrimaryKey: QueryFragment { fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> { + // Needed because of the keys loop + out.unsafe_to_cache_prepared(); + out.push_sql("MERGE INTO "); self.target.walk_ast(out.reborrow())?; - out.push_sql("USING (VALUES (1)) AS uplete_source ON ("); - self.filter.walk_ast(out.reborrow())?; - out.push_sql(") WHEN MATCHED AND ("); + out.push_sql("USING (VALUES "); + for (i, key) in (&self.keys).into_iter().enumerate() { + if i != 0 { + out.push_sql(","); + } + out.push_sql("(ROW("); + key.walk_ast(out.reborrow())?; + out.push_sql("))"); + } + out.push_sql(") AS uplete_source (uplete_key) ON ROW("); + self.target.primary_key().walk_ast(out.reborrow())?; + out.push_sql(") = uplete_source.uplete_key WHEN MATCHED AND ("); self.delete_condition.walk_ast(out.reborrow())?; out.push_sql(") THEN DELETE WHEN MATCHED THEN UPDATE SET "); self.update_values.walk_ast(out.reborrow())?; From 9a18388e06d31ebd8bff0ae58b126a6f2342ae28 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sat, 24 Feb 2024 17:55:30 +0000 Subject: [PATCH 031/232] remove uplete --- crates/db_schema/src/impls/post.rs | 76 +++++++++------------------- crates/db_schema/src/source/post.rs | 5 +- crates/db_schema/src/utils.rs | 2 - crates/db_schema/src/utils/uplete.rs | 50 ------------------ 4 files changed, 26 insertions(+), 107 deletions(-) delete mode 100644 crates/db_schema/src/utils/uplete.rs diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index 23edc9813..be829af7c 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -32,23 +32,26 @@ use crate::{ }, traits::{Crud, Likeable, Saveable}, utils::{ - functions::coalesce, get_conn, naive_now, now, uplete::Uplete, DbPool, DELETED_REPLACEMENT_TEXT, FETCH_LIMIT_MAX, SITEMAP_DAYS, SITEMAP_LIMIT + functions::coalesce, + get_conn, + naive_now, + now, + DbPool, + DELETED_REPLACEMENT_TEXT, + FETCH_LIMIT_MAX, + SITEMAP_DAYS, + SITEMAP_LIMIT, }, }; use ::url::Url; use chrono::{DateTime, Duration, Utc}; use diesel::{ dsl::{self, insert_into}, - pg::Pg, result::Error, - sql_types, - BoxableExpression, ExpressionMethods, - IntoSql, - PgExpressionMethods, + NullableExpressionMethods, QueryDsl, TextExpressionMethods, - NullableExpressionMethods, }; use diesel_async::RunQueryDsl; use std::collections::HashSet; @@ -261,36 +264,6 @@ impl Post { } } -fn uplete_actions( - keys: impl IntoIterator, - update_values: T, -) -> Uplete< - post_actions::table, - Vec<(dsl::AsExprOf, dsl::AsExprOf)>, - Box>, - T, -> { - Uplete { - target: post_actions::table, - keys: keys.into_iter().map(|(a, b)| (a.into_sql::(), b.into_sql::())).collect::>(), - delete_condition: Box::new( - post_actions::all_columns - .into_sql::>() - .is_not_distinct_from(( - post_actions::person_id, - post_actions::post_id, - None::, - None::>, - None::>, - None::>, - None::>, - None::, - )), - ), - update_values, - } -} - impl PostLike { fn as_select_unwrap() -> ( post_actions::post_id, @@ -329,16 +302,13 @@ impl Likeable for PostLike { post_id: PostId, ) -> Result { let conn = &mut get_conn(pool).await?; - uplete_actions( - [(person_id, - post_id,)], - ( + diesel::update(post_actions::table.find((person_id, post_id))) + .set(( post_actions::like_score.eq(None::), post_actions::liked.eq(None::>), - ), - ) - .execute(conn) - .await + )) + .execute(conn) + .await } } @@ -358,7 +328,8 @@ impl Saveable for PostSaved { } async fn unsave(pool: &mut DbPool<'_>, post_saved_form: &PostSavedForm) -> Result { let conn = &mut get_conn(pool).await?; - uplete_actions([(post_saved_form.person_id, post_saved_form.post_id)], post_actions::saved.eq(None::>)) + diesel::update(post_actions::table.find((post_saved_form.person_id, post_saved_form.post_id))) + .set(post_actions::saved.eq(None::>)) .execute(conn) .await } @@ -374,10 +345,12 @@ impl PostRead { let forms = post_ids .into_iter() - .map(|post_id| ( - PostReadForm{post_id,person_id}, - post_actions::read.eq(now().nullable()) - )) + .map(|post_id| { + ( + PostReadForm { post_id, person_id }, + post_actions::read.eq(now().nullable()), + ) + }) .collect::>(); insert_into(post_actions::table) .values(forms) @@ -395,11 +368,12 @@ impl PostRead { ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::delete( + diesel::update( post_actions::table .filter(post_actions::post_id.eq_any(post_id_)) .filter(post_actions::person_id.eq(person_id_)), ) + .set(post_actions::read.eq(None::>)) .execute(conn) .await } diff --git a/crates/db_schema/src/source/post.rs b/crates/db_schema/src/source/post.rs index 5448b4d60..1ac43e4ea 100644 --- a/crates/db_schema/src/source/post.rs +++ b/crates/db_schema/src/source/post.rs @@ -160,10 +160,7 @@ pub struct PostSavedForm { } #[derive(PartialEq, Eq, Debug)] -#[cfg_attr( - feature = "full", - derive(Identifiable, Queryable, Associations) -)] +#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::post::Post)))] #[cfg_attr(feature = "full", diesel(table_name = post_actions))] #[cfg_attr(feature = "full", diesel(primary_key(post_id, person_id)))] diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index ad5cbc82b..878b0e561 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -1,5 +1,3 @@ -pub mod uplete; - use crate::{ diesel::Connection, diesel_migrations::MigrationHarness, diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs deleted file mode 100644 index f9dbd121d..000000000 --- a/crates/db_schema/src/utils/uplete.rs +++ /dev/null @@ -1,50 +0,0 @@ -use diesel::{ - pg::Pg, - query_builder::{AstPass, QueryFragment}, - QueryResult, Table, -}; - -// TODO: use trait bounds to validate fields - -/// Find each row in `target` that has its primary key listed in `keys`, and -/// if `delete_condition` is true, then delete the row, otherwise update it with `update_values` -#[derive(QueryId)] -pub struct Uplete { - pub target: T, - pub keys: K, - pub delete_condition: D, - pub update_values: U, -} - -impl + Table, K, D: QueryFragment, U: QueryFragment> - QueryFragment for Uplete - where - for<'a> &'a K: IntoIterator, - for<'a> <&'a K as IntoIterator>::Item: QueryFragment, - T::PrimaryKey: QueryFragment -{ - fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> { - // Needed because of the keys loop - out.unsafe_to_cache_prepared(); - - out.push_sql("MERGE INTO "); - self.target.walk_ast(out.reborrow())?; - out.push_sql("USING (VALUES "); - for (i, key) in (&self.keys).into_iter().enumerate() { - if i != 0 { - out.push_sql(","); - } - out.push_sql("(ROW("); - key.walk_ast(out.reborrow())?; - out.push_sql("))"); - } - out.push_sql(") AS uplete_source (uplete_key) ON ROW("); - self.target.primary_key().walk_ast(out.reborrow())?; - out.push_sql(") = uplete_source.uplete_key WHEN MATCHED AND ("); - self.delete_condition.walk_ast(out.reborrow())?; - out.push_sql(") THEN DELETE WHEN MATCHED THEN UPDATE SET "); - self.update_values.walk_ast(out.reborrow())?; - - Ok(()) - } -} From 3f563240b44e531e551e6b34345d48b50bfcc1e3 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sat, 24 Feb 2024 18:11:34 +0000 Subject: [PATCH 032/232] returning --- crates/db_schema/src/impls/post.rs | 17 +++++++++++++++++ crates/db_schema/src/source/post.rs | 7 ++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index be829af7c..a3e93d917 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -264,6 +264,8 @@ impl Post { } } +// TODO: replace `as_select_unwrap` definitions with `Default::default()` after next Diesel release which should +// implement `Default` for `AssumeNotNull` impl PostLike { fn as_select_unwrap() -> ( post_actions::post_id, @@ -312,6 +314,20 @@ impl Likeable for PostLike { } } +impl PostSaved { + fn as_select_unwrap() -> ( + post_actions::post_id, + post_actions::person_id, + dsl::AssumeNotNull, + ) { + ( + post_actions::post_id, + post_actions::person_id, + post_actions::saved.assume_not_null(), + ) + } +} + #[async_trait] impl Saveable for PostSaved { type Form = PostSavedForm; @@ -323,6 +339,7 @@ impl Saveable for PostSaved { .on_conflict((post_actions::post_id, post_actions::person_id)) .do_update() .set(post_saved_form) + .returning(PostSaved::as_select_unwrap()) .get_result::(conn) .await } diff --git a/crates/db_schema/src/source/post.rs b/crates/db_schema/src/source/post.rs index 1ac43e4ea..8fae08e9f 100644 --- a/crates/db_schema/src/source/post.rs +++ b/crates/db_schema/src/source/post.rs @@ -138,12 +138,9 @@ pub struct PostLikeForm { } #[derive(PartialEq, Eq, Debug)] -#[cfg_attr( - feature = "full", - derive(Identifiable, Queryable, Selectable, Associations) -)] +#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::post::Post)))] -#[cfg_attr(feature = "full", diesel(table_name = post_saved))] +#[cfg_attr(feature = "full", diesel(table_name = post_actions))] #[cfg_attr(feature = "full", diesel(primary_key(post_id, person_id)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] pub struct PostSaved { From af44c6c2bf3096cbd169b6551bdbc260fa252add Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sat, 24 Feb 2024 18:16:20 +0000 Subject: [PATCH 033/232] rename read_comments field --- crates/db_schema/src/schema.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 8b34c38d7..01f38c499 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -668,8 +668,8 @@ diesel::table! { post_actions (person_id, post_id) { person_id -> Int4, post_id -> Int4, - read_comments -> Int8, - read_comments_published -> Nullable, + read_comments -> Nullable, + read_comments_amount -> Int8, read -> Nullable, saved -> Nullable, liked -> Nullable, From 152a53f38cc37ded9d71ec2e523a55955f1d07c4 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sat, 24 Feb 2024 20:23:18 +0000 Subject: [PATCH 034/232] PersonPostAggregates --- .../src/aggregates/person_post_aggregates.rs | 38 ++++++++++++++++--- crates/db_schema/src/aggregates/structs.rs | 13 +++---- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/crates/db_schema/src/aggregates/person_post_aggregates.rs b/crates/db_schema/src/aggregates/person_post_aggregates.rs index 7657dae9e..dc7157132 100644 --- a/crates/db_schema/src/aggregates/person_post_aggregates.rs +++ b/crates/db_schema/src/aggregates/person_post_aggregates.rs @@ -1,23 +1,46 @@ use crate::{ aggregates::structs::{PersonPostAggregates, PersonPostAggregatesForm}, newtypes::{PersonId, PostId}, - schema::person_post_aggregates::dsl::{person_id, person_post_aggregates, post_id}, - utils::{get_conn, DbPool}, + schema::post_actions, + utils::{get_conn, now, DbPool}, +}; +use diesel::{ + dsl, + insert_into, + result::Error, + ExpressionMethods, + NullableExpressionMethods, + QueryDsl, }; -use diesel::{insert_into, result::Error, QueryDsl}; use diesel_async::RunQueryDsl; impl PersonPostAggregates { + fn as_select_unwrap() -> ( + post_actions::person_id, + post_actions::post_id, + dsl::AssumeNotNull, + dsl::AssumeNotNull, + ) { + ( + post_actions::person_id, + post_actions::post_id, + post_actions::read_comments_amount.assume_not_null(), + post_actions::read_comments.assume_not_null(), + ) + } + pub async fn upsert( pool: &mut DbPool<'_>, form: &PersonPostAggregatesForm, ) -> Result { let conn = &mut get_conn(pool).await?; - insert_into(person_post_aggregates) + let form = (form, post_actions::read_comments.eq(now().nullable())); + insert_into(post_actions::table) .values(form) - .on_conflict((person_id, post_id)) + .on_conflict((post_actions::person_id, post_actions::post_id)) .do_update() .set(form) + .returning(Self::as_select_unwrap()) .get_result::(conn) .await } @@ -27,8 +50,11 @@ impl PersonPostAggregates { post_id_: PostId, ) -> Result { let conn = &mut get_conn(pool).await?; - person_post_aggregates + post_actions::table .find((person_id_, post_id_)) + .filter(post_actions::read_comments.is_not_null()) + .filter(post_actions::read_comments_amount.is_not_null()) + .select(Self::as_select_unwrap()) .first::(conn) .await } diff --git a/crates/db_schema/src/aggregates/structs.rs b/crates/db_schema/src/aggregates/structs.rs index 45a43adf8..45fbcfb50 100644 --- a/crates/db_schema/src/aggregates/structs.rs +++ b/crates/db_schema/src/aggregates/structs.rs @@ -4,7 +4,7 @@ use crate::schema::{ comment_aggregates, community_aggregates, person_aggregates, - person_post_aggregates, + post_actions, post_aggregates, site_aggregates, }; @@ -147,11 +147,8 @@ pub struct PostAggregates { } #[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)] -#[cfg_attr( - feature = "full", - derive(Queryable, Selectable, Associations, Identifiable) -)] -#[cfg_attr(feature = "full", diesel(table_name = person_post_aggregates))] +#[cfg_attr(feature = "full", derive(Queryable, Associations, Identifiable))] +#[cfg_attr(feature = "full", diesel(table_name = post_actions))] #[cfg_attr(feature = "full", diesel(primary_key(person_id, post_id)))] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::person::Person)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] @@ -168,12 +165,12 @@ pub struct PersonPostAggregates { #[derive(Clone, Default)] #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] -#[cfg_attr(feature = "full", diesel(table_name = person_post_aggregates))] +#[cfg_attr(feature = "full", diesel(table_name = post_actions))] pub struct PersonPostAggregatesForm { pub person_id: PersonId, pub post_id: PostId, + #[cfg_attr(feature = "full", diesel(column_name = read_comments_amount))] pub read_comments: i64, - pub published: Option>, } #[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)] From 61c75ea70df6ba83e620355415ac69778b3e2191 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sat, 24 Feb 2024 20:37:02 +0000 Subject: [PATCH 035/232] a --- crates/db_schema/src/impls/post.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index a3e93d917..b9383854f 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -288,7 +288,7 @@ impl Likeable for PostLike { type IdType = PostId; async fn like(pool: &mut DbPool<'_>, post_like_form: &PostLikeForm) -> Result { let conn = &mut get_conn(pool).await?; - let post_like_form = (post_like_form.clone(), post_actions::liked.eq(now()), "a"); + let post_like_form = (post_like_form.clone(), post_actions::liked.eq(now())); insert_into(post_actions::table) .values(post_like_form) .on_conflict((post_actions::post_id, post_actions::person_id)) From cedce7d46a6c56cbbe884b388aa5cd664dadaa78 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sat, 24 Feb 2024 20:54:20 +0000 Subject: [PATCH 036/232] fix usage of read_comments_amount --- crates/db_schema/src/aggregates/person_post_aggregates.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/db_schema/src/aggregates/person_post_aggregates.rs b/crates/db_schema/src/aggregates/person_post_aggregates.rs index dc7157132..53dc4ed4e 100644 --- a/crates/db_schema/src/aggregates/person_post_aggregates.rs +++ b/crates/db_schema/src/aggregates/person_post_aggregates.rs @@ -18,13 +18,13 @@ impl PersonPostAggregates { fn as_select_unwrap() -> ( post_actions::person_id, post_actions::post_id, - dsl::AssumeNotNull, + post_actions::read_comments_amount, dsl::AssumeNotNull, ) { ( post_actions::person_id, post_actions::post_id, - post_actions::read_comments_amount.assume_not_null(), + post_actions::read_comments_amount, post_actions::read_comments.assume_not_null(), ) } @@ -53,7 +53,6 @@ impl PersonPostAggregates { post_actions::table .find((person_id_, post_id_)) .filter(post_actions::read_comments.is_not_null()) - .filter(post_actions::read_comments_amount.is_not_null()) .select(Self::as_select_unwrap()) .first::(conn) .await From fb143b58edeca939d0d0914b50870637bb337b58 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sat, 24 Feb 2024 21:43:09 +0000 Subject: [PATCH 037/232] comment --- crates/db_schema/src/impls/comment.rs | 75 +++++++++++++++++++++----- crates/db_schema/src/impls/post.rs | 4 +- crates/db_schema/src/source/comment.rs | 21 +++----- 3 files changed, 71 insertions(+), 29 deletions(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index c8a389475..fe15e03c7 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -1,6 +1,9 @@ use crate::{ newtypes::{CommentId, DbUrl, PersonId}, - schema::comment::dsl::{ap_id, comment, content, creator_id, deleted, path, removed, updated}, + schema::{ + comment::dsl::{ap_id, comment, content, creator_id, deleted, path, removed, updated}, + comment_actions, + }, source::comment::{ Comment, CommentInsertForm, @@ -11,10 +14,11 @@ use crate::{ CommentUpdateForm, }, traits::{Crud, Likeable, Saveable}, - utils::{get_conn, naive_now, DbPool, DELETED_REPLACEMENT_TEXT}, + utils::{get_conn, naive_now, now, DbPool, DELETED_REPLACEMENT_TEXT}, }; +use chrono::{DateTime, Utc}; use diesel::{ - dsl::{insert_into, sql_query}, + dsl::{self, insert_into, sql_query}, result::Error, ExpressionMethods, QueryDsl, @@ -178,18 +182,40 @@ impl Crud for Comment { } } +impl CommentLike { + fn as_select_unwrap() -> ( + comment_actions::person_id, + comment_actions::comment_id, + comment_actions::post_id, + dsl::AssumeNotNull, + dsl::AssumeNotNull, + ) { + ( + comment_actions::person_id, + comment_actions::comment_id, + comment_actions::post_id, + comment_actions::like_score.assume_not_null(), + comment_actions::liked.assume_not_null(), + ) + } +} + #[async_trait] impl Likeable for CommentLike { type Form = CommentLikeForm; type IdType = CommentId; async fn like(pool: &mut DbPool<'_>, comment_like_form: &CommentLikeForm) -> Result { - use crate::schema::comment_like::dsl::{comment_id, comment_like, person_id}; let conn = &mut get_conn(pool).await?; - insert_into(comment_like) + let comment_like_form = ( + comment_like_form, + comment_actions::liked.eq(now().nullable()), + ); + insert_into(comment_actions::table) .values(comment_like_form) - .on_conflict((comment_id, person_id)) + .on_conflict((comment_actions::comment_id, comment_actions::person_id)) .do_update() .set(comment_like_form) + .returning(Self::as_select_unwrap()) .get_result::(conn) .await } @@ -198,14 +224,31 @@ impl Likeable for CommentLike { person_id: PersonId, comment_id: CommentId, ) -> Result { - use crate::schema::comment_like::dsl::comment_like; let conn = &mut get_conn(pool).await?; - diesel::delete(comment_like.find((person_id, comment_id))) + diesel::update(comment_actions::table.find((person_id, comment_id))) + .set(( + comment_actions::like_score.eq(None::), + comment_actions::liked.eq(None::>), + )) .execute(conn) .await } } +impl CommentSaved { + fn as_select_unwrap() -> ( + comment_actions::comment_id, + comment_actions::person_id, + dsl::AssumeNotNull, + ) { + ( + comment_actions::comment_id, + comment_actions::person_id, + comment_actions::saved.assume_not_null(), + ) + } +} + #[async_trait] impl Saveable for CommentSaved { type Form = CommentSavedForm; @@ -213,13 +256,17 @@ impl Saveable for CommentSaved { pool: &mut DbPool<'_>, comment_saved_form: &CommentSavedForm, ) -> Result { - use crate::schema::comment_saved::dsl::{comment_id, comment_saved, person_id}; let conn = &mut get_conn(pool).await?; - insert_into(comment_saved) + let comment_saved_form = ( + comment_saved_form, + comment_actions::saved.eq(now().nullable()), + ); + insert_into(comment_actions::table) .values(comment_saved_form) - .on_conflict((comment_id, person_id)) + .on_conflict((comment_actions::comment_id, comment_actions::person_id)) .do_update() .set(comment_saved_form) + .returning(Self::as_select_unwrap()) .get_result::(conn) .await } @@ -227,11 +274,11 @@ impl Saveable for CommentSaved { pool: &mut DbPool<'_>, comment_saved_form: &CommentSavedForm, ) -> Result { - use crate::schema::comment_saved::dsl::comment_saved; let conn = &mut get_conn(pool).await?; - diesel::delete( - comment_saved.find((comment_saved_form.person_id, comment_saved_form.comment_id)), + diesel::update( + comment_actions::table.find((comment_saved_form.person_id, comment_saved_form.comment_id)), ) + .set(comment_actions::saved.eq(None::>)) .execute(conn) .await } diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index b9383854f..ec7fb488c 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -294,7 +294,7 @@ impl Likeable for PostLike { .on_conflict((post_actions::post_id, post_actions::person_id)) .do_update() .set(post_like_form) - .returning(PostLike::as_select_unwrap()) + .returning(Self::as_select_unwrap()) .get_result::(conn) .await } @@ -339,7 +339,7 @@ impl Saveable for PostSaved { .on_conflict((post_actions::post_id, post_actions::person_id)) .do_update() .set(post_saved_form) - .returning(PostSaved::as_select_unwrap()) + .returning(Self::as_select_unwrap()) .get_result::(conn) .await } diff --git a/crates/db_schema/src/source/comment.rs b/crates/db_schema/src/source/comment.rs index 3ebea42c1..c8872a818 100644 --- a/crates/db_schema/src/source/comment.rs +++ b/crates/db_schema/src/source/comment.rs @@ -2,7 +2,7 @@ use crate::newtypes::LtreeDef; use crate::newtypes::{CommentId, DbUrl, LanguageId, PersonId, PostId}; #[cfg(feature = "full")] -use crate::schema::{comment, comment_like, comment_saved}; +use crate::schema::{comment, comment_actions}; use chrono::{DateTime, Utc}; #[cfg(feature = "full")] use diesel_ltree::Ltree; @@ -87,12 +87,9 @@ pub struct CommentUpdateForm { } #[derive(PartialEq, Eq, Debug, Clone)] -#[cfg_attr( - feature = "full", - derive(Identifiable, Queryable, Selectable, Associations) -)] +#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::comment::Comment)))] -#[cfg_attr(feature = "full", diesel(table_name = comment_like))] +#[cfg_attr(feature = "full", diesel(table_name = comment_actions))] #[cfg_attr(feature = "full", diesel(primary_key(person_id, comment_id)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] pub struct CommentLike { @@ -105,21 +102,19 @@ pub struct CommentLike { #[derive(Clone)] #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] -#[cfg_attr(feature = "full", diesel(table_name = comment_like))] +#[cfg_attr(feature = "full", diesel(table_name = comment_actions))] pub struct CommentLikeForm { pub person_id: PersonId, pub comment_id: CommentId, pub post_id: PostId, // TODO this is redundant + #[cfg_attr(feature = "full", diesel(column_name = like_score))] pub score: i16, } #[derive(PartialEq, Eq, Debug)] -#[cfg_attr( - feature = "full", - derive(Identifiable, Queryable, Selectable, Associations) -)] +#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::comment::Comment)))] -#[cfg_attr(feature = "full", diesel(table_name = comment_saved))] +#[cfg_attr(feature = "full", diesel(table_name = comment_actions))] #[cfg_attr(feature = "full", diesel(primary_key(person_id, comment_id)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] pub struct CommentSaved { @@ -129,7 +124,7 @@ pub struct CommentSaved { } #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] -#[cfg_attr(feature = "full", diesel(table_name = comment_saved))] +#[cfg_attr(feature = "full", diesel(table_name = comment_actions))] pub struct CommentSavedForm { pub comment_id: CommentId, pub person_id: PersonId, From 042860c2d9398995b05eb72b0cdc9c6b7bf0f6a9 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sun, 25 Feb 2024 02:09:01 +0000 Subject: [PATCH 038/232] community --- crates/db_schema/src/impls/community.rs | 143 +++++++++++++++++------ crates/db_schema/src/source/community.rs | 31 ++--- 2 files changed, 120 insertions(+), 54 deletions(-) diff --git a/crates/db_schema/src/impls/community.rs b/crates/db_schema/src/impls/community.rs index 3298da894..f0d8c8070 100644 --- a/crates/db_schema/src/impls/community.rs +++ b/crates/db_schema/src/impls/community.rs @@ -1,6 +1,6 @@ use crate::{ newtypes::{CommunityId, DbUrl, PersonId}, - schema::{community, community_follower, instance}, + schema::{community, community_actions, instance}, source::{ actor_language::CommunityLanguage, community::{ @@ -16,9 +16,10 @@ use crate::{ }, }, traits::{ApubActor, Bannable, Crud, Followable, Joinable}, - utils::{functions::lower, get_conn, DbPool}, + utils::{functions::lower, get_conn, now, DbPool}, SubscribedType, }; +use chrono::{DateTime, Utc}; use diesel::{ deserialize, dsl, @@ -77,6 +78,20 @@ impl Crud for Community { } } +impl CommunityModerator { + fn as_select_unwrap() -> ( + community_actions::community_id, + community_actions::person_id, + dsl::AssumeNotNull, + ) { + ( + community_actions::community_id, + community_actions::person_id, + community_actions::became_moderator.assume_not_null(), + ) + } +} + #[async_trait] impl Joinable for CommunityModerator { type Form = CommunityModeratorForm; @@ -84,10 +99,14 @@ impl Joinable for CommunityModerator { pool: &mut DbPool<'_>, community_moderator_form: &CommunityModeratorForm, ) -> Result { - use crate::schema::community_moderator::dsl::community_moderator; let conn = &mut get_conn(pool).await?; - insert_into(community_moderator) + let community_moderator_form = ( + community_moderator_form, + community_actions::became_moderator.eq(now().nullable()), + ); + insert_into(community_actions::table) .values(community_moderator_form) + .returning(Self::as_select_unwrap()) .get_result::(conn) .await } @@ -96,12 +115,12 @@ impl Joinable for CommunityModerator { pool: &mut DbPool<'_>, community_moderator_form: &CommunityModeratorForm, ) -> Result { - use crate::schema::community_moderator::dsl::community_moderator; let conn = &mut get_conn(pool).await?; - diesel::delete(community_moderator.find(( + diesel::update(community_actions::table.find(( community_moderator_form.person_id, community_moderator_form.community_id, ))) + .set(community_actions::became_moderator.eq(None::>)) .execute(conn) .await } @@ -144,21 +163,23 @@ impl CommunityModerator { pool: &mut DbPool<'_>, for_community_id: CommunityId, ) -> Result { - use crate::schema::community_moderator::dsl::{community_id, community_moderator}; let conn = &mut get_conn(pool).await?; - diesel::delete(community_moderator.filter(community_id.eq(for_community_id))) - .execute(conn) - .await + diesel::update( + community_actions::table.filter(community_actions::community_id.eq(for_community_id)), + ) + .set(community_actions::became_moderator.eq(None::>)) + .execute(conn) + .await } pub async fn leave_all_communities( pool: &mut DbPool<'_>, for_person_id: PersonId, ) -> Result { - use crate::schema::community_moderator::dsl::{community_moderator, person_id}; let conn = &mut get_conn(pool).await?; - diesel::delete(community_moderator.filter(person_id.eq(for_person_id))) + diesel::update(community_actions::table.filter(community_actions::person_id.eq(for_person_id))) + .set(community_actions::became_moderator.eq(None::>)) .execute(conn) .await } @@ -167,16 +188,32 @@ impl CommunityModerator { pool: &mut DbPool<'_>, for_person_id: PersonId, ) -> Result, Error> { - use crate::schema::community_moderator::dsl::{community_id, community_moderator, person_id}; let conn = &mut get_conn(pool).await?; - community_moderator - .filter(person_id.eq(for_person_id)) - .select(community_id) + community_actions::table + .filter(community_actions::person_id.eq(for_person_id)) + .filter(community_actions::became_moderator.is_not_null()) + .select(community_actions::community_id) .load::(conn) .await } } +impl CommunityPersonBan { + fn as_select_unwrap() -> ( + community_actions::community_id, + community_actions::person_id, + dsl::AssumeNotNull, + community_actions::ban_expires, + ) { + ( + community_actions::community_id, + community_actions::person_id, + community_actions::received_ban.assume_not_null(), + community_actions::ban_expires, + ) + } +} + #[async_trait] impl Bannable for CommunityPersonBan { type Form = CommunityPersonBanForm; @@ -184,13 +221,20 @@ impl Bannable for CommunityPersonBan { pool: &mut DbPool<'_>, community_person_ban_form: &CommunityPersonBanForm, ) -> Result { - use crate::schema::community_person_ban::dsl::{community_id, community_person_ban, person_id}; let conn = &mut get_conn(pool).await?; - insert_into(community_person_ban) + let community_person_ban_form = ( + community_person_ban_form, + community_actions::received_ban.eq(now().nullable()), + ); + insert_into(community_actions::table) .values(community_person_ban_form) - .on_conflict((community_id, person_id)) + .on_conflict(( + community_actions::community_id, + community_actions::person_id, + )) .do_update() .set(community_person_ban_form) + .returning(Self::as_select_unwrap()) .get_result::(conn) .await } @@ -199,18 +243,35 @@ impl Bannable for CommunityPersonBan { pool: &mut DbPool<'_>, community_person_ban_form: &CommunityPersonBanForm, ) -> Result { - use crate::schema::community_person_ban::dsl::community_person_ban; let conn = &mut get_conn(pool).await?; - diesel::delete(community_person_ban.find(( + diesel::update(community_actions::table.find(( community_person_ban_form.person_id, community_person_ban_form.community_id, ))) + .set(( + community_actions::received_ban.eq(None::>), + community_actions::ban_expires.eq(None::>), + )) .execute(conn) .await } } impl CommunityFollower { + fn as_select_unwrap() -> ( + community_actions::community_id, + community_actions::person_id, + dsl::AssumeNotNull, + dsl::AssumeNotNull, + ) { + ( + community_actions::community_id, + community_actions::person_id, + community_actions::followed.assume_not_null(), + community_actions::follow_pending.assume_not_null(), + ) + } + pub fn to_subscribed_type(follower: &Option) -> SubscribedType { match follower { Some(f) => { @@ -225,8 +286,8 @@ impl CommunityFollower { } } - pub fn select_subscribed_type() -> dsl::Nullable { - community_follower::pending.nullable() + pub fn select_subscribed_type() -> dsl::Nullable { + community_actions::follow_pending.nullable() } /// Check if a remote instance has any followers on local instance. For this it is enough to check @@ -235,10 +296,11 @@ impl CommunityFollower { pool: &mut DbPool<'_>, remote_community_id: CommunityId, ) -> Result { - use crate::schema::community_follower::dsl::{community_follower, community_id}; let conn = &mut get_conn(pool).await?; select(exists( - community_follower.filter(community_id.eq(remote_community_id)), + community_actions::table + .filter(community_actions::community_id.eq(remote_community_id)) + .filter(community_actions::followed.is_not_null()), )) .get_result(conn) .await @@ -260,13 +322,17 @@ impl Queryable, Pg> for SubscribedType { impl Followable for CommunityFollower { type Form = CommunityFollowerForm; async fn follow(pool: &mut DbPool<'_>, form: &CommunityFollowerForm) -> Result { - use crate::schema::community_follower::dsl::{community_follower, community_id, person_id}; let conn = &mut get_conn(pool).await?; - insert_into(community_follower) + let form = (form, community_actions::followed.eq(now().nullable())); + insert_into(community_actions::table) .values(form) - .on_conflict((community_id, person_id)) + .on_conflict(( + community_actions::community_id, + community_actions::person_id, + )) .do_update() .set(form) + .returning(Self::as_select_unwrap()) .get_result::(conn) .await } @@ -275,17 +341,24 @@ impl Followable for CommunityFollower { community_id: CommunityId, person_id: PersonId, ) -> Result { - use crate::schema::community_follower::dsl::{community_follower, pending}; let conn = &mut get_conn(pool).await?; - diesel::update(community_follower.find((person_id, community_id))) - .set(pending.eq(false)) - .get_result::(conn) - .await + diesel::update( + community_actions::table + .find((person_id, community_id)) + .filter(community_actions::follow_pending.is_not_null()), + ) + .set(community_actions::follow_pending.eq(Some(false))) + .returning(Self::as_select_unwrap()) + .get_result::(conn) + .await } async fn unfollow(pool: &mut DbPool<'_>, form: &CommunityFollowerForm) -> Result { - use crate::schema::community_follower::dsl::community_follower; let conn = &mut get_conn(pool).await?; - diesel::delete(community_follower.find((form.person_id, form.community_id))) + diesel::update(community_actions::table.find((form.person_id, form.community_id))) + .set(( + community_actions::followed.eq(None::>), + community_actions::follow_pending.eq(None::), + )) .execute(conn) .await } diff --git a/crates/db_schema/src/source/community.rs b/crates/db_schema/src/source/community.rs index 434fa7037..b8a97c14c 100644 --- a/crates/db_schema/src/source/community.rs +++ b/crates/db_schema/src/source/community.rs @@ -1,5 +1,5 @@ #[cfg(feature = "full")] -use crate::schema::{community, community_follower, community_moderator, community_person_ban}; +use crate::schema::{community, community_actions}; use crate::{ newtypes::{CommunityId, DbUrl, InstanceId, PersonId}, source::placeholder_apub_url, @@ -133,15 +133,12 @@ pub struct CommunityUpdateForm { } #[derive(PartialEq, Eq, Debug)] -#[cfg_attr( - feature = "full", - derive(Identifiable, Queryable, Selectable, Associations) -)] +#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] #[cfg_attr( feature = "full", diesel(belongs_to(crate::source::community::Community)) )] -#[cfg_attr(feature = "full", diesel(table_name = community_moderator))] +#[cfg_attr(feature = "full", diesel(table_name = community_actions))] #[cfg_attr(feature = "full", diesel(primary_key(person_id, community_id)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] pub struct CommunityModerator { @@ -152,22 +149,19 @@ pub struct CommunityModerator { #[derive(Clone)] #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] -#[cfg_attr(feature = "full", diesel(table_name = community_moderator))] +#[cfg_attr(feature = "full", diesel(table_name = community_actions))] pub struct CommunityModeratorForm { pub community_id: CommunityId, pub person_id: PersonId, } #[derive(PartialEq, Eq, Debug)] -#[cfg_attr( - feature = "full", - derive(Identifiable, Queryable, Selectable, Associations) -)] +#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] #[cfg_attr( feature = "full", diesel(belongs_to(crate::source::community::Community)) )] -#[cfg_attr(feature = "full", diesel(table_name = community_person_ban))] +#[cfg_attr(feature = "full", diesel(table_name = community_actions))] #[cfg_attr(feature = "full", diesel(primary_key(person_id, community_id)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] pub struct CommunityPersonBan { @@ -179,23 +173,21 @@ pub struct CommunityPersonBan { #[derive(Clone)] #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] -#[cfg_attr(feature = "full", diesel(table_name = community_person_ban))] +#[cfg_attr(feature = "full", diesel(table_name = community_actions))] pub struct CommunityPersonBanForm { pub community_id: CommunityId, pub person_id: PersonId, + #[cfg_attr(feature = "full", diesel(column_name = ban_expires))] pub expires: Option>>, } #[derive(PartialEq, Eq, Debug)] -#[cfg_attr( - feature = "full", - derive(Identifiable, Queryable, Selectable, Associations) -)] +#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] #[cfg_attr( feature = "full", diesel(belongs_to(crate::source::community::Community)) )] -#[cfg_attr(feature = "full", diesel(table_name = community_follower))] +#[cfg_attr(feature = "full", diesel(table_name = community_actions))] #[cfg_attr(feature = "full", diesel(primary_key(person_id, community_id)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] pub struct CommunityFollower { @@ -207,9 +199,10 @@ pub struct CommunityFollower { #[derive(Clone)] #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] -#[cfg_attr(feature = "full", diesel(table_name = community_follower))] +#[cfg_attr(feature = "full", diesel(table_name = community_actions))] pub struct CommunityFollowerForm { pub community_id: CommunityId, pub person_id: PersonId, + #[cfg_attr(feature = "full", diesel(column_name = follow_pending))] pub pending: bool, } From c93994b7c92860f46edd688ec886f1e2ee75d36c Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sun, 25 Feb 2024 16:45:38 +0000 Subject: [PATCH 039/232] community_block --- crates/db_schema/src/impls/community_block.rs | 39 +++++++++++++++---- .../db_schema/src/source/community_block.rs | 11 ++---- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/crates/db_schema/src/impls/community_block.rs b/crates/db_schema/src/impls/community_block.rs index 1393f49d3..fcb7d32cf 100644 --- a/crates/db_schema/src/impls/community_block.rs +++ b/crates/db_schema/src/impls/community_block.rs @@ -1,19 +1,34 @@ use crate::{ newtypes::{CommunityId, PersonId}, - schema::community_block::dsl::{community_block, community_id, person_id}, + schema::community_actions, source::community_block::{CommunityBlock, CommunityBlockForm}, traits::Blockable, - utils::{get_conn, DbPool}, + utils::{get_conn, now, DbPool}, }; +use chrono::{DateTime, Utc}; use diesel::{ - dsl::{exists, insert_into}, + dsl::{self, exists, insert_into}, result::Error, select, + ExpressionMethods, + NullableExpressionMethods, QueryDsl, }; use diesel_async::RunQueryDsl; impl CommunityBlock { + fn as_select_unwrap() -> ( + community_actions::person_id, + community_actions::community_id, + dsl::AssumeNotNull, + ) { + ( + community_actions::person_id, + community_actions::community_id, + community_actions::blocked.assume_not_null(), + ) + } + pub async fn read( pool: &mut DbPool<'_>, for_person_id: PersonId, @@ -21,7 +36,9 @@ impl CommunityBlock { ) -> Result { let conn = &mut get_conn(pool).await?; select(exists( - community_block.find((for_person_id, for_community_id)), + community_actions::table + .find((for_person_id, for_community_id)) + .filter(community_actions::blocked.is_not_null()), )) .get_result(conn) .await @@ -33,9 +50,16 @@ impl Blockable for CommunityBlock { type Form = CommunityBlockForm; async fn block(pool: &mut DbPool<'_>, community_block_form: &Self::Form) -> Result { let conn = &mut get_conn(pool).await?; - insert_into(community_block) + let community_block_form = ( + community_block_form, + community_actions::blocked.eq(now().nullable()), + ); + insert_into(community_actions::table) .values(community_block_form) - .on_conflict((person_id, community_id)) + .on_conflict(( + community_actions::person_id, + community_actions::community_id, + )) .do_update() .set(community_block_form) .get_result::(conn) @@ -46,10 +70,11 @@ impl Blockable for CommunityBlock { community_block_form: &Self::Form, ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::delete(community_block.find(( + diesel::update(community_actions::table.find(( community_block_form.person_id, community_block_form.community_id, ))) + .set(community_actions::blocked.eq(None::>)) .execute(conn) .await } diff --git a/crates/db_schema/src/source/community_block.rs b/crates/db_schema/src/source/community_block.rs index 7d43af173..d46ade3e8 100644 --- a/crates/db_schema/src/source/community_block.rs +++ b/crates/db_schema/src/source/community_block.rs @@ -1,19 +1,16 @@ use crate::newtypes::{CommunityId, PersonId}; #[cfg(feature = "full")] -use crate::schema::community_block; +use crate::schema::community_actions; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] -#[cfg_attr( - feature = "full", - derive(Queryable, Selectable, Associations, Identifiable) -)] +#[cfg_attr(feature = "full", derive(Queryable, Associations, Identifiable))] #[cfg_attr( feature = "full", diesel(belongs_to(crate::source::community::Community)) )] -#[cfg_attr(feature = "full", diesel(table_name = community_block))] +#[cfg_attr(feature = "full", diesel(table_name = community_actions))] #[cfg_attr(feature = "full", diesel(primary_key(person_id, community_id)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] pub struct CommunityBlock { @@ -23,7 +20,7 @@ pub struct CommunityBlock { } #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] -#[cfg_attr(feature = "full", diesel(table_name = community_block))] +#[cfg_attr(feature = "full", diesel(table_name = community_actions))] pub struct CommunityBlockForm { pub person_id: PersonId, pub community_id: CommunityId, From 5293929644c11666702219df4f9f2e68c8e43291 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sun, 25 Feb 2024 16:54:29 +0000 Subject: [PATCH 040/232] instance_block --- crates/db_schema/src/impls/instance_block.rs | 37 +++++++++++++++---- crates/db_schema/src/source/instance_block.rs | 11 ++---- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/crates/db_schema/src/impls/instance_block.rs b/crates/db_schema/src/impls/instance_block.rs index e32688411..f6f92b4bd 100644 --- a/crates/db_schema/src/impls/instance_block.rs +++ b/crates/db_schema/src/impls/instance_block.rs @@ -1,19 +1,34 @@ use crate::{ newtypes::{InstanceId, PersonId}, - schema::instance_block::dsl::{instance_block, instance_id, person_id}, + schema::instance_actions, source::instance_block::{InstanceBlock, InstanceBlockForm}, traits::Blockable, - utils::{get_conn, DbPool}, + utils::{get_conn, now, DbPool}, }; +use chrono::{DateTime, Utc}; use diesel::{ - dsl::{exists, insert_into}, + dsl::{self, exists, insert_into}, result::Error, select, + ExpressionMethods, + NullableExpressionMethods, QueryDsl, }; use diesel_async::RunQueryDsl; impl InstanceBlock { + fn as_select_unwrap() -> ( + instance_actions::person_id, + instance_actions::instance_id, + dsl::AssumeNotNull, + ) { + ( + instance_actions::person_id, + instance_actions::instance_id, + instance_actions::blocked.assume_not_null(), + ) + } + pub async fn read( pool: &mut DbPool<'_>, for_person_id: PersonId, @@ -21,7 +36,9 @@ impl InstanceBlock { ) -> Result { let conn = &mut get_conn(pool).await?; select(exists( - instance_block.find((for_person_id, for_instance_id)), + instance_actions::table + .find((for_person_id, for_instance_id)) + .filter(instance_actions::blocked.is_not_null()), )) .get_result(conn) .await @@ -33,11 +50,16 @@ impl Blockable for InstanceBlock { type Form = InstanceBlockForm; async fn block(pool: &mut DbPool<'_>, instance_block_form: &Self::Form) -> Result { let conn = &mut get_conn(pool).await?; - insert_into(instance_block) + let instance_block_form = ( + instance_block_form, + instance_actions::blocked.eq(now().nullable()), + ); + insert_into(instance_actions::table) .values(instance_block_form) - .on_conflict((person_id, instance_id)) + .on_conflict((instance_actions::person_id, instance_actions::instance_id)) .do_update() .set(instance_block_form) + .returning(Self::as_select_unwrap()) .get_result::(conn) .await } @@ -46,10 +68,11 @@ impl Blockable for InstanceBlock { instance_block_form: &Self::Form, ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::delete(instance_block.find(( + diesel::update(instance_actions::table.find(( instance_block_form.person_id, instance_block_form.instance_id, ))) + .set(instance_actions::blocked.eq(None::>)) .execute(conn) .await } diff --git a/crates/db_schema/src/source/instance_block.rs b/crates/db_schema/src/source/instance_block.rs index 4eebbf1a8..237b21bc9 100644 --- a/crates/db_schema/src/source/instance_block.rs +++ b/crates/db_schema/src/source/instance_block.rs @@ -1,19 +1,16 @@ use crate::newtypes::{InstanceId, PersonId}; #[cfg(feature = "full")] -use crate::schema::instance_block; +use crate::schema::instance_actions; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] -#[cfg_attr( - feature = "full", - derive(Queryable, Selectable, Associations, Identifiable) -)] +#[cfg_attr(feature = "full", derive(Queryable, Associations, Identifiable))] #[cfg_attr( feature = "full", diesel(belongs_to(crate::source::instance::Instance)) )] -#[cfg_attr(feature = "full", diesel(table_name = instance_block))] +#[cfg_attr(feature = "full", diesel(table_name = instance_actions))] #[cfg_attr(feature = "full", diesel(primary_key(person_id, instance_id)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] pub struct InstanceBlock { @@ -23,7 +20,7 @@ pub struct InstanceBlock { } #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] -#[cfg_attr(feature = "full", diesel(table_name = instance_block))] +#[cfg_attr(feature = "full", diesel(table_name = instance_actions))] pub struct InstanceBlockForm { pub person_id: PersonId, pub instance_id: InstanceId, From 798e32650002bf1b3781acfc10af791159386618 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sun, 25 Feb 2024 17:04:26 +0000 Subject: [PATCH 041/232] LocalUser::export_backup --- crates/db_schema/src/impls/local_user.rs | 49 +++++++++++++----------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/crates/db_schema/src/impls/local_user.rs b/crates/db_schema/src/impls/local_user.rs index 14da24bae..5afc0d0ed 100644 --- a/crates/db_schema/src/impls/local_user.rs +++ b/crates/db_schema/src/impls/local_user.rs @@ -98,55 +98,60 @@ impl LocalUser { ) -> Result { use crate::schema::{ comment, - comment_saved, + comment_actions, community, - community_block, - community_follower, + community_actions, instance, - instance_block, - person_block, + instance_actions, + person_actions, post, - post_saved, + post_actions, }; let conn = &mut get_conn(pool).await?; - let followed_communities = community_follower::dsl::community_follower - .filter(community_follower::person_id.eq(person_id_)) - .inner_join(community::table.on(community_follower::community_id.eq(community::id))) + let followed_communities = community_actions::table + .filter(community_actions::person_id.eq(person_id_)) + .filter(community_actions::followed.is_not_null()) + .inner_join(community::table.on(community_actions::community_id.eq(community::id))) .select(community::actor_id) .get_results(conn) .await?; - let saved_posts = post_saved::dsl::post_saved - .filter(post_saved::person_id.eq(person_id_)) - .inner_join(post::table.on(post_saved::post_id.eq(post::id))) + let saved_posts = post_actions::table + .filter(post_actions::person_id.eq(person_id_)) + .filter(post_actions::saved.is_not_null()) + .inner_join(post::table.on(post_actions::post_id.eq(post::id))) .select(post::ap_id) .get_results(conn) .await?; - let saved_comments = comment_saved::dsl::comment_saved - .filter(comment_saved::person_id.eq(person_id_)) - .inner_join(comment::table.on(comment_saved::comment_id.eq(comment::id))) + let saved_comments = comment_actions::table + .filter(comment_actions::person_id.eq(person_id_)) + .filter(comment_actions::saved.is_not_null()) + .inner_join(comment::table.on(comment_actions::comment_id.eq(comment::id))) .select(comment::ap_id) .get_results(conn) .await?; - let blocked_communities = community_block::dsl::community_block - .filter(community_block::person_id.eq(person_id_)) + let blocked_communities = community_actions::table + .filter(community_actions::person_id.eq(person_id_)) + .filter(community_actions::blocked.is_not_null()) .inner_join(community::table) .select(community::actor_id) .get_results(conn) .await?; - let blocked_users = person_block::dsl::person_block - .filter(person_block::person_id.eq(person_id_)) - .inner_join(person::table.on(person_block::target_id.eq(person::id))) + let blocked_users = person_actions::table + .filter(person_actions::person_id.eq(person_id_)) + .filter(person_actions::blocked.is_not_null()) + .inner_join(person::table.on(person_actions::target_id.eq(person::id))) .select(person::actor_id) .get_results(conn) .await?; - let blocked_instances = instance_block::dsl::instance_block - .filter(instance_block::person_id.eq(person_id_)) + let blocked_instances = instance_actions::table + .filter(instance_actions::person_id.eq(person_id_)) + .filter(instance_actions::blocked.is_not_null()) .inner_join(instance::table) .select(instance::domain) .get_results(conn) From ea69354c7b8f7c444977726cc0baab545e304409 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Mon, 26 Feb 2024 00:11:52 +0000 Subject: [PATCH 042/232] person_block --- crates/db_schema/src/impls/person_block.rs | 48 ++++++++++++++++----- crates/db_schema/src/source/person_block.rs | 11 ++--- 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/crates/db_schema/src/impls/person_block.rs b/crates/db_schema/src/impls/person_block.rs index 0dbf003d8..15c4d721a 100644 --- a/crates/db_schema/src/impls/person_block.rs +++ b/crates/db_schema/src/impls/person_block.rs @@ -1,28 +1,48 @@ use crate::{ newtypes::PersonId, - schema::person_block::dsl::{person_block, person_id, target_id}, + schema::person_actions, source::person_block::{PersonBlock, PersonBlockForm}, traits::Blockable, - utils::{get_conn, DbPool}, + utils::{get_conn, now, DbPool}, }; +use chrono::{DateTime, Utc}; use diesel::{ + dsl, dsl::{exists, insert_into}, result::Error, select, + ExpressionMethods, + NullableExpressionMethods, QueryDsl, }; use diesel_async::RunQueryDsl; impl PersonBlock { + fn as_select_unwrap() -> ( + person_actions::person_id, + person_actions::target_id, + dsl::AssumeNotNull, + ) { + ( + person_actions::person_id, + person_actions::target_id, + person_actions::blocked.assume_not_null(), + ) + } + pub async fn read( pool: &mut DbPool<'_>, for_person_id: PersonId, for_recipient_id: PersonId, ) -> Result { let conn = &mut get_conn(pool).await?; - select(exists(person_block.find((for_person_id, for_recipient_id)))) - .get_result(conn) - .await + select(exists( + person_actions::table + .find((for_person_id, for_recipient_id)) + .filter(person_actions::blocked.is_not_null()), + )) + .get_result(conn) + .await } } @@ -34,18 +54,26 @@ impl Blockable for PersonBlock { person_block_form: &PersonBlockForm, ) -> Result { let conn = &mut get_conn(pool).await?; - insert_into(person_block) + let person_block_form = ( + person_block_form, + person_actions::blocked.eq(now().nullable()), + ); + insert_into(person_actions::table) .values(person_block_form) - .on_conflict((person_id, target_id)) + .on_conflict((person_actions::person_id, person_actions::target_id)) .do_update() .set(person_block_form) + .returning(Self::as_select_unwrap()) .get_result::(conn) .await } async fn unblock(pool: &mut DbPool<'_>, person_block_form: &Self::Form) -> Result { let conn = &mut get_conn(pool).await?; - diesel::delete(person_block.find((person_block_form.person_id, person_block_form.target_id))) - .execute(conn) - .await + diesel::update( + person_actions::table.find((person_block_form.person_id, person_block_form.target_id)), + ) + .set(person_actions::blocked.eq(None::>)) + .execute(conn) + .await } } diff --git a/crates/db_schema/src/source/person_block.rs b/crates/db_schema/src/source/person_block.rs index 43048fb39..0d3f8118c 100644 --- a/crates/db_schema/src/source/person_block.rs +++ b/crates/db_schema/src/source/person_block.rs @@ -1,16 +1,13 @@ use crate::newtypes::PersonId; #[cfg(feature = "full")] -use crate::schema::person_block; +use crate::schema::person_actions; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] -#[cfg_attr( - feature = "full", - derive(Queryable, Selectable, Associations, Identifiable) -)] +#[cfg_attr(feature = "full", derive(Queryable, Associations, Identifiable))] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::person::Person)))] -#[cfg_attr(feature = "full", diesel(table_name = person_block))] +#[cfg_attr(feature = "full", diesel(table_name = person_actions))] #[cfg_attr(feature = "full", diesel(primary_key(person_id, target_id)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] pub struct PersonBlock { @@ -20,7 +17,7 @@ pub struct PersonBlock { } #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] -#[cfg_attr(feature = "full", diesel(table_name = person_block))] +#[cfg_attr(feature = "full", diesel(table_name = person_actions))] pub struct PersonBlockForm { pub person_id: PersonId, pub target_id: PersonId, From d3996dd2bf4518e5505e9b4902919c0b3003c265 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Mon, 26 Feb 2024 00:26:56 +0000 Subject: [PATCH 043/232] person --- crates/db_schema/src/impls/person.rs | 50 +++++++++++++++++++++------ crates/db_schema/src/source/person.rs | 14 ++++---- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs index 9fb1ee1c5..4f19a7884 100644 --- a/crates/db_schema/src/impls/person.rs +++ b/crates/db_schema/src/impls/person.rs @@ -1,6 +1,6 @@ use crate::{ newtypes::{CommunityId, DbUrl, InstanceId, PersonId}, - schema::{instance, local_user, person, person_follower}, + schema::{instance, local_user, person, person_actions}, source::person::{ Person, PersonFollower, @@ -9,9 +9,16 @@ use crate::{ PersonUpdateForm, }, traits::{ApubActor, Crud, Followable}, - utils::{functions::lower, get_conn, naive_now, DbPool}, + utils::{functions::lower, get_conn, naive_now, now, DbPool}, +}; +use chrono::{DateTime, Utc}; +use diesel::{ + dsl::{self, insert_into}, + result::Error, + ExpressionMethods, + JoinOnDsl, + QueryDsl, }; -use diesel::{dsl::insert_into, result::Error, ExpressionMethods, JoinOnDsl, QueryDsl}; use diesel_async::RunQueryDsl; #[async_trait] @@ -147,17 +154,34 @@ impl ApubActor for Person { } } +impl PersonFollower { + fn as_select_unwrap() -> ( + person_actions::target_id, + person_actions::person_id, + dsl::AssumeNotNull, + dsl::AssumeNotNull, + ) { + ( + person_actions::target_id, + person_actions::person_id, + person_actions::followed.assume_not_null(), + person_actions::follow_pending.assume_not_null(), + ) + } +} + #[async_trait] impl Followable for PersonFollower { type Form = PersonFollowerForm; async fn follow(pool: &mut DbPool<'_>, form: &PersonFollowerForm) -> Result { - use crate::schema::person_follower::dsl::{follower_id, person_follower, person_id}; let conn = &mut get_conn(pool).await?; - insert_into(person_follower) + let form = (form, person_actions::followed.eq(now().nullable())); + insert_into(person_actions::table) .values(form) - .on_conflict((follower_id, person_id)) + .on_conflict((person_actions::person_id, person_actions::target_id)) .do_update() .set(form) + .returning(Self::as_select_unwrap()) .get_result::(conn) .await } @@ -165,9 +189,12 @@ impl Followable for PersonFollower { unimplemented!() } async fn unfollow(pool: &mut DbPool<'_>, form: &PersonFollowerForm) -> Result { - use crate::schema::person_follower::dsl::person_follower; let conn = &mut get_conn(pool).await?; - diesel::delete(person_follower.find((form.follower_id, form.person_id))) + diesel::update(person_actions::table.find((form.follower_id, form.person_id))) + .set(( + person_actions::followed.eq(None::>), + person_actions::follow_pending.eq(None::), + )) .execute(conn) .await } @@ -179,9 +206,10 @@ impl PersonFollower { for_person_id: PersonId, ) -> Result, Error> { let conn = &mut get_conn(pool).await?; - person_follower::table - .inner_join(person::table.on(person_follower::follower_id.eq(person::id))) - .filter(person_follower::person_id.eq(for_person_id)) + person_actions::table + .inner_join(person::table.on(person_actions::person_id.eq(person::id))) + .filter(person_actions::target_id.eq(for_person_id)) + .filter(person_actions::followed.is_not_null()) .select(person::all_columns) .load(conn) .await diff --git a/crates/db_schema/src/source/person.rs b/crates/db_schema/src/source/person.rs index 25e65ae79..86f93bdd4 100644 --- a/crates/db_schema/src/source/person.rs +++ b/crates/db_schema/src/source/person.rs @@ -1,5 +1,5 @@ #[cfg(feature = "full")] -use crate::schema::{person, person_follower}; +use crate::schema::{person, person_actions}; use crate::{ newtypes::{DbUrl, InstanceId, PersonId}, source::placeholder_apub_url, @@ -113,12 +113,9 @@ pub struct PersonUpdateForm { } #[derive(PartialEq, Eq, Debug)] -#[cfg_attr( - feature = "full", - derive(Identifiable, Queryable, Selectable, Associations) -)] +#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::person::Person)))] -#[cfg_attr(feature = "full", diesel(table_name = person_follower))] +#[cfg_attr(feature = "full", diesel(table_name = person_actions))] #[cfg_attr(feature = "full", diesel(primary_key(follower_id, person_id)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] pub struct PersonFollower { @@ -130,9 +127,12 @@ pub struct PersonFollower { #[derive(Clone)] #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] -#[cfg_attr(feature = "full", diesel(table_name = person_follower))] +#[cfg_attr(feature = "full", diesel(table_name = person_actions))] pub struct PersonFollowerForm { + #[cfg_attr(feature = "full", diesel(column_name = target_id))] pub person_id: PersonId, + #[cfg_attr(feature = "full", diesel(column_name = person_id))] pub follower_id: PersonId, + #[cfg_attr(feature = "full", diesel(column_name = follow_pending))] pub pending: bool, } From 074a11272a562720a2a779337645dcf3d20d9404 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Thu, 7 Mar 2024 16:07:39 +0000 Subject: [PATCH 044/232] stuff (partial) --- crates/db_schema/src/impls/comment.rs | 2 +- crates/db_schema/src/impls/community_block.rs | 1 + crates/db_schema/src/impls/person.rs | 2 +- crates/db_schema/src/impls/post.rs | 8 ++++---- crates/db_schema/src/lib.rs | 3 +-- crates/db_schema/src/source/post.rs | 2 +- crates/db_schema/src/utils.rs | 5 +++-- 7 files changed, 12 insertions(+), 11 deletions(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index fe15e03c7..04c86b112 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -21,7 +21,7 @@ use diesel::{ dsl::{self, insert_into, sql_query}, result::Error, ExpressionMethods, - QueryDsl, + QueryDsl,NullableExpressionMethods }; use diesel_async::RunQueryDsl; use diesel_ltree::Ltree; diff --git a/crates/db_schema/src/impls/community_block.rs b/crates/db_schema/src/impls/community_block.rs index fcb7d32cf..0d015dc56 100644 --- a/crates/db_schema/src/impls/community_block.rs +++ b/crates/db_schema/src/impls/community_block.rs @@ -62,6 +62,7 @@ impl Blockable for CommunityBlock { )) .do_update() .set(community_block_form) + .returning(Self::as_select_unwrap()) .get_result::(conn) .await } diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs index 4f19a7884..dde176ef8 100644 --- a/crates/db_schema/src/impls/person.rs +++ b/crates/db_schema/src/impls/person.rs @@ -17,7 +17,7 @@ use diesel::{ result::Error, ExpressionMethods, JoinOnDsl, - QueryDsl, + QueryDsl,NullableExpressionMethods }; use diesel_async::RunQueryDsl; diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index ec7fb488c..0fabaf872 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -288,12 +288,12 @@ impl Likeable for PostLike { type IdType = PostId; async fn like(pool: &mut DbPool<'_>, post_like_form: &PostLikeForm) -> Result { let conn = &mut get_conn(pool).await?; - let post_like_form = (post_like_form.clone(), post_actions::liked.eq(now())); + let post_like_form = (post_like_form.clone(), post_actions::liked.eq(now().nullable())); insert_into(post_actions::table) - .values(post_like_form) + .values(&post_like_form) .on_conflict((post_actions::post_id, post_actions::person_id)) .do_update() - .set(post_like_form) + .set(&post_like_form) .returning(Self::as_select_unwrap()) .get_result::(conn) .await @@ -333,7 +333,7 @@ impl Saveable for PostSaved { type Form = PostSavedForm; async fn save(pool: &mut DbPool<'_>, post_saved_form: &PostSavedForm) -> Result { let conn = &mut get_conn(pool).await?; - let post_saved_form = (post_saved_form.clone(), post_actions::saved.eq(now())); + let post_saved_form = (post_saved_form.clone(), post_actions::saved.eq(now().nullable())); insert_into(post_actions::table) .values(post_saved_form) .on_conflict((post_actions::post_id, post_actions::person_id)) diff --git a/crates/db_schema/src/lib.rs b/crates/db_schema/src/lib.rs index 05663ff3e..393ff8971 100644 --- a/crates/db_schema/src/lib.rs +++ b/crates/db_schema/src/lib.rs @@ -30,11 +30,10 @@ pub mod newtypes; pub mod schema; #[cfg(feature = "full")] pub mod aliases { - use crate::schema::{community_moderator, person}; + use crate::schema::{person}; diesel::alias!( person as person1: Person1, person as person2: Person2, - community_moderator as community_moderator1: CommunityModerator1 ); } pub mod source; diff --git a/crates/db_schema/src/source/post.rs b/crates/db_schema/src/source/post.rs index 8fae08e9f..347b2ea53 100644 --- a/crates/db_schema/src/source/post.rs +++ b/crates/db_schema/src/source/post.rs @@ -150,7 +150,7 @@ pub struct PostSaved { } #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] -#[cfg_attr(feature = "full", diesel(table_name = post_saved))] +#[cfg_attr(feature = "full", diesel(table_name = post_actions))] pub struct PostSavedForm { pub post_id: PostId, pub person_id: PersonId, diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index 878b0e561..e973247a2 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -1,3 +1,4 @@ +use diesel::JoinOnDsl; use crate::{ diesel::Connection, diesel_migrations::MigrationHarness, @@ -8,7 +9,7 @@ use crate::{ use anyhow::Context; use chrono::{DateTime, Utc}; use deadpool::Runtime; -use diesel::{ +use diesel::{NullableExpressionMethods,ExpressionMethods,BoolExpressionMethods, dsl, expression::AsExpression, helper_types::AsExprOf, @@ -20,7 +21,7 @@ use diesel::{ ConnectionResult, Error::{self as DieselError, QueryBuilderError}, }, - sql_types::{self, SqlType, Text, Timestamptz}, + sql_types::{self, SqlType, Timestamptz}, Expression, IntoSql, PgConnection, From fdb9f79820a433c7f655d95a977f12d5b46b9bf2 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Thu, 7 Mar 2024 21:05:49 +0000 Subject: [PATCH 045/232] update cargo.lock --- Cargo.lock | 2 -- 1 file changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e4c55f082..b7990d250 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2577,7 +2577,6 @@ version = "0.19.3" dependencies = [ "activitypub_federation", "actix-web", - "anyhow", "chrono", "encoding", "enum-map", @@ -2599,7 +2598,6 @@ dependencies = [ "serde", "serde_with", "serial_test", - "task-local-extensions", "tokio", "tracing", "ts-rs", From 0d0fa01ae4edc575d9d271e7bd486260a23ec623 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Thu, 7 Mar 2024 21:28:29 +0000 Subject: [PATCH 046/232] fix lemmy_db_schema --- crates/db_schema/src/impls/comment.rs | 3 ++- crates/db_schema/src/impls/person.rs | 4 +++- crates/db_schema/src/impls/post.rs | 8 ++++---- crates/db_schema/src/lib.rs | 2 +- crates/db_schema/src/source/post.rs | 15 ++++++--------- crates/db_schema/src/utils.rs | 7 +++++-- 6 files changed, 21 insertions(+), 18 deletions(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index 28dc5a5c1..1f5b66255 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -18,7 +18,8 @@ use diesel::{ dsl::{self, insert_into, sql_query}, result::Error, ExpressionMethods, - QueryDsl,NullableExpressionMethods + NullableExpressionMethods, + QueryDsl, }; use diesel_async::RunQueryDsl; use diesel_ltree::Ltree; diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs index f59c86f89..f4fd94a3a 100644 --- a/crates/db_schema/src/impls/person.rs +++ b/crates/db_schema/src/impls/person.rs @@ -15,9 +15,11 @@ use chrono::{DateTime, Utc}; use diesel::{ dsl::{self, insert_into}, result::Error, + CombineDsl, ExpressionMethods, JoinOnDsl, - QueryDsl,NullableExpressionMethods + NullableExpressionMethods, + QueryDsl, }; use diesel_async::RunQueryDsl; diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index 9cfb8cc9a..7f7d02dfa 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -272,12 +272,12 @@ impl Likeable for PostLike { type IdType = PostId; async fn like(pool: &mut DbPool<'_>, post_like_form: &PostLikeForm) -> Result { let conn = &mut get_conn(pool).await?; - let post_like_form = (post_like_form.clone(), post_actions::liked.eq(now().nullable())); + let post_like_form = (post_like_form, post_actions::liked.eq(now().nullable())); insert_into(post_actions::table) - .values(&post_like_form) + .values(post_like_form) .on_conflict((post_actions::post_id, post_actions::person_id)) .do_update() - .set(&post_like_form) + .set(post_like_form) .returning(Self::as_select_unwrap()) .get_result::(conn) .await @@ -317,7 +317,7 @@ impl Saveable for PostSaved { type Form = PostSavedForm; async fn save(pool: &mut DbPool<'_>, post_saved_form: &PostSavedForm) -> Result { let conn = &mut get_conn(pool).await?; - let post_saved_form = (post_saved_form.clone(), post_actions::saved.eq(now().nullable())); + let post_saved_form = (post_saved_form, post_actions::saved.eq(now().nullable())); insert_into(post_actions::table) .values(post_saved_form) .on_conflict((post_actions::post_id, post_actions::person_id)) diff --git a/crates/db_schema/src/lib.rs b/crates/db_schema/src/lib.rs index 393ff8971..c47b0ae2a 100644 --- a/crates/db_schema/src/lib.rs +++ b/crates/db_schema/src/lib.rs @@ -30,7 +30,7 @@ pub mod newtypes; pub mod schema; #[cfg(feature = "full")] pub mod aliases { - use crate::schema::{person}; + use crate::schema::person; diesel::alias!( person as person1: Person1, person as person2: Person2, diff --git a/crates/db_schema/src/source/post.rs b/crates/db_schema/src/source/post.rs index e0bc06ad3..1e980ef34 100644 --- a/crates/db_schema/src/source/post.rs +++ b/crates/db_schema/src/source/post.rs @@ -145,7 +145,7 @@ pub struct PostLikeForm { #[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::post::Post)))] #[cfg_attr(feature = "full", diesel(table_name = post_actions))] -#[cfg_attr(feature = "full", diesel(primary_key(post_id, person_id)))] +#[cfg_attr(feature = "full", diesel(primary_key(person_id, post_id)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] pub struct PostSaved { pub post_id: PostId, @@ -164,7 +164,7 @@ pub struct PostSavedForm { #[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::post::Post)))] #[cfg_attr(feature = "full", diesel(table_name = post_actions))] -#[cfg_attr(feature = "full", diesel(primary_key(post_id, person_id)))] +#[cfg_attr(feature = "full", diesel(primary_key(person_id, post_id)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] pub struct PostRead { pub post_id: PostId, @@ -180,13 +180,10 @@ pub(crate) struct PostReadForm { } #[derive(PartialEq, Eq, Debug)] -#[cfg_attr( - feature = "full", - derive(Identifiable, Queryable, Selectable, Associations) -)] +#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::post::Post)))] -#[cfg_attr(feature = "full", diesel(table_name = post_hide))] -#[cfg_attr(feature = "full", diesel(primary_key(post_id, person_id)))] +#[cfg_attr(feature = "full", diesel(table_name = post_actions))] +#[cfg_attr(feature = "full", diesel(primary_key(person_id, post_id)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] pub struct PostHide { pub post_id: PostId, @@ -195,7 +192,7 @@ pub struct PostHide { } #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] -#[cfg_attr(feature = "full", diesel(table_name = post_hide))] +#[cfg_attr(feature = "full", diesel(table_name = post_actions))] pub(crate) struct PostHideForm { pub post_id: PostId, pub person_id: PersonId, diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index 66349ea90..aa0874ab8 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -1,4 +1,3 @@ -use diesel::JoinOnDsl; use crate::{ diesel::Connection, diesel_migrations::MigrationHarness, @@ -9,7 +8,7 @@ use crate::{ use anyhow::Context; use chrono::{DateTime, Utc}; use deadpool::Runtime; -use diesel::{NullableExpressionMethods,ExpressionMethods,BoolExpressionMethods, +use diesel::{ dsl, expression::AsExpression, helper_types::AsExprOf, @@ -22,8 +21,12 @@ use diesel::{NullableExpressionMethods,ExpressionMethods,BoolExpressionMethods, Error::{self as DieselError, QueryBuilderError}, }, sql_types::{self, SqlType, Timestamptz}, + BoolExpressionMethods, Expression, + ExpressionMethods, IntoSql, + JoinOnDsl, + NullableExpressionMethods, PgConnection, Table, }; From db403ecc4b0014aa721c58e643f4918df6d5fb1d Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Fri, 8 Mar 2024 03:41:38 +0000 Subject: [PATCH 047/232] post_view --- crates/db_schema/src/lib.rs | 3 +- crates/db_schema/src/utils.rs | 31 +++++++++ crates/db_views/src/post_view.rs | 108 +++++++++++++------------------ 3 files changed, 78 insertions(+), 64 deletions(-) diff --git a/crates/db_schema/src/lib.rs b/crates/db_schema/src/lib.rs index c47b0ae2a..8ed71e3c2 100644 --- a/crates/db_schema/src/lib.rs +++ b/crates/db_schema/src/lib.rs @@ -30,8 +30,9 @@ pub mod newtypes; pub mod schema; #[cfg(feature = "full")] pub mod aliases { - use crate::schema::person; + use crate::schema::{community_actions, person}; diesel::alias!( + community_actions as creator_community_actions: CreatorCommunityActions, person as person1: Person1, person as person2: Person2, ); diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index aa0874ab8..c9dd16d75 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -15,6 +15,7 @@ use diesel::{ pg::Pg, query_builder::{Query, QueryFragment}, query_dsl::methods::LimitDsl, + query_source::AliasSource, result::{ ConnectionError, ConnectionResult, @@ -513,6 +514,36 @@ where ) } +/*pub fn actions_alias( + actions_table: Alias, + person_id: Option, + target_id: C, +) -> dsl::On, dsl::And>, Option>, dsl::Eq, C>>> +where + AS: AliasSource, + Alias: QuerySource + Clone + Copy, + AS::Target: Table, + K0: Default + Column, + AliasedField: Expression + Sized, + dsl::Nullable>: diesel::ExpressionMethods, + > as Expression>::SqlType: SqlType, + Option: AsExpression<> as Expression>::SqlType>, + K1: Default + Column
, + AliasedField: diesel::ExpressionMethods, + as Expression>::SqlType: SqlType, + C: AsExpression< as Expression>::SqlType>, + dsl::Eq>, Option>: + Expression>, + dsl::Eq, C>: Expression, +{ + actions_table.on( + actions_table.field(K0::default()) + .nullable() + .eq(person_id) + .and(actions_table.field(K1::default()).eq(target_id)), + ) +}*/ + pub type ResultFuture<'a, T> = BoxFuture<'a, Result>; pub trait ReadFn<'a, T, Args>: Fn(DbConn<'a>, Args) -> ResultFuture<'a, T> {} diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 3efc47635..16306da7a 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -1,16 +1,12 @@ use crate::structs::{LocalUserView, PaginationCursor, PostView}; -use chrono::{DateTime, Utc}; use diesel::{ debug_query, - dsl::{exists, not, IntervalDsl}, + dsl::{exists, IntervalDsl}, pg::Pg, query_builder::AsQuery, result::Error, - sql_types, BoolExpressionMethods, - BoxableExpression, ExpressionMethods, - IntoSql, JoinOnDsl, NullableExpressionMethods, OptionalExtension, @@ -25,25 +21,19 @@ use lemmy_db_schema::{ newtypes::{CommunityId, LocalUserId, PersonId, PostId}, schema::{ community, - community_block, - community_follower, - community_moderator, - community_person_ban, - instance_block, + community_actions, + instance_actions, local_user, local_user_language, person, - person_block, - person_post_aggregates, + person_actions, post, + post_actions, post_aggregates, - post_hide, - post_like, - post_read, - post_saved, }, source::site::Site, utils::{ + actions, functions::coalesce, fuzzy_search, get_conn, @@ -70,8 +60,7 @@ fn queries<'a>() -> Queries< let all_joins = move |query: post_aggregates::BoxedQuery<'a, Pg>, my_person_id: Option| { query - .inner_join(person::table) - .left_join(local_user::table) + .inner_join(person::table.left_join(local_user::table)) .inner_join(community::table) .inner_join(post::table) .left_join(actions( @@ -94,30 +83,39 @@ fn queries<'a>() -> Queries< my_person_id, post_aggregates::instance_id, )) - .left_join(actions( - creator_community_actions, - post_aggregates::creator_id.nullable(), - post_aggregates::community_id, - )) + .left_join( + creator_community_actions.on( + creator_community_actions + .field(community_actions::person_id) + .eq(post_aggregates::creator_id) + .and( + creator_community_actions + .field(community_actions::community_id) + .eq(post_aggregates::community_id), + ), + ), + ) .select(( post::all_columns, person::all_columns, community::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(), - creator_is_admin, + coalesce(local_user::admin.nullable(), false), post_aggregates::all_columns, community_actions::follow_pending.nullable(), - post_actions::saved.is_not_null(), - post_actions::read.is_not_null(), - post_actions::hidden.is_not_null(), - person_actions::blocked.is_not_null(), + 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(), - post_aggregates::comments - coalesce(post_actions::read_comments.nullable(), 0), + post_aggregates::comments - coalesce(post_actions::read_comments_amount.nullable(), 0), )) }; @@ -176,7 +174,6 @@ fn queries<'a>() -> Queries< let my_local_user_id = options.local_user.map(|l| l.local_user.id); // The left join below will return None in this case - let person_id_join = my_person_id.unwrap_or(PersonId(-1)); let local_user_id_join = my_local_user_id.unwrap_or(LocalUserId(-1)); let mut query = all_joins(post_aggregates::table.into_boxed(), my_person_id); @@ -210,30 +207,17 @@ fn queries<'a>() -> Queries< } if let Some(listing_type) = options.listing_type { - if let Some(person_id) = my_person_id { - let is_subscribed = community_actions::followed.is_not_null(); - match listing_type { - ListingType::Subscribed => query = query.filter(is_subscribed), - ListingType::Local => { - query = query - .filter(community::local.eq(true)) - .filter(community::hidden.eq(false).or(is_subscribed)); - } - ListingType::All => query = query.filter(community::hidden.eq(false).or(is_subscribed)), - ListingType::ModeratorView => { - query = query.filter(community_actions::became_moderator.is_not_null()); - } + let is_subscribed = community_actions::followed.is_not_null(); + match listing_type { + ListingType::Subscribed => query = query.filter(is_subscribed), + ListingType::Local => { + query = query + .filter(community::local.eq(true)) + .filter(community::hidden.eq(false).or(is_subscribed)); } - } - // If your person_id is missing, only show local - else { - match listing_type { - ListingType::Local => { - query = query - .filter(community::local.eq(true)) - .filter(community::hidden.eq(false)); - } - _ => query = query.filter(community::hidden.eq(false)), + ListingType::All => query = query.filter(community::hidden.eq(false).or(is_subscribed)), + ListingType::ModeratorView => { + query = query.filter(community_actions::became_moderator.is_not_null()); } } } else { @@ -488,13 +472,10 @@ impl<'a> PostQuery<'a> { // // the results are correct no matter which community we fetch these for, since it basically covers the "worst case" of the whole page consisting of posts from one community // but using the largest community decreases the pagination-frame so make the real query more efficient. - use lemmy_db_schema::schema::{ - community_aggregates::dsl::{community_aggregates, community_id, users_active_month}, - community_follower::dsl::{ - community_follower, - community_id as follower_community_id, - person_id, - }, + use lemmy_db_schema::schema::community_aggregates::dsl::{ + community_aggregates, + community_id, + users_active_month, }; let (limit, offset) = limit_and_offset(self.page, self.limit)?; if offset != 0 && self.page_after.is_some() { @@ -509,9 +490,10 @@ impl<'a> PostQuery<'a> { .person_id; let largest_subscribed = { let conn = &mut get_conn(pool).await?; - community_follower - .filter(person_id.eq(self_person_id)) - .inner_join(community_aggregates.on(community_id.eq(follower_community_id))) + community_actions::table + .filter(community_actions::person_id.eq(self_person_id)) + .filter(community_actions::followed.is_not_null()) + .inner_join(community_aggregates.on(community_id.eq(community_actions::community_id))) .order_by(users_active_month.desc()) .select(community_id) .limit(1) From f84e731582ac1b8f0feddc4f36433b3318ecd23b Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Fri, 8 Mar 2024 19:52:23 +0000 Subject: [PATCH 048/232] comment_report_view --- crates/db_views/src/comment_report_view.rs | 73 ++++++++++++++-------- 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/crates/db_views/src/comment_report_view.rs b/crates/db_views/src/comment_report_view.rs index d0851acfd..40e0a1786 100644 --- a/crates/db_views/src/comment_report_view.rs +++ b/crates/db_views/src/comment_report_view.rs @@ -11,20 +11,29 @@ use diesel::{ }; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ - aliases, + aliases::{self, creator_community_actions}, newtypes::{CommentId, CommentReportId, CommunityId, PersonId}, schema::{ comment, + comment_actions, comment_aggregates, - comment_like, comment_report, community, - community_moderator, - community_person_ban, + community_actions, person, post, }, - utils::{get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, + utils::{ + actions, + functions::coalesce, + get_conn, + limit_and_offset, + DbConn, + DbPool, + ListFn, + Queries, + ReadFn, + }, }; fn queries<'a>() -> Queries< @@ -50,11 +59,18 @@ fn queries<'a>() -> Queries< aliases::person2 .on(comment_report::resolver_id.eq(aliases::person2.field(person::id).nullable())), ) - .left_join(actions( - creator_community_actions, - comment::creator_id.nullable(), - post_aggregates::community_id, - )) + .left_join( + creator_community_actions.on( + creator_community_actions + .field(community_actions::person_id) + .eq(comment::creator_id) + .and( + creator_community_actions + .field(community_actions::community_id) + .eq(post::community_id), + ), + ), + ) .select(( comment_report::all_columns, comment::all_columns, @@ -63,15 +79,20 @@ fn queries<'a>() -> Queries< person::all_columns, aliases::person1.fields(person::all_columns), comment_aggregates::all_columns, - creator_community_actions - .field(community_actions::received_ban) - .is_null() - .or( - creator_community_actions - .field(community_actions::ban_expires) - .gt(now), - ), - post_actions::like_score.nullable(), + coalesce( + creator_community_actions + .field(community_actions::received_ban) + .nullable() + .is_null() + .or( + creator_community_actions + .field(community_actions::ban_expires) + .nullable() + .gt(now), + ), + false, + ), + comment_actions::like_score.nullable(), aliases::person2.fields(person::all_columns).nullable(), )) }; @@ -114,10 +135,11 @@ fn queries<'a>() -> Queries< if !user.local_user.admin { query .inner_join( - community_moderator::table.on( - community_moderator::community_id + community_actions::table.on( + community_actions::community_id .eq(post::community_id) - .and(community_moderator::person_id.eq(user.person.id)), + .and(community_actions::person_id.eq(user.person.id)) + .and(community_actions::became_moderator.is_not_null()), ), ) .load::(&mut conn) @@ -167,10 +189,11 @@ impl CommentReportView { if !admin { query .inner_join( - community_moderator::table.on( - community_moderator::community_id + community_actions::table.on( + community_actions::community_id .eq(post::community_id) - .and(community_moderator::person_id.eq(my_person_id)), + .and(community_actions::person_id.eq(my_person_id)) + .and(community_actions::became_moderator.is_not_null()), ), ) .select(count(comment_report::id)) From c46ae9ae872513b163d2a876b206311ba1a37254 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Fri, 8 Mar 2024 20:16:33 +0000 Subject: [PATCH 049/232] comment_view --- crates/db_views/src/comment_view.rs | 227 +++++++++------------------- 1 file changed, 73 insertions(+), 154 deletions(-) diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs index a72d0b210..84c318bff 100644 --- a/crates/db_views/src/comment_view.rs +++ b/crates/db_views/src/comment_view.rs @@ -1,14 +1,10 @@ use crate::structs::{CommentView, LocalUserView}; -use chrono::{DateTime, Utc}; use diesel::{ - dsl::{exists, not}, + dsl::exists, pg::Pg, result::Error, - sql_types, BoolExpressionMethods, - BoxableExpression, ExpressionMethods, - IntoSql, JoinOnDsl, NullableExpressionMethods, PgTextExpressionMethods, @@ -17,25 +13,32 @@ use diesel::{ use diesel_async::RunQueryDsl; use diesel_ltree::{nlevel, subpath, Ltree, LtreeExtensions}; use lemmy_db_schema::{ + aliases::creator_community_actions, newtypes::{CommentId, CommunityId, LocalUserId, PersonId, PostId}, schema::{ comment, + comment_actions, comment_aggregates, - comment_like, - comment_saved, community, - community_block, - community_follower, - community_moderator, - community_person_ban, - instance_block, + community_actions, + instance_actions, local_user, local_user_language, person, - person_block, + person_actions, post, }, - utils::{fuzzy_search, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, + utils::{ + actions, + functions::coalesce, + fuzzy_search, + limit_and_offset, + DbConn, + DbPool, + ListFn, + Queries, + ReadFn, + }, CommentSortType, CommunityVisibility, ListingType, @@ -45,123 +48,63 @@ fn queries<'a>() -> Queries< impl ReadFn<'a, CommentView, (CommentId, Option)>, impl ListFn<'a, CommentView, CommentQuery<'a>>, > { - let is_creator_banned_from_community = exists( - community_person_ban::table.filter( - community::id - .eq(community_person_ban::community_id) - .and(community_person_ban::person_id.eq(comment::creator_id)), - ), - ); - - let is_saved = |person_id| { - comment_saved::table - .filter( - comment::id - .eq(comment_saved::comment_id) - .and(comment_saved::person_id.eq(person_id)), - ) - .select(comment_saved::published.nullable()) - .single_value() - }; - - let is_community_followed = |person_id| { - community_follower::table - .filter( - post::community_id - .eq(community_follower::community_id) - .and(community_follower::person_id.eq(person_id)), - ) - .select(community_follower::pending.nullable()) - .single_value() - }; - - let is_creator_blocked = |person_id| { - exists( - person_block::table.filter( - comment::creator_id - .eq(person_block::target_id) - .and(person_block::person_id.eq(person_id)), - ), - ) - }; - - let score = |person_id| { - comment_like::table - .filter( - comment::id - .eq(comment_like::comment_id) - .and(comment_like::person_id.eq(person_id)), - ) - .select(comment_like::score.nullable()) - .single_value() - }; - - let creator_is_moderator = exists( - community_moderator::table.filter( - community::id - .eq(community_moderator::community_id) - .and(community_moderator::person_id.eq(comment::creator_id)), - ), - ); - - let creator_is_admin = exists( - local_user::table.filter( - comment::creator_id - .eq(local_user::person_id) - .and(local_user::admin.eq(true)), - ), - ); - let all_joins = move |query: comment::BoxedQuery<'a, Pg>, my_person_id: Option| { - let score_selection: Box< - dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable>, - > = if let Some(person_id) = my_person_id { - Box::new(score(person_id)) - } else { - Box::new(None::.into_sql::>()) - }; - - let subscribed_type_selection: Box< - dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable>, - > = if let Some(person_id) = my_person_id { - Box::new(is_community_followed(person_id)) - } else { - Box::new(None::.into_sql::>()) - }; - - let is_saved_selection: Box< - dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable>, - > = if let Some(person_id) = my_person_id { - Box::new(is_saved(person_id)) - } else { - Box::new(None::>.into_sql::>()) - }; - - let is_creator_blocked_selection: Box> = - if let Some(person_id) = my_person_id { - Box::new(is_creator_blocked(person_id)) - } else { - Box::new(false.into_sql::()) - }; - query - .inner_join(person::table) + .inner_join(person::table.left_join(local_user::table)) .inner_join(post::table) .inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(comment_aggregates::table) + .left_join(actions( + community_actions::table, + my_person_id, + post::community_id, + )) + .left_join(actions( + comment_actions::table, + my_person_id, + comment_aggregates::comment_id, + )) + .left_join(actions( + person_actions::table, + my_person_id, + comment::creator_id, + )) + .left_join(actions( + instance_actions::table, + my_person_id, + community::instance_id, + )) + .left_join( + creator_community_actions.on( + creator_community_actions + .field(community_actions::person_id) + .eq(comment::creator_id) + .and( + creator_community_actions + .field(community_actions::community_id) + .eq(post::community_id), + ), + ), + ) .select(( comment::all_columns, person::all_columns, post::all_columns, community::all_columns, comment_aggregates::all_columns, - is_creator_banned_from_community, - creator_is_moderator, - creator_is_admin, - subscribed_type_selection, - is_saved_selection.is_not_null(), - is_creator_blocked_selection, - score_selection, + creator_community_actions + .field(community_actions::received_ban) + .nullable() + .is_not_null(), + creator_community_actions + .field(community_actions::became_moderator) + .nullable() + .is_not_null(), + coalesce(local_user::admin.nullable(), false), + community_actions::follow_pending.nullable(), + comment_actions::saved.nullable().is_not_null(), + person_actions::blocked.nullable().is_not_null(), + comment_actions::like_score.nullable(), )) }; @@ -180,7 +123,6 @@ fn queries<'a>() -> Queries< let my_local_user_id = options.local_user.map(|l| l.local_user.id); // The left join below will return None in this case - let person_id_join = my_person_id.unwrap_or(PersonId(-1)); let local_user_id_join = my_local_user_id.unwrap_or(LocalUserId(-1)); let mut query = all_joins(comment::table.into_boxed(), my_person_id); @@ -206,13 +148,7 @@ fn queries<'a>() -> Queries< } if let Some(listing_type) = options.listing_type { - let is_subscribed = exists( - community_follower::table.filter( - post::community_id - .eq(community_follower::community_id) - .and(community_follower::person_id.eq(person_id_join)), - ), - ); + let is_subscribed = community_actions::followed.is_not_null(); match listing_type { ListingType::Subscribed => query = query.filter(is_subscribed), // TODO could be this: and(community_follower::person_id.eq(person_id_join)), @@ -223,13 +159,7 @@ fn queries<'a>() -> Queries< } ListingType::All => query = query.filter(community::hidden.eq(false).or(is_subscribed)), ListingType::ModeratorView => { - query = query.filter(exists( - community_moderator::table.filter( - post::community_id - .eq(community_moderator::community_id) - .and(community_moderator::person_id.eq(person_id_join)), - ), - )); + query = query.filter(community_actions::became_moderator.is_not_null()); } } } @@ -237,14 +167,14 @@ fn queries<'a>() -> Queries< // If its saved only, then filter, and order by the saved time, not the comment creation time. if options.saved_only { query = query - .filter(is_saved(person_id_join).is_not_null()) - .then_order_by(is_saved(person_id_join).desc()); + .filter(comment_actions::saved.is_not_null()) + .then_order_by(comment_actions::saved.desc()); } if options.liked_only { - query = query.filter(score(person_id_join).eq(1)); + query = query.filter(comment_actions::like_score.eq(1)); } else if options.disliked_only { - query = query.filter(score(person_id_join).eq(-1)); + query = query.filter(comment_actions::like_score.eq(-1)); } if !options @@ -268,21 +198,10 @@ fn queries<'a>() -> Queries< )); // Don't show blocked communities or persons - query = query.filter(not(exists( - instance_block::table.filter( - community::instance_id - .eq(instance_block::instance_id) - .and(instance_block::person_id.eq(person_id_join)), - ), - ))); - query = query.filter(not(exists( - community_block::table.filter( - community::id - .eq(community_block::community_id) - .and(community_block::person_id.eq(person_id_join)), - ), - ))); - query = query.filter(not(is_creator_blocked(person_id_join))); + query = query + .filter(instance_actions::blocked.is_null()) + .filter(community_actions::blocked.is_null()) + .filter(person_actions::blocked.is_null()); }; // Hide comments in local only communities from unauthenticated users From 27bb4b1ee84867a08f0ac8fa96525a922ea06b3d Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Fri, 8 Mar 2024 20:28:34 +0000 Subject: [PATCH 050/232] post_report_view --- crates/db_views/src/post_report_view.rs | 57 +++++++++++++------------ 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/crates/db_views/src/post_report_view.rs b/crates/db_views/src/post_report_view.rs index ddd12d226..8bbe6015f 100644 --- a/crates/db_views/src/post_report_view.rs +++ b/crates/db_views/src/post_report_view.rs @@ -10,19 +10,18 @@ use diesel::{ }; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ - aliases, + aliases::{self, creator_community_actions}, newtypes::{CommunityId, PersonId, PostId, PostReportId}, schema::{ community, - community_moderator, - community_person_ban, + community_actions, person, post, + post_actions, post_aggregates, - post_like, post_report, }, - utils::{get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, + utils::{actions, get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, }; fn queries<'a>() -> Queries< @@ -35,33 +34,35 @@ fn queries<'a>() -> Queries< .inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(person::table.on(post_report::creator_id.eq(person::id))) .inner_join(aliases::person1.on(post::creator_id.eq(aliases::person1.field(person::id)))) - .left_join( - community_person_ban::table.on( - post::community_id - .eq(community_person_ban::community_id) - .and(community_person_ban::person_id.eq(post::creator_id)), - ), - ) - .left_join( - post_like::table.on( - post::id - .eq(post_like::post_id) - .and(post_like::person_id.eq(my_person_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())), ) + .left_join(actions(post_actions::table, Some(my_person_id), post::id)) + .left_join( + creator_community_actions.on( + creator_community_actions + .field(community_actions::person_id) + .eq(post::creator_id) + .and( + creator_community_actions + .field(community_actions::community_id) + .eq(post::community_id), + ), + ), + ) .select(( post_report::all_columns, post::all_columns, community::all_columns, person::all_columns, aliases::person1.fields(person::all_columns), - community_person_ban::community_id.nullable().is_not_null(), - post_like::score.nullable(), + creator_community_actions + .field(community_actions::received_ban) + .nullable() + .is_not_null(), + post_actions::like_score.nullable(), post_aggregates::all_columns, aliases::person2.fields(person::all_columns.nullable()), )) @@ -104,10 +105,11 @@ fn queries<'a>() -> Queries< if !user.local_user.admin { query .inner_join( - community_moderator::table.on( - community_moderator::community_id + community_actions::table.on( + community_actions::community_id .eq(post::community_id) - .and(community_moderator::person_id.eq(user.person.id)), + .and(community_actions::person_id.eq(user.person.id)) + .and(community_actions::became_moderator.is_not_null()), ), ) .load::(&mut conn) @@ -154,10 +156,11 @@ impl PostReportView { if !admin { query .inner_join( - community_moderator::table.on( - community_moderator::community_id + community_actions::table.on( + community_actions::community_id .eq(post::community_id) - .and(community_moderator::person_id.eq(my_person_id)), + .and(community_actions::person_id.eq(my_person_id)) + .and(community_actions::became_moderator.is_not_null()), ), ) .select(count(post_report::id)) From 2233feacf5aee5cac70a540f67b8382e0171a07e Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Fri, 8 Mar 2024 20:35:07 +0000 Subject: [PATCH 051/232] find and replace some selected values --- crates/db_views_actor/src/comment_reply_view.rs | 11 +++++++---- crates/db_views_actor/src/person_mention_view.rs | 11 +++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/crates/db_views_actor/src/comment_reply_view.rs b/crates/db_views_actor/src/comment_reply_view.rs index 6d122291a..805e58eea 100644 --- a/crates/db_views_actor/src/comment_reply_view.rs +++ b/crates/db_views_actor/src/comment_reply_view.rs @@ -153,11 +153,14 @@ fn queries<'a>() -> Queries< aliases::person1.fields(person::all_columns), comment_aggregates::all_columns, is_creator_banned_from_community, - creator_is_moderator, - creator_is_admin, - subscribed_type_selection, + creator_community_actions + .field(community_actions::became_moderator) + .nullable() + .is_not_null(), + coalesce(local_user::admin, false), + community_actions::follow_pending.nullable(), is_saved_selection, - is_creator_blocked_selection, + person_actions::blocked.nullable().is_not_null(), score_selection, )) }; diff --git a/crates/db_views_actor/src/person_mention_view.rs b/crates/db_views_actor/src/person_mention_view.rs index 21a1bd0de..c80f96f61 100644 --- a/crates/db_views_actor/src/person_mention_view.rs +++ b/crates/db_views_actor/src/person_mention_view.rs @@ -153,11 +153,14 @@ fn queries<'a>() -> Queries< aliases::person1.fields(person::all_columns), comment_aggregates::all_columns, is_creator_banned_from_community, - creator_is_moderator, - creator_is_admin, - subscribed_type_selection, + creator_community_actions + .field(community_actions::became_moderator) + .nullable() + .is_not_null(), + coalesce(local_user::admin, false), + community_actions::follow_pending.nullable(), is_saved_selection, - is_creator_blocked_selection, + person_actions::blocked.nullable().is_not_null(), score_selection, )) }; From af5929877e5b650c4ffa9a4ca92d3ccf0b826bca Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sat, 9 Mar 2024 18:25:34 +0000 Subject: [PATCH 052/232] private_message_view --- Cargo.lock | 8 +++ Cargo.toml | 1 + crates/db_schema/Cargo.toml | 1 + crates/db_schema/src/utils.rs | 24 ++++++--- crates/db_views/src/private_message_view.rs | 60 +++++++++------------ 5 files changed, 53 insertions(+), 41 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b7990d250..ca8466be9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1441,6 +1441,13 @@ dependencies = [ "tokio-postgres", ] +[[package]] +name = "diesel-bind-if-some" +version = "0.1.0" +dependencies = [ + "diesel", +] + [[package]] name = "diesel-derive-enum" version = "2.1.0" @@ -2695,6 +2702,7 @@ dependencies = [ "deadpool 0.10.0", "diesel", "diesel-async", + "diesel-bind-if-some", "diesel-derive-enum", "diesel-derive-newtype", "diesel_ltree", diff --git a/Cargo.toml b/Cargo.toml index 037d03919..1c79bf6c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -164,6 +164,7 @@ moka = { version = "0.12.4", features = ["future"] } i-love-jesus = { version = "0.1.0" } clap = { version = "4.4.18", features = ["derive"] } pretty_assertions = "1.4.0" +diesel-bind-if-some = { path = "../diesel-utils/crates/diesel-bind-if-some" } [dependencies] lemmy_api = { workspace = true } diff --git a/crates/db_schema/Cargo.toml b/crates/db_schema/Cargo.toml index d0d66d69f..3f26d64c2 100644 --- a/crates/db_schema/Cargo.toml +++ b/crates/db_schema/Cargo.toml @@ -80,6 +80,7 @@ rustls = { workspace = true, optional = true } uuid = { workspace = true, features = ["v4"] } i-love-jesus = { workspace = true, optional = true } anyhow = { workspace = true } +diesel-bind-if-some = { workspace = true } [dev-dependencies] serial_test = { workspace = true } diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index c9dd16d75..caf7fc25e 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -40,6 +40,7 @@ use diesel_async::{ }, SimpleAsyncConnection, }; +use diesel_bind_if_some::BindIfSome; use diesel_migrations::EmbeddedMigrations; use futures_util::{future::BoxFuture, Future, FutureExt}; use i_love_jesus::CursorKey; @@ -487,29 +488,38 @@ pub fn now() -> AsExprOf { diesel::dsl::now.into_sql::() } -// TODO: BindIfSome -pub fn actions( +pub fn actions( actions_table: T, - person_id: Option, + person_id: Option

, target_id: C, -) -> dsl::On, Option>, dsl::Eq>> +) -> dsl::On< + T, + dsl::And< + dsl::Eq, BindIfSome>>, + dsl::Eq, + >, +> where + P: AsExpression, T: Table, K0: Default + Expression + Sized, dsl::Nullable: diesel::ExpressionMethods, as Expression>::SqlType: SqlType, - Option: AsExpression< as Expression>::SqlType>, + BindIfSome>: + AsExpression< as Expression>::SqlType>, K1: Default + diesel::ExpressionMethods, ::SqlType: SqlType, C: AsExpression<::SqlType>, - dsl::Eq, Option>: + dsl::Eq, BindIfSome>>: Expression>, dsl::Eq: Expression, { actions_table.on( K0::default() .nullable() - .eq(person_id) + .eq(BindIfSome( + person_id.map(|id| id.into_sql::()), + )) .and(K1::default().eq(target_id)), ) } diff --git a/crates/db_views/src/private_message_view.rs b/crates/db_views/src/private_message_view.rs index a3e2469c9..2555b6b66 100644 --- a/crates/db_views/src/private_message_view.rs +++ b/crates/db_views/src/private_message_view.rs @@ -12,8 +12,8 @@ use diesel_async::RunQueryDsl; use lemmy_db_schema::{ aliases, newtypes::{PersonId, PrivateMessageId}, - schema::{instance_block, person, person_block, private_message}, - utils::{get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, + schema::{instance_actions, person, person_actions, private_message}, + utils::{actions, get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, }; use tracing::debug; @@ -27,20 +27,16 @@ fn queries<'a>() -> Queries< .inner_join( aliases::person1.on(private_message::recipient_id.eq(aliases::person1.field(person::id))), ) - .left_join( - person_block::table.on( - private_message::creator_id - .eq(person_block::target_id) - .and(person_block::person_id.eq(aliases::person1.field(person::id))), - ), - ) - .left_join( - instance_block::table.on( - person::instance_id - .eq(instance_block::instance_id) - .and(instance_block::person_id.eq(aliases::person1.field(person::id))), - ), - ) + .left_join(actions( + person_actions::table, + Some(aliases::person1.field(person::id)), + private_message::creator_id, + )) + .left_join(actions( + instance_actions::table, + Some(aliases::person1.field(person::id)), + person::instance_id, + )) }; let selection = ( @@ -62,9 +58,9 @@ fn queries<'a>() -> Queries< let mut query = all_joins(private_message::table.into_boxed()) .select(selection) // Dont show replies from blocked users - .filter(person_block::person_id.is_null()) + .filter(person_actions::blocked.is_null()) // Dont show replies from blocked instances - .filter(instance_block::person_id.is_null()); + .filter(instance_actions::blocked.is_null()); // If its unread, I only want the ones to me if options.unread_only { @@ -127,24 +123,20 @@ impl PrivateMessageView { private_message::table // Necessary to get the senders instance_id .inner_join(person::table.on(private_message::creator_id.eq(person::id))) - .left_join( - person_block::table.on( - private_message::creator_id - .eq(person_block::target_id) - .and(person_block::person_id.eq(my_person_id)), - ), - ) - .left_join( - instance_block::table.on( - person::instance_id - .eq(instance_block::instance_id) - .and(instance_block::person_id.eq(my_person_id)), - ), - ) + .left_join(actions( + person_actions::table, + Some(my_person_id), + private_message::creator_id, + )) + .left_join(actions( + instance_actions::table, + Some(my_person_id), + person::instance_id, + )) // Dont count replies from blocked users - .filter(person_block::person_id.is_null()) + .filter(person_actions::blocked.is_null()) // Dont count replies from blocked instances - .filter(instance_block::person_id.is_null()) + .filter(instance_actions::blocked.is_null()) .filter(private_message::read.eq(false)) .filter(private_message::recipient_id.eq(my_person_id)) .filter(private_message::deleted.eq(false)) From 40916064aa1e815b143f1584b8ccb56068b1a5d0 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sat, 9 Mar 2024 18:30:07 +0000 Subject: [PATCH 053/232] vote_view --- crates/db_views/src/vote_view.rs | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/crates/db_views/src/vote_view.rs b/crates/db_views/src/vote_view.rs index 723c188f5..7a3d44b1d 100644 --- a/crates/db_views/src/vote_view.rs +++ b/crates/db_views/src/vote_view.rs @@ -1,9 +1,9 @@ use crate::structs::VoteView; -use diesel::{result::Error, ExpressionMethods, QueryDsl}; +use diesel::{result::Error, ExpressionMethods, NullableExpressionMethods, QueryDsl}; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ newtypes::{CommentId, PostId}, - schema::{comment_like, person, post_like}, + schema::{comment_actions, person, post_actions}, utils::{get_conn, limit_and_offset, DbPool}, }; @@ -17,11 +17,15 @@ impl VoteView { let conn = &mut get_conn(pool).await?; let (limit, offset) = limit_and_offset(page, limit)?; - post_like::table + post_actions::table .inner_join(person::table) - .filter(post_like::post_id.eq(post_id)) - .select((person::all_columns, post_like::score)) - .order_by(post_like::score) + .filter(post_actions::post_id.eq(post_id)) + .filter(post_actions::like_score.is_not_null()) + .select(( + person::all_columns, + post_actions::like_score.assume_not_null(), + )) + .order_by(post_actions::like_score) .limit(limit) .offset(offset) .load::(conn) @@ -37,11 +41,15 @@ impl VoteView { let conn = &mut get_conn(pool).await?; let (limit, offset) = limit_and_offset(page, limit)?; - comment_like::table + comment_actions::table .inner_join(person::table) - .filter(comment_like::comment_id.eq(comment_id)) - .select((person::all_columns, comment_like::score)) - .order_by(comment_like::score) + .filter(comment_actions::comment_id.eq(comment_id)) + .filter(comment_actions::like_score.is_not_null()) + .select(( + person::all_columns, + comment_actions::like_score.assume_not_null(), + )) + .order_by(comment_actions::like_score) .limit(limit) .offset(offset) .load::(conn) From 0b3090b46dedab3220cedfd454e325cab1d76135 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sat, 9 Mar 2024 20:43:25 +0000 Subject: [PATCH 054/232] comment_reply_view --- .../db_views_actor/src/comment_reply_view.rs | 182 ++++++------------ 1 file changed, 57 insertions(+), 125 deletions(-) diff --git a/crates/db_views_actor/src/comment_reply_view.rs b/crates/db_views_actor/src/comment_reply_view.rs index 805e58eea..3cced4f29 100644 --- a/crates/db_views_actor/src/comment_reply_view.rs +++ b/crates/db_views_actor/src/comment_reply_view.rs @@ -1,37 +1,40 @@ use crate::structs::CommentReplyView; use diesel::{ - dsl::exists, pg::Pg, result::Error, - sql_types, BoolExpressionMethods, - BoxableExpression, ExpressionMethods, - IntoSql, JoinOnDsl, NullableExpressionMethods, QueryDsl, }; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ - aliases, + aliases::{self, creator_community_actions}, newtypes::{CommentReplyId, PersonId}, schema::{ comment, + comment_actions, comment_aggregates, - comment_like, comment_reply, - comment_saved, community, - community_follower, - community_moderator, - community_person_ban, + community_actions, local_user, person, - person_block, + person_actions, post, }, - utils::{get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, + utils::{ + actions, + functions::coalesce, + get_conn, + limit_and_offset, + DbConn, + DbPool, + ListFn, + Queries, + ReadFn, + }, CommentSortType, }; @@ -39,111 +42,39 @@ fn queries<'a>() -> Queries< impl ReadFn<'a, CommentReplyView, (CommentReplyId, Option)>, impl ListFn<'a, CommentReplyView, CommentReplyQuery>, > { - let is_creator_banned_from_community = exists( - community_person_ban::table.filter( - community::id - .eq(community_person_ban::community_id) - .and(community_person_ban::person_id.eq(comment::creator_id)), - ), - ); - - let is_saved = |person_id| { - exists( - comment_saved::table.filter( - comment::id - .eq(comment_saved::comment_id) - .and(comment_saved::person_id.eq(person_id)), - ), - ) - }; - - let is_community_followed = |person_id| { - community_follower::table - .filter( - post::community_id - .eq(community_follower::community_id) - .and(community_follower::person_id.eq(person_id)), - ) - .select(community_follower::pending.nullable()) - .single_value() - }; - - let is_creator_blocked = |person_id| { - exists( - person_block::table.filter( - comment::creator_id - .eq(person_block::target_id) - .and(person_block::person_id.eq(person_id)), - ), - ) - }; - - let score = |person_id| { - comment_like::table - .filter( - comment::id - .eq(comment_like::comment_id) - .and(comment_like::person_id.eq(person_id)), - ) - .select(comment_like::score.nullable()) - .single_value() - }; - - let creator_is_moderator = exists( - community_moderator::table.filter( - community::id - .eq(community_moderator::community_id) - .and(community_moderator::person_id.eq(comment::creator_id)), - ), - ); - - let creator_is_admin = exists( - local_user::table.filter( - comment::creator_id - .eq(local_user::person_id) - .and(local_user::admin.eq(true)), - ), - ); - let all_joins = move |query: comment_reply::BoxedQuery<'a, Pg>, my_person_id: Option| { - let score_selection: Box< - dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable>, - > = if let Some(person_id) = my_person_id { - Box::new(score(person_id)) - } else { - Box::new(None::.into_sql::>()) - }; - - let subscribed_type_selection: Box< - dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable>, - > = if let Some(person_id) = my_person_id { - Box::new(is_community_followed(person_id)) - } else { - Box::new(None::.into_sql::>()) - }; - - let is_saved_selection: Box> = - if let Some(person_id) = my_person_id { - Box::new(is_saved(person_id)) - } else { - Box::new(false.into_sql::()) - }; - - let is_creator_blocked_selection: Box> = - if let Some(person_id) = my_person_id { - Box::new(is_creator_blocked(person_id)) - } else { - Box::new(false.into_sql::()) - }; - query - .inner_join(comment::table) - .inner_join(person::table.on(comment::creator_id.eq(person::id))) - .inner_join(post::table.on(comment::post_id.eq(post::id))) - .inner_join(community::table.on(post::community_id.eq(community::id))) + .inner_join( + comment::table + .inner_join(person::table.left_join(local_user::table)) + .inner_join(post::table.inner_join(community::table)) + .inner_join(comment_aggregates::table), + ) .inner_join(aliases::person1) - .inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id))) + .left_join(actions(comment_actions::table, my_person_id, comment::id)) + .left_join(actions( + community_actions::table, + my_person_id, + post::community_id, + )) + .left_join(actions( + person_actions::table, + my_person_id, + comment::creator_id, + )) + .left_join( + creator_community_actions.on( + creator_community_actions + .field(community_actions::person_id) + .eq(comment::creator_id) + .and( + creator_community_actions + .field(community_actions::community_id) + .eq(post::community_id), + ), + ), + ) .select(( comment_reply::all_columns, comment::all_columns, @@ -152,16 +83,19 @@ fn queries<'a>() -> Queries< community::all_columns, aliases::person1.fields(person::all_columns), comment_aggregates::all_columns, - is_creator_banned_from_community, + creator_community_actions + .field(community_actions::received_ban) + .nullable() + .is_not_null(), creator_community_actions .field(community_actions::became_moderator) .nullable() .is_not_null(), - coalesce(local_user::admin, false), + coalesce(local_user::admin.nullable(), false), community_actions::follow_pending.nullable(), - is_saved_selection, + comment_actions::saved.nullable().is_not_null(), person_actions::blocked.nullable().is_not_null(), - score_selection, + comment_actions::like_score.nullable(), )) }; @@ -233,15 +167,13 @@ impl CommentReplyView { comment_reply::table .inner_join(comment::table) - .left_join( - person_block::table.on( - comment::creator_id - .eq(person_block::target_id) - .and(person_block::person_id.eq(my_person_id)), - ), - ) + .left_join(actions( + person_actions::table, + Some(my_person_id), + comment::creator_id, + )) // Dont count replies from blocked users - .filter(person_block::person_id.is_null()) + .filter(person_actions::blocked.is_null()) .filter(comment_reply::recipient_id.eq(my_person_id)) .filter(comment_reply::read.eq(false)) .filter(comment::deleted.eq(false)) From 9bde05435d0f1fa3c0f308df1762848334356e03 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sat, 9 Mar 2024 21:01:38 +0000 Subject: [PATCH 055/232] some action views --- .../src/community_block_view.rs | 9 +++-- .../src/community_follower_view.rs | 21 +++++----- .../src/community_moderator_view.rs | 39 +++++++++---------- .../src/community_person_ban_view.rs | 8 ++-- 4 files changed, 40 insertions(+), 37 deletions(-) diff --git a/crates/db_views_actor/src/community_block_view.rs b/crates/db_views_actor/src/community_block_view.rs index c7d3d1836..15b385105 100644 --- a/crates/db_views_actor/src/community_block_view.rs +++ b/crates/db_views_actor/src/community_block_view.rs @@ -3,21 +3,22 @@ use diesel::{result::Error, ExpressionMethods, QueryDsl}; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ newtypes::PersonId, - schema::{community, community_block, person}, + schema::{community, community_actions, person}, utils::{get_conn, DbPool}, }; impl CommunityBlockView { pub async fn for_person(pool: &mut DbPool<'_>, person_id: PersonId) -> Result, Error> { let conn = &mut get_conn(pool).await?; - community_block::table + community_actions::table .inner_join(person::table) .inner_join(community::table) .select((person::all_columns, community::all_columns)) - .filter(community_block::person_id.eq(person_id)) + .filter(community_actions::person_id.eq(person_id)) + .filter(community_actions::blocked.is_not_null()) .filter(community::deleted.eq(false)) .filter(community::removed.eq(false)) - .order_by(community_block::published) + .order_by(community_actions::blocked) .load::(conn) .await } diff --git a/crates/db_views_actor/src/community_follower_view.rs b/crates/db_views_actor/src/community_follower_view.rs index b2eeda29e..c935bb218 100644 --- a/crates/db_views_actor/src/community_follower_view.rs +++ b/crates/db_views_actor/src/community_follower_view.rs @@ -9,7 +9,7 @@ use diesel::{ use diesel_async::RunQueryDsl; use lemmy_db_schema::{ newtypes::{CommunityId, DbUrl, InstanceId, PersonId}, - schema::{community, community_follower, person}, + schema::{community, community_actions, person}, utils::{functions::coalesce, get_conn, DbPool}, }; @@ -27,13 +27,13 @@ impl CommunityFollowerView { // that would work for all instances that support fully shared inboxes. // It would be a bit more complicated though to keep it in sync. - community_follower::table + community_actions::table .inner_join(community::table) .inner_join(person::table) .filter(person::instance_id.eq(instance_id)) .filter(community::local) // this should be a no-op since community_followers table only has local-person+remote-community or remote-person+local-community .filter(not(person::local)) - .filter(community_follower::published.gt(published_since.naive_utc())) + .filter(community_actions::followed.gt(published_since.naive_utc())) .select(( community::id, coalesce(person::shared_inbox_url, person::inbox_url), @@ -47,8 +47,9 @@ impl CommunityFollowerView { community_id: CommunityId, ) -> Result, Error> { let conn = &mut get_conn(pool).await?; - let res = community_follower::table - .filter(community_follower::community_id.eq(community_id)) + let res = community_actions::table + .filter(community_actions::community_id.eq(community_id)) + .filter(community_actions::followed.is_not_null()) .filter(not(person::local)) .inner_join(person::table) .select(coalesce(person::shared_inbox_url, person::inbox_url)) @@ -63,8 +64,9 @@ impl CommunityFollowerView { community_id: CommunityId, ) -> Result { let conn = &mut get_conn(pool).await?; - let res = community_follower::table - .filter(community_follower::community_id.eq(community_id)) + let res = community_actions::table + .filter(community_actions::community_id.eq(community_id)) + .filter(community_actions::followed.is_not_null()) .select(count_star()) .first::(conn) .await?; @@ -74,11 +76,12 @@ impl CommunityFollowerView { pub async fn for_person(pool: &mut DbPool<'_>, person_id: PersonId) -> Result, Error> { let conn = &mut get_conn(pool).await?; - community_follower::table + community_actions::table .inner_join(community::table) .inner_join(person::table) .select((community::all_columns, person::all_columns)) - .filter(community_follower::person_id.eq(person_id)) + .filter(community_actions::person_id.eq(person_id)) + .filter(community_actions::followed.is_not_null()) .filter(community::deleted.eq(false)) .filter(community::removed.eq(false)) .order_by(community::title) diff --git a/crates/db_views_actor/src/community_moderator_view.rs b/crates/db_views_actor/src/community_moderator_view.rs index 808fc0340..c0345ef3e 100644 --- a/crates/db_views_actor/src/community_moderator_view.rs +++ b/crates/db_views_actor/src/community_moderator_view.rs @@ -3,7 +3,7 @@ use diesel::{dsl::exists, result::Error, select, ExpressionMethods, QueryDsl}; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ newtypes::{CommunityId, PersonId}, - schema::{community, community_moderator, person}, + schema::{community, community_actions, person}, utils::{get_conn, DbPool}, CommunityVisibility, }; @@ -14,16 +14,11 @@ impl CommunityModeratorView { find_community_id: CommunityId, find_person_id: PersonId, ) -> Result { - use lemmy_db_schema::schema::community_moderator::dsl::{ - community_id, - community_moderator, - person_id, - }; let conn = &mut get_conn(pool).await?; select(exists( - community_moderator - .filter(community_id.eq(find_community_id)) - .filter(person_id.eq(find_person_id)), + community_actions::table + .find((find_person_id, find_community_id)) + .filter(community_actions::became_moderator.is_not_null()), )) .get_result::(conn) .await @@ -33,10 +28,11 @@ impl CommunityModeratorView { pool: &mut DbPool<'_>, find_person_id: PersonId, ) -> Result { - use lemmy_db_schema::schema::community_moderator::dsl::{community_moderator, person_id}; let conn = &mut get_conn(pool).await?; select(exists( - community_moderator.filter(person_id.eq(find_person_id)), + community_actions::table + .filter(community_actions::person_id.eq(find_person_id)) + .filter(community_actions::became_moderator.is_not_null()), )) .get_result::(conn) .await @@ -47,12 +43,13 @@ impl CommunityModeratorView { community_id: CommunityId, ) -> Result, Error> { let conn = &mut get_conn(pool).await?; - community_moderator::table + community_actions::table .inner_join(community::table) .inner_join(person::table) - .filter(community_moderator::community_id.eq(community_id)) + .filter(community_actions::community_id.eq(community_id)) + .filter(community_actions::became_moderator.is_not_null()) .select((community::all_columns, person::all_columns)) - .order_by(community_moderator::published) + .order_by(community_actions::became_moderator) .load::(conn) .await } @@ -63,10 +60,11 @@ impl CommunityModeratorView { is_authenticated: bool, ) -> Result, Error> { let conn = &mut get_conn(pool).await?; - let mut query = community_moderator::table + let mut query = community_actions::table .inner_join(community::table) .inner_join(person::table) - .filter(community_moderator::person_id.eq(person_id)) + .filter(community_actions::person_id.eq(person_id)) + .filter(community_actions::became_moderator.is_not_null()) .filter(community::deleted.eq(false)) .filter(community::removed.eq(false)) .select((community::all_columns, person::all_columns)) @@ -81,16 +79,17 @@ impl CommunityModeratorView { /// Ideally this should be a group by, but diesel doesn't support it yet pub async fn get_community_first_mods(pool: &mut DbPool<'_>) -> Result, Error> { let conn = &mut get_conn(pool).await?; - community_moderator::table + community_actions::table .inner_join(community::table) .inner_join(person::table) + .filter(community_actions::became_moderator.is_not_null()) .select((community::all_columns, person::all_columns)) // A hacky workaround instead of group_bys // https://stackoverflow.com/questions/24042359/how-to-join-only-one-row-in-joined-table-with-postgres - .distinct_on(community_moderator::community_id) + .distinct_on(community_actions::community_id) .order_by(( - community_moderator::community_id, - community_moderator::person_id, + community_actions::community_id, + community_actions::person_id, )) .load::(conn) .await diff --git a/crates/db_views_actor/src/community_person_ban_view.rs b/crates/db_views_actor/src/community_person_ban_view.rs index 712bb2d3a..66062d243 100644 --- a/crates/db_views_actor/src/community_person_ban_view.rs +++ b/crates/db_views_actor/src/community_person_ban_view.rs @@ -3,7 +3,7 @@ use diesel::{dsl::exists, result::Error, select, ExpressionMethods, QueryDsl}; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ newtypes::{CommunityId, PersonId}, - schema::community_person_ban, + schema::community_actions, utils::{get_conn, DbPool}, }; @@ -15,9 +15,9 @@ impl CommunityPersonBanView { ) -> Result { let conn = &mut get_conn(pool).await?; select(exists( - community_person_ban::table - .filter(community_person_ban::community_id.eq(from_community_id)) - .filter(community_person_ban::person_id.eq(from_person_id)), + community_actions::table + .find((from_person_id, from_community_id)) + .filter(community_actions::received_ban.is_not_null()), )) .get_result::(conn) .await From 5c68ec08be6ec57d571babcb8b626b068f3dd07f Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sun, 10 Mar 2024 02:39:52 +0000 Subject: [PATCH 056/232] action_query, find_action --- .../src/aggregates/person_post_aggregates.rs | 6 +-- crates/db_schema/src/impls/community.rs | 19 +++---- crates/db_schema/src/impls/community_block.rs | 11 ++--- crates/db_schema/src/impls/instance_block.rs | 11 ++--- crates/db_schema/src/impls/local_user.rs | 19 +++---- crates/db_schema/src/impls/person.rs | 5 +- crates/db_schema/src/impls/person_block.rs | 11 ++--- crates/db_schema/src/utils.rs | 49 ++++++++++++++++--- crates/db_views/src/post_view.rs | 6 +-- crates/db_views/src/vote_view.rs | 8 ++- .../src/community_block_view.rs | 5 +- .../src/community_follower_view.rs | 11 ++--- .../src/community_moderator_view.rs | 25 ++++------ .../src/community_person_ban_view.rs | 7 +-- 14 files changed, 100 insertions(+), 93 deletions(-) diff --git a/crates/db_schema/src/aggregates/person_post_aggregates.rs b/crates/db_schema/src/aggregates/person_post_aggregates.rs index 53dc4ed4e..b959a5abd 100644 --- a/crates/db_schema/src/aggregates/person_post_aggregates.rs +++ b/crates/db_schema/src/aggregates/person_post_aggregates.rs @@ -2,7 +2,7 @@ use crate::{ aggregates::structs::{PersonPostAggregates, PersonPostAggregatesForm}, newtypes::{PersonId, PostId}, schema::post_actions, - utils::{get_conn, now, DbPool}, + utils::{find_action, get_conn, now, DbPool}, }; use diesel::{ dsl, @@ -50,9 +50,7 @@ impl PersonPostAggregates { post_id_: PostId, ) -> Result { let conn = &mut get_conn(pool).await?; - post_actions::table - .find((person_id_, post_id_)) - .filter(post_actions::read_comments.is_not_null()) + find_action(post_actions::read_comments, (person_id_, post_id_)) .select(Self::as_select_unwrap()) .first::(conn) .await diff --git a/crates/db_schema/src/impls/community.rs b/crates/db_schema/src/impls/community.rs index a976bb138..11f648612 100644 --- a/crates/db_schema/src/impls/community.rs +++ b/crates/db_schema/src/impls/community.rs @@ -17,7 +17,7 @@ use crate::{ post::Post, }, traits::{ApubActor, Bannable, Crud, Followable, Joinable}, - utils::{functions::lower, get_conn, now, DbPool}, + utils::{action_query, find_action, functions::lower, get_conn, now, DbPool}, SubscribedType, }; use chrono::{DateTime, Utc}; @@ -227,9 +227,8 @@ impl CommunityModerator { for_person_id: PersonId, ) -> Result, Error> { let conn = &mut get_conn(pool).await?; - community_actions::table + action_query(community_actions::became_moderator) .filter(community_actions::person_id.eq(for_person_id)) - .filter(community_actions::became_moderator.is_not_null()) .select(community_actions::community_id) .load::(conn) .await @@ -336,9 +335,8 @@ impl CommunityFollower { ) -> Result { let conn = &mut get_conn(pool).await?; select(exists( - community_actions::table - .filter(community_actions::community_id.eq(remote_community_id)) - .filter(community_actions::followed.is_not_null()), + action_query(community_actions::followed) + .filter(community_actions::community_id.eq(remote_community_id)), )) .get_result(conn) .await @@ -380,11 +378,10 @@ impl Followable for CommunityFollower { person_id: PersonId, ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::update( - community_actions::table - .find((person_id, community_id)) - .filter(community_actions::follow_pending.is_not_null()), - ) + diesel::update(find_action( + community_actions::follow_pending, + (person_id, community_id), + )) .set(community_actions::follow_pending.eq(Some(false))) .returning(Self::as_select_unwrap()) .get_result::(conn) diff --git a/crates/db_schema/src/impls/community_block.rs b/crates/db_schema/src/impls/community_block.rs index 0d015dc56..4b5b05605 100644 --- a/crates/db_schema/src/impls/community_block.rs +++ b/crates/db_schema/src/impls/community_block.rs @@ -3,7 +3,7 @@ use crate::{ schema::community_actions, source::community_block::{CommunityBlock, CommunityBlockForm}, traits::Blockable, - utils::{get_conn, now, DbPool}, + utils::{find_action, get_conn, now, DbPool}, }; use chrono::{DateTime, Utc}; use diesel::{ @@ -35,11 +35,10 @@ impl CommunityBlock { for_community_id: CommunityId, ) -> Result { let conn = &mut get_conn(pool).await?; - select(exists( - community_actions::table - .find((for_person_id, for_community_id)) - .filter(community_actions::blocked.is_not_null()), - )) + select(exists(find_action( + community_actions::blocked, + (for_person_id, for_community_id), + ))) .get_result(conn) .await } diff --git a/crates/db_schema/src/impls/instance_block.rs b/crates/db_schema/src/impls/instance_block.rs index f6f92b4bd..6076cca47 100644 --- a/crates/db_schema/src/impls/instance_block.rs +++ b/crates/db_schema/src/impls/instance_block.rs @@ -3,7 +3,7 @@ use crate::{ schema::instance_actions, source::instance_block::{InstanceBlock, InstanceBlockForm}, traits::Blockable, - utils::{get_conn, now, DbPool}, + utils::{find_action, get_conn, now, DbPool}, }; use chrono::{DateTime, Utc}; use diesel::{ @@ -35,11 +35,10 @@ impl InstanceBlock { for_instance_id: InstanceId, ) -> Result { let conn = &mut get_conn(pool).await?; - select(exists( - instance_actions::table - .find((for_person_id, for_instance_id)) - .filter(instance_actions::blocked.is_not_null()), - )) + select(exists(find_action( + instance_actions::blocked, + (for_person_id, for_instance_id), + ))) .get_result(conn) .await } diff --git a/crates/db_schema/src/impls/local_user.rs b/crates/db_schema/src/impls/local_user.rs index 5afc0d0ed..bbbc016f4 100644 --- a/crates/db_schema/src/impls/local_user.rs +++ b/crates/db_schema/src/impls/local_user.rs @@ -7,6 +7,7 @@ use crate::{ }, traits::Crud, utils::{ + action_query, functions::{coalesce, lower}, get_conn, now, @@ -109,49 +110,43 @@ impl LocalUser { }; let conn = &mut get_conn(pool).await?; - let followed_communities = community_actions::table + let followed_communities = action_query(community_actions::followed) .filter(community_actions::person_id.eq(person_id_)) - .filter(community_actions::followed.is_not_null()) .inner_join(community::table.on(community_actions::community_id.eq(community::id))) .select(community::actor_id) .get_results(conn) .await?; - let saved_posts = post_actions::table + let saved_posts = action_query(post_actions::saved) .filter(post_actions::person_id.eq(person_id_)) - .filter(post_actions::saved.is_not_null()) .inner_join(post::table.on(post_actions::post_id.eq(post::id))) .select(post::ap_id) .get_results(conn) .await?; - let saved_comments = comment_actions::table + let saved_comments = action_query(comment_actions::saved) .filter(comment_actions::person_id.eq(person_id_)) - .filter(comment_actions::saved.is_not_null()) .inner_join(comment::table.on(comment_actions::comment_id.eq(comment::id))) .select(comment::ap_id) .get_results(conn) .await?; - let blocked_communities = community_actions::table + let blocked_communities = action_query(community_actions::blocked) .filter(community_actions::person_id.eq(person_id_)) - .filter(community_actions::blocked.is_not_null()) .inner_join(community::table) .select(community::actor_id) .get_results(conn) .await?; - let blocked_users = person_actions::table + let blocked_users = action_query(person_actions::blocked) .filter(person_actions::person_id.eq(person_id_)) - .filter(person_actions::blocked.is_not_null()) .inner_join(person::table.on(person_actions::target_id.eq(person::id))) .select(person::actor_id) .get_results(conn) .await?; - let blocked_instances = instance_actions::table + let blocked_instances = action_query(instance_actions::blocked) .filter(instance_actions::person_id.eq(person_id_)) - .filter(instance_actions::blocked.is_not_null()) .inner_join(instance::table) .select(instance::domain) .get_results(conn) diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs index f4fd94a3a..f7c3b9192 100644 --- a/crates/db_schema/src/impls/person.rs +++ b/crates/db_schema/src/impls/person.rs @@ -9,7 +9,7 @@ use crate::{ PersonUpdateForm, }, traits::{ApubActor, Crud, Followable}, - utils::{functions::lower, get_conn, naive_now, now, DbPool}, + utils::{action_query, functions::lower, get_conn, naive_now, now, DbPool}, }; use chrono::{DateTime, Utc}; use diesel::{ @@ -231,10 +231,9 @@ impl PersonFollower { for_person_id: PersonId, ) -> Result, Error> { let conn = &mut get_conn(pool).await?; - person_actions::table + action_query(person_actions::followed) .inner_join(person::table.on(person_actions::person_id.eq(person::id))) .filter(person_actions::target_id.eq(for_person_id)) - .filter(person_actions::followed.is_not_null()) .select(person::all_columns) .load(conn) .await diff --git a/crates/db_schema/src/impls/person_block.rs b/crates/db_schema/src/impls/person_block.rs index 15c4d721a..cabfcaf21 100644 --- a/crates/db_schema/src/impls/person_block.rs +++ b/crates/db_schema/src/impls/person_block.rs @@ -3,7 +3,7 @@ use crate::{ schema::person_actions, source::person_block::{PersonBlock, PersonBlockForm}, traits::Blockable, - utils::{get_conn, now, DbPool}, + utils::{find_action, get_conn, now, DbPool}, }; use chrono::{DateTime, Utc}; use diesel::{ @@ -36,11 +36,10 @@ impl PersonBlock { for_recipient_id: PersonId, ) -> Result { let conn = &mut get_conn(pool).await?; - select(exists( - person_actions::table - .find((for_person_id, for_recipient_id)) - .filter(person_actions::blocked.is_not_null()), - )) + select(exists(find_action( + person_actions::blocked, + (for_person_id, for_recipient_id), + ))) .get_result(conn) .await } diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index caf7fc25e..45ffc811b 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -1,7 +1,7 @@ use crate::{ diesel::Connection, diesel_migrations::MigrationHarness, - newtypes::{DbUrl, PersonId}, + newtypes::DbUrl, CommentSortType, SortType, }; @@ -14,15 +14,15 @@ use diesel::{ helper_types::AsExprOf, pg::Pg, query_builder::{Query, QueryFragment}, - query_dsl::methods::LimitDsl, - query_source::AliasSource, + query_dsl::methods::{FilterDsl, FindDsl, LimitDsl}, result::{ ConnectionError, ConnectionResult, Error::{self as DieselError, QueryBuilderError}, }, - sql_types::{self, SqlType, Timestamptz}, + sql_types::{self, SingleValue, SqlType, Timestamptz}, BoolExpressionMethods, + Column, Expression, ExpressionMethods, IntoSql, @@ -517,9 +517,7 @@ where actions_table.on( K0::default() .nullable() - .eq(BindIfSome( - person_id.map(|id| id.into_sql::()), - )) + .eq(BindIfSome(person_id.map(diesel::IntoSql::into_sql))) .and(K1::default().eq(target_id)), ) } @@ -554,6 +552,43 @@ where ) }*/ +/// `action_query(table_name::action_name)` is the same as +/// `table_name::table.filter(table_name::action_name.is_not_null())`. +pub fn action_query(column: C) -> dsl::Filter> +where + C: Column, + C::Table: Default + FilterDsl>, + C::SqlType: SingleValue, +{ + action_query_with_fn(column, |t| t) +} + +pub fn find_action( + column: C, + key: K, +) -> dsl::Filter, dsl::IsNotNull> +where + C: Column, + C::Table: Default + FindDsl, + dsl::Find: FilterDsl>, + C::SqlType: SingleValue, +{ + action_query_with_fn(column, |t| t.find(key)) +} + +fn action_query_with_fn( + column: C, + f: impl FnOnce(C::Table) -> Q, +) -> dsl::Filter> +where + C: Column, + C::Table: Default, + C::SqlType: SingleValue, + Q: FilterDsl>, +{ + f(C::Table::default()).filter(column.is_not_null()) +} + pub type ResultFuture<'a, T> = BoxFuture<'a, Result>; pub trait ReadFn<'a, T, Args>: Fn(DbConn<'a>, Args) -> ResultFuture<'a, T> {} diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 16306da7a..dab6d2f9b 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -33,6 +33,7 @@ use lemmy_db_schema::{ }, source::site::Site, utils::{ + action_query, actions, functions::coalesce, fuzzy_search, @@ -272,7 +273,7 @@ fn queries<'a>() -> Queries< { // Do not hide read posts when it is a user profile view // Or, only hide read posts on non-profile views - if let None = options.creator_id { + if options.creator_id.is_none() { query = query.filter(post_actions::read.is_null()); } } @@ -490,9 +491,8 @@ impl<'a> PostQuery<'a> { .person_id; let largest_subscribed = { let conn = &mut get_conn(pool).await?; - community_actions::table + action_query(community_actions::followed) .filter(community_actions::person_id.eq(self_person_id)) - .filter(community_actions::followed.is_not_null()) .inner_join(community_aggregates.on(community_id.eq(community_actions::community_id))) .order_by(users_active_month.desc()) .select(community_id) diff --git a/crates/db_views/src/vote_view.rs b/crates/db_views/src/vote_view.rs index 7a3d44b1d..be6ff72ba 100644 --- a/crates/db_views/src/vote_view.rs +++ b/crates/db_views/src/vote_view.rs @@ -4,7 +4,7 @@ use diesel_async::RunQueryDsl; use lemmy_db_schema::{ newtypes::{CommentId, PostId}, schema::{comment_actions, person, post_actions}, - utils::{get_conn, limit_and_offset, DbPool}, + utils::{action_query, get_conn, limit_and_offset, DbPool}, }; impl VoteView { @@ -17,10 +17,9 @@ impl VoteView { let conn = &mut get_conn(pool).await?; let (limit, offset) = limit_and_offset(page, limit)?; - post_actions::table + action_query(post_actions::like_score) .inner_join(person::table) .filter(post_actions::post_id.eq(post_id)) - .filter(post_actions::like_score.is_not_null()) .select(( person::all_columns, post_actions::like_score.assume_not_null(), @@ -41,10 +40,9 @@ impl VoteView { let conn = &mut get_conn(pool).await?; let (limit, offset) = limit_and_offset(page, limit)?; - comment_actions::table + action_query(comment_actions::like_score) .inner_join(person::table) .filter(comment_actions::comment_id.eq(comment_id)) - .filter(comment_actions::like_score.is_not_null()) .select(( person::all_columns, comment_actions::like_score.assume_not_null(), diff --git a/crates/db_views_actor/src/community_block_view.rs b/crates/db_views_actor/src/community_block_view.rs index 15b385105..f959b5701 100644 --- a/crates/db_views_actor/src/community_block_view.rs +++ b/crates/db_views_actor/src/community_block_view.rs @@ -4,18 +4,17 @@ use diesel_async::RunQueryDsl; use lemmy_db_schema::{ newtypes::PersonId, schema::{community, community_actions, person}, - utils::{get_conn, DbPool}, + utils::{action_query, get_conn, DbPool}, }; impl CommunityBlockView { pub async fn for_person(pool: &mut DbPool<'_>, person_id: PersonId) -> Result, Error> { let conn = &mut get_conn(pool).await?; - community_actions::table + action_query(community_actions::blocked) .inner_join(person::table) .inner_join(community::table) .select((person::all_columns, community::all_columns)) .filter(community_actions::person_id.eq(person_id)) - .filter(community_actions::blocked.is_not_null()) .filter(community::deleted.eq(false)) .filter(community::removed.eq(false)) .order_by(community_actions::blocked) diff --git a/crates/db_views_actor/src/community_follower_view.rs b/crates/db_views_actor/src/community_follower_view.rs index c935bb218..ecd2558d6 100644 --- a/crates/db_views_actor/src/community_follower_view.rs +++ b/crates/db_views_actor/src/community_follower_view.rs @@ -10,7 +10,7 @@ use diesel_async::RunQueryDsl; use lemmy_db_schema::{ newtypes::{CommunityId, DbUrl, InstanceId, PersonId}, schema::{community, community_actions, person}, - utils::{functions::coalesce, get_conn, DbPool}, + utils::{action_query, functions::coalesce, get_conn, DbPool}, }; impl CommunityFollowerView { @@ -47,9 +47,8 @@ impl CommunityFollowerView { community_id: CommunityId, ) -> Result, Error> { let conn = &mut get_conn(pool).await?; - let res = community_actions::table + let res = action_query(community_actions::followed) .filter(community_actions::community_id.eq(community_id)) - .filter(community_actions::followed.is_not_null()) .filter(not(person::local)) .inner_join(person::table) .select(coalesce(person::shared_inbox_url, person::inbox_url)) @@ -64,9 +63,8 @@ impl CommunityFollowerView { community_id: CommunityId, ) -> Result { let conn = &mut get_conn(pool).await?; - let res = community_actions::table + let res = action_query(community_actions::followed) .filter(community_actions::community_id.eq(community_id)) - .filter(community_actions::followed.is_not_null()) .select(count_star()) .first::(conn) .await?; @@ -76,12 +74,11 @@ impl CommunityFollowerView { pub async fn for_person(pool: &mut DbPool<'_>, person_id: PersonId) -> Result, Error> { let conn = &mut get_conn(pool).await?; - community_actions::table + action_query(community_actions::followed) .inner_join(community::table) .inner_join(person::table) .select((community::all_columns, person::all_columns)) .filter(community_actions::person_id.eq(person_id)) - .filter(community_actions::followed.is_not_null()) .filter(community::deleted.eq(false)) .filter(community::removed.eq(false)) .order_by(community::title) diff --git a/crates/db_views_actor/src/community_moderator_view.rs b/crates/db_views_actor/src/community_moderator_view.rs index c0345ef3e..e145394d4 100644 --- a/crates/db_views_actor/src/community_moderator_view.rs +++ b/crates/db_views_actor/src/community_moderator_view.rs @@ -4,7 +4,7 @@ use diesel_async::RunQueryDsl; use lemmy_db_schema::{ newtypes::{CommunityId, PersonId}, schema::{community, community_actions, person}, - utils::{get_conn, DbPool}, + utils::{action_query, find_action, get_conn, DbPool}, CommunityVisibility, }; @@ -15,11 +15,10 @@ impl CommunityModeratorView { find_person_id: PersonId, ) -> Result { let conn = &mut get_conn(pool).await?; - select(exists( - community_actions::table - .find((find_person_id, find_community_id)) - .filter(community_actions::became_moderator.is_not_null()), - )) + select(exists(find_action( + community_actions::became_moderator, + (find_person_id, find_community_id), + ))) .get_result::(conn) .await } @@ -30,9 +29,8 @@ impl CommunityModeratorView { ) -> Result { let conn = &mut get_conn(pool).await?; select(exists( - community_actions::table - .filter(community_actions::person_id.eq(find_person_id)) - .filter(community_actions::became_moderator.is_not_null()), + action_query(community_actions::became_moderator) + .filter(community_actions::person_id.eq(find_person_id)), )) .get_result::(conn) .await @@ -43,11 +41,10 @@ impl CommunityModeratorView { community_id: CommunityId, ) -> Result, Error> { let conn = &mut get_conn(pool).await?; - community_actions::table + action_query(community_actions::became_moderator) .inner_join(community::table) .inner_join(person::table) .filter(community_actions::community_id.eq(community_id)) - .filter(community_actions::became_moderator.is_not_null()) .select((community::all_columns, person::all_columns)) .order_by(community_actions::became_moderator) .load::(conn) @@ -60,11 +57,10 @@ impl CommunityModeratorView { is_authenticated: bool, ) -> Result, Error> { let conn = &mut get_conn(pool).await?; - let mut query = community_actions::table + let mut query = action_query(community_actions::became_moderator) .inner_join(community::table) .inner_join(person::table) .filter(community_actions::person_id.eq(person_id)) - .filter(community_actions::became_moderator.is_not_null()) .filter(community::deleted.eq(false)) .filter(community::removed.eq(false)) .select((community::all_columns, person::all_columns)) @@ -79,10 +75,9 @@ impl CommunityModeratorView { /// Ideally this should be a group by, but diesel doesn't support it yet pub async fn get_community_first_mods(pool: &mut DbPool<'_>) -> Result, Error> { let conn = &mut get_conn(pool).await?; - community_actions::table + action_query(community_actions::became_moderator) .inner_join(community::table) .inner_join(person::table) - .filter(community_actions::became_moderator.is_not_null()) .select((community::all_columns, person::all_columns)) // A hacky workaround instead of group_bys // https://stackoverflow.com/questions/24042359/how-to-join-only-one-row-in-joined-table-with-postgres diff --git a/crates/db_views_actor/src/community_person_ban_view.rs b/crates/db_views_actor/src/community_person_ban_view.rs index 66062d243..d37eb1b78 100644 --- a/crates/db_views_actor/src/community_person_ban_view.rs +++ b/crates/db_views_actor/src/community_person_ban_view.rs @@ -4,7 +4,7 @@ use diesel_async::RunQueryDsl; use lemmy_db_schema::{ newtypes::{CommunityId, PersonId}, schema::community_actions, - utils::{get_conn, DbPool}, + utils::{find_action, get_conn, DbPool}, }; impl CommunityPersonBanView { @@ -14,10 +14,7 @@ impl CommunityPersonBanView { from_community_id: CommunityId, ) -> Result { let conn = &mut get_conn(pool).await?; - select(exists( - community_actions::table - .find((from_person_id, from_community_id)) - .filter(community_actions::received_ban.is_not_null()), + select(exists(find_action(community_actions::received_ban, (from_person_id, from_community_id)) )) .get_result::(conn) .await From 1650fa8ec79300cfd406ebb2ad6bd255f98de827 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sun, 10 Mar 2024 02:45:04 +0000 Subject: [PATCH 057/232] community_view --- .../src/community_person_ban_view.rs | 8 ++- crates/db_views_actor/src/community_view.rs | 65 +++++-------------- 2 files changed, 23 insertions(+), 50 deletions(-) diff --git a/crates/db_views_actor/src/community_person_ban_view.rs b/crates/db_views_actor/src/community_person_ban_view.rs index d37eb1b78..fa5a07f87 100644 --- a/crates/db_views_actor/src/community_person_ban_view.rs +++ b/crates/db_views_actor/src/community_person_ban_view.rs @@ -1,5 +1,5 @@ use crate::structs::CommunityPersonBanView; -use diesel::{dsl::exists, result::Error, select, ExpressionMethods, QueryDsl}; +use diesel::{dsl::exists, result::Error, select}; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ newtypes::{CommunityId, PersonId}, @@ -14,8 +14,10 @@ impl CommunityPersonBanView { from_community_id: CommunityId, ) -> Result { let conn = &mut get_conn(pool).await?; - select(exists(find_action(community_actions::received_ban, (from_person_id, from_community_id)) - )) + select(exists(find_action( + community_actions::received_ban, + (from_person_id, from_community_id), + ))) .get_result::(conn) .await } diff --git a/crates/db_views_actor/src/community_view.rs b/crates/db_views_actor/src/community_view.rs index c1cb6eee1..8ab15957a 100644 --- a/crates/db_views_actor/src/community_view.rs +++ b/crates/db_views_actor/src/community_view.rs @@ -12,17 +12,9 @@ use diesel::{ use diesel_async::RunQueryDsl; use lemmy_db_schema::{ newtypes::{CommunityId, PersonId}, - schema::{ - community, - community_aggregates, - community_block, - community_follower, - community_person_ban, - instance_block, - local_user, - }, + schema::{community, community_actions, community_aggregates, instance_actions, local_user}, source::{community::CommunityFollower, local_user::LocalUser, site::Site}, - utils::{fuzzy_search, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, + utils::{actions, fuzzy_search, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, CommunityVisibility, ListingType, SortType, @@ -33,47 +25,26 @@ fn queries<'a>() -> Queries< impl ListFn<'a, CommunityView, (CommunityQuery<'a>, &'a Site)>, > { let all_joins = |query: community::BoxedQuery<'a, Pg>, my_person_id: Option| { - // The left join below will return None in this case - let person_id_join = my_person_id.unwrap_or(PersonId(-1)); - query .inner_join(community_aggregates::table) - .left_join( - community_follower::table.on( - community::id - .eq(community_follower::community_id) - .and(community_follower::person_id.eq(person_id_join)), - ), - ) - .left_join( - instance_block::table.on( - community::instance_id - .eq(instance_block::instance_id) - .and(instance_block::person_id.eq(person_id_join)), - ), - ) - .left_join( - community_block::table.on( - community::id - .eq(community_block::community_id) - .and(community_block::person_id.eq(person_id_join)), - ), - ) - .left_join( - community_person_ban::table.on( - community::id - .eq(community_person_ban::community_id) - .and(community_person_ban::person_id.eq(person_id_join)), - ), - ) + .left_join(actions( + community_actions::table, + my_person_id, + community::id, + )) + .left_join(actions( + instance_actions::table, + my_person_id, + community::instance_id, + )) }; let selection = ( community::all_columns, CommunityFollower::select_subscribed_type(), - community_block::community_id.nullable().is_not_null(), + community_actions::blocked.nullable().is_not_null(), community_aggregates::all_columns, - community_person_ban::person_id.nullable().is_not_null(), + community_actions::received_ban.nullable().is_not_null(), ); let not_removed_or_deleted = community::removed @@ -129,7 +100,7 @@ fn queries<'a>() -> Queries< query = query.filter(not_removed_or_deleted).filter( community::hidden .eq(false) - .or(community_follower::person_id.eq(person_id_join)), + .or(community_actions::follow_pending.is_not_null()), ); } @@ -154,7 +125,7 @@ fn queries<'a>() -> Queries< if let Some(listing_type) = options.listing_type { query = match listing_type { - ListingType::Subscribed => query.filter(community_follower::pending.is_not_null()), // TODO could be this: and(community_follower::person_id.eq(person_id_join)), + ListingType::Subscribed => query.filter(community_actions::follow_pending.is_not_null()), ListingType::Local => query.filter(community::local.eq(true)), _ => query, }; @@ -163,8 +134,8 @@ fn queries<'a>() -> Queries< // Don't show blocked communities and communities on blocked instances. nsfw communities are // also hidden (based on profile setting) if options.local_user.is_some() { - query = query.filter(instance_block::person_id.is_null()); - query = query.filter(community_block::person_id.is_null()); + query = query.filter(instance_actions::blocked.is_null()); + query = query.filter(community_actions::blocked.is_null()); query = query.filter(community::nsfw.eq(false).or(local_user::show_nsfw.eq(true))); } else { // No person in request, only show nsfw communities if show_nsfw is passed into request or if From 82414e184d13aa533e4c04532a3146601098bf32 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sun, 10 Mar 2024 15:26:17 +0000 Subject: [PATCH 058/232] block views --- crates/db_views_actor/src/instance_block_view.rs | 10 +++++----- crates/db_views_actor/src/person_block_view.rs | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/crates/db_views_actor/src/instance_block_view.rs b/crates/db_views_actor/src/instance_block_view.rs index 05820862a..91d7fafbb 100644 --- a/crates/db_views_actor/src/instance_block_view.rs +++ b/crates/db_views_actor/src/instance_block_view.rs @@ -3,14 +3,14 @@ use diesel::{result::Error, ExpressionMethods, JoinOnDsl, NullableExpressionMeth use diesel_async::RunQueryDsl; use lemmy_db_schema::{ newtypes::PersonId, - schema::{instance, instance_block, person, site}, - utils::{get_conn, DbPool}, + schema::{instance, instance_actions, person, site}, + utils::{action_query, get_conn, DbPool}, }; impl InstanceBlockView { pub async fn for_person(pool: &mut DbPool<'_>, person_id: PersonId) -> Result, Error> { let conn = &mut get_conn(pool).await?; - instance_block::table + action_query(instance_actions::blocked) .inner_join(person::table) .inner_join(instance::table) .left_join(site::table.on(site::instance_id.eq(instance::id))) @@ -19,8 +19,8 @@ impl InstanceBlockView { instance::all_columns, site::all_columns.nullable(), )) - .filter(instance_block::person_id.eq(person_id)) - .order_by(instance_block::published) + .filter(instance_actions::person_id.eq(person_id)) + .order_by(instance_actions::blocked) .load::(conn) .await } diff --git a/crates/db_views_actor/src/person_block_view.rs b/crates/db_views_actor/src/person_block_view.rs index 5f028acd8..fdb5b1dbf 100644 --- a/crates/db_views_actor/src/person_block_view.rs +++ b/crates/db_views_actor/src/person_block_view.rs @@ -3,8 +3,8 @@ use diesel::{result::Error, ExpressionMethods, JoinOnDsl, QueryDsl}; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ newtypes::PersonId, - schema::{person, person_block}, - utils::{get_conn, DbPool}, + schema::{person, person_actions}, + utils::{action_query, get_conn, DbPool}, }; impl PersonBlockView { @@ -12,18 +12,18 @@ impl PersonBlockView { let conn = &mut get_conn(pool).await?; let target_person_alias = diesel::alias!(person as person1); - person_block::table - .inner_join(person::table.on(person_block::person_id.eq(person::id))) + action_query(person_actions::blocked) + .inner_join(person::table.on(person_actions::person_id.eq(person::id))) .inner_join( - target_person_alias.on(person_block::target_id.eq(target_person_alias.field(person::id))), + target_person_alias.on(person_actions::target_id.eq(target_person_alias.field(person::id))), ) .select(( person::all_columns, target_person_alias.fields(person::all_columns), )) - .filter(person_block::person_id.eq(person_id)) + .filter(person_actions::person_id.eq(person_id)) .filter(target_person_alias.field(person::deleted).eq(false)) - .order_by(person_block::published) + .order_by(person_actions::blocked) .load::(conn) .await } From 4b9291c6ce82e79a3c8c3fbf9ff87e3987eafeca Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sun, 10 Mar 2024 16:03:15 +0000 Subject: [PATCH 059/232] person_mention_view --- crates/db_views/src/comment_view.rs | 3 +- crates/db_views/src/post_view.rs | 4 +- .../db_views_actor/src/comment_reply_view.rs | 3 +- .../db_views_actor/src/person_mention_view.rs | 171 ++++++------------ 4 files changed, 59 insertions(+), 122 deletions(-) diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs index 84c318bff..c51b4dd38 100644 --- a/crates/db_views/src/comment_view.rs +++ b/crates/db_views/src/comment_view.rs @@ -28,6 +28,7 @@ use lemmy_db_schema::{ person_actions, post, }, + source::community::CommunityFollower, utils::{ actions, functions::coalesce, @@ -101,7 +102,7 @@ fn queries<'a>() -> Queries< .nullable() .is_not_null(), coalesce(local_user::admin.nullable(), false), - community_actions::follow_pending.nullable(), + CommunityFollower::select_subscribed_type(), comment_actions::saved.nullable().is_not_null(), person_actions::blocked.nullable().is_not_null(), comment_actions::like_score.nullable(), diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index dab6d2f9b..3183b841d 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -31,7 +31,7 @@ use lemmy_db_schema::{ post_actions, post_aggregates, }, - source::site::Site, + source::{community::CommunityFollower, site::Site}, utils::{ action_query, actions, @@ -110,7 +110,7 @@ fn queries<'a>() -> Queries< .is_not_null(), coalesce(local_user::admin.nullable(), false), post_aggregates::all_columns, - community_actions::follow_pending.nullable(), + 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(), diff --git a/crates/db_views_actor/src/comment_reply_view.rs b/crates/db_views_actor/src/comment_reply_view.rs index 3cced4f29..6373ea4f9 100644 --- a/crates/db_views_actor/src/comment_reply_view.rs +++ b/crates/db_views_actor/src/comment_reply_view.rs @@ -24,6 +24,7 @@ use lemmy_db_schema::{ person_actions, post, }, + source::community::CommunityFollower, utils::{ actions, functions::coalesce, @@ -92,7 +93,7 @@ fn queries<'a>() -> Queries< .nullable() .is_not_null(), coalesce(local_user::admin.nullable(), false), - community_actions::follow_pending.nullable(), + CommunityFollower::select_subscribed_type(), comment_actions::saved.nullable().is_not_null(), person_actions::blocked.nullable().is_not_null(), comment_actions::like_score.nullable(), diff --git a/crates/db_views_actor/src/person_mention_view.rs b/crates/db_views_actor/src/person_mention_view.rs index c80f96f61..b66c8a60d 100644 --- a/crates/db_views_actor/src/person_mention_view.rs +++ b/crates/db_views_actor/src/person_mention_view.rs @@ -1,37 +1,41 @@ use crate::structs::PersonMentionView; use diesel::{ - dsl::exists, pg::Pg, result::Error, - sql_types, BoolExpressionMethods, - BoxableExpression, ExpressionMethods, - IntoSql, JoinOnDsl, NullableExpressionMethods, QueryDsl, }; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ - aliases, + aliases::{self, creator_community_actions}, newtypes::{PersonId, PersonMentionId}, schema::{ comment, + comment_actions, comment_aggregates, - comment_like, - comment_saved, community, - community_follower, - community_moderator, - community_person_ban, + community_actions, local_user, person, - person_block, + person_actions, person_mention, post, }, - utils::{get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, + source::community::CommunityFollower, + utils::{ + actions, + functions::coalesce, + get_conn, + limit_and_offset, + DbConn, + DbPool, + ListFn, + Queries, + ReadFn, + }, CommentSortType, }; @@ -39,111 +43,39 @@ fn queries<'a>() -> Queries< impl ReadFn<'a, PersonMentionView, (PersonMentionId, Option)>, impl ListFn<'a, PersonMentionView, PersonMentionQuery>, > { - let is_creator_banned_from_community = exists( - community_person_ban::table.filter( - community::id - .eq(community_person_ban::community_id) - .and(community_person_ban::person_id.eq(comment::creator_id)), - ), - ); - - let is_saved = |person_id| { - exists( - comment_saved::table.filter( - comment::id - .eq(comment_saved::comment_id) - .and(comment_saved::person_id.eq(person_id)), - ), - ) - }; - - let is_community_followed = |person_id| { - community_follower::table - .filter( - post::community_id - .eq(community_follower::community_id) - .and(community_follower::person_id.eq(person_id)), - ) - .select(community_follower::pending.nullable()) - .single_value() - }; - - let is_creator_blocked = |person_id| { - exists( - person_block::table.filter( - comment::creator_id - .eq(person_block::target_id) - .and(person_block::person_id.eq(person_id)), - ), - ) - }; - - let score = |person_id| { - comment_like::table - .filter( - comment::id - .eq(comment_like::comment_id) - .and(comment_like::person_id.eq(person_id)), - ) - .select(comment_like::score.nullable()) - .single_value() - }; - - let creator_is_moderator = exists( - community_moderator::table.filter( - community::id - .eq(community_moderator::community_id) - .and(community_moderator::person_id.eq(comment::creator_id)), - ), - ); - - let creator_is_admin = exists( - local_user::table.filter( - comment::creator_id - .eq(local_user::person_id) - .and(local_user::admin.eq(true)), - ), - ); - let all_joins = move |query: person_mention::BoxedQuery<'a, Pg>, my_person_id: Option| { - let score_selection: Box< - dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable>, - > = if let Some(person_id) = my_person_id { - Box::new(score(person_id)) - } else { - Box::new(None::.into_sql::>()) - }; - - let subscribed_type_selection: Box< - dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable>, - > = if let Some(person_id) = my_person_id { - Box::new(is_community_followed(person_id)) - } else { - Box::new(None::.into_sql::>()) - }; - - let is_saved_selection: Box> = - if let Some(person_id) = my_person_id { - Box::new(is_saved(person_id)) - } else { - Box::new(false.into_sql::()) - }; - - let is_creator_blocked_selection: Box> = - if let Some(person_id) = my_person_id { - Box::new(is_creator_blocked(person_id)) - } else { - Box::new(false.into_sql::()) - }; - query - .inner_join(comment::table) - .inner_join(person::table.on(comment::creator_id.eq(person::id))) - .inner_join(post::table.on(comment::post_id.eq(post::id))) - .inner_join(community::table.on(post::community_id.eq(community::id))) + .inner_join( + comment::table + .inner_join(person::table.left_join(local_user::table)) + .inner_join(post::table.inner_join(community::table)) + .inner_join(comment_aggregates::table), + ) .inner_join(aliases::person1) - .inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id))) + .left_join(actions( + community_actions::table, + my_person_id, + post::community_id, + )) + .left_join(actions(comment_actions::table, my_person_id, comment::id)) + .left_join(actions( + person_actions::table, + my_person_id, + comment::creator_id, + )) + .left_join( + creator_community_actions.on( + creator_community_actions + .field(community_actions::person_id) + .eq(comment::creator_id) + .and( + creator_community_actions + .field(community_actions::community_id) + .eq(post::community_id), + ), + ), + ) .select(( person_mention::all_columns, comment::all_columns, @@ -152,16 +84,19 @@ fn queries<'a>() -> Queries< community::all_columns, aliases::person1.fields(person::all_columns), comment_aggregates::all_columns, - is_creator_banned_from_community, + creator_community_actions + .field(community_actions::received_ban) + .nullable() + .is_not_null(), creator_community_actions .field(community_actions::became_moderator) .nullable() .is_not_null(), - coalesce(local_user::admin, false), - community_actions::follow_pending.nullable(), - is_saved_selection, + coalesce(local_user::admin.nullable(), false), + CommunityFollower::select_subscribed_type(), + comment_actions::saved.nullable().is_not_null(), person_actions::blocked.nullable().is_not_null(), - score_selection, + comment_actions::like_score.nullable(), )) }; From 5e27ed7ff64c00b4fcbda9e079c9cd22af539f8a Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sun, 10 Mar 2024 16:04:40 +0000 Subject: [PATCH 060/232] remove struct update --- crates/api_crud/src/post/read.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/api_crud/src/post/read.rs b/crates/api_crud/src/post/read.rs index e701008b7..affae4e87 100644 --- a/crates/api_crud/src/post/read.rs +++ b/crates/api_crud/src/post/read.rs @@ -78,7 +78,6 @@ pub async fn get_post( person_id, post_id, read_comments, - ..PersonPostAggregatesForm::default() }; PersonPostAggregates::upsert(&mut context.pool(), &person_post_agg_form) .await From 56e02626b6dca727660737e8ee1db8674b77e9fd Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sun, 10 Mar 2024 16:49:26 +0000 Subject: [PATCH 061/232] refactor actions function --- crates/db_schema/src/utils.rs | 78 ++++++++++++----------------------- 1 file changed, 27 insertions(+), 51 deletions(-) diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index 45ffc811b..16e9a2ca4 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -488,70 +488,46 @@ pub fn now() -> AsExprOf { diesel::dsl::now.into_sql::() } +pub type AsRecordOutput = dsl::AsExprOf::SqlType>>; + +pub trait AsRecord: Expression + AsExpression> +where + Self::SqlType: 'static, +{ +} + +impl>> AsRecord for T where + T::SqlType: 'static +{ +} + +// TODO: call `default` on whole tuple when impl for `Nullable` is added pub fn actions( actions_table: T, person_id: Option

, target_id: C, ) -> dsl::On< T, - dsl::And< - dsl::Eq, BindIfSome>>, - dsl::Eq, + dsl::Eq< + AsRecordOutput<(dsl::Nullable, K1)>, + (BindIfSome>, C), >, > where - P: AsExpression, T: Table, - K0: Default + Expression + Sized, - dsl::Nullable: diesel::ExpressionMethods, - as Expression>::SqlType: SqlType, - BindIfSome>: - AsExpression< as Expression>::SqlType>, - K1: Default + diesel::ExpressionMethods, - ::SqlType: SqlType, - C: AsExpression<::SqlType>, - dsl::Eq, BindIfSome>>: - Expression>, - dsl::Eq: Expression, + K0: Default + Expression, + K1: Default, + P: AsExpression, + (dsl::Nullable, K1): AsRecord, + (BindIfSome>, C): + AsExpression<, K1)> as Expression>::SqlType>, { - actions_table.on( - K0::default() - .nullable() - .eq(BindIfSome(person_id.map(diesel::IntoSql::into_sql))) - .and(K1::default().eq(target_id)), - ) + actions_table.on((K0::default().nullable(), K1::default()).into_sql().eq(( + BindIfSome(person_id.map(diesel::IntoSql::into_sql)), + target_id, + ))) } -/*pub fn actions_alias( - actions_table: Alias, - person_id: Option, - target_id: C, -) -> dsl::On, dsl::And>, Option>, dsl::Eq, C>>> -where - AS: AliasSource, - Alias: QuerySource + Clone + Copy, - AS::Target: Table, - K0: Default + Column

, - AliasedField: Expression + Sized, - dsl::Nullable>: diesel::ExpressionMethods, - > as Expression>::SqlType: SqlType, - Option: AsExpression<> as Expression>::SqlType>, - K1: Default + Column
, - AliasedField: diesel::ExpressionMethods, - as Expression>::SqlType: SqlType, - C: AsExpression< as Expression>::SqlType>, - dsl::Eq>, Option>: - Expression>, - dsl::Eq, C>: Expression, -{ - actions_table.on( - actions_table.field(K0::default()) - .nullable() - .eq(person_id) - .and(actions_table.field(K1::default()).eq(target_id)), - ) -}*/ - /// `action_query(table_name::action_name)` is the same as /// `table_name::table.filter(table_name::action_name.is_not_null())`. pub fn action_query(column: C) -> dsl::Filter> From dfe1c745a92063795f45bc12872039687d5c8894 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sun, 10 Mar 2024 21:43:53 +0000 Subject: [PATCH 062/232] actions_alias --- crates/db_schema/src/utils.rs | 35 +++++++++++++++++-- crates/db_views/src/comment_report_view.rs | 18 ++++------ crates/db_views/src/comment_view.rs | 18 ++++------ crates/db_views/src/post_report_view.rs | 29 ++++++++------- crates/db_views/src/post_view.rs | 18 ++++------ .../db_views_actor/src/comment_reply_view.rs | 28 ++++----------- .../db_views_actor/src/person_mention_view.rs | 28 ++++----------- 7 files changed, 81 insertions(+), 93 deletions(-) diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index 16e9a2ca4..5f0f3f689 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -15,13 +15,13 @@ use diesel::{ pg::Pg, query_builder::{Query, QueryFragment}, query_dsl::methods::{FilterDsl, FindDsl, LimitDsl}, + query_source::{Alias, AliasSource, AliasedField}, result::{ ConnectionError, ConnectionResult, Error::{self as DieselError, QueryBuilderError}, }, - sql_types::{self, SingleValue, SqlType, Timestamptz}, - BoolExpressionMethods, + sql_types::{self, SingleValue, Timestamptz}, Column, Expression, ExpressionMethods, @@ -29,6 +29,7 @@ use diesel::{ JoinOnDsl, NullableExpressionMethods, PgConnection, + QuerySource, Table, }; use diesel_async::{ @@ -528,6 +529,36 @@ where ))) } +//type TargetPrimaryKey = AliasedFields::Target as Table>::PrimaryKey>; + +/// Like `actions` but `actions_table` is an alias and person id is not nullable +pub fn actions_alias( + actions_table: Alias, + person_id: P, + target_id: C, +) -> dsl::On, dsl::Eq, AliasedField)>, (P, C)>> +where + Alias: QuerySource + Copy, + T: AliasSource, + T::Target: Table, + K0: Default + Column
, + K1: Default + Column
, + (AliasedField, AliasedField): AsRecord, + (P, C): AsExpression< + , AliasedField)> as Expression>::SqlType, + >, +{ + // TODO: Use `default` for whole tuple when `AliasedField` when impl is added + actions_table.on( + ( + actions_table.field(K0::default()), + actions_table.field(K1::default()), + ) + .into_sql() + .eq((person_id, target_id)), + ) +} + /// `action_query(table_name::action_name)` is the same as /// `table_name::table.filter(table_name::action_name.is_not_null())`. pub fn action_query(column: C) -> dsl::Filter> diff --git a/crates/db_views/src/comment_report_view.rs b/crates/db_views/src/comment_report_view.rs index 40e0a1786..847ea5b44 100644 --- a/crates/db_views/src/comment_report_view.rs +++ b/crates/db_views/src/comment_report_view.rs @@ -25,6 +25,7 @@ use lemmy_db_schema::{ }, utils::{ actions, + actions_alias, functions::coalesce, get_conn, limit_and_offset, @@ -59,18 +60,11 @@ fn queries<'a>() -> Queries< aliases::person2 .on(comment_report::resolver_id.eq(aliases::person2.field(person::id).nullable())), ) - .left_join( - creator_community_actions.on( - creator_community_actions - .field(community_actions::person_id) - .eq(comment::creator_id) - .and( - creator_community_actions - .field(community_actions::community_id) - .eq(post::community_id), - ), - ), - ) + .left_join(actions_alias( + creator_community_actions, + comment::creator_id, + post::community_id, + )) .select(( comment_report::all_columns, comment::all_columns, diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs index c51b4dd38..f862dbdea 100644 --- a/crates/db_views/src/comment_view.rs +++ b/crates/db_views/src/comment_view.rs @@ -31,6 +31,7 @@ use lemmy_db_schema::{ source::community::CommunityFollower, utils::{ actions, + actions_alias, functions::coalesce, fuzzy_search, limit_and_offset, @@ -75,18 +76,11 @@ fn queries<'a>() -> Queries< my_person_id, community::instance_id, )) - .left_join( - creator_community_actions.on( - creator_community_actions - .field(community_actions::person_id) - .eq(comment::creator_id) - .and( - creator_community_actions - .field(community_actions::community_id) - .eq(post::community_id), - ), - ), - ) + .left_join(actions_alias( + creator_community_actions, + comment::creator_id, + post::community_id, + )) .select(( comment::all_columns, person::all_columns, diff --git a/crates/db_views/src/post_report_view.rs b/crates/db_views/src/post_report_view.rs index 8bbe6015f..19ab03f48 100644 --- a/crates/db_views/src/post_report_view.rs +++ b/crates/db_views/src/post_report_view.rs @@ -21,7 +21,17 @@ use lemmy_db_schema::{ post_aggregates, post_report, }, - utils::{actions, get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, + utils::{ + actions, + actions_alias, + get_conn, + limit_and_offset, + DbConn, + DbPool, + ListFn, + Queries, + ReadFn, + }, }; fn queries<'a>() -> Queries< @@ -40,18 +50,11 @@ fn queries<'a>() -> Queries< .on(post_report::resolver_id.eq(aliases::person2.field(person::id).nullable())), ) .left_join(actions(post_actions::table, Some(my_person_id), post::id)) - .left_join( - creator_community_actions.on( - creator_community_actions - .field(community_actions::person_id) - .eq(post::creator_id) - .and( - creator_community_actions - .field(community_actions::community_id) - .eq(post::community_id), - ), - ), - ) + .left_join(actions_alias( + creator_community_actions, + post::creator_id, + post::community_id, + )) .select(( post_report::all_columns, post::all_columns, diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 3183b841d..f4c1e75f9 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -35,6 +35,7 @@ use lemmy_db_schema::{ utils::{ action_query, actions, + actions_alias, functions::coalesce, fuzzy_search, get_conn, @@ -84,18 +85,11 @@ fn queries<'a>() -> Queries< my_person_id, post_aggregates::instance_id, )) - .left_join( - creator_community_actions.on( - creator_community_actions - .field(community_actions::person_id) - .eq(post_aggregates::creator_id) - .and( - creator_community_actions - .field(community_actions::community_id) - .eq(post_aggregates::community_id), - ), - ), - ) + .left_join(actions_alias( + creator_community_actions, + post_aggregates::creator_id, + post_aggregates::community_id, + )) .select(( post::all_columns, person::all_columns, diff --git a/crates/db_views_actor/src/comment_reply_view.rs b/crates/db_views_actor/src/comment_reply_view.rs index 6373ea4f9..467f047aa 100644 --- a/crates/db_views_actor/src/comment_reply_view.rs +++ b/crates/db_views_actor/src/comment_reply_view.rs @@ -1,13 +1,5 @@ use crate::structs::CommentReplyView; -use diesel::{ - pg::Pg, - result::Error, - BoolExpressionMethods, - ExpressionMethods, - JoinOnDsl, - NullableExpressionMethods, - QueryDsl, -}; +use diesel::{pg::Pg, result::Error, ExpressionMethods, NullableExpressionMethods, QueryDsl}; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ aliases::{self, creator_community_actions}, @@ -27,6 +19,7 @@ use lemmy_db_schema::{ source::community::CommunityFollower, utils::{ actions, + actions_alias, functions::coalesce, get_conn, limit_and_offset, @@ -64,18 +57,11 @@ fn queries<'a>() -> Queries< my_person_id, comment::creator_id, )) - .left_join( - creator_community_actions.on( - creator_community_actions - .field(community_actions::person_id) - .eq(comment::creator_id) - .and( - creator_community_actions - .field(community_actions::community_id) - .eq(post::community_id), - ), - ), - ) + .left_join(actions_alias( + creator_community_actions, + comment::creator_id, + post::community_id, + )) .select(( comment_reply::all_columns, comment::all_columns, diff --git a/crates/db_views_actor/src/person_mention_view.rs b/crates/db_views_actor/src/person_mention_view.rs index b66c8a60d..99039e6ee 100644 --- a/crates/db_views_actor/src/person_mention_view.rs +++ b/crates/db_views_actor/src/person_mention_view.rs @@ -1,13 +1,5 @@ use crate::structs::PersonMentionView; -use diesel::{ - pg::Pg, - result::Error, - BoolExpressionMethods, - ExpressionMethods, - JoinOnDsl, - NullableExpressionMethods, - QueryDsl, -}; +use diesel::{pg::Pg, result::Error, ExpressionMethods, NullableExpressionMethods, QueryDsl}; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ aliases::{self, creator_community_actions}, @@ -27,6 +19,7 @@ use lemmy_db_schema::{ source::community::CommunityFollower, utils::{ actions, + actions_alias, functions::coalesce, get_conn, limit_and_offset, @@ -64,18 +57,11 @@ fn queries<'a>() -> Queries< my_person_id, comment::creator_id, )) - .left_join( - creator_community_actions.on( - creator_community_actions - .field(community_actions::person_id) - .eq(comment::creator_id) - .and( - creator_community_actions - .field(community_actions::community_id) - .eq(post::community_id), - ), - ), - ) + .left_join(actions_alias( + creator_community_actions, + comment::creator_id, + post::community_id, + )) .select(( person_mention::all_columns, comment::all_columns, From 231fadb6d64f37cc20691109b1b1648f85a5e4eb Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Tue, 12 Mar 2024 14:27:09 +0000 Subject: [PATCH 063/232] clean up return types and trait bounds --- crates/db_schema/src/utils.rs | 37 +++++++++++++---------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index 5f0f3f689..fb030ecea 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -502,58 +502,49 @@ impl>> AsRecord for T { } -// TODO: call `default` on whole tuple when impl for `Nullable` is added +type OnTupleEq = dsl::On, (R0, R1)>>; + pub fn actions( actions_table: T, person_id: Option

, target_id: C, -) -> dsl::On< - T, - dsl::Eq< - AsRecordOutput<(dsl::Nullable, K1)>, - (BindIfSome>, C), - >, -> +) -> OnTupleEq, K1, BindIfSome>, C> where - T: Table, - K0: Default + Expression, - K1: Default, + T: Table + Copy, + K0: Expression, P: AsExpression, (dsl::Nullable, K1): AsRecord, (BindIfSome>, C): AsExpression<, K1)> as Expression>::SqlType>, { - actions_table.on((K0::default().nullable(), K1::default()).into_sql().eq(( + let (k0, k1) = actions_table.primary_key(); + actions_table.on((k0.nullable(), k1).into_sql().eq(( BindIfSome(person_id.map(diesel::IntoSql::into_sql)), target_id, ))) } -//type TargetPrimaryKey = AliasedFields::Target as Table>::PrimaryKey>; - /// Like `actions` but `actions_table` is an alias and person id is not nullable +#[allow(clippy::type_complexity)] pub fn actions_alias( actions_table: Alias, person_id: P, target_id: C, -) -> dsl::On, dsl::Eq, AliasedField)>, (P, C)>> +) -> OnTupleEq, AliasedField, AliasedField, P, C> where Alias: QuerySource + Copy, - T: AliasSource, + T: AliasSource + Default, T::Target: Table, - K0: Default + Column

, - K1: Default + Column
, + K0: Column
, + K1: Column
, (AliasedField, AliasedField): AsRecord, (P, C): AsExpression< , AliasedField)> as Expression>::SqlType, >, { - // TODO: Use `default` for whole tuple when `AliasedField` when impl is added + let (k0, k1) = T::default().target().primary_key(); actions_table.on( - ( - actions_table.field(K0::default()), - actions_table.field(K1::default()), - ) + (actions_table.field(k0), actions_table.field(k1)) .into_sql() .eq((person_id, target_id)), ) From 1f96d7d13b6c363edae933d3ef9a5ce78ad72668 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Tue, 12 Mar 2024 14:34:52 +0000 Subject: [PATCH 064/232] fix all rust code --- src/scheduled_tasks.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scheduled_tasks.rs b/src/scheduled_tasks.rs index 38eb4ece2..647061ae8 100644 --- a/src/scheduled_tasks.rs +++ b/src/scheduled_tasks.rs @@ -15,7 +15,7 @@ use lemmy_db_schema::{ schema::{ captcha_answer, comment, - community_person_ban, + community_actions, instance, person, post, @@ -437,7 +437,7 @@ async fn update_banned_when_expired(pool: &mut DbPool<'_>) { .ok(); diesel::delete( - community_person_ban::table.filter(community_person_ban::expires.lt(now().nullable())), + community_actions::table.filter(community_actions::ban_expires.lt(now().nullable())), ) .execute(&mut conn) .await From 0f3df354cde110e0f006ede764cd036d6a56bd56 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Fri, 29 Mar 2024 16:35:46 +0000 Subject: [PATCH 065/232] fmt --- crates/db_views/src/comment_view.rs | 4 +--- crates/db_views/src/post_view.rs | 4 +--- crates/db_views/src/vote_view.rs | 25 ++++++++++++++++++++----- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs index 323c7bdf4..a216bd44b 100644 --- a/crates/db_views/src/comment_view.rs +++ b/crates/db_views/src/comment_view.rs @@ -91,9 +91,7 @@ fn queries<'a>() -> Queries< .field(community_actions::received_ban) .nullable() .is_not_null(), - community_actions::received_ban - .nullable() - .is_not_null(), + community_actions::received_ban.nullable().is_not_null(), creator_community_actions .field(community_actions::became_moderator) .nullable() diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index c5a8ccb22..c5c7caa37 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -98,9 +98,7 @@ fn queries<'a>() -> Queries< .field(community_actions::received_ban) .nullable() .is_not_null(), - community_actions::received_ban - .nullable() - .is_not_null(), + community_actions::received_ban.nullable().is_not_null(), creator_community_actions .field(community_actions::became_moderator) .nullable() diff --git a/crates/db_views/src/vote_view.rs b/crates/db_views/src/vote_view.rs index f4909a0fb..ecc4132dc 100644 --- a/crates/db_views/src/vote_view.rs +++ b/crates/db_views/src/vote_view.rs @@ -9,9 +9,10 @@ use diesel::{ }; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ + aliases::creator_community_actions, newtypes::{CommentId, PostId}, schema::{comment_actions, community_actions, person, post, post_actions}, - utils::{action_query, actions_alias, get_conn, limit_and_offset, DbPool},aliases::creator_community_actions + utils::{action_query, actions_alias, get_conn, limit_and_offset, DbPool}, }; impl VoteView { @@ -27,11 +28,18 @@ impl VoteView { action_query(post_actions::like_score) .inner_join(person::table) .inner_join(post::table) - .left_join(actions_alias(creator_community_actions, post_actions::person_id, post::community_id)) + .left_join(actions_alias( + creator_community_actions, + post_actions::person_id, + post::community_id, + )) .filter(post_actions::post_id.eq(post_id)) .select(( person::all_columns, - creator_community_actions.field(community_actions::received_ban).nullable().is_not_null(), + creator_community_actions + .field(community_actions::received_ban) + .nullable() + .is_not_null(), post_actions::like_score.assume_not_null(), )) .order_by(post_actions::like_score) @@ -53,11 +61,18 @@ impl VoteView { action_query(comment_actions::like_score) .inner_join(person::table) .inner_join(post::table) - .left_join(actions_alias(creator_community_actions, comment_actions::person_id, post::community_id)) + .left_join(actions_alias( + creator_community_actions, + comment_actions::person_id, + post::community_id, + )) .filter(comment_actions::comment_id.eq(comment_id)) .select(( person::all_columns, - creator_community_actions.field(community_actions::received_ban).nullable().is_not_null(), + creator_community_actions + .field(community_actions::received_ban) + .nullable() + .is_not_null(), comment_actions::like_score.assume_not_null(), )) .order_by(comment_actions::like_score) From f71e8b4f8c708cdaaf11e7d1dd1a3267a6562386 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Fri, 29 Mar 2024 16:42:50 +0000 Subject: [PATCH 066/232] clippy fix --- crates/db_views/src/vote_view.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/db_views/src/vote_view.rs b/crates/db_views/src/vote_view.rs index ecc4132dc..6353bcfaf 100644 --- a/crates/db_views/src/vote_view.rs +++ b/crates/db_views/src/vote_view.rs @@ -1,9 +1,7 @@ use crate::structs::VoteView; use diesel::{ result::Error, - BoolExpressionMethods, ExpressionMethods, - JoinOnDsl, NullableExpressionMethods, QueryDsl, }; From 7cf8684eacb1b4a41b33bf3c8ca0c16db520c51e Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Mon, 1 Apr 2024 21:09:46 +0000 Subject: [PATCH 067/232] Migrate tables --- crates/db_schema/src/schema.rs | 18 +- crates/db_views/src/vote_view.rs | 7 +- .../down.sql | 258 ++++++++++++++++++ .../up.sql | 248 +++++++++++++++++ 4 files changed, 516 insertions(+), 15 deletions(-) create mode 100644 migrations/2024-03-17-134311_smoosh-tables-together/down.sql create mode 100644 migrations/2024-03-17-134311_smoosh-tables-together/up.sql diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 3c4078045..4499ec5a8 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -103,9 +103,9 @@ diesel::table! { person_id -> Int4, comment_id -> Int4, post_id -> Int4, - saved -> Nullable, - liked -> Nullable, like_score -> Nullable, + liked -> Nullable, + saved -> Nullable, } } @@ -189,11 +189,11 @@ diesel::table! { diesel::table! { community_actions (person_id, community_id) { - person_id -> Int4, community_id -> Int4, - blocked -> Nullable, + person_id -> Int4, followed -> Nullable, follow_pending -> Nullable, + blocked -> Nullable, became_moderator -> Nullable, received_ban -> Nullable, ban_expires -> Nullable, @@ -618,11 +618,11 @@ diesel::table! { diesel::table! { person_actions (person_id, target_id) { - person_id -> Int4, target_id -> Int4, - blocked -> Nullable, + person_id -> Int4, followed -> Nullable, follow_pending -> Nullable, + blocked -> Nullable, } } @@ -685,12 +685,12 @@ diesel::table! { } diesel::table! { - post_actions (person_id, post_id) { - person_id -> Int4, + post_actions (person_id, post_id) { post_id -> Int4, + person_id -> Int4, + read -> Nullable, read_comments -> Nullable, read_comments_amount -> Int8, - read -> Nullable, saved -> Nullable, liked -> Nullable, like_score -> Nullable, diff --git a/crates/db_views/src/vote_view.rs b/crates/db_views/src/vote_view.rs index 6353bcfaf..0a0748df8 100644 --- a/crates/db_views/src/vote_view.rs +++ b/crates/db_views/src/vote_view.rs @@ -1,10 +1,5 @@ use crate::structs::VoteView; -use diesel::{ - result::Error, - ExpressionMethods, - NullableExpressionMethods, - QueryDsl, -}; +use diesel::{result::Error, ExpressionMethods, NullableExpressionMethods, QueryDsl}; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ aliases::creator_community_actions, diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/down.sql b/migrations/2024-03-17-134311_smoosh-tables-together/down.sql new file mode 100644 index 000000000..ac2e45ea7 --- /dev/null +++ b/migrations/2024-03-17-134311_smoosh-tables-together/down.sql @@ -0,0 +1,258 @@ +-- For each new actions table: +-- * Create tables that are dropped in up.sql, and insert into them +-- * Do the opposite of the `ALTER TABLE` commands in up.sql, with `DELETE` being used to +-- only keep rows where the preserved action is not null +-- +-- Create comment_like from comment_actions +CREATE TABLE comment_saved ( + person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + comment_id int REFERENCES COMMENT ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + published timestamptz DEFAULT now() NOT NULL, + PRIMARY KEY (person_id, comment_id) +); + +INSERT INTO comment_saved (person_id, comment_id, published) +SELECT + person_id, + comment_id, + saved +FROM + comment_actions +WHERE + saved IS NOT NULL; + +DELETE FROM comment_actions +WHERE liked IS NULL; + +ALTER TABLE comment_actions RENAME TO comment_like; + +ALTER TABLE comment_like RENAME COLUMN liked TO published; + +ALTER TABLE comment_like RENAME COLUMN like_score TO score; + +ALTER TABLE comment_like + DROP CONSTRAINT comment_actions_check_liked, + ALTER COLUMN published SET NOT NULL, + ALTER COLUMN published SET DEFAULT now(), + ALTER COLUMN score SET NOT NULL, + DROP COLUMN saved; + +-- Create community_follower from community_actions +CREATE TABLE community_block ( + person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + community_id int REFERENCES community ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + published timestamptz DEFAULT now() NOT NULL, + PRIMARY KEY (person_id, community_id) +); + +INSERT INTO community_block (person_id, community_id, published) +SELECT + person_id, + community_id, + blocked +FROM + community_actions +WHERE + blocked IS NOT NULL; + +CREATE TABLE community_moderator ( + community_id int REFERENCES community ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + published timestamptz DEFAULT now() NOT NULL, + PRIMARY KEY (person_id, community_id) +); + +INSERT INTO community_moderator (community_id, person_id, published) +SELECT + community_id, + person_id, + became_moderator +FROM + community_actions +WHERE + became_moderator IS NOT NULL; + +CREATE TABLE community_person_ban ( + community_id int REFERENCES community ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + published timestamptz DEFAULT now() NOT NULL, + expires timestamptz, + PRIMARY KEY (person_id, community_id) +); + +INSERT INTO community_person_ban (community_id, person_id, published, expires) +SELECT + community_id, + person_id, + received_ban, + ban_expires +FROM + community_actions +WHERE + received_ban IS NOT NULL; + +DELETE FROM community_actions +WHERE followed IS NULL; + +ALTER TABLE community_actions RENAME TO community_follower; + +ALTER TABLE community_follower RENAME COLUMN followed TO published; + +ALTER TABLE community_follower RENAME follow_pending TO pending; + +ALTER TABLE community_follower + DROP CONSTRAINT community_actions_check_followed, + DROP CONSTRAINT community_actions_check_received_ban, + ALTER COLUMN published SET NOT NULL, + ALTER COLUMN published SET DEFAULT now(), + ALTER COLUMN pending SET NOT NULL, + -- This `SET DEFAULT` is done for community follow, but not person follow. It's not a mistake + -- in this migration. Believe it or not, `pending` only had a default value in community follow. + ALTER COLUMN pending SET DEFAULT FALSE, + DROP COLUMN blocked, + DROP COLUMN became_moderator, + DROP COLUMN received_ban, + DROP COLUMN ban_expires; + +-- Create instance_block from instance_actions +DELETE FROM instance_actions +WHERE blocked IS NULL; + +ALTER TABLE instance_actions RENAME TO instance_block; + +ALTER TABLE instance_block RENAME COLUMN blocked TO published; + +ALTER TABLE instance_block + ALTER COLUMN published SET NOT NULL, + ALTER COLUMN published SET DEFAULT now(); + +-- Create person_follower from person_actions +CREATE TABLE person_block ( + person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + target_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + published timestamptz DEFAULT now() NOT NULL, + PRIMARY KEY (person_id, target_id) +); + +INSERT INTO person_block (person_id, target_id, published) +SELECT + person_id, + target_id, + blocked +FROM + person_actions +WHERE + blocked IS NOT NULL; + +DELETE FROM person_actions +WHERE followed IS NULL; + +ALTER TABLE person_actions RENAME TO person_follower; + +ALTER TABLE person_follower RENAME COLUMN person_id TO follower_id; + +ALTER TABLE person_follower RENAME COLUMN target_id TO person_id; + +ALTER TABLE person_follower RENAME COLUMN followed TO published; + +ALTER TABLE person_follower RENAME COLUMN follow_pending TO pending; + +ALTER TABLE person_follower + DROP CONSTRAINT person_actions_check_followed, + ALTER COLUMN published SET NOT NULL, + ALTER COLUMN published SET DEFAULT now(), + ALTER COLUMN pending SET NOT NULL, + DROP COLUMN blocked; + +-- Create post_read from post_actions +CREATE TABLE person_post_aggregates ( + person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + post_id int REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + read_comments bigint DEFAULT 0 NOT NULL, + published timestamptz NOT NULL, + PRIMARY KEY (person_id, post_id) +); + +INSERT INTO person_post_aggregates (person_id, post_id, read_comments, published) +SELECT + person_id, + post_id, + read_comments_amount, + read_comments +FROM + post_actions +WHERE + read_comments IS NOT NULL; + +CREATE TABLE post_hide ( + post_id int REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + published timestamptz DEFAULT now() NOT NULL, + PRIMARY KEY (person_id, post_id) +); + +INSERT INTO post_hide (post_id, person_id, published) +SELECT + post_id, + person_id, + hidden +FROM + post_actions +WHERE + hidden IS NOT NULL; + +CREATE TABLE post_like ( + post_id int REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + score smallint NOT NULL, + published timestamptz DEFAULT now() NOT NULL, + PRIMARY KEY (person_id, post_id) +); + +INSERT INTO post_like (post_id, person_id, score, published) +SELECT + post_id, + person_id, + like_score, + liked +FROM + post_actions +WHERE + liked IS NOT NULL; + +CREATE TABLE post_saved ( + post_id int REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + published timestamptz DEFAULT now() NOT NULL, + PRIMARY KEY (person_id, post_id) +); + +INSERT INTO post_saved (post_id, person_id, published) +SELECT + post_id, + person_id, + saved +FROM + post_actions +WHERE + saved IS NOT NULL; + +DELETE FROM post_actions +WHERE read IS NULL; + +ALTER TABLE post_actions RENAME TO post_read; + +ALTER TABLE post_read RENAME COLUMN read TO published; + +ALTER TABLE post_read + DROP CONSTRAINT post_actions_check_read_comments, + DROP CONSTRAINT post_actions_check_liked, + ALTER COLUMN published SET NOT NULL, + ALTER COLUMN published SET DEFAULT now(), + DROP COLUMN read_comments, + DROP COLUMN read_comments_amount, + DROP COLUMN saved, + DROP COLUMN liked, + DROP COLUMN like_score, + DROP COLUMN hidden; + diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql new file mode 100644 index 000000000..54471e326 --- /dev/null +++ b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql @@ -0,0 +1,248 @@ +-- For each new actions table: +-- * Transform the table previously used for the most common action type into the new actions table, +-- which should only change the table's metadata instead of rewriting the rows +-- * Add actions from other old tables to the new table +-- +-- Create comment_actions from comment_like +ALTER TABLE comment_like RENAME TO comment_actions; + +ALTER TABLE comment_actions RENAME COLUMN published TO liked; + +ALTER TABLE comment_actions RENAME COLUMN score TO like_score; + +ALTER TABLE comment_actions + ALTER COLUMN liked DROP NOT NULL, + ALTER COLUMN liked DROP DEFAULT, + ALTER COLUMN like_score DROP NOT NULL, + ADD COLUMN saved timestamptz, + ADD CONSTRAINT comment_actions_check_liked CHECK ((liked IS NULL) = (like_score IS NULL)); + +WITH old_comment_saved AS ( + DELETE FROM comment_saved +RETURNING + *) + INSERT INTO comment_actions (person_id, comment_id, saved, post_id) + SELECT + old_comment_saved.person_id, + old_comment_saved.comment_id, + old_comment_saved.published, + comment.post_id + FROM + old_comment_saved + INNER JOIN COMMENT ON comment.id = old_comment_saved.comment_id + ON CONFLICT (person_id, + comment_id) + DO UPDATE SET + saved = excluded.saved; + +-- Create community_actions from community_follower +ALTER TABLE community_follower RENAME TO community_actions; + +ALTER TABLE community_actions RENAME COLUMN published TO followed; + +ALTER TABLE community_actions RENAME pending TO follow_pending; + +ALTER TABLE community_actions + ALTER COLUMN followed DROP NOT NULL, + ALTER COLUMN followed DROP DEFAULT, + ALTER COLUMN follow_pending DROP NOT NULL, + -- This `DROP DEFAULT` is done for community follow, but not person follow. It's not a mistake + -- in this migration. Believe it or not, `pending` only had a default value in community follow. + ALTER COLUMN follow_pending DROP DEFAULT, + ADD COLUMN blocked timestamptz, + ADD COLUMN became_moderator timestamptz, + ADD COLUMN received_ban timestamptz, + ADD COLUMN ban_expires timestamptz, + ADD CONSTRAINT community_actions_check_followed CHECK ((followed IS NULL) = (follow_pending IS NULL)), + ADD CONSTRAINT community_actions_check_received_ban CHECK ((received_ban IS NULL, ban_expires IS NULL) != (FALSE, TRUE)); + +WITH old_community_block AS ( + DELETE FROM community_block +RETURNING + *) + INSERT INTO community_actions (person_id, community_id, blocked) + SELECT + person_id, + community_id, + published + FROM + old_community_block + ON CONFLICT (person_id, + community_id) + DO UPDATE SET + person_id = excluded.person_id, + community_id = excluded.community_id, + blocked = excluded.blocked; + +WITH old_community_moderator AS ( + DELETE FROM community_moderator +RETURNING + *) + INSERT INTO community_actions (person_id, community_id, became_moderator) + SELECT + person_id, + community_id, + published + FROM + old_community_moderator + ON CONFLICT (person_id, + community_id) + DO UPDATE SET + person_id = excluded.person_id, + community_id = excluded.community_id, + became_moderator = excluded.became_moderator; + +WITH old_community_person_ban AS ( + DELETE FROM community_person_ban +RETURNING + *) + INSERT INTO community_actions (person_id, community_id, received_ban, ban_expires) + SELECT + person_id, + community_id, + published, + expires + FROM + old_community_person_ban + ON CONFLICT (person_id, + community_id) + DO UPDATE SET + person_id = excluded.person_id, + community_id = excluded.community_id, + received_ban = excluded.received_ban, + ban_expires = excluded.ban_expires; + +-- Create instance_actions from instance_block +ALTER TABLE instance_block RENAME TO instance_actions; + +ALTER TABLE instance_actions RENAME COLUMN published TO blocked; + +ALTER TABLE instance_actions + ALTER COLUMN blocked DROP NOT NULL, + ALTER COLUMN blocked DROP DEFAULT; + +-- Create person_actions from person_follower +ALTER TABLE person_follower RENAME TO person_actions; + +ALTER TABLE person_actions RENAME COLUMN person_id TO target_id; + +ALTER TABLE person_actions RENAME COLUMN follower_id TO person_id; + +ALTER TABLE person_actions RENAME COLUMN published TO followed; + +ALTER TABLE person_actions RENAME COLUMN pending TO follow_pending; + +ALTER TABLE person_actions + ALTER COLUMN followed DROP NOT NULL, + ALTER COLUMN followed DROP DEFAULT, + ALTER COLUMN follow_pending DROP NOT NULL, + ADD COLUMN blocked timestamptz, + ADD CONSTRAINT person_actions_check_followed CHECK ((followed IS NULL) = (follow_pending IS NULL)); + +WITH old_person_block AS ( + DELETE FROM person_block +RETURNING + *) + INSERT INTO person_actions (person_id, target_id, blocked) + SELECT + person_id, + target_id, + published + FROM + old_person_block + ON CONFLICT (person_id, + target_id) + DO UPDATE SET + person_id = excluded.person_id, + target_id = excluded.target_id, + blocked = excluded.blocked; + +-- Create post_actions from post_read +ALTER TABLE post_read RENAME TO post_actions; + +ALTER TABLE post_actions RENAME COLUMN published TO read; + +ALTER TABLE post_actions + ALTER COLUMN read DROP NOT NULL, + ALTER COLUMN read DROP DEFAULT, + ADD COLUMN read_comments timestamptz, + -- TODO make nullable + ADD COLUMN read_comments_amount bigint NOT NULL, + ADD COLUMN saved timestamptz, + ADD COLUMN liked timestamptz, + ADD COLUMN like_score smallint, + ADD COLUMN hidden timestamptz, + ADD CONSTRAINT post_actions_check_read_comments CHECK ((read_comments IS NULL) = (read_comments_amount IS NULL)), + ADD CONSTRAINT post_actions_check_liked CHECK ((liked IS NULL) = (like_score IS NULL)); + +WITH old_person_post_aggregates AS ( + DELETE FROM person_post_aggregates +RETURNING + *) + INSERT INTO post_actions (person_id, post_id, read_comments, read_comments_amount) + SELECT + person_id, + post_id, + published, + read_comments + FROM + old_person_post_aggregates + ON CONFLICT (person_id, + post_id) + DO UPDATE SET + read_comments = excluded.read_comments, + read_comments_amount = excluded.read_comments_amount; + +WITH old_post_hide AS ( + DELETE FROM post_hide +RETURNING + *) + INSERT INTO post_actions (person_id, post_id, hidden) + SELECT + person_id, + post_id, + published + FROM + old_post_hide + ON CONFLICT (person_id, + post_id) + DO UPDATE SET + hidden = excluded.hidden; + +WITH old_post_like AS ( + DELETE FROM post_like +RETURNING + *) + INSERT INTO post_actions (person_id, post_id, liked, like_score) + SELECT + person_id, + post_id, + published, + score + FROM + old_post_like + ON CONFLICT (person_id, + post_id) + DO UPDATE SET + liked = excluded.liked, + like_score = excluded.like_score; + +WITH old_post_saved AS ( + DELETE FROM post_saved +RETURNING + *) + INSERT INTO post_actions (person_id, post_id, saved) + SELECT + person_id, + post_id, + published + FROM + old_post_saved + ON CONFLICT (person_id, + post_id) + DO UPDATE SET + saved = excluded.saved; + +-- Drop old tables +DROP TABLE comment_saved, community_block, community_moderator, community_person_ban, person_block, person_post_aggregates, post_hide, post_like, post_saved; + From 530926f04396c2a076eea586a2a5e4f08f8203bc Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Thu, 4 Apr 2024 17:27:04 +0000 Subject: [PATCH 068/232] migrate indexes and contraints, and add statistics --- .../down.sql | 73 +++++++++ .../up.sql | 141 ++++++++++++++++++ 2 files changed, 214 insertions(+) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/down.sql b/migrations/2024-03-17-134311_smoosh-tables-together/down.sql index ac2e45ea7..685cd39d6 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/down.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/down.sql @@ -256,3 +256,76 @@ ALTER TABLE post_read DROP COLUMN like_score, DROP COLUMN hidden; +-- Rename associated stuff +ALTER INDEX comment_actions_pkey RENAME TO comment_like_pkey; + +ALTER INDEX idx_comment_actions_comment RENAME TO idx_comment_like_comment; + +ALTER INDEX idx_comment_actions_post RENAME TO idx_comment_like_post; + +ALTER TABLE comment_like RENAME CONSTRAINT comment_actions_comment_id_fkey TO comment_like_comment_id_fkey; + +ALTER TABLE comment_like RENAME CONSTRAINT comment_actions_person_id_fkey TO comment_like_person_id_fkey; + +ALTER TABLE comment_like RENAME CONSTRAINT comment_actions_post_id_fkey TO comment_like_post_id_fkey; + +ALTER INDEX community_actions_pkey RENAME TO community_follower_pkey; + +ALTER INDEX idx_community_actions_community RENAME TO idx_community_follower_community; + +ALTER TABLE community_follower RENAME CONSTRAINT community_actions_community_id_fkey TO community_follower_community_id_fkey; + +ALTER TABLE community_follower RENAME CONSTRAINT community_actions_person_id_fkey TO community_follower_person_id_fkey; + +ALTER INDEX instance_actions_pkey RENAME TO instance_block_pkey; + +ALTER TABLE instance_block RENAME CONSTRAINT instance_actions_instance_id_fkey TO instance_block_instance_id_fkey; + +ALTER TABLE instance_block RENAME CONSTRAINT instance_actions_person_id_fkey TO instance_block_person_id_fkey; + +ALTER INDEX person_actions_pkey RENAME TO person_follower_pkey; + +ALTER TABLE person_follower RENAME CONSTRAINT person_actions_target_id_fkey TO person_follower_person_id_fkey; + +ALTER TABLE person_follower RENAME CONSTRAINT person_actions_person_id_fkey TO person_follower_follower_id_fkey; + +ALTER INDEX post_actions_pkey RENAME TO post_read_pkey; + +ALTER TABLE post_read RENAME CONSTRAINT post_actions_person_id_fkey TO post_read_person_id_fkey; + +ALTER TABLE post_read RENAME CONSTRAINT post_actions_post_id_fkey TO post_read_post_id_fkey; + +-- Rename idx_community_actions_followed and remove filter +CREATE INDEX idx_community_follower_published ON community_follower (published); + +DROP INDEX idx_community_actions_followed; + +-- Move indexes back to their original tables +CREATE INDEX idx_comment_saved_comment ON comment_saved (comment_id); + +CREATE INDEX idx_comment_saved_person ON comment_saved (person_id); + +CREATE INDEX idx_community_block_community ON community_block (community_id); + +CREATE INDEX idx_community_moderator_community ON community_moderator (community_id); + +CREATE INDEX idx_community_moderator_published ON community_moderator (published); + +CREATE INDEX idx_person_block_person ON person_block (person_id); + +CREATE INDEX idx_person_block_target ON person_block (target_id); + +CREATE INDEX idx_person_post_aggregates_person ON person_post_aggregates (person_id); + +CREATE INDEX idx_person_post_aggregates_post ON person_post_aggregates (post_id); + +CREATE INDEX idx_post_like_post ON post_like (post_id); + +DROP INDEX idx_person_actions_person, idx_person_actions_target, idx_post_actions_person, idx_post_actions_post; + +-- Drop `NOT NULL` indexes of columns that still exist +DROP INDEX idx_comment_actions_liked_not_null, idx_community_actions_followed_not_null, idx_person_actions_followed_not_null, idx_post_actions_read_not_null, idx_instance_actions_blocked_not_null; + +-- Drop statistics of columns that still exist +DROP statistics comment_actions_liked_stat, community_actions_followed_stat, person_actions_followed_stat; + diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql index d6035dde8..7a21d6a05 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql @@ -245,3 +245,144 @@ RETURNING -- Drop old tables DROP TABLE comment_saved, community_block, community_moderator, community_person_ban, person_block, person_post_aggregates, post_hide, post_like, post_saved; +-- Rename associated stuff +ALTER INDEX comment_like_pkey RENAME TO comment_actions_pkey; + +ALTER INDEX idx_comment_like_comment RENAME TO idx_comment_actions_comment; + +ALTER INDEX idx_comment_like_post RENAME TO idx_comment_actions_post; + +ALTER TABLE comment_actions RENAME CONSTRAINT comment_like_comment_id_fkey TO comment_actions_comment_id_fkey; + +ALTER TABLE comment_actions RENAME CONSTRAINT comment_like_person_id_fkey TO comment_actions_person_id_fkey; + +ALTER TABLE comment_actions RENAME CONSTRAINT comment_like_post_id_fkey TO comment_actions_post_id_fkey; + +ALTER INDEX community_follower_pkey RENAME TO community_actions_pkey; + +ALTER INDEX idx_community_follower_community RENAME TO idx_community_actions_community; + +ALTER TABLE community_actions RENAME CONSTRAINT community_follower_community_id_fkey TO community_actions_community_id_fkey; + +ALTER TABLE community_actions RENAME CONSTRAINT community_follower_person_id_fkey TO community_actions_person_id_fkey; + +ALTER INDEX instance_block_pkey RENAME TO instance_actions_pkey; + +ALTER TABLE instance_actions RENAME CONSTRAINT instance_block_instance_id_fkey TO instance_actions_instance_id_fkey; + +ALTER TABLE instance_actions RENAME CONSTRAINT instance_block_person_id_fkey TO instance_actions_person_id_fkey; + +ALTER INDEX person_follower_pkey RENAME TO person_actions_pkey; + +ALTER TABLE person_actions RENAME CONSTRAINT person_follower_person_id_fkey TO person_actions_target_id_fkey; + +ALTER TABLE person_actions RENAME CONSTRAINT person_follower_follower_id_fkey TO person_actions_person_id_fkey; + +ALTER INDEX post_read_pkey RENAME TO post_actions_pkey; + +ALTER TABLE post_actions RENAME CONSTRAINT post_read_person_id_fkey TO post_actions_person_id_fkey; + +ALTER TABLE post_actions RENAME CONSTRAINT post_read_post_id_fkey TO post_actions_post_id_fkey; + +-- Rename idx_community_follower_published and add filter +CREATE INDEX idx_community_actions_followed ON community_actions (followed) +WHERE + followed IS NOT NULL; + +DROP INDEX idx_community_follower_published; + +-- Restore indexes of dropped tables +CREATE INDEX idx_community_actions_became_moderator ON community_actions (became_moderator) +WHERE + became_moderator IS NOT NULL; + +CREATE INDEX idx_person_actions_person ON person_actions (person_id); + +CREATE INDEX idx_person_actions_target ON person_actions (target_id); + +CREATE INDEX idx_post_actions_person ON post_actions (person_id); + +CREATE INDEX idx_post_actions_post ON post_actions (post_id); + +-- Create new indexes, with `OR` being used to allow `IS NOT NULL` filters in queries to use either column in +-- a group (e.g. `liked IS NOT NULL` and `like_score IS NOT NULL` both work) +CREATE INDEX idx_comment_actions_liked_not_null ON comment_actions (person_id, comment_id) +WHERE + liked IS NOT NULL OR like_score IS NOT NULL; + +CREATE INDEX idx_comment_actions_saved_not_null ON comment_actions (person_id, comment_id) +WHERE + saved IS NOT NULL; + +CREATE INDEX idx_community_actions_followed_not_null ON community_actions (person_id, community_id) +WHERE + followed IS NOT NULL OR follow_pending IS NOT NULL; + +CREATE INDEX idx_community_actions_blocked_not_null ON community_actions (person_id, community_id) +WHERE + blocked IS NOT NULL; + +CREATE INDEX idx_community_actions_became_moderator_not_null ON community_actions (person_id, community_id) +WHERE + became_moderator IS NOT NULL; + +CREATE INDEX idx_community_actions_received_ban_not_null ON community_actions (person_id, community_id) +WHERE + received_ban IS NOT NULL; + +CREATE INDEX idx_person_actions_followed_not_null ON person_actions (person_id, target_id) +WHERE + followed IS NOT NULL OR follow_pending IS NOT NULL; + +CREATE INDEX idx_person_actions_blocked_not_null ON person_actions (person_id, target_id) +WHERE + blocked IS NOT NULL; + +CREATE INDEX idx_post_actions_read_not_null ON post_actions (person_id, post_id) +WHERE + read IS NOT NULL; + +CREATE INDEX idx_post_actions_read_comments_not_null ON post_actions (person_id, post_id) +WHERE + read_comments IS NOT NULL OR read_comments IS NOT NULL; + +CREATE INDEX idx_post_actions_saved_not_null ON post_actions (person_id, post_id) +WHERE + saved IS NOT NULL; + +CREATE INDEX idx_post_actions_liked_not_null ON post_actions (person_id, post_id) +WHERE + liked IS NOT NULL OR like_score IS NOT NULL; + +CREATE INDEX idx_post_actions_hidden_not_null ON post_actions (person_id, post_id) +WHERE + hidden IS NOT NULL; + +-- This index is currently redundant because instance_actions only has 1 action type, but inconsistency +-- with other tables would make it harder to do everything correctly when adding another action type. If +-- omitting this index is significantly beneficial, then it should be done when indexes are declared outside +-- of migrations in `lemmy_db_schema::schema_setup` and adding this index doesn't require changing code that +-- isn't right next to the code that needs to be changed to add another action type to instance_actions. +CREATE INDEX idx_instance_actions_blocked_not_null ON instance_actions (person_id, instance_id) +WHERE + blocked IS NOT NULL; + +-- Create new statistics for more accurate estimations of how much of an index will be read (e.g. for +-- `(liked, like_score)`, the query planner might othewise assume that `(TRUE, FALSE)` and `(TRUE, TRUE)` +-- are equally likely when only `(TRUE, TRUE)` is possible, which would make it severely underestimate +-- the efficiency of using the index) +CREATE statistics comment_actions_liked_stat ON (liked IS NULL), (like_score IS NULL) +FROM comment_actions; + +CREATE statistics community_actions_followed_stat ON (followed IS NULL), (follow_pending IS NULL) +FROM community_actions; + +CREATE statistics person_actions_followed_stat ON (followed IS NULL), (follow_pending IS NULL) +FROM person_actions; + +CREATE statistics post_actions_read_comments_stat ON (read_comments IS NULL), (read_comments_amount IS NULL) +FROM post_actions; + +CREATE statistics post_actions_liked_stat ON (liked IS NULL), (like_score IS NULL) +FROM post_actions; + From ded71ddd19fbc705116e9257bf11affd59817666 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Fri, 5 Apr 2024 20:35:34 +0000 Subject: [PATCH 069/232] fix what appears to be a messed up merge --- crates/api_common/src/build_response.rs | 91 +++++++++++++------------ 1 file changed, 48 insertions(+), 43 deletions(-) diff --git a/crates/api_common/src/build_response.rs b/crates/api_common/src/build_response.rs index 6fb96e113..19e0bb46b 100644 --- a/crates/api_common/src/build_response.rs +++ b/crates/api_common/src/build_response.rs @@ -112,7 +112,7 @@ pub async fn send_local_notifs( if let Ok(mention_user_view) = user_view { // TODO // At some point, make it so you can't tag the parent creator either - // This can cause two notifications, one for reply and the other for mention + // Potential duplication of notifications, one for reply and the other for mention, is handled below by checking recipient ids recipient_ids.push(mention_user_view.local_user.id); let user_mention_form = PersonMentionInsertForm { @@ -163,30 +163,33 @@ pub async fn send_local_notifs( if parent_comment.creator_id != person.id && !check_blocks { let user_view = LocalUserView::read_person(&mut context.pool(), parent_creator_id).await; if let Ok(parent_user_view) = user_view { - recipient_ids.push(parent_user_view.local_user.id); + // Don't duplicate notif if already mentioned by checking recipient ids + if !recipient_ids.contains(&parent_user_view.local_user.id) { + recipient_ids.push(parent_user_view.local_user.id); - let comment_reply_form = CommentReplyInsertForm { - recipient_id: parent_user_view.person.id, - comment_id: comment.id, - read: None, - }; + let comment_reply_form = CommentReplyInsertForm { + recipient_id: parent_user_view.person.id, + comment_id: comment.id, + read: None, + }; - // Allow this to fail softly, since comment edits might re-update or replace it - // Let the uniqueness handle this fail - CommentReply::create(&mut context.pool(), &comment_reply_form) - .await - .ok(); + // Allow this to fail softly, since comment edits might re-update or replace it + // Let the uniqueness handle this fail + CommentReply::create(&mut context.pool(), &comment_reply_form) + .await + .ok(); - if do_send_email { - let lang = get_interface_language(&parent_user_view); - let content = markdown_to_html(&comment.content); - send_email_to_user( - &parent_user_view, - &lang.notification_comment_reply_subject(&person.name), - &lang.notification_comment_reply_body(&content, &inbox_link, &person.name), - context.settings(), - ) - .await + if do_send_email { + let lang = get_interface_language(&parent_user_view); + let content = markdown_to_html(&comment.content); + send_email_to_user( + &parent_user_view, + &lang.notification_comment_reply_subject(&person.name), + &lang.notification_comment_reply_body(&content, &inbox_link, &person.name), + context.settings(), + ) + .await + } } } } @@ -205,30 +208,32 @@ pub async fn send_local_notifs( let creator_id = post.creator_id; let parent_user = LocalUserView::read_person(&mut context.pool(), creator_id).await; if let Ok(parent_user_view) = parent_user { - recipient_ids.push(parent_user_view.local_user.id); + if !recipient_ids.contains(&parent_user_view.local_user.id) { + recipient_ids.push(parent_user_view.local_user.id); - let comment_reply_form = CommentReplyInsertForm { - recipient_id: parent_user_view.person.id, - comment_id: comment.id, - read: None, - }; + let comment_reply_form = CommentReplyInsertForm { + recipient_id: parent_user_view.person.id, + comment_id: comment.id, + read: None, + }; - // Allow this to fail softly, since comment edits might re-update or replace it - // Let the uniqueness handle this fail - CommentReply::create(&mut context.pool(), &comment_reply_form) - .await - .ok(); + // Allow this to fail softly, since comment edits might re-update or replace it + // Let the uniqueness handle this fail + CommentReply::create(&mut context.pool(), &comment_reply_form) + .await + .ok(); - if do_send_email { - let lang = get_interface_language(&parent_user_view); - let content = markdown_to_html(&comment.content); - send_email_to_user( - &parent_user_view, - &lang.notification_post_reply_subject(&person.name), - &lang.notification_post_reply_body(&content, &inbox_link, &person.name), - context.settings(), - ) - .await + if do_send_email { + let lang = get_interface_language(&parent_user_view); + let content = markdown_to_html(&comment.content); + send_email_to_user( + &parent_user_view, + &lang.notification_post_reply_subject(&person.name), + &lang.notification_post_reply_body(&content, &inbox_link, &person.name), + context.settings(), + ) + .await + } } } } From afec4c0cfdf589a29bbd93f1bc51fdc44cee0f20 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Sun, 21 Apr 2024 14:38:46 +0000 Subject: [PATCH 070/232] commented thing --- .../up.sql | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql index 7a21d6a05..73fcc55bd 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql @@ -386,3 +386,39 @@ FROM post_actions; CREATE statistics post_actions_liked_stat ON (liked IS NULL), (like_score IS NULL) FROM post_actions; +-- TODO: move to replaceable_schema +/*CREATE SCHEMA IF NOT EXISTS r; + +CREATE FUNCTION r.delete_empty_comment_actions () + RETURNS TRIGGER + LANGUAGE plpgsql + AS $$ +BEGIN + DELETE FROM comment_actions USING ( + SELECT + (person_id, + comment_id, + post_id, + NULL, + NULL, + NULL) AS row_with_nulls + FROM + new_row + WHERE (new_row.*) = row_with_nulls) AS rows_to_check +WHERE (comment_actions.*) = row_with_nulls +END; +$$; +uplete::delete_empty(comment_actions::table, (comment_actions::person_id, comment_actions::comment_id, comment_actions::post_id, ))*/ + +/*WITH + update_result AS (UPDATE post_actions SET like_score = NULL, liked = NULL RETURNING *) +DELETE FROM post_actions +USING ( + -- I tried to put these selected values in a tuple with a name that can be referenced in the `WHERE` clause, but the name throws a parse error in the `WHERE` clause + SELECT post_actions.post_id, post_actions.person_id, NULL, NULL, NULL, NULL, NULL, NULL, NULL + FROM update_result AS post_actions + -- This check only affects performance, and it can't replace the `(post_actions.*) = (rows_with_nulls.*)` check below because this one is done before locking the rows + WHERE (post_actions.*) = (post_actions.post_id, post_actions.person_id, NULL, NULL, NULL, NULL, NULL, NULL, NULL) +) AS rows_with_nulls +WHERE (post_actions.*) = (rows_with_nulls.*);*/ + From a09f8a8e7ee3aabf4067f0042dc5db3798f2104d Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 07:18:05 -0700 Subject: [PATCH 071/232] Create uplete.rs --- crates/db_schema/src/utils/uplete.rs | 44 ++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 crates/db_schema/src/utils/uplete.rs diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs new file mode 100644 index 000000000..bd5205aa0 --- /dev/null +++ b/crates/db_schema/src/utils/uplete.rs @@ -0,0 +1,44 @@ +use diesel::{ + dsl, + expression::{is_aggregate, ValidGrouping}, + pg::Pg, + query_builder::{AsQuery, AstPass, QueryFragment}, + result::Error, + sql_types, + AppearsOnTable, + Expression, + Insertable, + QueryId, + SelectableExpression, + Table, +}; + +#[derive(QueryId)] +pub struct Uplete { + pub table: T, + pub update_values: U, + pub empty_row: E, +} + +impl + Table, U: QueryFragment, E: QueryFragment> QueryFragment for Uplete { + fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> Result<(), Error> { + out.push_sql("WITH update_result AS (UPDATE "); + self.update_values.walk_ast(out.reborrow())?; + self.push_sql(" RETURNING "); + self.table.all_columns().walk_ast(out.reborrow())?; + self.push_sql(") DELETE FROM "); + self.table.walk_ast(out.reborrow())?; + self.push_sql(" WHERE ("); + self.table.primary_key().walk_ast(out.reborrow())?; + self.push_sql(") = ANY (SELECT ("); + // In the parts below, `self.table` refers to `update_result` + self.table.primary_key().walk_ast(out.reborrow())?; + self.push_sql(") FROM update_result AS "); + self.table.walk_ast(out.reborrow())?; + self.push_sql(" WHERE ("); + self.table.all_columns().walk_ast(out.reborrow())?; + self.push_sql(") = ("); + self.empty_row.walk_ast(out.reborrow())?; + self.push_sql("))"); + } +} From bf541d7adb3664843a25bcbac4bc1cc75f3d1cb5 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 10:47:16 -0700 Subject: [PATCH 072/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 55 +++++++++++++++++++++------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index bd5205aa0..1d299f257 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -1,8 +1,8 @@ use diesel::{ dsl, - expression::{is_aggregate, ValidGrouping}, + expression::{is_aggregate, NonAggregate, ValidGrouping}, pg::Pg, - query_builder::{AsQuery, AstPass, QueryFragment}, + query_builder::{AsQuery, AstPass, QueryFragment, UpdateStatement}, result::Error, sql_types, AppearsOnTable, @@ -13,30 +13,57 @@ use diesel::{ Table, }; -#[derive(QueryId)] -pub struct Uplete { - pub table: T, - pub update_values: U, - pub empty_row: E, +pub trait UpleteTable: Table + Default { + type EmptyRow: Default + AsExpression>; } -impl + Table, U: QueryFragment, E: QueryFragment> QueryFragment for Uplete { +pub trait OrDelete { + type Output; + + fn or_delete() -> Self::Output; +} + +impl OrDelete for UpdateStatement { + type Output = SetOrDeleteQuery; + + fn or_delete() -> Self::Output { + SetOrDeleteQuery { + table: T::default(), + primary_key: T::primary_key(), + all_columns: T::all_columns(), + update_values: + } + } +} + +impl Uplete + +#[derive(QueryId)] +struct SetOrDeleteQuery { + table: T, + primary_key: PK, + all_columns: C, + update_statement: U, + empty_row: E, +} + +impl, PK: QueryFragment, C: QueryFragment, U: QueryFragment, E: QueryFragment> QueryFragment for SetOrDeleteQuery { fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> Result<(), Error> { - out.push_sql("WITH update_result AS (UPDATE "); - self.update_values.walk_ast(out.reborrow())?; + out.push_sql("WITH update_result AS ("); + self.update_statement.walk_ast(out.reborrow())?; self.push_sql(" RETURNING "); - self.table.all_columns().walk_ast(out.reborrow())?; + self.all_columns.walk_ast(out.reborrow())?; self.push_sql(") DELETE FROM "); self.table.walk_ast(out.reborrow())?; self.push_sql(" WHERE ("); - self.table.primary_key().walk_ast(out.reborrow())?; + self.primary_key.walk_ast(out.reborrow())?; self.push_sql(") = ANY (SELECT ("); // In the parts below, `self.table` refers to `update_result` - self.table.primary_key().walk_ast(out.reborrow())?; + self.primary_key.walk_ast(out.reborrow())?; self.push_sql(") FROM update_result AS "); self.table.walk_ast(out.reborrow())?; self.push_sql(" WHERE ("); - self.table.all_columns().walk_ast(out.reborrow())?; + self.all_columns.walk_ast(out.reborrow())?; self.push_sql(") = ("); self.empty_row.walk_ast(out.reborrow())?; self.push_sql("))"); From 43813cfcd76b57163ff326aed4ff4967a81b7c74 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 10:57:47 -0700 Subject: [PATCH 073/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 1d299f257..abc34f492 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -20,26 +20,25 @@ pub trait UpleteTable: Table + Default { pub trait OrDelete { type Output; - fn or_delete() -> Self::Output; + fn or_delete(self) -> Self::Output; } impl OrDelete for UpdateStatement { - type Output = SetOrDeleteQuery; + type Output = SetOrDeleteQuery>; - fn or_delete() -> Self::Output { + fn or_delete(self) -> Self::Output { SetOrDeleteQuery { table: T::default(), primary_key: T::primary_key(), all_columns: T::all_columns(), - update_values: + update_statement: self, + empty_row: T::EmptyRow::default().as_expression(); } } } -impl Uplete - #[derive(QueryId)] -struct SetOrDeleteQuery { +pub struct SetOrDeleteQuery { table: T, primary_key: PK, all_columns: C, @@ -49,23 +48,31 @@ struct SetOrDeleteQuery { impl, PK: QueryFragment, C: QueryFragment, U: QueryFragment, E: QueryFragment> QueryFragment for SetOrDeleteQuery { fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> Result<(), Error> { + // `update_result` CTE with new rows out.push_sql("WITH update_result AS ("); self.update_statement.walk_ast(out.reborrow())?; self.push_sql(" RETURNING "); self.all_columns.walk_ast(out.reborrow())?; + + // Delete self.push_sql(") DELETE FROM "); self.table.walk_ast(out.reborrow())?; self.push_sql(" WHERE ("); self.primary_key.walk_ast(out.reborrow())?; + + // Select from `update_result` with an alias that matches the original table's name self.push_sql(") = ANY (SELECT ("); - // In the parts below, `self.table` refers to `update_result` self.primary_key.walk_ast(out.reborrow())?; self.push_sql(") FROM update_result AS "); self.table.walk_ast(out.reborrow())?; + + // Filter the select statement self.push_sql(" WHERE ("); self.all_columns.walk_ast(out.reborrow())?; - self.push_sql(") = ("); + self.push_sql(") IS NOT DISTINCT FROM ("); self.empty_row.walk_ast(out.reborrow())?; self.push_sql("))"); + + Ok(()) } } From 3ae5eef294b0e8a2153ee18d984c4537d919588f Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 11:02:26 -0700 Subject: [PATCH 074/232] Update up.sql --- .../up.sql | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql index 73fcc55bd..7a21d6a05 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql @@ -386,39 +386,3 @@ FROM post_actions; CREATE statistics post_actions_liked_stat ON (liked IS NULL), (like_score IS NULL) FROM post_actions; --- TODO: move to replaceable_schema -/*CREATE SCHEMA IF NOT EXISTS r; - -CREATE FUNCTION r.delete_empty_comment_actions () - RETURNS TRIGGER - LANGUAGE plpgsql - AS $$ -BEGIN - DELETE FROM comment_actions USING ( - SELECT - (person_id, - comment_id, - post_id, - NULL, - NULL, - NULL) AS row_with_nulls - FROM - new_row - WHERE (new_row.*) = row_with_nulls) AS rows_to_check -WHERE (comment_actions.*) = row_with_nulls -END; -$$; -uplete::delete_empty(comment_actions::table, (comment_actions::person_id, comment_actions::comment_id, comment_actions::post_id, ))*/ - -/*WITH - update_result AS (UPDATE post_actions SET like_score = NULL, liked = NULL RETURNING *) -DELETE FROM post_actions -USING ( - -- I tried to put these selected values in a tuple with a name that can be referenced in the `WHERE` clause, but the name throws a parse error in the `WHERE` clause - SELECT post_actions.post_id, post_actions.person_id, NULL, NULL, NULL, NULL, NULL, NULL, NULL - FROM update_result AS post_actions - -- This check only affects performance, and it can't replace the `(post_actions.*) = (rows_with_nulls.*)` check below because this one is done before locking the rows - WHERE (post_actions.*) = (post_actions.post_id, post_actions.person_id, NULL, NULL, NULL, NULL, NULL, NULL, NULL) -) AS rows_with_nulls -WHERE (post_actions.*) = (rows_with_nulls.*);*/ - From 10b30095395e5f7043f3b35ee65f2fd879cd6a6f Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 11:27:26 -0700 Subject: [PATCH 075/232] Update comment.rs --- crates/db_schema/src/impls/comment.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index 5cca0de23..001e4068b 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -12,7 +12,15 @@ use crate::{ CommentUpdateForm, }, traits::{Crud, Likeable, Saveable}, - utils::{functions::coalesce, get_conn, naive_now, now, DbPool, DELETED_REPLACEMENT_TEXT}, + utils::{ + functions::coalesce, + get_conn, + naive_now, + now, + uplete::{OrDelete, UpleteTable}, + DbPool, + DELETED_REPLACEMENT_TEXT, + }, }; use chrono::{DateTime, Utc}; use diesel::{ @@ -26,6 +34,17 @@ use diesel_async::RunQueryDsl; use diesel_ltree::Ltree; use url::Url; +impl UpleteTable for comment_actions::table { + type EmptyRow = ( + comment_actions::person_id, + comment_actions::comment_id, + comment_actions::post_id, + None::, + None::, + None::, + ); +} + impl Comment { pub async fn permadelete_for_creator( pool: &mut DbPool<'_>, @@ -189,6 +208,7 @@ impl Likeable for CommentLike { comment_actions::like_score.eq(None::), comment_actions::liked.eq(None::>), )) + .or_delete() .execute(conn) .await } @@ -238,6 +258,7 @@ impl Saveable for CommentSaved { comment_actions::table.find((comment_saved_form.person_id, comment_saved_form.comment_id)), ) .set(comment_actions::saved.eq(None::>)) + .or_delete() .execute(conn) .await } From 59f41b20acf2a73bd625f1eea1c7ddee34cab37f Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 11:39:09 -0700 Subject: [PATCH 076/232] Update Cargo.toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f1809592d..c95e7350c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -167,7 +167,7 @@ moka = { version = "0.12.7", features = ["future"] } i-love-jesus = { version = "0.1.0" } clap = { version = "4.5.4", features = ["derive", "env"] } pretty_assertions = "1.4.0" -diesel-bind-if-some = { path = "../diesel-utils/crates/diesel-bind-if-some" } +diesel-bind-if-some = "0.1.0" [dependencies] lemmy_api = { workspace = true } From 3dc483c70816c2078bfed304790fb011f30218a5 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 11:41:35 -0700 Subject: [PATCH 077/232] Update comment.rs --- crates/db_schema/src/impls/comment.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index 001e4068b..a500e4f81 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -39,9 +39,9 @@ impl UpleteTable for comment_actions::table { comment_actions::person_id, comment_actions::comment_id, comment_actions::post_id, - None::, - None::, - None::, + None, + None, + None, ); } From 0174029794de2f770aa53ec766275916aad02f3c Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 11:42:42 -0700 Subject: [PATCH 078/232] Update post.rs --- crates/db_schema/src/impls/post.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index 2b7046114..a3b389a51 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -246,8 +246,8 @@ impl Post { } } -// TODO: replace `as_select_unwrap` definitions with `Default::default()` after next Diesel release which should -// implement `Default` for `AssumeNotNull` +// TODO: replace `as_select_unwrap` definitions with `Default::default()` after next Diesel release +// which should implement `Default` for `AssumeNotNull` impl PostLike { fn as_select_unwrap() -> ( post_actions::post_id, From 2b584e25f553610ea6cc17e6af18efc54d787948 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 11:44:25 -0700 Subject: [PATCH 079/232] Update comment_view.rs --- crates/db_views/src/comment_view.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs index 46c1d053a..8b4a6f2a0 100644 --- a/crates/db_views/src/comment_view.rs +++ b/crates/db_views/src/comment_view.rs @@ -174,9 +174,13 @@ fn queries<'a>() -> Queries< if let Some(my_id) = my_person_id { let not_creator_filter = comment::creator_id.ne(my_id); if options.liked_only { - query = query.filter(not_creator_filter).filter(comment_actions::like_score.eq(1)); + query = query + .filter(not_creator_filter) + .filter(comment_actions::like_score.eq(1)); } else if options.disliked_only { - query = query.filter(not_creator_filter).filter(comment_actions::like_score.eq(-1)); + query = query + .filter(not_creator_filter) + .filter(comment_actions::like_score.eq(-1)); } } From c4fba2840f3d95c4de970709cfb9772884202946 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 11:45:11 -0700 Subject: [PATCH 080/232] Update post_view.rs --- crates/db_views/src/post_view.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 52c27499e..713e8392d 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -283,9 +283,13 @@ fn queries<'a>() -> Queries< if let Some(my_id) = my_person_id { let not_creator_filter = post_aggregates::creator_id.ne(my_id); if options.liked_only { - query = query.filter(not_creator_filter).filter(post_actions::like_score.eq(1)); + query = query + .filter(not_creator_filter) + .filter(post_actions::like_score.eq(1)); } else if options.disliked_only { - query = query.filter(not_creator_filter).filter(post_actions::like_score.eq(-1)); + query = query + .filter(not_creator_filter) + .filter(post_actions::like_score.eq(-1)); } }; From 2de949985820e8aab3fe0fc97d6269b89d90781d Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 11:46:16 -0700 Subject: [PATCH 081/232] Update comment_reply_view.rs --- crates/db_views_actor/src/comment_reply_view.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/db_views_actor/src/comment_reply_view.rs b/crates/db_views_actor/src/comment_reply_view.rs index f2de64b6b..86c5a0e91 100644 --- a/crates/db_views_actor/src/comment_reply_view.rs +++ b/crates/db_views_actor/src/comment_reply_view.rs @@ -1,5 +1,12 @@ use crate::structs::CommentReplyView; -use diesel::{dsl::not, pg::Pg, result::Error, ExpressionMethods, NullableExpressionMethods, QueryDsl}; +use diesel::{ + dsl::not, + pg::Pg, + result::Error, + ExpressionMethods, + NullableExpressionMethods, + QueryDsl, +}; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ aliases::{self, creator_community_actions}, From ed7fcc620d29f12a1b913d2ad37d680c853f3a94 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 12:05:56 -0700 Subject: [PATCH 082/232] Update person_mention_view.rs --- crates/db_views_actor/src/person_mention_view.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/db_views_actor/src/person_mention_view.rs b/crates/db_views_actor/src/person_mention_view.rs index 071b5ccba..eca95f30c 100644 --- a/crates/db_views_actor/src/person_mention_view.rs +++ b/crates/db_views_actor/src/person_mention_view.rs @@ -1,5 +1,12 @@ use crate::structs::PersonMentionView; -use diesel::{dsl::not, pg::Pg, result::Error, ExpressionMethods, NullableExpressionMethods, QueryDsl}; +use diesel::{ + dsl::not, + pg::Pg, + result::Error, + ExpressionMethods, + NullableExpressionMethods, + QueryDsl, +}; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ aliases::{self, creator_community_actions}, From db475a9b263aef7cad23343973f3278c36ebdb00 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 12:10:49 -0700 Subject: [PATCH 083/232] Update Cargo.toml --- crates/db_schema/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/db_schema/Cargo.toml b/crates/db_schema/Cargo.toml index 15df6e39a..5adc04dc1 100644 --- a/crates/db_schema/Cargo.toml +++ b/crates/db_schema/Cargo.toml @@ -38,6 +38,7 @@ full = [ "tokio-postgres-rustls", "rustls", "i-love-jesus", + "diesel-bind-if-some", ] [dependencies] @@ -80,7 +81,7 @@ rustls = { workspace = true, optional = true } uuid = { workspace = true, features = ["v4"] } i-love-jesus = { workspace = true, optional = true } anyhow = { workspace = true } -diesel-bind-if-some = { workspace = true } +diesel-bind-if-some = { workspace = true, optional = true } moka.workspace = true [dev-dependencies] From 4f70eb18f5519f93cd4b075325185f3f2672aad0 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 12:16:20 -0700 Subject: [PATCH 084/232] Update utils.rs --- crates/db_schema/src/utils.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index da9c1129d..f78176036 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -1,3 +1,5 @@ +pub mod uplete; + use crate::{newtypes::DbUrl, CommentSortType, SortType}; use chrono::{DateTime, TimeDelta, Utc}; use deadpool::Runtime; From 7de09157453d516da129fc4da2777d3182955f2b Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 12:17:47 -0700 Subject: [PATCH 085/232] Update comment.rs --- crates/db_schema/src/impls/comment.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index a500e4f81..7dce1d02e 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -24,7 +24,7 @@ use crate::{ }; use chrono::{DateTime, Utc}; use diesel::{ - dsl::{self, insert_into, sql_query}, + dsl::{self, insert_into}, result::Error, ExpressionMethods, NullableExpressionMethods, @@ -39,9 +39,9 @@ impl UpleteTable for comment_actions::table { comment_actions::person_id, comment_actions::comment_id, comment_actions::post_id, - None, - None, - None, + Option, + Option, + Option, ); } From 3d5140e0a78682bb26a28b9918d417f6b391e4e5 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 12:19:41 -0700 Subject: [PATCH 086/232] Update utils.rs --- crates/db_schema/src/utils.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index f78176036..c44f4576e 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -24,7 +24,6 @@ use diesel::{ JoinOnDsl, NullableExpressionMethods, OptionalExtension, - PgConnection, QuerySource, Table, }; From 88a7ab596eb0c86ecfd49137a80c00c63b2d68f3 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 12:24:39 -0700 Subject: [PATCH 087/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index abc34f492..92d7e1591 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -32,7 +32,7 @@ impl OrDelete for UpdateStatement { primary_key: T::primary_key(), all_columns: T::all_columns(), update_statement: self, - empty_row: T::EmptyRow::default().as_expression(); + empty_row: T::EmptyRow::default().as_expression(), } } } @@ -46,7 +46,13 @@ pub struct SetOrDeleteQuery { empty_row: E, } -impl, PK: QueryFragment, C: QueryFragment, U: QueryFragment, E: QueryFragment> QueryFragment for SetOrDeleteQuery { +impl< + T: QueryFragment, + PK: QueryFragment, + C: QueryFragment, + U: QueryFragment, + E: QueryFragment, +> QueryFragment for SetOrDeleteQuery { fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> Result<(), Error> { // `update_result` CTE with new rows out.push_sql("WITH update_result AS ("); From dacdda2a921dad72caeaeb90e023c113b704a302 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 12:29:14 -0700 Subject: [PATCH 088/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 92d7e1591..af635939e 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -24,7 +24,8 @@ pub trait OrDelete { } impl OrDelete for UpdateStatement { - type Output = SetOrDeleteQuery>; + type Output = + SetOrDeleteQuery>; fn or_delete(self) -> Self::Output { SetOrDeleteQuery { @@ -47,12 +48,13 @@ pub struct SetOrDeleteQuery { } impl< - T: QueryFragment, - PK: QueryFragment, - C: QueryFragment, - U: QueryFragment, - E: QueryFragment, -> QueryFragment for SetOrDeleteQuery { + T: QueryFragment, + PK: QueryFragment, + C: QueryFragment, + U: QueryFragment, + E: QueryFragment, + > QueryFragment for SetOrDeleteQuery +{ fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> Result<(), Error> { // `update_result` CTE with new rows out.push_sql("WITH update_result AS ("); From 0b1132d6458b6167e3c44e9808e506f5a1f607b8 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 13:05:07 -0700 Subject: [PATCH 089/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index af635939e..858b03e1d 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -1,15 +1,11 @@ use diesel::{ dsl, - expression::{is_aggregate, NonAggregate, ValidGrouping}, + expression::AsExpression, pg::Pg, query_builder::{AsQuery, AstPass, QueryFragment, UpdateStatement}, result::Error, sql_types, - AppearsOnTable, - Expression, - Insertable, QueryId, - SelectableExpression, Table, }; @@ -53,7 +49,7 @@ impl< C: QueryFragment, U: QueryFragment, E: QueryFragment, - > QueryFragment for SetOrDeleteQuery + > QueryFragment for SetOrDeleteQuery { fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> Result<(), Error> { // `update_result` CTE with new rows From 235e5471702faa7ae4c18b735c6f6c18585a693b Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 13:05:43 -0700 Subject: [PATCH 090/232] Update comment.rs --- crates/db_schema/src/impls/comment.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index 7dce1d02e..b1c6bf9ca 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -40,8 +40,8 @@ impl UpleteTable for comment_actions::table { comment_actions::comment_id, comment_actions::post_id, Option, - Option, - Option, + Option>, + Option>, ); } From 3980cf1aec773c38a00b9388f45bbd0265c2de44 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 13:21:32 -0700 Subject: [PATCH 091/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 858b03e1d..9d36ed864 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -2,7 +2,7 @@ use diesel::{ dsl, expression::AsExpression, pg::Pg, - query_builder::{AsQuery, AstPass, QueryFragment, UpdateStatement}, + query_builder::{AstPass, QueryFragment, UpdateStatement}, result::Error, sql_types, QueryId, @@ -10,7 +10,7 @@ use diesel::{ }; pub trait UpleteTable: Table + Default { - type EmptyRow: Default + AsExpression>; + type EmptyRow; } pub trait OrDelete { @@ -19,7 +19,10 @@ pub trait OrDelete { fn or_delete(self) -> Self::Output; } -impl OrDelete for UpdateStatement { +impl OrDelete for UpdateStatement +where + T::EmptyRow: Default + AsExpression>, +{ type Output = SetOrDeleteQuery>; From 9d5f9caec05785e687671e0fd8cb19c066264f5f Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 13:36:39 -0700 Subject: [PATCH 092/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 9d36ed864..18ca134ba 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -1,6 +1,6 @@ use diesel::{ dsl, - expression::AsExpression, + expression::{AsExpression, SqlType, TypedExpressionType}, pg::Pg, query_builder::{AstPass, QueryFragment, UpdateStatement}, result::Error, @@ -21,6 +21,7 @@ pub trait OrDelete { impl OrDelete for UpdateStatement where + T::SqlType: SqlType + TypedExpressionType, T::EmptyRow: Default + AsExpression>, { type Output = From 237a38a1285a539498e36de54e07254882693717 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 13:53:59 -0700 Subject: [PATCH 093/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 18ca134ba..7f9c07de8 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -1,6 +1,6 @@ use diesel::{ dsl, - expression::{AsExpression, SqlType, TypedExpressionType}, + expression::{AsExpression, TypedExpressionType}, pg::Pg, query_builder::{AstPass, QueryFragment, UpdateStatement}, result::Error, @@ -21,7 +21,7 @@ pub trait OrDelete { impl OrDelete for UpdateStatement where - T::SqlType: SqlType + TypedExpressionType, + T::SqlType: sql_types::SqlType + TypedExpressionType, T::EmptyRow: Default + AsExpression>, { type Output = From df2d77693014d9cc1f9a1c8be2f4c46a2b0da8e4 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 14:11:09 -0700 Subject: [PATCH 094/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 7f9c07de8..4ceb8feff 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -25,7 +25,7 @@ where T::EmptyRow: Default + AsExpression>, { type Output = - SetOrDeleteQuery>; + SetOrDeleteQuery>>; fn or_delete(self) -> Self::Output { SetOrDeleteQuery { @@ -77,9 +77,9 @@ impl< // Filter the select statement self.push_sql(" WHERE ("); self.all_columns.walk_ast(out.reborrow())?; - self.push_sql(") IS NOT DISTINCT FROM ("); + self.push_sql(") IS NOT DISTINCT FROM "); self.empty_row.walk_ast(out.reborrow())?; - self.push_sql("))"); + self.push_sql(")"); Ok(()) } From e1aaf802ad41cbcaba01063a19a0d7df8ca4fd68 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 14:21:19 -0700 Subject: [PATCH 095/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 4ceb8feff..41c86fe03 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -24,8 +24,13 @@ where T::SqlType: sql_types::SqlType + TypedExpressionType, T::EmptyRow: Default + AsExpression>, { - type Output = - SetOrDeleteQuery>>; + type Output = SetOrDeleteQuery< + T, + T::PrimaryKey, + T::AllColumns, + Self, + dsl::AsExprOf>, + >; fn or_delete(self) -> Self::Output { SetOrDeleteQuery { From d68b3ad41f72bd9e12aedb679606efdb7b093a7c Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 14:47:16 -0700 Subject: [PATCH 096/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 41c86fe03..f199840c7 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -35,7 +35,7 @@ where fn or_delete(self) -> Self::Output { SetOrDeleteQuery { table: T::default(), - primary_key: T::primary_key(), + primary_key: T::default().primary_key(), all_columns: T::all_columns(), update_statement: self, empty_row: T::EmptyRow::default().as_expression(), @@ -64,27 +64,27 @@ impl< // `update_result` CTE with new rows out.push_sql("WITH update_result AS ("); self.update_statement.walk_ast(out.reborrow())?; - self.push_sql(" RETURNING "); + out.push_sql(" RETURNING "); self.all_columns.walk_ast(out.reborrow())?; // Delete - self.push_sql(") DELETE FROM "); + out.push_sql(") DELETE FROM "); self.table.walk_ast(out.reborrow())?; - self.push_sql(" WHERE ("); + out.push_sql(" WHERE ("); self.primary_key.walk_ast(out.reborrow())?; // Select from `update_result` with an alias that matches the original table's name - self.push_sql(") = ANY (SELECT ("); + out.push_sql(") = ANY (SELECT ("); self.primary_key.walk_ast(out.reborrow())?; - self.push_sql(") FROM update_result AS "); + out.push_sql(") FROM update_result AS "); self.table.walk_ast(out.reborrow())?; // Filter the select statement - self.push_sql(" WHERE ("); + out.push_sql(" WHERE ("); self.all_columns.walk_ast(out.reborrow())?; - self.push_sql(") IS NOT DISTINCT FROM "); + out.push_sql(") IS NOT DISTINCT FROM "); self.empty_row.walk_ast(out.reborrow())?; - self.push_sql(")"); + out.push_sql(")"); Ok(()) } From 0945a760950f41abdf2f30e54d6f1e459189bf9f Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 15:13:18 -0700 Subject: [PATCH 097/232] Update comment_view.rs --- crates/db_views/src/comment_view.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs index 8b4a6f2a0..4a67ef8a2 100644 --- a/crates/db_views/src/comment_view.rs +++ b/crates/db_views/src/comment_view.rs @@ -1,6 +1,6 @@ use crate::structs::{CommentView, LocalUserView}; use diesel::{ - dsl::exists, + dsl::{exists, not}, pg::Pg, result::Error, BoolExpressionMethods, From efc47c9bd8c6be5069a90485b27acc1f72a10769 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 15:13:39 -0700 Subject: [PATCH 098/232] Update post_view.rs --- crates/db_views/src/post_view.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 713e8392d..1cf1aad1d 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -1,7 +1,7 @@ use crate::structs::{LocalUserView, PaginationCursor, PostView}; use diesel::{ debug_query, - dsl::{exists, IntervalDsl}, + dsl::{exists, not, IntervalDsl}, pg::Pg, query_builder::AsQuery, result::Error, From beb3b9f5d95450c042215d6ca86b3060db974768 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 18:24:46 -0700 Subject: [PATCH 099/232] Update triggers.sql --- crates/db_schema/replaceable_schema/triggers.sql | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/db_schema/replaceable_schema/triggers.sql b/crates/db_schema/replaceable_schema/triggers.sql index fa5b01018..1ab62a66f 100644 --- a/crates/db_schema/replaceable_schema/triggers.sql +++ b/crates/db_schema/replaceable_schema/triggers.sql @@ -33,7 +33,7 @@ AS $a$ BEGIN EXECUTE replace($b$ -- When a thing gets a vote, update its aggregates and its creator's aggregates - CALL r.create_triggers ('thing_like', $$ + CALL r.create_triggers ('thing_actions', $$ BEGIN WITH thing_diff AS ( UPDATE thing_aggregates AS a @@ -41,7 +41,7 @@ BEGIN score = a.score + diff.upvotes - diff.downvotes, upvotes = a.upvotes + diff.upvotes, downvotes = a.downvotes + diff.downvotes, controversy_rank = r.controversy_rank ((a.upvotes + diff.upvotes)::numeric, (a.downvotes + diff.downvotes)::numeric) FROM ( SELECT - (thing_like).thing_id, coalesce(sum(count_diff) FILTER (WHERE (thing_like).score = 1), 0) AS upvotes, coalesce(sum(count_diff) FILTER (WHERE (thing_like).score != 1), 0) AS downvotes FROM select_old_and_new_rows AS old_and_new_rows GROUP BY (thing_like).thing_id) AS diff + (thing_actions).thing_id, coalesce(sum(count_diff) FILTER (WHERE (thing_actions).like_score = 1), 0) AS upvotes, coalesce(sum(count_diff) FILTER (WHERE (thing_actions).like_score != 1), 0) AS downvotes FROM select_old_and_new_rows AS old_and_new_rows WHERE (thing_actions).like_score IS NOT NULL GROUP BY (thing_actions).thing_id) AS diff WHERE a.thing_id = diff.thing_id AND (diff.upvotes, diff.downvotes) != (0, 0) @@ -355,7 +355,7 @@ CREATE TRIGGER comment_count -- Count subscribers for communities. -- subscribers should be updated only when a local community is followed by a local or remote person. -- subscribers_local should be updated only when a local person follows a local or remote community. -CALL r.create_triggers ('community_follower', $$ +CALL r.create_triggers ('community_actions', $$ BEGIN UPDATE community_aggregates AS a @@ -363,10 +363,10 @@ BEGIN subscribers = a.subscribers + diff.subscribers, subscribers_local = a.subscribers_local + diff.subscribers_local FROM ( SELECT - (community_follower).community_id, coalesce(sum(count_diff) FILTER (WHERE community.local), 0) AS subscribers, coalesce(sum(count_diff) FILTER (WHERE person.local), 0) AS subscribers_local + (community_actions).community_id, coalesce(sum(count_diff) FILTER (WHERE community.local), 0) AS subscribers, coalesce(sum(count_diff) FILTER (WHERE person.local), 0) AS subscribers_local FROM select_old_and_new_rows AS old_and_new_rows - LEFT JOIN community ON community.id = (community_follower).community_id - LEFT JOIN person ON person.id = (community_follower).person_id GROUP BY (community_follower).community_id) AS diff + LEFT JOIN community ON community.id = (community_actions).community_id + LEFT JOIN person ON person.id = (community_actions).person_id WHERE (community_actions).followed IS NOT NULL GROUP BY (community_actions).community_id) AS diff WHERE a.community_id = diff.community_id AND (diff.subscribers, diff.subscribers_local) != (0, 0); From a8215385544c0640b5137ffd11ff8572cd6dd89e Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 18:37:54 -0700 Subject: [PATCH 100/232] Update triggers.sql --- crates/db_schema/replaceable_schema/triggers.sql | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/db_schema/replaceable_schema/triggers.sql b/crates/db_schema/replaceable_schema/triggers.sql index 1ab62a66f..033b33ddf 100644 --- a/crates/db_schema/replaceable_schema/triggers.sql +++ b/crates/db_schema/replaceable_schema/triggers.sql @@ -41,7 +41,8 @@ BEGIN score = a.score + diff.upvotes - diff.downvotes, upvotes = a.upvotes + diff.upvotes, downvotes = a.downvotes + diff.downvotes, controversy_rank = r.controversy_rank ((a.upvotes + diff.upvotes)::numeric, (a.downvotes + diff.downvotes)::numeric) FROM ( SELECT - (thing_actions).thing_id, coalesce(sum(count_diff) FILTER (WHERE (thing_actions).like_score = 1), 0) AS upvotes, coalesce(sum(count_diff) FILTER (WHERE (thing_actions).like_score != 1), 0) AS downvotes FROM select_old_and_new_rows AS old_and_new_rows WHERE (thing_actions).like_score IS NOT NULL GROUP BY (thing_actions).thing_id) AS diff + (thing_actions).thing_id, coalesce(sum(count_diff) FILTER (WHERE (thing_actions).like_score = 1), 0) AS upvotes, coalesce(sum(count_diff) FILTER (WHERE (thing_actions).like_score != 1), 0) AS downvotes FROM select_old_and_new_rows AS old_and_new_rows + WHERE (thing_actions).like_score IS NOT NULL GROUP BY (thing_actions).thing_id) AS diff WHERE a.thing_id = diff.thing_id AND (diff.upvotes, diff.downvotes) != (0, 0) @@ -366,7 +367,8 @@ BEGIN (community_actions).community_id, coalesce(sum(count_diff) FILTER (WHERE community.local), 0) AS subscribers, coalesce(sum(count_diff) FILTER (WHERE person.local), 0) AS subscribers_local FROM select_old_and_new_rows AS old_and_new_rows LEFT JOIN community ON community.id = (community_actions).community_id - LEFT JOIN person ON person.id = (community_actions).person_id WHERE (community_actions).followed IS NOT NULL GROUP BY (community_actions).community_id) AS diff + LEFT JOIN person ON person.id = (community_actions).person_id + WHERE (community_actions).followed IS NOT NULL GROUP BY (community_actions).community_id) AS diff WHERE a.community_id = diff.community_id AND (diff.subscribers, diff.subscribers_local) != (0, 0); From 6bbe0a939a7ead2661d2fb21e15a0a53f5890a32 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 18:46:39 -0700 Subject: [PATCH 101/232] Update triggers.sql --- crates/db_schema/replaceable_schema/triggers.sql | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/db_schema/replaceable_schema/triggers.sql b/crates/db_schema/replaceable_schema/triggers.sql index 033b33ddf..ada6f124c 100644 --- a/crates/db_schema/replaceable_schema/triggers.sql +++ b/crates/db_schema/replaceable_schema/triggers.sql @@ -533,21 +533,21 @@ CREATE TRIGGER delete_comments FOR EACH ROW EXECUTE FUNCTION r.delete_comments_before_post (); -CREATE FUNCTION r.delete_follow_before_person () +CREATE FUNCTION r.delete_community_actions_before_person () RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN - DELETE FROM community_follower AS c + DELETE FROM community_actions AS c WHERE c.person_id = OLD.id; RETURN OLD; END; $$; -CREATE TRIGGER delete_follow +CREATE TRIGGER delete_community_actions BEFORE DELETE ON person FOR EACH ROW - EXECUTE FUNCTION r.delete_follow_before_person (); + EXECUTE FUNCTION r.delete_community_actions_before_person (); -- Triggers that change values before insert or update CREATE FUNCTION r.comment_change_values () From eccd72207c90e2e1bc82894a7cf1687589195829 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 19:25:29 -0700 Subject: [PATCH 102/232] Update comment_reply_view.rs --- crates/db_views_actor/src/comment_reply_view.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/db_views_actor/src/comment_reply_view.rs b/crates/db_views_actor/src/comment_reply_view.rs index 86c5a0e91..83cf9f290 100644 --- a/crates/db_views_actor/src/comment_reply_view.rs +++ b/crates/db_views_actor/src/comment_reply_view.rs @@ -1,6 +1,5 @@ use crate::structs::CommentReplyView; use diesel::{ - dsl::not, pg::Pg, result::Error, ExpressionMethods, @@ -131,9 +130,7 @@ fn queries<'a>() -> Queries< }; // Don't show replies from blocked persons - if let Some(my_person_id) = options.my_person_id { - query = query.filter(not(is_creator_blocked(my_person_id))); - } + query = query.filter(person_actions::blocked.is_null()); let (limit, offset) = limit_and_offset(options.page, options.limit)?; From 5bc8e792621aebd078512825b12649ab73079242 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 19:29:44 -0700 Subject: [PATCH 103/232] Update person_mention_view.rs --- .../db_views_actor/src/person_mention_view.rs | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/crates/db_views_actor/src/person_mention_view.rs b/crates/db_views_actor/src/person_mention_view.rs index eca95f30c..b9c390d37 100644 --- a/crates/db_views_actor/src/person_mention_view.rs +++ b/crates/db_views_actor/src/person_mention_view.rs @@ -1,6 +1,5 @@ use crate::structs::PersonMentionView; use diesel::{ - dsl::not, pg::Pg, result::Error, ExpressionMethods, @@ -131,9 +130,7 @@ fn queries<'a>() -> Queries< }; // Don't show mentions from blocked persons - if let Some(my_person_id) = options.my_person_id { - query = query.filter(not(is_creator_blocked(my_person_id))); - } + query = query.filter(person_actions::blocked.is_null()); let (limit, offset) = limit_and_offset(options.page, options.limit)?; @@ -168,15 +165,13 @@ impl PersonMentionView { person_mention::table .inner_join(comment::table) - .left_join( - person_block::table.on( - comment::creator_id - .eq(person_block::target_id) - .and(person_block::person_id.eq(my_person_id)), - ), - ) + .left_join(actions( + person_actions::table, + Some(my_person_id), + comment::creator_id, + )) // Dont count replies from blocked users - .filter(person_block::person_id.is_null()) + .filter(person_actions::blocked.is_null()) .filter(person_mention::recipient_id.eq(my_person_id)) .filter(person_mention::read.eq(false)) .filter(comment::deleted.eq(false)) From 4ae63c6ce251cb7593cc056b5b15fcd50cbef970 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 19:37:02 -0700 Subject: [PATCH 104/232] Update person_mention_view.rs --- crates/db_views_actor/src/person_mention_view.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/crates/db_views_actor/src/person_mention_view.rs b/crates/db_views_actor/src/person_mention_view.rs index b9c390d37..3a39943ae 100644 --- a/crates/db_views_actor/src/person_mention_view.rs +++ b/crates/db_views_actor/src/person_mention_view.rs @@ -1,11 +1,5 @@ use crate::structs::PersonMentionView; -use diesel::{ - pg::Pg, - result::Error, - ExpressionMethods, - NullableExpressionMethods, - QueryDsl, -}; +use diesel::{pg::Pg, result::Error, ExpressionMethods, NullableExpressionMethods, QueryDsl}; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ aliases::{self, creator_community_actions}, From 66628717a42aa70a3c1c6c6fabafacfdbe5f5a4a Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 19:37:37 -0700 Subject: [PATCH 105/232] Update comment_reply_view.rs --- crates/db_views_actor/src/comment_reply_view.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/crates/db_views_actor/src/comment_reply_view.rs b/crates/db_views_actor/src/comment_reply_view.rs index 83cf9f290..7c9bf1468 100644 --- a/crates/db_views_actor/src/comment_reply_view.rs +++ b/crates/db_views_actor/src/comment_reply_view.rs @@ -1,11 +1,5 @@ use crate::structs::CommentReplyView; -use diesel::{ - pg::Pg, - result::Error, - ExpressionMethods, - NullableExpressionMethods, - QueryDsl, -}; +use diesel::{pg::Pg, result::Error, ExpressionMethods, NullableExpressionMethods, QueryDsl}; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ aliases::{self, creator_community_actions}, From c73ab7ff4d71a9e1a13d78911f6282d6b87b4090 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 20:05:37 -0700 Subject: [PATCH 106/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index f199840c7..2ae8c3fe5 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -74,9 +74,9 @@ impl< self.primary_key.walk_ast(out.reborrow())?; // Select from `update_result` with an alias that matches the original table's name - out.push_sql(") = ANY (SELECT ("); + out.push_sql(") = ANY (SELECT "); self.primary_key.walk_ast(out.reborrow())?; - out.push_sql(") FROM update_result AS "); + out.push_sql(" FROM update_result AS "); self.table.walk_ast(out.reborrow())?; // Filter the select statement From 34cba5be3994107c1e66a958ef267bf23d41ab12 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 20:08:00 -0700 Subject: [PATCH 107/232] start removing post_id column --- migrations/2024-03-17-134311_smoosh-tables-together/up.sql | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql index 7a21d6a05..5c4d9ab08 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql @@ -386,3 +386,7 @@ FROM post_actions; CREATE statistics post_actions_liked_stat ON (liked IS NULL), (like_score IS NULL) FROM post_actions; +-- TODO: drop the column +ALTER TABLE comment_actions + ALTER COLUMN post_id DROP NOT NULL; + From 4771e6992af1b0458ccd9d5d080a0d3b1a02dea6 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 20:08:31 -0700 Subject: [PATCH 108/232] Update down.sql --- migrations/2024-03-17-134311_smoosh-tables-together/down.sql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/down.sql b/migrations/2024-03-17-134311_smoosh-tables-together/down.sql index 685cd39d6..3e1cde50b 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/down.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/down.sql @@ -329,3 +329,6 @@ DROP INDEX idx_comment_actions_liked_not_null, idx_community_actions_followed_no -- Drop statistics of columns that still exist DROP statistics comment_actions_liked_stat, community_actions_followed_stat, person_actions_followed_stat; +ALTER TABLE comment_actions + ALTER COLUMN post_id SET NOT NULL; + From 9dd9057fbf4d19429c244db1855a24a253ba4690 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 20:09:15 -0700 Subject: [PATCH 109/232] Update schema.rs --- crates/db_schema/src/schema.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 6af8b0b98..1c6652ee6 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -102,7 +102,7 @@ diesel::table! { comment_actions (person_id, comment_id) { person_id -> Int4, comment_id -> Int4, - post_id -> Int4, + post_id -> Nullable, like_score -> Nullable, liked -> Nullable, saved -> Nullable, From 2935ff4f6e3e59b207da74e6b2499079d30d0e4c Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 20:10:09 -0700 Subject: [PATCH 110/232] Update comment.rs --- crates/db_schema/src/source/comment.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/db_schema/src/source/comment.rs b/crates/db_schema/src/source/comment.rs index d5568dd08..194fcff17 100644 --- a/crates/db_schema/src/source/comment.rs +++ b/crates/db_schema/src/source/comment.rs @@ -96,7 +96,6 @@ pub struct CommentUpdateForm { pub struct CommentLike { pub person_id: PersonId, pub comment_id: CommentId, - pub post_id: PostId, // TODO this is redundant pub score: i16, pub published: DateTime, } From 7c00bcc8a535a0ab75b57859f2be225b04d117fa Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 24 May 2024 20:11:40 -0700 Subject: [PATCH 111/232] Update comment.rs --- crates/db_schema/src/impls/comment.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index b1c6bf9ca..482ba9fe4 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -375,7 +375,6 @@ mod tests { let expected_comment_like = CommentLike { comment_id: inserted_comment.id, - post_id: inserted_post.id, person_id: inserted_person.id, published: inserted_comment_like.published, score: 1, From 1cd396930c6726c540a11f25a6917ebd974eb658 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 08:01:46 -0700 Subject: [PATCH 112/232] Update comment.rs --- crates/db_schema/src/impls/comment.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index 482ba9fe4..7e897535a 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -164,14 +164,12 @@ impl CommentLike { fn as_select_unwrap() -> ( comment_actions::person_id, comment_actions::comment_id, - comment_actions::post_id, dsl::AssumeNotNull, dsl::AssumeNotNull, ) { ( comment_actions::person_id, comment_actions::comment_id, - comment_actions::post_id, comment_actions::like_score.assume_not_null(), comment_actions::liked.assume_not_null(), ) From d5740bc02148e52c52578ffc751dfa77dbca24f6 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 08:29:14 -0700 Subject: [PATCH 113/232] Update schema.rs --- crates/db_schema/src/schema.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 1c6652ee6..2ed170b0e 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -102,7 +102,6 @@ diesel::table! { comment_actions (person_id, comment_id) { person_id -> Int4, comment_id -> Int4, - post_id -> Nullable, like_score -> Nullable, liked -> Nullable, saved -> Nullable, From bfb5698375eeb982e137f88886e5852277196e71 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 08:30:06 -0700 Subject: [PATCH 114/232] Update comment.rs --- crates/db_schema/src/source/comment.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/db_schema/src/source/comment.rs b/crates/db_schema/src/source/comment.rs index 194fcff17..2f235932e 100644 --- a/crates/db_schema/src/source/comment.rs +++ b/crates/db_schema/src/source/comment.rs @@ -106,7 +106,6 @@ pub struct CommentLike { pub struct CommentLikeForm { pub person_id: PersonId, pub comment_id: CommentId, - pub post_id: PostId, // TODO this is redundant #[cfg_attr(feature = "full", diesel(column_name = like_score))] pub score: i16, } From b7a904b765ef12576783c9ca4da78e5757a4f41c Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 08:32:25 -0700 Subject: [PATCH 115/232] Update like.rs --- crates/api/src/comment/like.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/api/src/comment/like.rs b/crates/api/src/comment/like.rs index d0aa4a6c2..aa76b91e6 100644 --- a/crates/api/src/comment/like.rs +++ b/crates/api/src/comment/like.rs @@ -59,7 +59,6 @@ pub async fn like_comment( let like_form = CommentLikeForm { comment_id: data.comment_id, - post_id: orig_comment.post.id, person_id: local_user_view.person.id, score: data.score, }; From 71b0fe7a41bc9ed0b031e254e4c998ac53c92f47 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 08:34:02 -0700 Subject: [PATCH 116/232] Update comment.rs --- crates/db_schema/src/impls/comment.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index 7e897535a..6f86f9dd5 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -364,7 +364,6 @@ mod tests { // Comment Like let comment_like_form = CommentLikeForm { comment_id: inserted_comment.id, - post_id: inserted_post.id, person_id: inserted_person.id, score: 1, }; From 67eadceac2c0a711f4864344a9d281f0aef68ac3 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 08:35:42 -0700 Subject: [PATCH 117/232] Update up.sql --- migrations/2024-03-17-134311_smoosh-tables-together/up.sql | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql index 5c4d9ab08..753c18dec 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql @@ -11,6 +11,7 @@ ALTER TABLE comment_actions RENAME COLUMN published TO liked; ALTER TABLE comment_actions RENAME COLUMN score TO like_score; ALTER TABLE comment_actions + DROP COLUMN post_id, ALTER COLUMN liked DROP NOT NULL, ALTER COLUMN liked DROP DEFAULT, ALTER COLUMN like_score DROP NOT NULL, @@ -386,7 +387,3 @@ FROM post_actions; CREATE statistics post_actions_liked_stat ON (liked IS NULL), (like_score IS NULL) FROM post_actions; --- TODO: drop the column -ALTER TABLE comment_actions - ALTER COLUMN post_id DROP NOT NULL; - From 398718b2f052c07b89a6110dee2c07ac868bf50a Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 08:41:44 -0700 Subject: [PATCH 118/232] Update down.sql --- .../2024-03-17-134311_smoosh-tables-together/down.sql | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/down.sql b/migrations/2024-03-17-134311_smoosh-tables-together/down.sql index 3e1cde50b..45c493d7a 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/down.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/down.sql @@ -35,7 +35,15 @@ ALTER TABLE comment_like ALTER COLUMN published SET NOT NULL, ALTER COLUMN published SET DEFAULT now(), ALTER COLUMN score SET NOT NULL, - DROP COLUMN saved; + DROP COLUMN saved, + ADD COLUMN post_id int REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE; + +UPDATE comment_like +SET + post_id = (SELECT post_id FROM comment WHERE comment.id = comment_like.comment_id); + +ALTER TABLE comment_like + ALTER COLUMN post_id SET NOT NULL; -- Create community_follower from community_actions CREATE TABLE community_block ( From b2d0ff5c83d3d879a1bfac2dd0378169b7df75ae Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 08:55:21 -0700 Subject: [PATCH 119/232] Update down.sql --- .../2024-03-17-134311_smoosh-tables-together/down.sql | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/down.sql b/migrations/2024-03-17-134311_smoosh-tables-together/down.sql index 45c493d7a..9143d3623 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/down.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/down.sql @@ -38,9 +38,16 @@ ALTER TABLE comment_like DROP COLUMN saved, ADD COLUMN post_id int REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE; -UPDATE comment_like +UPDATE + comment_like SET - post_id = (SELECT post_id FROM comment WHERE comment.id = comment_like.comment_id); + post_id = ( + SELECT + post_id + FROM + comment + WHERE + comment.id = comment_like.comment_id); ALTER TABLE comment_like ALTER COLUMN post_id SET NOT NULL; From 1e112c05235b9b229a447489842ca58c22208d06 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 09:09:48 -0700 Subject: [PATCH 120/232] Update up.sql --- .../2024-03-17-134311_smoosh-tables-together/up.sql | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql index 753c18dec..234aa2548 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql @@ -22,15 +22,13 @@ WITH old_comment_saved AS ( DELETE FROM comment_saved RETURNING *) - INSERT INTO comment_actions (person_id, comment_id, saved, post_id) + INSERT INTO comment_actions (person_id, comment_id, saved) SELECT - old_comment_saved.person_id, - old_comment_saved.comment_id, - old_comment_saved.published, - comment.post_id + person_id, + comment_id, + published FROM old_comment_saved - INNER JOIN COMMENT ON comment.id = old_comment_saved.comment_id ON CONFLICT (person_id, comment_id) DO UPDATE SET From b6de369993dbe6fdcce07beb40002740dc8842ed Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 09:21:43 -0700 Subject: [PATCH 121/232] Update up.sql --- migrations/2024-03-17-134311_smoosh-tables-together/up.sql | 4 ---- 1 file changed, 4 deletions(-) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql index 234aa2548..8a36b209d 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql @@ -249,14 +249,10 @@ ALTER INDEX comment_like_pkey RENAME TO comment_actions_pkey; ALTER INDEX idx_comment_like_comment RENAME TO idx_comment_actions_comment; -ALTER INDEX idx_comment_like_post RENAME TO idx_comment_actions_post; - ALTER TABLE comment_actions RENAME CONSTRAINT comment_like_comment_id_fkey TO comment_actions_comment_id_fkey; ALTER TABLE comment_actions RENAME CONSTRAINT comment_like_person_id_fkey TO comment_actions_person_id_fkey; -ALTER TABLE comment_actions RENAME CONSTRAINT comment_like_post_id_fkey TO comment_actions_post_id_fkey; - ALTER INDEX community_follower_pkey RENAME TO community_actions_pkey; ALTER INDEX idx_community_follower_community RENAME TO idx_community_actions_community; From 0f2916c45d5cc027ebf9a98e934efaec701ae799 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 09:22:45 -0700 Subject: [PATCH 122/232] Update down.sql --- migrations/2024-03-17-134311_smoosh-tables-together/down.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/down.sql b/migrations/2024-03-17-134311_smoosh-tables-together/down.sql index 9143d3623..68b9d9070 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/down.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/down.sql @@ -320,6 +320,8 @@ CREATE INDEX idx_comment_saved_comment ON comment_saved (comment_id); CREATE INDEX idx_comment_saved_person ON comment_saved (person_id); +CREATE INDEX idx_comment_like_post ON comment_like (post_id); + CREATE INDEX idx_community_block_community ON community_block (community_id); CREATE INDEX idx_community_moderator_community ON community_moderator (community_id); From f25205ce0f800e3b6795d399ef47becb12d55ad0 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 09:47:19 -0700 Subject: [PATCH 123/232] Update comment.rs --- crates/db_schema/src/impls/comment.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index 6f86f9dd5..edfc3e300 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -38,7 +38,6 @@ impl UpleteTable for comment_actions::table { type EmptyRow = ( comment_actions::person_id, comment_actions::comment_id, - comment_actions::post_id, Option, Option>, Option>, From 5e3ce5ab1c24da1a30ba00336ffd63abcb1f7d04 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 09:57:43 -0700 Subject: [PATCH 124/232] Update vote_view.rs --- crates/db_views/src/vote_view.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_views/src/vote_view.rs b/crates/db_views/src/vote_view.rs index 0a0748df8..a893ff1dd 100644 --- a/crates/db_views/src/vote_view.rs +++ b/crates/db_views/src/vote_view.rs @@ -53,7 +53,7 @@ impl VoteView { action_query(comment_actions::like_score) .inner_join(person::table) - .inner_join(post::table) + .inner_join(comment::table.inner_join(post::table)) .left_join(actions_alias( creator_community_actions, comment_actions::person_id, From a309aaa199cd58a2dd3ef05273c315599ec3ae99 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 10:03:43 -0700 Subject: [PATCH 125/232] Update vote_view.rs --- crates/db_views/src/vote_view.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_views/src/vote_view.rs b/crates/db_views/src/vote_view.rs index a893ff1dd..d8e5cce4b 100644 --- a/crates/db_views/src/vote_view.rs +++ b/crates/db_views/src/vote_view.rs @@ -4,7 +4,7 @@ use diesel_async::RunQueryDsl; use lemmy_db_schema::{ aliases::creator_community_actions, newtypes::{CommentId, PostId}, - schema::{comment_actions, community_actions, person, post, post_actions}, + schema::{comment, comment_actions, community_actions, person, post, post_actions}, utils::{action_query, actions_alias, get_conn, limit_and_offset, DbPool}, }; From 86838e2951bea8749f6d372b897d3cd9839734be Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 10:18:41 -0700 Subject: [PATCH 126/232] Update comment_aggregates.rs --- crates/db_schema/src/aggregates/comment_aggregates.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/db_schema/src/aggregates/comment_aggregates.rs b/crates/db_schema/src/aggregates/comment_aggregates.rs index 915d17b1d..1baa48881 100644 --- a/crates/db_schema/src/aggregates/comment_aggregates.rs +++ b/crates/db_schema/src/aggregates/comment_aggregates.rs @@ -118,7 +118,6 @@ mod tests { let comment_like = CommentLikeForm { comment_id: inserted_comment.id, - post_id: inserted_post.id, person_id: inserted_person.id, score: 1, }; @@ -137,7 +136,6 @@ mod tests { // Add a post dislike from the other person let comment_dislike = CommentLikeForm { comment_id: inserted_comment.id, - post_id: inserted_post.id, person_id: another_inserted_person.id, score: -1, }; From 7a8e53d3d70e8105d684213ec82fbb3a41c94765 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 10:19:47 -0700 Subject: [PATCH 127/232] Update person_aggregates.rs --- crates/db_schema/src/aggregates/person_aggregates.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/db_schema/src/aggregates/person_aggregates.rs b/crates/db_schema/src/aggregates/person_aggregates.rs index 03295173f..8315b5afc 100644 --- a/crates/db_schema/src/aggregates/person_aggregates.rs +++ b/crates/db_schema/src/aggregates/person_aggregates.rs @@ -101,7 +101,6 @@ mod tests { let mut comment_like = CommentLikeForm { comment_id: inserted_comment.id, person_id: inserted_person.id, - post_id: inserted_post.id, score: 1, }; @@ -121,7 +120,6 @@ mod tests { let child_comment_like = CommentLikeForm { comment_id: inserted_child_comment.id, person_id: another_inserted_person.id, - post_id: inserted_post.id, score: 1, }; From fde92c612ae78f7cf6ba082a36ed59bf792ca9de Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 10:38:04 -0700 Subject: [PATCH 128/232] Update comment_view.rs --- crates/db_views/src/comment_view.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs index 4a67ef8a2..babc3592e 100644 --- a/crates/db_views/src/comment_view.rs +++ b/crates/db_views/src/comment_view.rs @@ -525,7 +525,6 @@ mod tests { let comment_like_form = CommentLikeForm { comment_id: inserted_comment_0.id, - post_id: inserted_post.id, person_id: inserted_timmy_person.id, score: 1, }; @@ -625,7 +624,6 @@ mod tests { // Like a new comment let comment_like_form = CommentLikeForm { comment_id: data.inserted_comment_1.id, - post_id: data.inserted_post.id, person_id: data.timmy_local_user_view.person.id, score: 1, }; From 0794ff93f21e3d4a02b8a7bb9c9e320c1e18600e Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 10:39:09 -0700 Subject: [PATCH 129/232] Update vote_view.rs --- crates/db_views/src/vote_view.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/db_views/src/vote_view.rs b/crates/db_views/src/vote_view.rs index d8e5cce4b..647f152a4 100644 --- a/crates/db_views/src/vote_view.rs +++ b/crates/db_views/src/vote_view.rs @@ -183,7 +183,6 @@ mod tests { // Timothy votes down his own comment let timmy_comment_vote_form = CommentLikeForm { - post_id: inserted_post.id, comment_id: inserted_comment.id, person_id: inserted_timmy.id, score: -1, @@ -194,7 +193,6 @@ mod tests { // Sara upvotes timmy's comment let sara_comment_vote_form = CommentLikeForm { - post_id: inserted_post.id, comment_id: inserted_comment.id, person_id: inserted_sara.id, score: 1, From 4918e728ae863b39e506426c40f3df29ee974687 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 11:02:58 -0700 Subject: [PATCH 130/232] Update mod.rs --- crates/apub/src/activities/voting/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/apub/src/activities/voting/mod.rs b/crates/apub/src/activities/voting/mod.rs index 3e59cb7d0..7c39b2246 100644 --- a/crates/apub/src/activities/voting/mod.rs +++ b/crates/apub/src/activities/voting/mod.rs @@ -62,7 +62,6 @@ async fn vote_comment( let comment_id = comment.id; let like_form = CommentLikeForm { comment_id, - post_id: comment.post_id, person_id: actor.id, score: vote_type.into(), }; From 421e05670e166e411416a3164204f12cfb6f4735 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 11:03:57 -0700 Subject: [PATCH 131/232] Update create.rs --- crates/api_crud/src/comment/create.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/api_crud/src/comment/create.rs b/crates/api_crud/src/comment/create.rs index 6493d6803..285b68303 100644 --- a/crates/api_crud/src/comment/create.rs +++ b/crates/api_crud/src/comment/create.rs @@ -149,7 +149,6 @@ pub async fn create_comment( // You like your own comment by default let like_form = CommentLikeForm { comment_id: inserted_comment.id, - post_id: post.id, person_id: local_user_view.person.id, score: 1, }; From 1a08f27fae5978a2bbe64acf917e2503e5ab8ab8 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 11:04:41 -0700 Subject: [PATCH 132/232] Update comment.rs --- crates/apub/src/activities/create_or_update/comment.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/apub/src/activities/create_or_update/comment.rs b/crates/apub/src/activities/create_or_update/comment.rs index 2406d2eb3..e068b5621 100644 --- a/crates/apub/src/activities/create_or_update/comment.rs +++ b/crates/apub/src/activities/create_or_update/comment.rs @@ -160,7 +160,6 @@ impl ActivityHandler for CreateOrUpdateNote { // author likes their own comment by default let like_form = CommentLikeForm { comment_id: comment.id, - post_id: comment.post_id, person_id: comment.creator_id, score: 1, }; From 437200f26aa97afc07837e8b830aa867f4e1e529 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 12:48:49 -0700 Subject: [PATCH 133/232] Update community.rs --- crates/db_schema/src/impls/community.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/db_schema/src/impls/community.rs b/crates/db_schema/src/impls/community.rs index 26a4a333e..0cca082fc 100644 --- a/crates/db_schema/src/impls/community.rs +++ b/crates/db_schema/src/impls/community.rs @@ -107,6 +107,12 @@ impl Joinable for CommunityModerator { ); insert_into(community_actions::table) .values(community_moderator_form) + .on_conflict(( + community_actions::person_id, + community_actions::community_id, + )) + .do_update() + .set(community_moderator_form), .returning(Self::as_select_unwrap()) .get_result::(conn) .await From f62fcc4d0644e85935ead58b4e2f82659c6dba36 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 12:56:46 -0700 Subject: [PATCH 134/232] Update community.rs --- crates/db_schema/src/impls/community.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/impls/community.rs b/crates/db_schema/src/impls/community.rs index 0cca082fc..f438477f5 100644 --- a/crates/db_schema/src/impls/community.rs +++ b/crates/db_schema/src/impls/community.rs @@ -112,7 +112,7 @@ impl Joinable for CommunityModerator { community_actions::community_id, )) .do_update() - .set(community_moderator_form), + .set(community_moderator_form) .returning(Self::as_select_unwrap()) .get_result::(conn) .await From 488797b3cf003226a6a94ee939d8b3d04484cc5c Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 12:59:02 -0700 Subject: [PATCH 135/232] Update up.sql --- migrations/2024-03-17-134311_smoosh-tables-together/up.sql | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql index 8a36b209d..90111b9c1 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql @@ -354,10 +354,7 @@ WHERE hidden IS NOT NULL; -- This index is currently redundant because instance_actions only has 1 action type, but inconsistency --- with other tables would make it harder to do everything correctly when adding another action type. If --- omitting this index is significantly beneficial, then it should be done when indexes are declared outside --- of migrations in `lemmy_db_schema::schema_setup` and adding this index doesn't require changing code that --- isn't right next to the code that needs to be changed to add another action type to instance_actions. +-- with other tables would make it harder to do everything correctly when adding another action type CREATE INDEX idx_instance_actions_blocked_not_null ON instance_actions (person_id, instance_id) WHERE blocked IS NOT NULL; From 90b10b799495b52d0c34a19ba47c9bf6933fd7b1 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 13:59:00 -0700 Subject: [PATCH 136/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 39 ++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 2ae8c3fe5..97bf080ad 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -2,7 +2,7 @@ use diesel::{ dsl, expression::{AsExpression, TypedExpressionType}, pg::Pg, - query_builder::{AstPass, QueryFragment, UpdateStatement}, + query_builder::{AstPass, Query, QueryFragment, UpdateStatement}, result::Error, sql_types, QueryId, @@ -16,6 +16,7 @@ pub trait UpleteTable: Table + Default { pub trait OrDelete { type Output; + /// Change an update query so rows that equal `UpleteTable::EmptyRow::default()` are deleted fn or_delete(self) -> Self::Output; } @@ -52,6 +53,10 @@ pub struct SetOrDeleteQuery { empty_row: E, } +impl Query for SetOrDeleteQuery { + type SqlType = (sql_types::BigInt, sql_types::BigInt); +} + impl< T: QueryFragment, PK: QueryFragment, @@ -61,14 +66,14 @@ impl< > QueryFragment for SetOrDeleteQuery { fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> Result<(), Error> { - // `update_result` CTE with new rows + // `update_result` CTE with new rows (concurrent writers to these rows are blocked until this query ends) out.push_sql("WITH update_result AS ("); self.update_statement.walk_ast(out.reborrow())?; out.push_sql(" RETURNING "); self.all_columns.walk_ast(out.reborrow())?; - // Delete - out.push_sql(") DELETE FROM "); + // Beginning of `delete_result` CTE with 1 row per deleted row + out.push_sql("), delete_result AS (DELETE FROM "); self.table.walk_ast(out.reborrow())?; out.push_sql(" WHERE ("); self.primary_key.walk_ast(out.reborrow())?; @@ -84,8 +89,32 @@ impl< self.all_columns.walk_ast(out.reborrow())?; out.push_sql(") IS NOT DISTINCT FROM "); self.empty_row.walk_ast(out.reborrow())?; - out.push_sql(")"); + + // Select count from each CTE + out.push_sql(") RETURNING 1) SELECT (SELECT count(*) from update_result), (SELECT count(*) FROM delete_result)"); Ok(()) } } + +#[derive(Queryable, PartialEq, Eq, Debug)] +pub struct UpleteCount { + pub all: i64, + pub deleted: i64, +} + +impl UpleteCount { + pub fn only_updated(n: i64) -> Self { + UpleteCount { + all: n, + deleted: 0, + } + } + + pub fn only_deleted(n: i64) -> Self { + UpleteCount { + all: n, + deleted: n, + } + } +} From d502b68a6e48ab3e9d44af08a02f86792d34513b Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 14:43:30 -0700 Subject: [PATCH 137/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 55 ++++++++++++++++++---------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 97bf080ad..1f7830c03 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -1,4 +1,5 @@ use diesel::{ + deserialize::Queryable, dsl, expression::{AsExpression, TypedExpressionType}, pg::Pg, @@ -53,8 +54,11 @@ pub struct SetOrDeleteQuery { empty_row: E, } -impl Query for SetOrDeleteQuery { - type SqlType = (sql_types::BigInt, sql_types::BigInt); +impl Query for SetOrDeleteQuery +where + T::SqlType: 'static, +{ + type SqlType = (sql_types::Array>, sql_types::BigInt); } impl< @@ -66,7 +70,8 @@ impl< > QueryFragment for SetOrDeleteQuery { fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> Result<(), Error> { - // `update_result` CTE with new rows (concurrent writers to these rows are blocked until this query ends) + // `update_result` CTE with new rows (concurrent writers to these rows are blocked until this + // query ends) out.push_sql("WITH update_result AS ("); self.update_statement.walk_ast(out.reborrow())?; out.push_sql(" RETURNING "); @@ -90,31 +95,41 @@ impl< out.push_sql(") IS NOT DISTINCT FROM "); self.empty_row.walk_ast(out.reborrow())?; - // Select count from each CTE - out.push_sql(") RETURNING 1) SELECT (SELECT count(*) from update_result), (SELECT count(*) FROM delete_result)"); + out.push_sql(") RETURNING "); + self.all_columns.walk_ast(out.reborrow())?; + + // Select values to be received + out.push_sql( + ") SELECT (SELECT array_agg(update_result.*) from update_result WHERE (update_result.*) != ALL (SELECT * FROM delete_result)), (SELECT count(*) FROM delete_result)" + ); Ok(()) } } -#[derive(Queryable, PartialEq, Eq, Debug)] -pub struct UpleteCount { - pub all: i64, - pub deleted: i64, +#[derive(PartialEq, Eq, Debug)] +pub struct UpletedRows { + pub updated_rows: Vec, + pub deleted_rows_count: i64, } -impl UpleteCount { - pub fn only_updated(n: i64) -> Self { - UpleteCount { - all: n, - deleted: 0, - } +impl UpletedRows { + pub fn only_updated(updated_rows: Vec) -> Self { + UpleteCount { updated_rows, deleted_rows_count: 0 } } - pub fn only_deleted(n: i64) -> Self { - UpleteCount { - all: n, - deleted: n, - } + pub fn only_deleted(deleted_rows_count: i64) -> Self { + UpleteCount { updated_rows: Vec::new(), deleted_rows_count } + } +} + +impl> Queryable<(sql_types::Array>, sql_types::BigInt), Pg> for UpletedRows { + type Row = (Vec, i64); + + fn build((updated_rows, deleted_rows_count): Self::Row) -> diesel::deserialize::Result { + Ok(UpletedRows { + updated_rows: updated_rows.into_iter().map(T::build).collect::, _>>()?, + deleted_rows_count, + }) } } From 29f4fa7dc19dfdbfcd949e527904fabc3269477d Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 14:56:19 -0700 Subject: [PATCH 138/232] revert to UpleteCount --- crates/db_schema/src/utils/uplete.rs | 46 ++++++++-------------------- 1 file changed, 13 insertions(+), 33 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 1f7830c03..685dd8c86 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -1,5 +1,4 @@ use diesel::{ - deserialize::Queryable, dsl, expression::{AsExpression, TypedExpressionType}, pg::Pg, @@ -54,11 +53,8 @@ pub struct SetOrDeleteQuery { empty_row: E, } -impl Query for SetOrDeleteQuery -where - T::SqlType: 'static, -{ - type SqlType = (sql_types::Array>, sql_types::BigInt); +impl Query for SetOrDeleteQuery { + type SqlType = (sql_types::BigInt, sql_types::BigInt); } impl< @@ -95,41 +91,25 @@ impl< out.push_sql(") IS NOT DISTINCT FROM "); self.empty_row.walk_ast(out.reborrow())?; - out.push_sql(") RETURNING "); - self.all_columns.walk_ast(out.reborrow())?; - - // Select values to be received - out.push_sql( - ") SELECT (SELECT array_agg(update_result.*) from update_result WHERE (update_result.*) != ALL (SELECT * FROM delete_result)), (SELECT count(*) FROM delete_result)" - ); + // Select count from each CTE + out.push_sql(") RETURNING 1) SELECT (SELECT count(*) from update_result), (SELECT count(*) FROM delete_result)"); Ok(()) } } -#[derive(PartialEq, Eq, Debug)] -pub struct UpletedRows { - pub updated_rows: Vec, - pub deleted_rows_count: i64, +#[derive(Queryable, PartialEq, Eq, Debug)] +pub struct UpleteCount { + pub all: i64, + pub deleted: i64, } -impl UpletedRows { - pub fn only_updated(updated_rows: Vec) -> Self { - UpleteCount { updated_rows, deleted_rows_count: 0 } +impl UpleteCount { + pub fn only_updated(n: i64) -> Self { + UpleteCount { all: n, deleted: 0 } } - pub fn only_deleted(deleted_rows_count: i64) -> Self { - UpleteCount { updated_rows: Vec::new(), deleted_rows_count } - } -} - -impl> Queryable<(sql_types::Array>, sql_types::BigInt), Pg> for UpletedRows { - type Row = (Vec, i64); - - fn build((updated_rows, deleted_rows_count): Self::Row) -> diesel::deserialize::Result { - Ok(UpletedRows { - updated_rows: updated_rows.into_iter().map(T::build).collect::, _>>()?, - deleted_rows_count, - }) + pub fn only_deleted(n: i64) -> Self { + UpleteCount { all: n, deleted: n } } } From 730f4cbaa63b7dc4f000025a10836ee1c0eb5a44 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 15:00:34 -0700 Subject: [PATCH 139/232] Update comment.rs --- crates/db_schema/src/impls/comment.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index edfc3e300..ff49bd7e8 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -17,7 +17,7 @@ use crate::{ get_conn, naive_now, now, - uplete::{OrDelete, UpleteTable}, + uplete::{OrDelete, UpleteCount, UpleteTable}, DbPool, DELETED_REPLACEMENT_TEXT, }, @@ -198,7 +198,7 @@ impl Likeable for CommentLike { pool: &mut DbPool<'_>, person_id: PersonId, comment_id: CommentId, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; diesel::update(comment_actions::table.find((person_id, comment_id))) .set(( @@ -249,7 +249,7 @@ impl Saveable for CommentSaved { async fn unsave( pool: &mut DbPool<'_>, comment_saved_form: &CommentSavedForm, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; diesel::update( comment_actions::table.find((comment_saved_form.person_id, comment_saved_form.comment_id)), @@ -429,8 +429,8 @@ mod tests { format!("0.{}.{}", expected_comment.id, inserted_child_comment.id), inserted_child_comment.path.0, ); - assert_eq!(1, like_removed); - assert_eq!(1, saved_removed); + assert_eq!(UpleteCount::only_updated(1), like_removed); + assert_eq!(UpleteCount::only_deleted(1), saved_removed); assert_eq!(1, num_deleted); } } From cadab90c6060e759b1864ca0b9979d9fa09a02f7 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sat, 25 May 2024 15:17:08 -0700 Subject: [PATCH 140/232] Update traits.rs --- crates/db_schema/src/traits.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/db_schema/src/traits.rs b/crates/db_schema/src/traits.rs index 2b0da6c7f..4779c0a83 100644 --- a/crates/db_schema/src/traits.rs +++ b/crates/db_schema/src/traits.rs @@ -1,7 +1,7 @@ use crate::{ diesel::OptionalExtension, newtypes::{CommunityId, DbUrl, PersonId}, - utils::{get_conn, DbPool}, + utils::{get_conn, uplete::UpleteCount, DbPool}, }; use diesel::{ associations::HasTable, @@ -77,7 +77,7 @@ pub trait Followable { ) -> Result where Self: Sized; - async fn unfollow(pool: &mut DbPool<'_>, form: &Self::Form) -> Result + async fn unfollow(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; } @@ -88,7 +88,7 @@ pub trait Joinable { async fn join(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; - async fn leave(pool: &mut DbPool<'_>, form: &Self::Form) -> Result + async fn leave(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; } @@ -104,7 +104,7 @@ pub trait Likeable { pool: &mut DbPool<'_>, person_id: PersonId, item_id: Self::IdType, - ) -> Result + ) -> Result where Self: Sized; } @@ -115,7 +115,7 @@ pub trait Bannable { async fn ban(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; - async fn unban(pool: &mut DbPool<'_>, form: &Self::Form) -> Result + async fn unban(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; } @@ -126,7 +126,7 @@ pub trait Saveable { async fn save(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; - async fn unsave(pool: &mut DbPool<'_>, form: &Self::Form) -> Result + async fn unsave(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; } @@ -137,7 +137,7 @@ pub trait Blockable { async fn block(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; - async fn unblock(pool: &mut DbPool<'_>, form: &Self::Form) -> Result + async fn unblock(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; } From f613f986b2ed533fcc90bc049719dcc455b8365a Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 07:40:12 -0700 Subject: [PATCH 141/232] Update comment.rs --- crates/db_schema/src/impls/comment.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index ff49bd7e8..ea1526ce5 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -206,7 +206,7 @@ impl Likeable for CommentLike { comment_actions::liked.eq(None::>), )) .or_delete() - .execute(conn) + .get_result(conn) .await } } @@ -256,7 +256,7 @@ impl Saveable for CommentSaved { ) .set(comment_actions::saved.eq(None::>)) .or_delete() - .execute(conn) + .get_result(conn) .await } } From 8c42d95e17a114ae61756f9c3f8cc219244c1892 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 07:59:59 -0700 Subject: [PATCH 142/232] Update community.rs --- crates/db_schema/src/impls/community.rs | 45 ++++++++++++++++++------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/crates/db_schema/src/impls/community.rs b/crates/db_schema/src/impls/community.rs index f438477f5..bb32a944a 100644 --- a/crates/db_schema/src/impls/community.rs +++ b/crates/db_schema/src/impls/community.rs @@ -24,6 +24,7 @@ use crate::{ functions::{coalesce, lower}, get_conn, now, + uplete::{OrDelete, UpleteCount, UpleteTable}, DbPool, }, SubscribedType, @@ -46,6 +47,19 @@ use diesel::{ }; use diesel_async::RunQueryDsl; +impl UpleteTable for community_actions::table { + type EmptyRow = ( + community_actions::community_id, + community_actions::person_id, + Option>, + Option, + Option>, + Option>, + Option>, + Option>, + ); +} + #[async_trait] impl Crud for Community { type InsertForm = CommunityInsertForm; @@ -121,14 +135,15 @@ impl Joinable for CommunityModerator { async fn leave( pool: &mut DbPool<'_>, community_moderator_form: &CommunityModeratorForm, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; diesel::update(community_actions::table.find(( community_moderator_form.person_id, community_moderator_form.community_id, ))) .set(community_actions::became_moderator.eq(None::>)) - .execute(conn) + .or_delete() + .get_result(conn) .await } } @@ -226,25 +241,27 @@ impl CommunityModerator { pub async fn delete_for_community( pool: &mut DbPool<'_>, for_community_id: CommunityId, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; diesel::update( community_actions::table.filter(community_actions::community_id.eq(for_community_id)), ) .set(community_actions::became_moderator.eq(None::>)) - .execute(conn) + .or_delete() + .get_result(conn) .await } pub async fn leave_all_communities( pool: &mut DbPool<'_>, for_person_id: PersonId, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; diesel::update(community_actions::table.filter(community_actions::person_id.eq(for_person_id))) .set(community_actions::became_moderator.eq(None::>)) - .execute(conn) + .or_delete() + .get_result(conn) .await } @@ -305,7 +322,7 @@ impl Bannable for CommunityPersonBan { async fn unban( pool: &mut DbPool<'_>, community_person_ban_form: &CommunityPersonBanForm, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; diesel::update(community_actions::table.find(( community_person_ban_form.person_id, @@ -315,7 +332,8 @@ impl Bannable for CommunityPersonBan { community_actions::received_ban.eq(None::>), community_actions::ban_expires.eq(None::>), )) - .execute(conn) + .or_delete() + .get_result(conn) .await } } @@ -413,14 +431,15 @@ impl Followable for CommunityFollower { .get_result::(conn) .await } - async fn unfollow(pool: &mut DbPool<'_>, form: &CommunityFollowerForm) -> Result { + async fn unfollow(pool: &mut DbPool<'_>, form: &CommunityFollowerForm) -> Result { let conn = &mut get_conn(pool).await?; diesel::update(community_actions::table.find((form.person_id, form.community_id))) .set(( community_actions::followed.eq(None::>), community_actions::follow_pending.eq(None::), )) - .execute(conn) + .or_delete() + .get_result(conn) .await } } @@ -640,9 +659,9 @@ mod tests { assert_eq!(expected_community_follower, inserted_community_follower); assert_eq!(expected_community_moderator, inserted_community_moderator); assert_eq!(expected_community_person_ban, inserted_community_person_ban); - assert_eq!(1, ignored_community); - assert_eq!(1, left_community); - assert_eq!(1, unban); + assert_eq!(UpleteCount::only_updated(1), ignored_community); + assert_eq!(UpleteCount::only_updated(1), left_community); + assert_eq!(UpleteCount::only_deleted(1), unban); // assert_eq!(2, loaded_count); assert_eq!(1, num_deleted); } From dabb47987288a66e2688ddd80d8998391bee7d04 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 08:01:43 -0700 Subject: [PATCH 143/232] Update community_block.rs --- crates/db_schema/src/impls/community_block.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/crates/db_schema/src/impls/community_block.rs b/crates/db_schema/src/impls/community_block.rs index 4b5b05605..b53d981d2 100644 --- a/crates/db_schema/src/impls/community_block.rs +++ b/crates/db_schema/src/impls/community_block.rs @@ -3,7 +3,13 @@ use crate::{ schema::community_actions, source::community_block::{CommunityBlock, CommunityBlockForm}, traits::Blockable, - utils::{find_action, get_conn, now, DbPool}, + utils::{ + find_action, + get_conn, + now, + uplete::{OrDelete, UpleteCount, UpleteTable}, + DbPool, + }, }; use chrono::{DateTime, Utc}; use diesel::{ @@ -68,14 +74,15 @@ impl Blockable for CommunityBlock { async fn unblock( pool: &mut DbPool<'_>, community_block_form: &Self::Form, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; diesel::update(community_actions::table.find(( community_block_form.person_id, community_block_form.community_id, ))) .set(community_actions::blocked.eq(None::>)) - .execute(conn) + .or_delete() + .get_result(conn) .await } } From 4c3af86c00cc84b97c4f8ace91f9d7ce6323c832 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 08:02:41 -0700 Subject: [PATCH 144/232] Update community.rs --- crates/db_schema/src/impls/community.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/db_schema/src/impls/community.rs b/crates/db_schema/src/impls/community.rs index bb32a944a..244c6cb18 100644 --- a/crates/db_schema/src/impls/community.rs +++ b/crates/db_schema/src/impls/community.rs @@ -431,7 +431,10 @@ impl Followable for CommunityFollower { .get_result::(conn) .await } - async fn unfollow(pool: &mut DbPool<'_>, form: &CommunityFollowerForm) -> Result { + async fn unfollow( + pool: &mut DbPool<'_>, + form: &CommunityFollowerForm, + ) -> Result { let conn = &mut get_conn(pool).await?; diesel::update(community_actions::table.find((form.person_id, form.community_id))) .set(( From c3e4835ece24b5b655bf9599b390f00f0b9cc790 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 08:07:26 -0700 Subject: [PATCH 145/232] Update instance_block.rs --- crates/db_schema/src/impls/instance_block.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/db_schema/src/impls/instance_block.rs b/crates/db_schema/src/impls/instance_block.rs index 6076cca47..d526e4d6b 100644 --- a/crates/db_schema/src/impls/instance_block.rs +++ b/crates/db_schema/src/impls/instance_block.rs @@ -3,7 +3,13 @@ use crate::{ schema::instance_actions, source::instance_block::{InstanceBlock, InstanceBlockForm}, traits::Blockable, - utils::{find_action, get_conn, now, DbPool}, + utils::{ + find_action, + get_conn, + now, + uplete::{OrDelete, UpleteCount}, + DbPool, + }, }; use chrono::{DateTime, Utc}; use diesel::{ @@ -65,7 +71,7 @@ impl Blockable for InstanceBlock { async fn unblock( pool: &mut DbPool<'_>, instance_block_form: &Self::Form, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; diesel::update(instance_actions::table.find(( instance_block_form.person_id, From 11a90f178b015db6052a51d3565cfd66a79e7da5 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 08:08:10 -0700 Subject: [PATCH 146/232] Update instance.rs --- crates/db_schema/src/impls/instance.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/db_schema/src/impls/instance.rs b/crates/db_schema/src/impls/instance.rs index 8d2e4b75a..ae1ead279 100644 --- a/crates/db_schema/src/impls/instance.rs +++ b/crates/db_schema/src/impls/instance.rs @@ -6,6 +6,7 @@ use crate::{ federation_blocklist, federation_queue_state, instance, + instance_actions, local_site, site, }, @@ -18,6 +19,7 @@ use crate::{ get_conn, naive_now, now, + uplete::UpleteTable, DbPool, }, }; @@ -32,6 +34,14 @@ use diesel::{ }; use diesel_async::RunQueryDsl; +impl UpleteTable for instance_actions::table { + type EmptyRow = ( + instance_actions::person_id, + instance_actions::instance_id, + Option>, + ); +} + impl Instance { /// Attempt to read Instance column for the given domain. If it doesn't exist, insert a new one. /// There is no need for update as the domain of an existing instance cant change. From 7b56d5ba4d710f7dce7a46a81fe5ab128702bb4d Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 08:08:28 -0700 Subject: [PATCH 147/232] Update community_block.rs --- crates/db_schema/src/impls/community_block.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/impls/community_block.rs b/crates/db_schema/src/impls/community_block.rs index b53d981d2..da9ba3315 100644 --- a/crates/db_schema/src/impls/community_block.rs +++ b/crates/db_schema/src/impls/community_block.rs @@ -7,7 +7,7 @@ use crate::{ find_action, get_conn, now, - uplete::{OrDelete, UpleteCount, UpleteTable}, + uplete::{OrDelete, UpleteCount}, DbPool, }, }; From d264f0445f6f9737834afecce9d44cbb13931804 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 08:14:47 -0700 Subject: [PATCH 148/232] Update person.rs --- crates/db_schema/src/impls/person.rs | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs index fd95515e5..085e96a6d 100644 --- a/crates/db_schema/src/impls/person.rs +++ b/crates/db_schema/src/impls/person.rs @@ -10,7 +10,15 @@ use crate::{ PersonUpdateForm, }, traits::{ApubActor, Crud, Followable}, - utils::{action_query, functions::lower, get_conn, naive_now, now, DbPool}, + utils::{ + action_query, + functions::lower, + get_conn, + naive_now, + now, + upsert::{OrTable, UpleteCount, UpleteTable}, + DbPool, + }, }; use chrono::{DateTime, Utc}; use diesel::{ @@ -24,6 +32,16 @@ use diesel::{ }; use diesel_async::RunQueryDsl; +impl UpleteTable for person_actions::table { + type EmptyRow = ( + person_actions::target_id, + person_actions::person_id, + Option>, + Option, + Option>, + ); +} + #[async_trait] impl Crud for Person { type InsertForm = PersonInsertForm; @@ -216,14 +234,15 @@ impl Followable for PersonFollower { async fn follow_accepted(_: &mut DbPool<'_>, _: CommunityId, _: PersonId) -> Result { unimplemented!() } - async fn unfollow(pool: &mut DbPool<'_>, form: &PersonFollowerForm) -> Result { + async fn unfollow(pool: &mut DbPool<'_>, form: &PersonFollowerForm) -> Result { let conn = &mut get_conn(pool).await?; diesel::update(person_actions::table.find((form.follower_id, form.person_id))) .set(( person_actions::followed.eq(None::>), person_actions::follow_pending.eq(None::), )) - .execute(conn) + .or_delete() + .get_result(conn) .await } } @@ -361,6 +380,6 @@ mod tests { assert_eq!(vec![person_2], followers); let unfollow = PersonFollower::unfollow(pool, &follow_form).await.unwrap(); - assert_eq!(1, unfollow); + assert_eq!(UpleteCount::only_deleted(1), unfollow); } } From 436dc11be015c63baaf2bfff11f09554f135c584 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 08:16:08 -0700 Subject: [PATCH 149/232] Update person_block.rs --- crates/db_schema/src/impls/person_block.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/crates/db_schema/src/impls/person_block.rs b/crates/db_schema/src/impls/person_block.rs index cabfcaf21..ff6bf2348 100644 --- a/crates/db_schema/src/impls/person_block.rs +++ b/crates/db_schema/src/impls/person_block.rs @@ -3,7 +3,13 @@ use crate::{ schema::person_actions, source::person_block::{PersonBlock, PersonBlockForm}, traits::Blockable, - utils::{find_action, get_conn, now, DbPool}, + utils::{ + find_action, + get_conn, + now, + uplete::{OrDelete, UpleteCount}, + DbPool, + }, }; use chrono::{DateTime, Utc}; use diesel::{ @@ -66,13 +72,14 @@ impl Blockable for PersonBlock { .get_result::(conn) .await } - async fn unblock(pool: &mut DbPool<'_>, person_block_form: &Self::Form) -> Result { + async fn unblock(pool: &mut DbPool<'_>, person_block_form: &Self::Form) -> Result { let conn = &mut get_conn(pool).await?; diesel::update( person_actions::table.find((person_block_form.person_id, person_block_form.target_id)), ) .set(person_actions::blocked.eq(None::>)) - .execute(conn) + .or_delete() + .get_result(conn) .await } } From 86a174032e8304c2459100529826b11f2168603e Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 08:17:30 -0700 Subject: [PATCH 150/232] Update person.rs --- crates/db_schema/src/impls/person.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs index 085e96a6d..33e7fc435 100644 --- a/crates/db_schema/src/impls/person.rs +++ b/crates/db_schema/src/impls/person.rs @@ -234,7 +234,10 @@ impl Followable for PersonFollower { async fn follow_accepted(_: &mut DbPool<'_>, _: CommunityId, _: PersonId) -> Result { unimplemented!() } - async fn unfollow(pool: &mut DbPool<'_>, form: &PersonFollowerForm) -> Result { + async fn unfollow( + pool: &mut DbPool<'_>, + form: &PersonFollowerForm, + ) -> Result { let conn = &mut get_conn(pool).await?; diesel::update(person_actions::table.find((form.follower_id, form.person_id))) .set(( From 6090afe3e525de95c3f5a037cbeaabda55cce84d Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 08:18:16 -0700 Subject: [PATCH 151/232] Update person_block.rs --- crates/db_schema/src/impls/person_block.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/db_schema/src/impls/person_block.rs b/crates/db_schema/src/impls/person_block.rs index ff6bf2348..e54019018 100644 --- a/crates/db_schema/src/impls/person_block.rs +++ b/crates/db_schema/src/impls/person_block.rs @@ -72,7 +72,10 @@ impl Blockable for PersonBlock { .get_result::(conn) .await } - async fn unblock(pool: &mut DbPool<'_>, person_block_form: &Self::Form) -> Result { + async fn unblock( + pool: &mut DbPool<'_>, + person_block_form: &Self::Form, + ) -> Result { let conn = &mut get_conn(pool).await?; diesel::update( person_actions::table.find((person_block_form.person_id, person_block_form.target_id)), From 09dea6bcf6b0ea3fb56ff3daf024c7ef91e6d16b Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 09:12:41 -0700 Subject: [PATCH 152/232] Update person.rs --- crates/db_schema/src/impls/person.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs index 33e7fc435..61df18e1b 100644 --- a/crates/db_schema/src/impls/person.rs +++ b/crates/db_schema/src/impls/person.rs @@ -16,7 +16,7 @@ use crate::{ get_conn, naive_now, now, - upsert::{OrTable, UpleteCount, UpleteTable}, + uplete::{OrTable, UpleteCount, UpleteTable}, DbPool, }, }; From 7c6ffb426478901c1be6d0ebaefecff2d6d27dff Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 09:13:34 -0700 Subject: [PATCH 153/232] Update instance.rs --- crates/db_schema/src/impls/instance.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/db_schema/src/impls/instance.rs b/crates/db_schema/src/impls/instance.rs index ae1ead279..10fee8ff8 100644 --- a/crates/db_schema/src/impls/instance.rs +++ b/crates/db_schema/src/impls/instance.rs @@ -1,3 +1,4 @@ +use chrono::{DateTime, Utc}; use crate::{ diesel::dsl::IntervalDsl, newtypes::InstanceId, From abb1a7405f0c15eeb70da9ec2f283f5aa9dea2a0 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 09:14:01 -0700 Subject: [PATCH 154/232] Update instance_block.rs --- crates/db_schema/src/impls/instance_block.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/db_schema/src/impls/instance_block.rs b/crates/db_schema/src/impls/instance_block.rs index d526e4d6b..13c55d7ad 100644 --- a/crates/db_schema/src/impls/instance_block.rs +++ b/crates/db_schema/src/impls/instance_block.rs @@ -78,7 +78,8 @@ impl Blockable for InstanceBlock { instance_block_form.instance_id, ))) .set(instance_actions::blocked.eq(None::>)) - .execute(conn) + .or_delete() + .get_result(conn) .await } } From 322aa73aa0e58c0fe3841241f62936dc997a7dc7 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 09:21:32 -0700 Subject: [PATCH 155/232] Update instance.rs --- crates/db_schema/src/impls/instance.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/impls/instance.rs b/crates/db_schema/src/impls/instance.rs index 10fee8ff8..4df7cd0c6 100644 --- a/crates/db_schema/src/impls/instance.rs +++ b/crates/db_schema/src/impls/instance.rs @@ -1,4 +1,3 @@ -use chrono::{DateTime, Utc}; use crate::{ diesel::dsl::IntervalDsl, newtypes::InstanceId, @@ -24,6 +23,7 @@ use crate::{ DbPool, }, }; +use chrono::{DateTime, Utc}; use diesel::{ dsl::{count_star, insert_into}, result::Error, From dba0e37b0a63e0badec2160993c506038ba6929e Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 09:32:36 -0700 Subject: [PATCH 156/232] Update person.rs --- crates/db_schema/src/impls/person.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs index 61df18e1b..38586561c 100644 --- a/crates/db_schema/src/impls/person.rs +++ b/crates/db_schema/src/impls/person.rs @@ -16,7 +16,7 @@ use crate::{ get_conn, naive_now, now, - uplete::{OrTable, UpleteCount, UpleteTable}, + uplete::{OrDelete, UpleteCount, UpleteTable}, DbPool, }, }; From b70c9fe36b96951520be796f3660344aa00c5d1f Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 09:43:49 -0700 Subject: [PATCH 157/232] Update post.rs --- crates/db_schema/src/impls/post.rs | 46 ++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index a3b389a51..df09253bd 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -21,6 +21,7 @@ use crate::{ get_conn, naive_now, now, + uplete::{OrDelete, UpleteCount, UpleteTable}, DbPool, DELETED_REPLACEMENT_TEXT, FETCH_LIMIT_MAX, @@ -42,6 +43,20 @@ use diesel::{ use diesel_async::RunQueryDsl; use std::collections::HashSet; +impl UpleteTable for post_actions::table { + type EmptyRow = ( + post_actions::post_id, + post_actions::person_id, + Option>, + Option>, + Option, + Option>, + Option>, + Option, + Option>, + ); +} + #[async_trait] impl Crud for Post { type InsertForm = PostInsertForm; @@ -284,14 +299,15 @@ impl Likeable for PostLike { pool: &mut DbPool<'_>, person_id: PersonId, post_id: PostId, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; diesel::update(post_actions::table.find((person_id, post_id))) .set(( post_actions::like_score.eq(None::), post_actions::liked.eq(None::>), )) - .execute(conn) + .or_delete() + .get_result(conn) .await } } @@ -325,11 +341,15 @@ impl Saveable for PostSaved { .get_result::(conn) .await } - async fn unsave(pool: &mut DbPool<'_>, post_saved_form: &PostSavedForm) -> Result { + async fn unsave( + pool: &mut DbPool<'_>, + post_saved_form: &PostSavedForm, + ) -> Result { let conn = &mut get_conn(pool).await?; diesel::update(post_actions::table.find((post_saved_form.person_id, post_saved_form.post_id))) .set(post_actions::saved.eq(None::>)) - .execute(conn) + .or_delete() + .get_result(conn) .await } } @@ -364,7 +384,7 @@ impl PostRead { pool: &mut DbPool<'_>, post_id_: HashSet, person_id_: PersonId, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; diesel::update( @@ -373,7 +393,8 @@ impl PostRead { .filter(post_actions::person_id.eq(person_id_)), ) .set(post_actions::read.eq(None::>)) - .execute(conn) + .or_delete() + .get_result(conn) .await } } @@ -408,7 +429,7 @@ impl PostHide { pool: &mut DbPool<'_>, post_id_: HashSet, person_id_: PersonId, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; diesel::update( @@ -417,7 +438,8 @@ impl PostHide { .filter(post_actions::person_id.eq(person_id_)), ) .set(post_actions::hidden.eq(None::>)) - .execute(conn) + .or_delete() + .get_result(conn) .await } } @@ -444,7 +466,7 @@ mod tests { }, }, traits::{Crud, Likeable, Saveable}, - utils::build_db_pool_for_tests, + utils::{build_db_pool_for_tests, uplete::UpleteCount}, }; use pretty_assertions::assert_eq; use serial_test::serial; @@ -571,9 +593,9 @@ mod tests { let like_removed = PostLike::remove(pool, inserted_person.id, inserted_post.id) .await .unwrap(); - assert_eq!(1, like_removed); + assert_eq!(UpleteCount::only_updated(1), like_removed); let saved_removed = PostSaved::unsave(pool, &post_saved_form).await.unwrap(); - assert_eq!(1, saved_removed); + assert_eq!(UpleteCount::only_updated(1), saved_removed); let read_removed = PostRead::mark_as_unread( pool, HashSet::from([inserted_post.id, inserted_post2.id]), @@ -581,7 +603,7 @@ mod tests { ) .await .unwrap(); - assert_eq!(2, read_removed); + assert_eq!(UpleteCount::only_deleted(2), read_removed); let num_deleted = Post::delete(pool, inserted_post.id).await.unwrap() + Post::delete(pool, inserted_post2.id).await.unwrap(); From d8946522d3cc565530ecccea98deecf838fe3817 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 09:45:34 -0700 Subject: [PATCH 158/232] Update comment.rs --- crates/db_schema/src/impls/comment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index ea1526ce5..4f32c163d 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -284,7 +284,7 @@ mod tests { post::{Post, PostInsertForm}, }, traits::{Crud, Likeable, Saveable}, - utils::build_db_pool_for_tests, + utils::{build_db_pool_for_tests, uplete::UpleteCount}, }; use diesel_ltree::Ltree; use pretty_assertions::assert_eq; From 4b3d9ce15f69bb4aa79a34e2637cb104e714d1f4 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 09:47:02 -0700 Subject: [PATCH 159/232] Update community.rs --- crates/db_schema/src/impls/community.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/impls/community.rs b/crates/db_schema/src/impls/community.rs index 244c6cb18..242c7532e 100644 --- a/crates/db_schema/src/impls/community.rs +++ b/crates/db_schema/src/impls/community.rs @@ -518,7 +518,7 @@ mod tests { person::{Person, PersonInsertForm}, }, traits::{Bannable, Crud, Followable, Joinable}, - utils::build_db_pool_for_tests, + utils::{build_db_pool_for_tests, uplete::UpleteCount}, CommunityVisibility, }; use pretty_assertions::assert_eq; From e454d81098f201b97eca12ac286c27284d2c5b94 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 09:48:18 -0700 Subject: [PATCH 160/232] Update person.rs --- crates/db_schema/src/impls/person.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs index 38586561c..6c2295ada 100644 --- a/crates/db_schema/src/impls/person.rs +++ b/crates/db_schema/src/impls/person.rs @@ -276,7 +276,7 @@ mod tests { person::{Person, PersonFollower, PersonFollowerForm, PersonInsertForm, PersonUpdateForm}, }, traits::{Crud, Followable}, - utils::build_db_pool_for_tests, + utils::{build_db_pool_for_tests, uplete::UpleteCount}, }; use pretty_assertions::assert_eq; use serial_test::serial; From c82c8e0dde1f823f57541eef68c5328b02e8298d Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 10:18:41 -0700 Subject: [PATCH 161/232] Update post_view.rs --- crates/db_views/src/post_view.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 1cf1aad1d..f622aede8 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -602,7 +602,7 @@ mod tests { site::Site, }, traits::{Bannable, Blockable, Crud, Joinable, Likeable}, - utils::{build_db_pool, build_db_pool_for_tests, DbPool, RANK_DEFAULT}, + utils::{build_db_pool, build_db_pool_for_tests, uplete::UpleteCount, DbPool, RANK_DEFAULT}, CommunityVisibility, SortType, SubscribedType, @@ -942,7 +942,7 @@ mod tests { let like_removed = PostLike::remove(pool, data.local_user_view.person.id, data.inserted_post.id).await?; - assert_eq!(1, like_removed); + assert_eq!(UpleteCount::only_deleted(1), like_removed); cleanup(data, pool).await } From 422df50b74ad584d02e5492d2f4e2fd4e6f0c989 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Sun, 26 May 2024 19:13:18 -0700 Subject: [PATCH 162/232] Update comment.rs --- crates/db_schema/src/impls/comment.rs | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index 4f32c163d..260047f66 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -17,7 +17,7 @@ use crate::{ get_conn, naive_now, now, - uplete::{OrDelete, UpleteCount, UpleteTable}, + uplete::{uplete, UpleteCount}, DbPool, DELETED_REPLACEMENT_TEXT, }, @@ -34,16 +34,6 @@ use diesel_async::RunQueryDsl; use diesel_ltree::Ltree; use url::Url; -impl UpleteTable for comment_actions::table { - type EmptyRow = ( - comment_actions::person_id, - comment_actions::comment_id, - Option, - Option>, - Option>, - ); -} - impl Comment { pub async fn permadelete_for_creator( pool: &mut DbPool<'_>, @@ -200,12 +190,9 @@ impl Likeable for CommentLike { comment_id: CommentId, ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::update(comment_actions::table.find((person_id, comment_id))) - .set(( - comment_actions::like_score.eq(None::), - comment_actions::liked.eq(None::>), - )) - .or_delete() + uplete(comment_actions::table.find((person_id, comment_id))) + .set_null(comment_actions::like_score) + .set_null(comment_actions::liked) .get_result(conn) .await } @@ -251,11 +238,10 @@ impl Saveable for CommentSaved { comment_saved_form: &CommentSavedForm, ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::update( + uplete( comment_actions::table.find((comment_saved_form.person_id, comment_saved_form.comment_id)), ) - .set(comment_actions::saved.eq(None::>)) - .or_delete() + .set_null(comment_actions::saved) .get_result(conn) .await } From 0d210d9dbbac2763cd995af63b387bd280f6ea5e Mon Sep 17 00:00:00 2001 From: dullbananas Date: Mon, 27 May 2024 09:43:28 -0700 Subject: [PATCH 163/232] reduce diff --- crates/api_common/src/utils.rs | 1 - .../db_schema/replaceable_schema/triggers.sql | 6 +-- .../src/aggregates/person_post_aggregates.rs | 19 ++----- crates/db_schema/src/aggregates/structs.rs | 11 +++- crates/db_schema/src/impls/comment.rs | 35 ++---------- crates/db_schema/src/impls/community.rs | 53 ++----------------- crates/db_schema/src/impls/community_block.rs | 15 +----- crates/db_schema/src/impls/instance_block.rs | 15 +----- crates/db_schema/src/impls/person.rs | 19 +------ crates/db_schema/src/impls/person_block.rs | 15 +----- crates/db_schema/src/impls/post.rs | 37 ++----------- crates/db_schema/src/source/comment.rs | 18 ++++++- crates/db_schema/src/source/community.rs | 27 ++++++++-- .../db_schema/src/source/community_block.rs | 9 +++- crates/db_schema/src/source/instance_block.rs | 9 +++- crates/db_schema/src/source/person.rs | 11 +++- crates/db_schema/src/source/person_block.rs | 9 +++- crates/db_schema/src/source/post.rs | 32 +++++++++-- 18 files changed, 137 insertions(+), 204 deletions(-) diff --git a/crates/api_common/src/utils.rs b/crates/api_common/src/utils.rs index bad3b8180..995d9dbbd 100644 --- a/crates/api_common/src/utils.rs +++ b/crates/api_common/src/utils.rs @@ -165,7 +165,6 @@ pub async fn update_read_comments( person_id, post_id, read_comments, - ..PersonPostAggregatesForm::default() }; PersonPostAggregates::upsert(pool, &person_post_agg_form) diff --git a/crates/db_schema/replaceable_schema/triggers.sql b/crates/db_schema/replaceable_schema/triggers.sql index ada6f124c..9ec240cc9 100644 --- a/crates/db_schema/replaceable_schema/triggers.sql +++ b/crates/db_schema/replaceable_schema/triggers.sql @@ -533,7 +533,7 @@ CREATE TRIGGER delete_comments FOR EACH ROW EXECUTE FUNCTION r.delete_comments_before_post (); -CREATE FUNCTION r.delete_community_actions_before_person () +CREATE FUNCTION r.delete_follow_before_person () RETURNS TRIGGER LANGUAGE plpgsql AS $$ @@ -544,10 +544,10 @@ BEGIN END; $$; -CREATE TRIGGER delete_community_actions +CREATE TRIGGER delete_follow BEFORE DELETE ON person FOR EACH ROW - EXECUTE FUNCTION r.delete_community_actions_before_person (); + EXECUTE FUNCTION r.delete_follow_before_person (); -- Triggers that change values before insert or update CREATE FUNCTION r.comment_change_values () diff --git a/crates/db_schema/src/aggregates/person_post_aggregates.rs b/crates/db_schema/src/aggregates/person_post_aggregates.rs index 85c9692e5..6140a7706 100644 --- a/crates/db_schema/src/aggregates/person_post_aggregates.rs +++ b/crates/db_schema/src/aggregates/person_post_aggregates.rs @@ -7,6 +7,7 @@ use crate::{ }; use diesel::{ dsl, + expression::SelectableHelper, insert_into, result::Error, ExpressionMethods, @@ -16,20 +17,6 @@ use diesel::{ use diesel_async::RunQueryDsl; impl PersonPostAggregates { - fn as_select_unwrap() -> ( - post_actions::person_id, - post_actions::post_id, - dsl::AssumeNotNull, - dsl::AssumeNotNull, - ) { - ( - post_actions::person_id, - post_actions::post_id, - post_actions::read_comments_amount.assume_not_null(), - post_actions::read_comments.assume_not_null(), - ) - } - pub async fn upsert( pool: &mut DbPool<'_>, form: &PersonPostAggregatesForm, @@ -41,7 +28,7 @@ impl PersonPostAggregates { .on_conflict((post_actions::person_id, post_actions::post_id)) .do_update() .set(form) - .returning(Self::as_select_unwrap()) + .returning(Self::as_select()) .get_result::(conn) .await } @@ -52,7 +39,7 @@ impl PersonPostAggregates { ) -> Result, Error> { let conn = &mut get_conn(pool).await?; find_action(post_actions::read_comments, (person_id_, post_id_)) - .select(Self::as_select_unwrap()) + .select(Self::as_select()) .first(conn) .await .optional() diff --git a/crates/db_schema/src/aggregates/structs.rs b/crates/db_schema/src/aggregates/structs.rs index 40895d6a8..dcd927868 100644 --- a/crates/db_schema/src/aggregates/structs.rs +++ b/crates/db_schema/src/aggregates/structs.rs @@ -10,6 +10,8 @@ use crate::schema::{ }; use chrono::{DateTime, Utc}; #[cfg(feature = "full")] +use diesel::{dsl, expression_methods::NullableExpressionMethods}; +#[cfg(feature = "full")] use i_love_jesus::CursorKeysModule; use serde::{Deserialize, Serialize}; #[cfg(feature = "full")] @@ -147,7 +149,10 @@ pub struct PostAggregates { } #[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)] -#[cfg_attr(feature = "full", derive(Queryable, Associations, Identifiable))] +#[cfg_attr( + feature = "full", + derive(Queryable, Selectable, Associations, Identifiable) +)] #[cfg_attr(feature = "full", diesel(table_name = post_actions))] #[cfg_attr(feature = "full", diesel(primary_key(person_id, post_id)))] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::person::Person)))] @@ -159,7 +164,11 @@ pub struct PersonPostAggregates { /// The number of comments they've read on that post. /// /// This is updated to the current post comment count every time they view a post. + #[diesel(select_expression = post_actions::read_comments_amount.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub read_comments: i64, + #[diesel(select_expression = post_actions::read_comments.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub published: DateTime, } diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index 260047f66..67d9ecedf 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -13,6 +13,7 @@ use crate::{ }, traits::{Crud, Likeable, Saveable}, utils::{ + expression::SelectableHelper, functions::coalesce, get_conn, naive_now, @@ -149,22 +150,6 @@ impl Crud for Comment { } } -impl CommentLike { - fn as_select_unwrap() -> ( - comment_actions::person_id, - comment_actions::comment_id, - dsl::AssumeNotNull, - dsl::AssumeNotNull, - ) { - ( - comment_actions::person_id, - comment_actions::comment_id, - comment_actions::like_score.assume_not_null(), - comment_actions::liked.assume_not_null(), - ) - } -} - #[async_trait] impl Likeable for CommentLike { type Form = CommentLikeForm; @@ -180,7 +165,7 @@ impl Likeable for CommentLike { .on_conflict((comment_actions::comment_id, comment_actions::person_id)) .do_update() .set(comment_like_form) - .returning(Self::as_select_unwrap()) + .returning(Self::as_select()) .get_result::(conn) .await } @@ -198,20 +183,6 @@ impl Likeable for CommentLike { } } -impl CommentSaved { - fn as_select_unwrap() -> ( - comment_actions::comment_id, - comment_actions::person_id, - dsl::AssumeNotNull, - ) { - ( - comment_actions::comment_id, - comment_actions::person_id, - comment_actions::saved.assume_not_null(), - ) - } -} - #[async_trait] impl Saveable for CommentSaved { type Form = CommentSavedForm; @@ -229,7 +200,7 @@ impl Saveable for CommentSaved { .on_conflict((comment_actions::comment_id, comment_actions::person_id)) .do_update() .set(comment_saved_form) - .returning(Self::as_select_unwrap()) + .returning(Self::as_select()) .get_result::(conn) .await } diff --git a/crates/db_schema/src/impls/community.rs b/crates/db_schema/src/impls/community.rs index 242c7532e..a270f393d 100644 --- a/crates/db_schema/src/impls/community.rs +++ b/crates/db_schema/src/impls/community.rs @@ -20,6 +20,7 @@ use crate::{ traits::{ApubActor, Bannable, Crud, Followable, Joinable}, utils::{ action_query, + expression::SelectableHelper, find_action, functions::{coalesce, lower}, get_conn, @@ -93,20 +94,6 @@ impl Crud for Community { } } -impl CommunityModerator { - fn as_select_unwrap() -> ( - community_actions::community_id, - community_actions::person_id, - dsl::AssumeNotNull, - ) { - ( - community_actions::community_id, - community_actions::person_id, - community_actions::became_moderator.assume_not_null(), - ) - } -} - #[async_trait] impl Joinable for CommunityModerator { type Form = CommunityModeratorForm; @@ -127,7 +114,7 @@ impl Joinable for CommunityModerator { )) .do_update() .set(community_moderator_form) - .returning(Self::as_select_unwrap()) + .returning(Self::as_select()) .get_result::(conn) .await } @@ -278,22 +265,6 @@ impl CommunityModerator { } } -impl CommunityPersonBan { - fn as_select_unwrap() -> ( - community_actions::community_id, - community_actions::person_id, - dsl::AssumeNotNull, - community_actions::ban_expires, - ) { - ( - community_actions::community_id, - community_actions::person_id, - community_actions::received_ban.assume_not_null(), - community_actions::ban_expires, - ) - } -} - #[async_trait] impl Bannable for CommunityPersonBan { type Form = CommunityPersonBanForm; @@ -314,7 +285,7 @@ impl Bannable for CommunityPersonBan { )) .do_update() .set(community_person_ban_form) - .returning(Self::as_select_unwrap()) + .returning(Self::as_select()) .get_result::(conn) .await } @@ -339,20 +310,6 @@ impl Bannable for CommunityPersonBan { } impl CommunityFollower { - fn as_select_unwrap() -> ( - community_actions::community_id, - community_actions::person_id, - dsl::AssumeNotNull, - dsl::AssumeNotNull, - ) { - ( - community_actions::community_id, - community_actions::person_id, - community_actions::followed.assume_not_null(), - community_actions::follow_pending.assume_not_null(), - ) - } - pub fn to_subscribed_type(follower: &Option) -> SubscribedType { match follower { Some(f) => { @@ -412,7 +369,7 @@ impl Followable for CommunityFollower { )) .do_update() .set(form) - .returning(Self::as_select_unwrap()) + .returning(Self::as_select()) .get_result::(conn) .await } @@ -427,7 +384,7 @@ impl Followable for CommunityFollower { (person_id, community_id), )) .set(community_actions::follow_pending.eq(Some(false))) - .returning(Self::as_select_unwrap()) + .returning(Self::as_select()) .get_result::(conn) .await } diff --git a/crates/db_schema/src/impls/community_block.rs b/crates/db_schema/src/impls/community_block.rs index da9ba3315..72eacb85d 100644 --- a/crates/db_schema/src/impls/community_block.rs +++ b/crates/db_schema/src/impls/community_block.rs @@ -14,6 +14,7 @@ use crate::{ use chrono::{DateTime, Utc}; use diesel::{ dsl::{self, exists, insert_into}, + expression::SelectableHelper, result::Error, select, ExpressionMethods, @@ -23,18 +24,6 @@ use diesel::{ use diesel_async::RunQueryDsl; impl CommunityBlock { - fn as_select_unwrap() -> ( - community_actions::person_id, - community_actions::community_id, - dsl::AssumeNotNull, - ) { - ( - community_actions::person_id, - community_actions::community_id, - community_actions::blocked.assume_not_null(), - ) - } - pub async fn read( pool: &mut DbPool<'_>, for_person_id: PersonId, @@ -67,7 +56,7 @@ impl Blockable for CommunityBlock { )) .do_update() .set(community_block_form) - .returning(Self::as_select_unwrap()) + .returning(Self::as_select()) .get_result::(conn) .await } diff --git a/crates/db_schema/src/impls/instance_block.rs b/crates/db_schema/src/impls/instance_block.rs index 13c55d7ad..f82452f1f 100644 --- a/crates/db_schema/src/impls/instance_block.rs +++ b/crates/db_schema/src/impls/instance_block.rs @@ -14,6 +14,7 @@ use crate::{ use chrono::{DateTime, Utc}; use diesel::{ dsl::{self, exists, insert_into}, + expression::SelectableHelper, result::Error, select, ExpressionMethods, @@ -23,18 +24,6 @@ use diesel::{ use diesel_async::RunQueryDsl; impl InstanceBlock { - fn as_select_unwrap() -> ( - instance_actions::person_id, - instance_actions::instance_id, - dsl::AssumeNotNull, - ) { - ( - instance_actions::person_id, - instance_actions::instance_id, - instance_actions::blocked.assume_not_null(), - ) - } - pub async fn read( pool: &mut DbPool<'_>, for_person_id: PersonId, @@ -64,7 +53,7 @@ impl Blockable for InstanceBlock { .on_conflict((instance_actions::person_id, instance_actions::instance_id)) .do_update() .set(instance_block_form) - .returning(Self::as_select_unwrap()) + .returning(Self::as_select()) .get_result::(conn) .await } diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs index 6c2295ada..1c7dbc7e5 100644 --- a/crates/db_schema/src/impls/person.rs +++ b/crates/db_schema/src/impls/person.rs @@ -23,6 +23,7 @@ use crate::{ use chrono::{DateTime, Utc}; use diesel::{ dsl::{self, insert_into}, + expression::SelectableHelper, result::Error, CombineDsl, ExpressionMethods, @@ -200,22 +201,6 @@ impl ApubActor for Person { } } -impl PersonFollower { - fn as_select_unwrap() -> ( - person_actions::target_id, - person_actions::person_id, - dsl::AssumeNotNull, - dsl::AssumeNotNull, - ) { - ( - person_actions::target_id, - person_actions::person_id, - person_actions::followed.assume_not_null(), - person_actions::follow_pending.assume_not_null(), - ) - } -} - #[async_trait] impl Followable for PersonFollower { type Form = PersonFollowerForm; @@ -227,7 +212,7 @@ impl Followable for PersonFollower { .on_conflict((person_actions::person_id, person_actions::target_id)) .do_update() .set(form) - .returning(Self::as_select_unwrap()) + .returning(Self::as_select()) .get_result::(conn) .await } diff --git a/crates/db_schema/src/impls/person_block.rs b/crates/db_schema/src/impls/person_block.rs index e54019018..b1c17cfbc 100644 --- a/crates/db_schema/src/impls/person_block.rs +++ b/crates/db_schema/src/impls/person_block.rs @@ -15,6 +15,7 @@ use chrono::{DateTime, Utc}; use diesel::{ dsl, dsl::{exists, insert_into}, + expression::SelectableHelper, result::Error, select, ExpressionMethods, @@ -24,18 +25,6 @@ use diesel::{ use diesel_async::RunQueryDsl; impl PersonBlock { - fn as_select_unwrap() -> ( - person_actions::person_id, - person_actions::target_id, - dsl::AssumeNotNull, - ) { - ( - person_actions::person_id, - person_actions::target_id, - person_actions::blocked.assume_not_null(), - ) - } - pub async fn read( pool: &mut DbPool<'_>, for_person_id: PersonId, @@ -68,7 +57,7 @@ impl Blockable for PersonBlock { .on_conflict((person_actions::person_id, person_actions::target_id)) .do_update() .set(person_block_form) - .returning(Self::as_select_unwrap()) + .returning(Self::as_select()) .get_result::(conn) .await } diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index df09253bd..06a979f83 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -33,6 +33,7 @@ use ::url::Url; use chrono::{DateTime, Utc}; use diesel::{ dsl::{self, insert_into}, + expression::SelectableHelper, result::Error, DecoratableTarget, ExpressionMethods, @@ -261,24 +262,6 @@ impl Post { } } -// TODO: replace `as_select_unwrap` definitions with `Default::default()` after next Diesel release -// which should implement `Default` for `AssumeNotNull` -impl PostLike { - fn as_select_unwrap() -> ( - post_actions::post_id, - post_actions::person_id, - dsl::AssumeNotNull, - dsl::AssumeNotNull, - ) { - ( - post_actions::post_id, - post_actions::person_id, - post_actions::like_score.assume_not_null(), - post_actions::liked.assume_not_null(), - ) - } -} - #[async_trait] impl Likeable for PostLike { type Form = PostLikeForm; @@ -291,7 +274,7 @@ impl Likeable for PostLike { .on_conflict((post_actions::post_id, post_actions::person_id)) .do_update() .set(post_like_form) - .returning(Self::as_select_unwrap()) + .returning(Self::as_select()) .get_result::(conn) .await } @@ -312,20 +295,6 @@ impl Likeable for PostLike { } } -impl PostSaved { - fn as_select_unwrap() -> ( - post_actions::post_id, - post_actions::person_id, - dsl::AssumeNotNull, - ) { - ( - post_actions::post_id, - post_actions::person_id, - post_actions::saved.assume_not_null(), - ) - } -} - #[async_trait] impl Saveable for PostSaved { type Form = PostSavedForm; @@ -337,7 +306,7 @@ impl Saveable for PostSaved { .on_conflict((post_actions::post_id, post_actions::person_id)) .do_update() .set(post_saved_form) - .returning(Self::as_select_unwrap()) + .returning(Self::as_select()) .get_result::(conn) .await } diff --git a/crates/db_schema/src/source/comment.rs b/crates/db_schema/src/source/comment.rs index 2f235932e..883719ba2 100644 --- a/crates/db_schema/src/source/comment.rs +++ b/crates/db_schema/src/source/comment.rs @@ -5,6 +5,8 @@ use crate::newtypes::{CommentId, DbUrl, LanguageId, PersonId, PostId}; use crate::schema::{comment, comment_actions}; use chrono::{DateTime, Utc}; #[cfg(feature = "full")] +use diesel::{dsl, expression_methods::NullableExpressionMethods} +#[cfg(feature = "full")] use diesel_ltree::Ltree; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; @@ -88,7 +90,10 @@ pub struct CommentUpdateForm { } #[derive(PartialEq, Eq, Debug, Clone)] -#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] +#[cfg_attr( + feature = "full", + derive(Identifiable, Queryable, Selectable, Associations) +)] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::comment::Comment)))] #[cfg_attr(feature = "full", diesel(table_name = comment_actions))] #[cfg_attr(feature = "full", diesel(primary_key(person_id, comment_id)))] @@ -96,7 +101,11 @@ pub struct CommentUpdateForm { pub struct CommentLike { pub person_id: PersonId, pub comment_id: CommentId, + #[diesel(select_expression = comment_actions::like_score.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub score: i16, + #[diesel(select_expression = comment_actions::liked.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub published: DateTime, } @@ -111,7 +120,10 @@ pub struct CommentLikeForm { } #[derive(PartialEq, Eq, Debug)] -#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] +#[cfg_attr( + feature = "full", + derive(Identifiable, Queryable, Selectable, Associations) +)] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::comment::Comment)))] #[cfg_attr(feature = "full", diesel(table_name = comment_actions))] #[cfg_attr(feature = "full", diesel(primary_key(person_id, comment_id)))] @@ -119,6 +131,8 @@ pub struct CommentLikeForm { pub struct CommentSaved { pub comment_id: CommentId, pub person_id: PersonId, + #[diesel(select_expression = comment_actions::saved.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub published: DateTime, } diff --git a/crates/db_schema/src/source/community.rs b/crates/db_schema/src/source/community.rs index 1be33d8b9..0b5ce60da 100644 --- a/crates/db_schema/src/source/community.rs +++ b/crates/db_schema/src/source/community.rs @@ -7,6 +7,8 @@ use crate::{ CommunityVisibility, }; use chrono::{DateTime, Utc}; +#[cfg(feature = "full")] +use diesel::{dsl, expression_methods::NullableExplessionMethods}; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; #[cfg(feature = "full")] @@ -134,7 +136,10 @@ pub struct CommunityUpdateForm { } #[derive(PartialEq, Eq, Debug)] -#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] +#[cfg_attr( + feature = "full", + derive(Identifiable, Queryable, Selectable, Associations) +)] #[cfg_attr( feature = "full", diesel(belongs_to(crate::source::community::Community)) @@ -145,6 +150,8 @@ pub struct CommunityUpdateForm { pub struct CommunityModerator { pub community_id: CommunityId, pub person_id: PersonId, + #[diesel(select_expression = community_actions::became_moderator.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub published: DateTime, } @@ -157,7 +164,10 @@ pub struct CommunityModeratorForm { } #[derive(PartialEq, Eq, Debug)] -#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] +#[cfg_attr( + feature = "full", + derive(Identifiable, Queryable, Selectable, Associations) +)] #[cfg_attr( feature = "full", diesel(belongs_to(crate::source::community::Community)) @@ -168,7 +178,11 @@ pub struct CommunityModeratorForm { pub struct CommunityPersonBan { pub community_id: CommunityId, pub person_id: PersonId, + #[diesel(select_expression = community_actions::received_ban.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub published: DateTime, + #[diesel(select_expression = community_actions::ban_expires.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub expires: Option>, } @@ -183,7 +197,10 @@ pub struct CommunityPersonBanForm { } #[derive(PartialEq, Eq, Debug)] -#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] +#[cfg_attr( + feature = "full", + derive(Identifiable, Queryable, Selectable, Associations) +)] #[cfg_attr( feature = "full", diesel(belongs_to(crate::source::community::Community)) @@ -194,7 +211,11 @@ pub struct CommunityPersonBanForm { pub struct CommunityFollower { pub community_id: CommunityId, pub person_id: PersonId, + #[diesel(select_expression = community_actions::followed.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub published: DateTime, + #[diesel(select_expression = community_actions::follow_pending.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub pending: bool, } diff --git a/crates/db_schema/src/source/community_block.rs b/crates/db_schema/src/source/community_block.rs index d46ade3e8..845238c7e 100644 --- a/crates/db_schema/src/source/community_block.rs +++ b/crates/db_schema/src/source/community_block.rs @@ -2,10 +2,15 @@ use crate::newtypes::{CommunityId, PersonId}; #[cfg(feature = "full")] use crate::schema::community_actions; use chrono::{DateTime, Utc}; +#[cfg(feature = "full")] +use diesel::{dsl, expression_methods::NullableExpressionMethods}; use serde::{Deserialize, Serialize}; #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] -#[cfg_attr(feature = "full", derive(Queryable, Associations, Identifiable))] +#[cfg_attr( + feature = "full", + derive(Queryable, Selectable, Associations, Identifiable) +)] #[cfg_attr( feature = "full", diesel(belongs_to(crate::source::community::Community)) @@ -16,6 +21,8 @@ use serde::{Deserialize, Serialize}; pub struct CommunityBlock { pub person_id: PersonId, pub community_id: CommunityId, + #[diesel(select_expression = community_actions::blocked.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub published: DateTime, } diff --git a/crates/db_schema/src/source/instance_block.rs b/crates/db_schema/src/source/instance_block.rs index 237b21bc9..530a9dd8d 100644 --- a/crates/db_schema/src/source/instance_block.rs +++ b/crates/db_schema/src/source/instance_block.rs @@ -2,10 +2,15 @@ use crate::newtypes::{InstanceId, PersonId}; #[cfg(feature = "full")] use crate::schema::instance_actions; use chrono::{DateTime, Utc}; +#[cfg(feature = "full")] +use diesel::{dsl, expression_methods::NullableExpressionMethods}; use serde::{Deserialize, Serialize}; #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] -#[cfg_attr(feature = "full", derive(Queryable, Associations, Identifiable))] +#[cfg_attr( + feature = "full", + derive(Queryable, Selectable, Associations, Identifiable) +)] #[cfg_attr( feature = "full", diesel(belongs_to(crate::source::instance::Instance)) @@ -16,6 +21,8 @@ use serde::{Deserialize, Serialize}; pub struct InstanceBlock { pub person_id: PersonId, pub instance_id: InstanceId, + #[diesel(select_expression = instance_actions::blocked.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub published: DateTime, } diff --git a/crates/db_schema/src/source/person.rs b/crates/db_schema/src/source/person.rs index 4e52b23a7..5f261f99d 100644 --- a/crates/db_schema/src/source/person.rs +++ b/crates/db_schema/src/source/person.rs @@ -6,6 +6,8 @@ use crate::{ source::placeholder_apub_url, }; use chrono::{DateTime, Utc}; +#[cfg(feature = "full")] +use diesel::{dsl, expression_methods::ExpressionMethods}; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; #[cfg(feature = "full")] @@ -114,7 +116,10 @@ pub struct PersonUpdateForm { } #[derive(PartialEq, Eq, Debug)] -#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] +#[cfg_attr( + feature = "full", + derive(Identifiable, Queryable, Selectable, Associations) +)] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::person::Person)))] #[cfg_attr(feature = "full", diesel(table_name = person_actions))] #[cfg_attr(feature = "full", diesel(primary_key(follower_id, person_id)))] @@ -122,7 +127,11 @@ pub struct PersonUpdateForm { pub struct PersonFollower { pub person_id: PersonId, pub follower_id: PersonId, + #[diesel(select_expression = person_actions::followed.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub published: DateTime, + #[diesel(select_expression = person_actions::follow_pending.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub pending: bool, } diff --git a/crates/db_schema/src/source/person_block.rs b/crates/db_schema/src/source/person_block.rs index 0d3f8118c..82c82b22f 100644 --- a/crates/db_schema/src/source/person_block.rs +++ b/crates/db_schema/src/source/person_block.rs @@ -2,10 +2,15 @@ use crate::newtypes::PersonId; #[cfg(feature = "full")] use crate::schema::person_actions; use chrono::{DateTime, Utc}; +#[cfg(feature = "full")] +use diesel::{dsl, expression_methods::NullableExpressionMethods}; use serde::{Deserialize, Serialize}; #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] -#[cfg_attr(feature = "full", derive(Queryable, Associations, Identifiable))] +#[cfg_attr( + feature = "full", + derive(Queryable, Selectable, Associations, Identifiable) +)] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::person::Person)))] #[cfg_attr(feature = "full", diesel(table_name = person_actions))] #[cfg_attr(feature = "full", diesel(primary_key(person_id, target_id)))] @@ -13,6 +18,8 @@ use serde::{Deserialize, Serialize}; pub struct PersonBlock { pub person_id: PersonId, pub target_id: PersonId, + #[diesel(select_expression = person_actions::blocked.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub published: DateTime, } diff --git a/crates/db_schema/src/source/post.rs b/crates/db_schema/src/source/post.rs index 1e980ef34..1dd61bae5 100644 --- a/crates/db_schema/src/source/post.rs +++ b/crates/db_schema/src/source/post.rs @@ -2,6 +2,8 @@ use crate::newtypes::{CommunityId, DbUrl, LanguageId, PersonId, PostId}; #[cfg(feature = "full")] use crate::schema::{post, post_actions}; use chrono::{DateTime, Utc}; +#[cfg(feature = "full")] +use diesel::{dsl, expression_methods::NullableExpressionMethods}; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; #[cfg(feature = "full")] @@ -119,7 +121,10 @@ pub struct PostUpdateForm { } #[derive(PartialEq, Eq, Debug)] -#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] +#[cfg_attr( + feature = "full", + derive(Identifiable, Queryable, Selectable, Associations) +)] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::post::Post)))] #[cfg_attr(feature = "full", diesel(table_name = post_actions))] #[cfg_attr(feature = "full", diesel(primary_key(person_id, post_id)))] @@ -127,7 +132,11 @@ pub struct PostUpdateForm { pub struct PostLike { pub post_id: PostId, pub person_id: PersonId, + #[diesel(select_expression = post_actions::like_score.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub score: i16, + #[diesel(select_expression = post_actions::liked.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub published: DateTime, } @@ -142,7 +151,10 @@ pub struct PostLikeForm { } #[derive(PartialEq, Eq, Debug)] -#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] +#[cfg_attr( + feature = "full", + derive(Identifiable, Queryable, Selectable, Associations) +)] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::post::Post)))] #[cfg_attr(feature = "full", diesel(table_name = post_actions))] #[cfg_attr(feature = "full", diesel(primary_key(person_id, post_id)))] @@ -150,6 +162,8 @@ pub struct PostLikeForm { pub struct PostSaved { pub post_id: PostId, pub person_id: PersonId, + #[diesel(select_expression = post_actions::saved.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub published: DateTime, } @@ -161,7 +175,10 @@ pub struct PostSavedForm { } #[derive(PartialEq, Eq, Debug)] -#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] +#[cfg_attr( + feature = "full", + derive(Identifiable, Queryable, Selectable, Associations) +)] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::post::Post)))] #[cfg_attr(feature = "full", diesel(table_name = post_actions))] #[cfg_attr(feature = "full", diesel(primary_key(person_id, post_id)))] @@ -169,6 +186,8 @@ pub struct PostSavedForm { pub struct PostRead { pub post_id: PostId, pub person_id: PersonId, + #[diesel(select_expression = post_actions::read.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub published: DateTime, } @@ -180,7 +199,10 @@ pub(crate) struct PostReadForm { } #[derive(PartialEq, Eq, Debug)] -#[cfg_attr(feature = "full", derive(Identifiable, Queryable, Associations))] +#[cfg_attr( + feature = "full", + derive(Identifiable, Queryable, Selectable, Associations) +)] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::post::Post)))] #[cfg_attr(feature = "full", diesel(table_name = post_actions))] #[cfg_attr(feature = "full", diesel(primary_key(person_id, post_id)))] @@ -188,6 +210,8 @@ pub(crate) struct PostReadForm { pub struct PostHide { pub post_id: PostId, pub person_id: PersonId, + #[diesel(select_expression = post_actions::hidden.assume_not_null())] + #[diesel(select_expression_type = dsl::AssumeNotNull)] pub published: DateTime, } From b23429cfe99587f3df838a78d301f9c7506e1b23 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 11:13:19 -0700 Subject: [PATCH 164/232] revert some changes in views --- crates/db_views/src/comment_report_view.rs | 36 ++++++++------- crates/db_views/src/comment_view.rs | 12 ++++- crates/db_views/src/post_report_view.rs | 44 +++++++++++-------- crates/db_views/src/post_view.rs | 17 +++++-- .../db_views_actor/src/comment_reply_view.rs | 30 +++++++++---- .../db_views_actor/src/person_mention_view.rs | 30 +++++++++---- 6 files changed, 115 insertions(+), 54 deletions(-) diff --git a/crates/db_views/src/comment_report_view.rs b/crates/db_views/src/comment_report_view.rs index 806eb47bf..94e65f96e 100644 --- a/crates/db_views/src/comment_report_view.rs +++ b/crates/db_views/src/comment_report_view.rs @@ -46,12 +46,11 @@ fn queries<'a>() -> Queries< > { let all_joins = |query: comment_report::BoxedQuery<'a, Pg>, my_person_id: PersonId| { query + .inner_join(comment::table) + .inner_join(post::table.on(comment::post_id.eq(post::id))) + .inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(person::table.on(comment_report::creator_id.eq(person::id))) - .inner_join( - comment::table - .inner_join(post::table.inner_join(community::table)) - .inner_join(aliases::person1.left_join(local_user::table)), - ) + .inner_join(aliases::person1.on(comment::creator_id.eq(aliases::person1.field(person::id)))) .inner_join( comment_aggregates::table.on(comment_report::comment_id.eq(comment_aggregates::comment_id)), ) @@ -60,6 +59,22 @@ fn queries<'a>() -> Queries< Some(my_person_id), comment_report::comment_id, )) + .left_join( + aliases::person2 + .on(comment_report::resolver_id.eq(aliases::person2.field(person::id).nullable())), + ) + .left_join(actions_alias( + creator_community_actions, + comment::creator_id, + post::community_id, + )) + .left_join( + local_user::table.on( + comment::creator_id + .eq(local_user::person_id) + .and(local_user::admin.eq(true)), + ), + ) .left_join(actions( person_actions::table, Some(my_person_id), @@ -70,15 +85,6 @@ fn queries<'a>() -> Queries< Some(my_person_id), post::community_id, )) - .left_join( - aliases::person2 - .on(comment_report::resolver_id.eq(aliases::person2.field(person::id).nullable())), - ) - .left_join(actions_alias( - creator_community_actions, - comment::creator_id, - post::community_id, - )) .select(( comment_report::all_columns, comment::all_columns, @@ -104,7 +110,7 @@ fn queries<'a>() -> Queries< .field(community_actions::became_moderator) .nullable() .is_not_null(), - coalesce(local_user::admin.nullable(), false), + local_user::admin.nullable().is_not_null(), person_actions::blocked.nullable().is_not_null(), CommunityFollower::select_subscribed_type(), comment_actions::saved.nullable().is_not_null(), diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs index babc3592e..6ea2374bf 100644 --- a/crates/db_views/src/comment_view.rs +++ b/crates/db_views/src/comment_view.rs @@ -50,9 +50,17 @@ fn queries<'a>() -> Queries< impl ReadFn<'a, CommentView, (CommentId, Option)>, impl ListFn<'a, CommentView, CommentQuery<'a>>, > { + let creator_is_admin = exists( + local_user::table.filter( + comment::creator_id + .eq(local_user::person_id) + .and(local_user::admin.eq(true)), + ), + ); + let all_joins = move |query: comment::BoxedQuery<'a, Pg>, my_person_id: Option| { query - .inner_join(person::table.left_join(local_user::table)) + .inner_join(person::table) .inner_join(post::table) .inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(comment_aggregates::table) @@ -96,7 +104,7 @@ fn queries<'a>() -> Queries< .field(community_actions::became_moderator) .nullable() .is_not_null(), - coalesce(local_user::admin.nullable(), false), + creator_is_admin, CommunityFollower::select_subscribed_type(), comment_actions::saved.nullable().is_not_null(), person_actions::blocked.nullable().is_not_null(), diff --git a/crates/db_views/src/post_report_view.rs b/crates/db_views/src/post_report_view.rs index ab8bf4fee..b7827dc79 100644 --- a/crates/db_views/src/post_report_view.rs +++ b/crates/db_views/src/post_report_view.rs @@ -44,33 +44,38 @@ fn queries<'a>() -> Queries< > { let all_joins = |query: post_report::BoxedQuery<'a, Pg>, my_person_id: PersonId| { query - .inner_join( - post::table - .inner_join(community::table) - .inner_join(aliases::person1.left_join(local_user::table)), - ) + .inner_join(post::table) + .inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(person::table.on(post_report::creator_id.eq(person::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())), - ) - .left_join(actions(post_actions::table, Some(my_person_id), post::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( - person_actions::table, - Some(my_person_id), - post::creator_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, post::all_columns, @@ -85,14 +90,17 @@ fn queries<'a>() -> Queries< .field(community_actions::became_moderator) .nullable() .is_not_null(), - coalesce(local_user::admin.nullable(), false), + 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(), - post_aggregates::comments - coalesce(post_actions::read_comments_amount.nullable(), 0), + 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()), )) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index f0ffc4d9c..aa901db8d 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -59,10 +59,18 @@ fn queries<'a>() -> Queries< impl ReadFn<'a, PostView, (PostId, Option, bool)>, impl ListFn<'a, PostView, (PostQuery<'a>, &'a Site)>, > { + let creator_is_admin = exists( + local_user::table.filter( + comment::creator_id + .eq(local_user::person_id) + .and(local_user::admin.eq(true)), + ), + ); + let all_joins = move |query: post_aggregates::BoxedQuery<'a, Pg>, my_person_id: Option| { query - .inner_join(person::table.left_join(local_user::table)) + .inner_join(person::table) .inner_join(community::table) .inner_join(post::table) .left_join(actions( @@ -103,7 +111,7 @@ fn queries<'a>() -> Queries< .field(community_actions::became_moderator) .nullable() .is_not_null(), - coalesce(local_user::admin.nullable(), false), + creator_is_admin, post_aggregates::all_columns, CommunityFollower::select_subscribed_type(), post_actions::saved.nullable().is_not_null(), @@ -111,7 +119,10 @@ fn queries<'a>() -> Queries< post_actions::hidden.nullable().is_not_null(), person_actions::blocked.nullable().is_not_null(), post_actions::like_score.nullable(), - post_aggregates::comments - coalesce(post_actions::read_comments_amount.nullable(), 0), + coalesce( + post_aggregates::comments.nullable() - post_actions::read_comments_amount.nullable(), + post_aggregates::comments, + ), )) }; diff --git a/crates/db_views_actor/src/comment_reply_view.rs b/crates/db_views_actor/src/comment_reply_view.rs index 7c9bf1468..956f449b3 100644 --- a/crates/db_views_actor/src/comment_reply_view.rs +++ b/crates/db_views_actor/src/comment_reply_view.rs @@ -1,5 +1,12 @@ use crate::structs::CommentReplyView; -use diesel::{pg::Pg, result::Error, ExpressionMethods, NullableExpressionMethods, QueryDsl}; +use diesel::{ + dsl::exists, + pg::Pg, + result::Error, + ExpressionMethods, + NullableExpressionMethods, + QueryDsl, +}; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ aliases::{self, creator_community_actions}, @@ -36,16 +43,23 @@ fn queries<'a>() -> Queries< impl ReadFn<'a, CommentReplyView, (CommentReplyId, Option)>, impl ListFn<'a, CommentReplyView, CommentReplyQuery>, > { + let creator_is_admin = exists( + local_user::table.filter( + comment::creator_id + .eq(local_user::person_id) + .and(local_user::admin.eq(true)), + ), + ); + let all_joins = move |query: comment_reply::BoxedQuery<'a, Pg>, my_person_id: Option| { query - .inner_join( - comment::table - .inner_join(person::table.left_join(local_user::table)) - .inner_join(post::table.inner_join(community::table)) - .inner_join(comment_aggregates::table), - ) + .inner_join(comment::table) + .inner_join(person::table.on(comment::creator_id.eq(person::id))) + .inner_join(post::table.on(comment::post_id.eq(post::id))) + .inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(aliases::person1) + .inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id))) .left_join(actions(comment_actions::table, my_person_id, comment::id)) .left_join(actions( community_actions::table, @@ -79,7 +93,7 @@ fn queries<'a>() -> Queries< .field(community_actions::became_moderator) .nullable() .is_not_null(), - coalesce(local_user::admin.nullable(), false), + creator_is_admin, CommunityFollower::select_subscribed_type(), comment_actions::saved.nullable().is_not_null(), person_actions::blocked.nullable().is_not_null(), diff --git a/crates/db_views_actor/src/person_mention_view.rs b/crates/db_views_actor/src/person_mention_view.rs index 3a39943ae..a048b7d6d 100644 --- a/crates/db_views_actor/src/person_mention_view.rs +++ b/crates/db_views_actor/src/person_mention_view.rs @@ -1,5 +1,12 @@ use crate::structs::PersonMentionView; -use diesel::{pg::Pg, result::Error, ExpressionMethods, NullableExpressionMethods, QueryDsl}; +use diesel::{ + dsl::exists, + pg::Pg, + result::Error, + ExpressionMethods, + NullableExpressionMethods, + QueryDsl, +}; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ aliases::{self, creator_community_actions}, @@ -36,16 +43,23 @@ fn queries<'a>() -> Queries< impl ReadFn<'a, PersonMentionView, (PersonMentionId, Option)>, impl ListFn<'a, PersonMentionView, PersonMentionQuery>, > { + let creator_is_admin = exists( + local_user::table.filter( + comment::creator_id + .eq(local_user::person_id) + .and(local_user::admin.eq(true)), + ), + ); + let all_joins = move |query: person_mention::BoxedQuery<'a, Pg>, my_person_id: Option| { query - .inner_join( - comment::table - .inner_join(person::table.left_join(local_user::table)) - .inner_join(post::table.inner_join(community::table)) - .inner_join(comment_aggregates::table), - ) + .inner_join(comment::table) + .inner_join(person::table.on(comment::creator_id.eq(person::id))) + .inner_join(post::table.on(comment::post_id.eq(post::id))) + .inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(aliases::person1) + .inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id))) .left_join(actions( community_actions::table, my_person_id, @@ -79,7 +93,7 @@ fn queries<'a>() -> Queries< .field(community_actions::became_moderator) .nullable() .is_not_null(), - coalesce(local_user::admin.nullable(), false), + creator_is_admin, CommunityFollower::select_subscribed_type(), comment_actions::saved.nullable().is_not_null(), person_actions::blocked.nullable().is_not_null(), From 602db61ec7df1efd33b401eb82451ab4d794a5d0 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 11:20:59 -0700 Subject: [PATCH 165/232] Update post_view.rs --- crates/db_views/src/post_view.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index aa901db8d..ec3bfd01c 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -60,7 +60,7 @@ fn queries<'a>() -> Queries< impl ListFn<'a, PostView, (PostQuery<'a>, &'a Site)>, > { let creator_is_admin = exists( - local_user::table.filter( + post::table.filter( comment::creator_id .eq(local_user::person_id) .and(local_user::admin.eq(true)), From 56ba24be14132c5c659e136c90f8383d33a08d22 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 11:29:54 -0700 Subject: [PATCH 166/232] Update comment.rs --- crates/db_schema/src/source/comment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/source/comment.rs b/crates/db_schema/src/source/comment.rs index 883719ba2..44759fbff 100644 --- a/crates/db_schema/src/source/comment.rs +++ b/crates/db_schema/src/source/comment.rs @@ -5,7 +5,7 @@ use crate::newtypes::{CommentId, DbUrl, LanguageId, PersonId, PostId}; use crate::schema::{comment, comment_actions}; use chrono::{DateTime, Utc}; #[cfg(feature = "full")] -use diesel::{dsl, expression_methods::NullableExpressionMethods} +use diesel::{dsl, expression_methods::NullableExpressionMethods}; #[cfg(feature = "full")] use diesel_ltree::Ltree; use serde::{Deserialize, Serialize}; From 1c1249ab9eca98ca925e3e82681bc1795044093a Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 12:39:22 -0700 Subject: [PATCH 167/232] Update post.rs --- crates/db_schema/src/source/post.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/db_schema/src/source/post.rs b/crates/db_schema/src/source/post.rs index 1dd61bae5..da253253d 100644 --- a/crates/db_schema/src/source/post.rs +++ b/crates/db_schema/src/source/post.rs @@ -132,11 +132,11 @@ pub struct PostUpdateForm { pub struct PostLike { pub post_id: PostId, pub person_id: PersonId, - #[diesel(select_expression = post_actions::like_score.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = post_actions::like_score.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub score: i16, - #[diesel(select_expression = post_actions::liked.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = post_actions::liked.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub published: DateTime, } @@ -162,8 +162,8 @@ pub struct PostLikeForm { pub struct PostSaved { pub post_id: PostId, pub person_id: PersonId, - #[diesel(select_expression = post_actions::saved.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = post_actions::saved.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub published: DateTime, } @@ -186,8 +186,8 @@ pub struct PostSavedForm { pub struct PostRead { pub post_id: PostId, pub person_id: PersonId, - #[diesel(select_expression = post_actions::read.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = post_actions::read.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub published: DateTime, } @@ -210,8 +210,8 @@ pub(crate) struct PostReadForm { pub struct PostHide { pub post_id: PostId, pub person_id: PersonId, - #[diesel(select_expression = post_actions::hidden.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = post_actions::hidden.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub published: DateTime, } From 89a7f6a02871b7c73a287039ac12dc6a7f8166f4 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 12:57:22 -0700 Subject: [PATCH 168/232] fix missing cfg_attr --- crates/db_schema/src/aggregates/structs.rs | 8 ++++---- crates/db_schema/src/source/comment.rs | 12 +++++------ crates/db_schema/src/source/community.rs | 20 +++++++++---------- .../db_schema/src/source/community_block.rs | 4 ++-- crates/db_schema/src/source/instance_block.rs | 4 ++-- crates/db_schema/src/source/person.rs | 8 ++++---- crates/db_schema/src/source/person_block.rs | 4 ++-- 7 files changed, 30 insertions(+), 30 deletions(-) diff --git a/crates/db_schema/src/aggregates/structs.rs b/crates/db_schema/src/aggregates/structs.rs index dcd927868..c2e54ae5c 100644 --- a/crates/db_schema/src/aggregates/structs.rs +++ b/crates/db_schema/src/aggregates/structs.rs @@ -164,11 +164,11 @@ pub struct PersonPostAggregates { /// The number of comments they've read on that post. /// /// This is updated to the current post comment count every time they view a post. - #[diesel(select_expression = post_actions::read_comments_amount.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = post_actions::read_comments_amount.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub read_comments: i64, - #[diesel(select_expression = post_actions::read_comments.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = post_actions::read_comments.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub published: DateTime, } diff --git a/crates/db_schema/src/source/comment.rs b/crates/db_schema/src/source/comment.rs index 44759fbff..14b2bd20b 100644 --- a/crates/db_schema/src/source/comment.rs +++ b/crates/db_schema/src/source/comment.rs @@ -101,11 +101,11 @@ pub struct CommentUpdateForm { pub struct CommentLike { pub person_id: PersonId, pub comment_id: CommentId, - #[diesel(select_expression = comment_actions::like_score.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = comment_actions::like_score.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub score: i16, - #[diesel(select_expression = comment_actions::liked.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = comment_actions::liked.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub published: DateTime, } @@ -131,8 +131,8 @@ pub struct CommentLikeForm { pub struct CommentSaved { pub comment_id: CommentId, pub person_id: PersonId, - #[diesel(select_expression = comment_actions::saved.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = comment_actions::saved.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub published: DateTime, } diff --git a/crates/db_schema/src/source/community.rs b/crates/db_schema/src/source/community.rs index 0b5ce60da..0f0d078f0 100644 --- a/crates/db_schema/src/source/community.rs +++ b/crates/db_schema/src/source/community.rs @@ -150,8 +150,8 @@ pub struct CommunityUpdateForm { pub struct CommunityModerator { pub community_id: CommunityId, pub person_id: PersonId, - #[diesel(select_expression = community_actions::became_moderator.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = community_actions::became_moderator.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub published: DateTime, } @@ -178,11 +178,11 @@ pub struct CommunityModeratorForm { pub struct CommunityPersonBan { pub community_id: CommunityId, pub person_id: PersonId, - #[diesel(select_expression = community_actions::received_ban.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = community_actions::received_ban.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub published: DateTime, - #[diesel(select_expression = community_actions::ban_expires.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = community_actions::ban_expires.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub expires: Option>, } @@ -211,11 +211,11 @@ pub struct CommunityPersonBanForm { pub struct CommunityFollower { pub community_id: CommunityId, pub person_id: PersonId, - #[diesel(select_expression = community_actions::followed.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = community_actions::followed.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub published: DateTime, - #[diesel(select_expression = community_actions::follow_pending.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = community_actions::follow_pending.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub pending: bool, } diff --git a/crates/db_schema/src/source/community_block.rs b/crates/db_schema/src/source/community_block.rs index 845238c7e..a7c23419c 100644 --- a/crates/db_schema/src/source/community_block.rs +++ b/crates/db_schema/src/source/community_block.rs @@ -21,8 +21,8 @@ use serde::{Deserialize, Serialize}; pub struct CommunityBlock { pub person_id: PersonId, pub community_id: CommunityId, - #[diesel(select_expression = community_actions::blocked.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = community_actions::blocked.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub published: DateTime, } diff --git a/crates/db_schema/src/source/instance_block.rs b/crates/db_schema/src/source/instance_block.rs index 530a9dd8d..e1963c894 100644 --- a/crates/db_schema/src/source/instance_block.rs +++ b/crates/db_schema/src/source/instance_block.rs @@ -21,8 +21,8 @@ use serde::{Deserialize, Serialize}; pub struct InstanceBlock { pub person_id: PersonId, pub instance_id: InstanceId, - #[diesel(select_expression = instance_actions::blocked.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = instance_actions::blocked.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub published: DateTime, } diff --git a/crates/db_schema/src/source/person.rs b/crates/db_schema/src/source/person.rs index 5f261f99d..6dd792f1a 100644 --- a/crates/db_schema/src/source/person.rs +++ b/crates/db_schema/src/source/person.rs @@ -127,11 +127,11 @@ pub struct PersonUpdateForm { pub struct PersonFollower { pub person_id: PersonId, pub follower_id: PersonId, - #[diesel(select_expression = person_actions::followed.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = person_actions::followed.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub published: DateTime, - #[diesel(select_expression = person_actions::follow_pending.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = person_actions::follow_pending.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub pending: bool, } diff --git a/crates/db_schema/src/source/person_block.rs b/crates/db_schema/src/source/person_block.rs index 82c82b22f..ec988a60f 100644 --- a/crates/db_schema/src/source/person_block.rs +++ b/crates/db_schema/src/source/person_block.rs @@ -18,8 +18,8 @@ use serde::{Deserialize, Serialize}; pub struct PersonBlock { pub person_id: PersonId, pub target_id: PersonId, - #[diesel(select_expression = person_actions::blocked.assume_not_null())] - #[diesel(select_expression_type = dsl::AssumeNotNull)] + #[cfg_attr(feature = "full", diesel(select_expression = person_actions::blocked.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub published: DateTime, } From aa157d473988a190daa60d9c6a4b1acfa788a2b4 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 14:13:33 -0700 Subject: [PATCH 169/232] rewrite uplete --- crates/db_schema/src/utils/uplete.rs | 198 ++++++++++++++++++--------- 1 file changed, 131 insertions(+), 67 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 685dd8c86..d958eab0f 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -1,115 +1,179 @@ use diesel::{ + associations::HasTable, dsl, expression::{AsExpression, TypedExpressionType}, pg::Pg, - query_builder::{AstPass, Query, QueryFragment, UpdateStatement}, + query_builder::{ + methods::{SelectDsl, FilterDsl}, + AstPass, + AsQuery, + Query, + QueryFragment, + UpdateStatement, + }, result::Error, sql_types, + Column, QueryId, Table, }; +use tuplex::{IntoArray, Len}; -pub trait UpleteTable: Table + Default { - type EmptyRow; +pub type CountSqlType = (sql_types::BigInt, sql_types::BigInt); + +/// Set columns to null and delete the row if all columns not in the primary key are null +pub fn uplete(query: Q) -> UpleteBuilder { + UpleteBuilder { + query, + set_null_columns: Vec::new(), + } } -pub trait OrDelete { - type Output; - - /// Change an update query so rows that equal `UpleteTable::EmptyRow::default()` are deleted - fn or_delete(self) -> Self::Output; +pub struct UpleteBuilder { + query: Q, + set_null_columns: Vec, } -impl OrDelete for UpdateStatement +impl UpleteBuilder { + pub fn set_null + Into>(mut self, column: C) -> Self { + self.set_null_columns.push(column.into()); + self + } +} + +impl AsQuery for UpleteBuilder where - T::SqlType: sql_types::SqlType + TypedExpressionType, - T::EmptyRow: Default + AsExpression>, + Q::Table: Default + Table, + Q::Table::AllColumns: IntoArray, + Q::Query: SelectDsl<(K0, K1)>, + dsl::Select: Clone + FilterDsl + FilterDsl>, { - type Output = SetOrDeleteQuery< - T, - T::PrimaryKey, - T::AllColumns, - Self, - dsl::AsExprOf>, - >; + type Query = UpleteQuery; - fn or_delete(self) -> Self::Output { - SetOrDeleteQuery { - table: T::default(), - primary_key: T::default().primary_key(), - all_columns: T::all_columns(), - update_statement: self, - empty_row: T::EmptyRow::default().as_expression(), + type SqlType = CountSqlType; + + fn as_query(self) -> Self::Query { + let primary_key = Q::Table::default().primary_key(); + let primary_key_type_ids = [primary_key.0.type_id(), primary_key.1.type_id()]; + let other_columns = Q::Table::all_columns().into_array().into_iter().filter(|c: DynColumn| { + primary_key_type_ids + .iter() + .chain(self.set_null_columns.iter().map(|c| c.type_id())) + .all(|other| other != c.type_id()); + }).collect::>(); + let subquery = self.query.select(primary_key.clone()); + UpleteQuery { + // Updated rows and deleted rows must not overlap, so updating all rows and using the returned new rows to determine which ones to delete is not an option. + // + // https://www.postgresql.org/docs/16/queries-with.html#QUERIES-WITH-MODIFYING + // + // "Trying to update the same row twice in a single statement is not supported. Only one of the modifications takes place, but it is not easy (and sometimes not possible) to reliably predict which one. This also applies to deleting a row that was already updated in the same statement: only the update is performed." + update_subquery: Box::new(subquery.clone().filter(not(AllNull(other_columns.clone())))), + delete_subquery: Box::new(subquery.filter(AllNull(other_columns))), + table: Box::new(Q::Table::default()), + primary_key: Box::new(primary_key), + set_null_columns: self.set_null_columns, } } } -#[derive(QueryId)] -pub struct SetOrDeleteQuery { - table: T, - primary_key: PK, - all_columns: C, - update_statement: U, - empty_row: E, +pub struct UpleteQuery { + update_subquery: Box>, + delete_subquery: Box>, + table: Box>, + primary_key: Box>, + set_null_columns: Vec, } -impl Query for SetOrDeleteQuery { - type SqlType = (sql_types::BigInt, sql_types::BigInt); +impl QueryId for UpleteQuery { + type QueryId = (); + + const HAS_STATIC_QUERY_ID: bool = false; } -impl< - T: QueryFragment, - PK: QueryFragment, - C: QueryFragment, - U: QueryFragment, - E: QueryFragment, - > QueryFragment for SetOrDeleteQuery -{ +impl QueryFragment for UpleteQuery { fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> Result<(), Error> { - // `update_result` CTE with new rows (concurrent writers to these rows are blocked until this - // query ends) - out.push_sql("WITH update_result AS ("); - self.update_statement.walk_ast(out.reborrow())?; - out.push_sql(" RETURNING "); - self.all_columns.walk_ast(out.reborrow())?; + assert_ne!(self.set_null_columns.len(), 0, "`set_null` was not called"); - // Beginning of `delete_result` CTE with 1 row per deleted row - out.push_sql("), delete_result AS (DELETE FROM "); + // Which rows to update + out.push_sql("WITH update_keys AS ("); + self.update_subquery.walk_ast(out.reborrow())?; + out.push_sql(" FOR UPDATE)"); + + // Which rows to delete + out.push_sql(", delete_keys AS ("); + self.delete_subquery.walk_ast(out.reborrow())?; + out.push_sql(" FOR UPDATE)"); + + // Update rows + out.push_sql(", update_result AS (UPDATE "); + self.table.walk_ast(out.reborrow())?; + let mut item_prefix = " SET "; + for column in &self.set_null_columns { + out.push_sql(item_prefix); + column.walk_ast(out.reborrow())?; + out.push_sql(" = NULL"); + item_prefix = ","; + } + out.push_sql(" WHERE ("); + self.primary_key.walk_ast(out.reborrow())?; + out.push_sql(") = ANY (SELECT * FROM update_keys) RETURNING 1)"); + + // Delete rows + out.push_sql(", delete_result AS (DELETE FROM "); self.table.walk_ast(out.reborrow())?; out.push_sql(" WHERE ("); self.primary_key.walk_ast(out.reborrow())?; + out.push_sql(") = ANY (SELECT * FROM update_keys) RETURNING 1)"); - // Select from `update_result` with an alias that matches the original table's name - out.push_sql(") = ANY (SELECT "); - self.primary_key.walk_ast(out.reborrow())?; - out.push_sql(" FROM update_result AS "); - self.table.walk_ast(out.reborrow())?; - - // Filter the select statement - out.push_sql(" WHERE ("); - self.all_columns.walk_ast(out.reborrow())?; - out.push_sql(") IS NOT DISTINCT FROM "); - self.empty_row.walk_ast(out.reborrow())?; - - // Select count from each CTE - out.push_sql(") RETURNING 1) SELECT (SELECT count(*) from update_result), (SELECT count(*) FROM delete_result)"); + // Count updated rows and deleted rows (`RETURNING 1` makes this possible) + out.push_sql(" SELECT (SELECT count(*) FROM update_result), (SELECT count(*) FROM delete_result)"); Ok(()) } } +struct AllNull(Vec); + +impl Expression for AllNull { + type SqlType = sql_types::Bool; +} + +impl QueryFragment for AllNull { + fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> Result<(), Error> { + let mut item_prefix = "("; + for column in &self.0 { + out.push_sql(item_prefix); + column.walk_ast(out.reborrow())?; + out.push_sql(" IS NOT NULL"); + item_prefix = " AND "; + } + out.push_sql(")"); + + Ok(()) + } +} + +struct DynColumn(Box>); + +impl> From for DynColumn { + fn from(value: T) -> Self { + DynColumn(Box::new(value)) + } +} + #[derive(Queryable, PartialEq, Eq, Debug)] pub struct UpleteCount { - pub all: i64, + pub updated: i64, pub deleted: i64, } impl UpleteCount { pub fn only_updated(n: i64) -> Self { - UpleteCount { all: n, deleted: 0 } + UpleteCount { updated: n, deleted: 0 } } pub fn only_deleted(n: i64) -> Self { - UpleteCount { all: n, deleted: n } + UpleteCount { updated: 0, deleted: n } } } From 216b6d2c8838e3f0ccafa199127311dd28babe9b Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 14:14:49 -0700 Subject: [PATCH 170/232] Update Cargo.toml --- crates/db_schema/Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/db_schema/Cargo.toml b/crates/db_schema/Cargo.toml index 5adc04dc1..98c035d6e 100644 --- a/crates/db_schema/Cargo.toml +++ b/crates/db_schema/Cargo.toml @@ -39,6 +39,7 @@ full = [ "rustls", "i-love-jesus", "diesel-bind-if-some", + "tuplex", ] [dependencies] @@ -83,6 +84,7 @@ i-love-jesus = { workspace = true, optional = true } anyhow = { workspace = true } diesel-bind-if-some = { workspace = true, optional = true } moka.workspace = true +tuplex = { workspace = true } [dev-dependencies] serial_test = { workspace = true } From db20b69de25cbbb8f294bd0c0aa9e2ccbf82d816 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 14:15:59 -0700 Subject: [PATCH 171/232] Update Cargo.toml --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 83d12d813..e92c6d35a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -168,6 +168,7 @@ i-love-jesus = { version = "0.1.0" } clap = { version = "4.5.4", features = ["derive", "env"] } pretty_assertions = "1.4.0" diesel-bind-if-some = "0.1.0" +tuplex = "0.1.2" [dependencies] lemmy_api = { workspace = true } From 7f8a689e81575a61bffc9a40c387aaeea23a7560 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 14:21:15 -0700 Subject: [PATCH 172/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 41 +++++++++++++++++++--------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index d958eab0f..db9bee21f 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -4,9 +4,9 @@ use diesel::{ expression::{AsExpression, TypedExpressionType}, pg::Pg, query_builder::{ - methods::{SelectDsl, FilterDsl}, - AstPass, + methods::{FilterDsl, SelectDsl}, AsQuery, + AstPass, Query, QueryFragment, UpdateStatement, @@ -55,19 +55,27 @@ where fn as_query(self) -> Self::Query { let primary_key = Q::Table::default().primary_key(); let primary_key_type_ids = [primary_key.0.type_id(), primary_key.1.type_id()]; - let other_columns = Q::Table::all_columns().into_array().into_iter().filter(|c: DynColumn| { - primary_key_type_ids - .iter() - .chain(self.set_null_columns.iter().map(|c| c.type_id())) - .all(|other| other != c.type_id()); - }).collect::>(); + let other_columns = Q::Table::all_columns() + .into_array() + .into_iter() + .filter(|c: DynColumn| { + primary_key_type_ids + .iter() + .chain(self.set_null_columns.iter().map(|c| c.type_id())) + .all(|other| other != c.type_id()) + }) + .collect::>(); let subquery = self.query.select(primary_key.clone()); UpleteQuery { - // Updated rows and deleted rows must not overlap, so updating all rows and using the returned new rows to determine which ones to delete is not an option. + // Updated rows and deleted rows must not overlap, so updating all rows and using the returned + // new rows to determine which ones to delete is not an option. // // https://www.postgresql.org/docs/16/queries-with.html#QUERIES-WITH-MODIFYING // - // "Trying to update the same row twice in a single statement is not supported. Only one of the modifications takes place, but it is not easy (and sometimes not possible) to reliably predict which one. This also applies to deleting a row that was already updated in the same statement: only the update is performed." + // "Trying to update the same row twice in a single statement is not supported. Only one of + // the modifications takes place, but it is not easy (and sometimes not possible) to reliably + // predict which one. This also applies to deleting a row that was already updated in the same + // statement: only the update is performed." update_subquery: Box::new(subquery.clone().filter(not(AllNull(other_columns.clone())))), delete_subquery: Box::new(subquery.filter(AllNull(other_columns))), table: Box::new(Q::Table::default()), @@ -127,7 +135,8 @@ impl QueryFragment for UpleteQuery { out.push_sql(") = ANY (SELECT * FROM update_keys) RETURNING 1)"); // Count updated rows and deleted rows (`RETURNING 1` makes this possible) - out.push_sql(" SELECT (SELECT count(*) FROM update_result), (SELECT count(*) FROM delete_result)"); + out.push_sql(" SELECT (SELECT count(*) FROM update_result)"); + out.push_sql(", (SELECT count(*) FROM delete_result)"); Ok(()) } @@ -170,10 +179,16 @@ pub struct UpleteCount { impl UpleteCount { pub fn only_updated(n: i64) -> Self { - UpleteCount { updated: n, deleted: 0 } + UpleteCount { + updated: n, + deleted: 0, + } } pub fn only_deleted(n: i64) -> Self { - UpleteCount { updated: 0, deleted: n } + UpleteCount { + updated: 0, + deleted: n, + } } } From e6a7a5a0fdd70a7d037b2783c9c111349e59626c Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 14:22:13 -0700 Subject: [PATCH 173/232] add `pub` to structs that appear in trait bounds --- crates/db_schema/src/utils/uplete.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index db9bee21f..9453f6f9f 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -142,7 +142,7 @@ impl QueryFragment for UpleteQuery { } } -struct AllNull(Vec); +pub struct AllNull(Vec); impl Expression for AllNull { type SqlType = sql_types::Bool; @@ -163,7 +163,7 @@ impl QueryFragment for AllNull { } } -struct DynColumn(Box>); +pub struct DynColumn(Box>); impl> From for DynColumn { fn from(value: T) -> Self { From c1435b68426bc82c514f291f4e1fde5238692482 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 14:23:07 -0700 Subject: [PATCH 174/232] optional = true --- crates/db_schema/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/Cargo.toml b/crates/db_schema/Cargo.toml index 98c035d6e..79e15dba3 100644 --- a/crates/db_schema/Cargo.toml +++ b/crates/db_schema/Cargo.toml @@ -84,7 +84,7 @@ i-love-jesus = { workspace = true, optional = true } anyhow = { workspace = true } diesel-bind-if-some = { workspace = true, optional = true } moka.workspace = true -tuplex = { workspace = true } +tuplex = { workspace = true, optional = true } [dev-dependencies] serial_test = { workspace = true } From cd508cc7596dacf22fd4a30e87819572d86e5b4e Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 14:42:14 -0700 Subject: [PATCH 175/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 9453f6f9f..e9d5d4e4e 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -1,26 +1,24 @@ use diesel::{ associations::HasTable, dsl, - expression::{AsExpression, TypedExpressionType}, pg::Pg, query_builder::{ - methods::{FilterDsl, SelectDsl}, AsQuery, AstPass, Query, QueryFragment, - UpdateStatement, + QueryId, }, + query_dsl::methods::{FilterDsl, SelectDsl}, result::Error, sql_types, Column, - QueryId, + Expression, Table, }; +use std::any::Any; use tuplex::{IntoArray, Len}; -pub type CountSqlType = (sql_types::BigInt, sql_types::BigInt); - /// Set columns to null and delete the row if all columns not in the primary key are null pub fn uplete(query: Q) -> UpleteBuilder { UpleteBuilder { @@ -76,7 +74,7 @@ where // the modifications takes place, but it is not easy (and sometimes not possible) to reliably // predict which one. This also applies to deleting a row that was already updated in the same // statement: only the update is performed." - update_subquery: Box::new(subquery.clone().filter(not(AllNull(other_columns.clone())))), + update_subquery: Box::new(subquery.clone().filter(dsl::not(AllNull(other_columns.clone())))), delete_subquery: Box::new(subquery.filter(AllNull(other_columns))), table: Box::new(Q::Table::default()), primary_key: Box::new(primary_key), @@ -99,6 +97,10 @@ impl QueryId for UpleteQuery { const HAS_STATIC_QUERY_ID: bool = false; } +impl Query for UpleteQuery { + type SqlType = (sql_types::BigInt, sql_types::BigInt); +} + impl QueryFragment for UpleteQuery { fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> Result<(), Error> { assert_ne!(self.set_null_columns.len(), 0, "`set_null` was not called"); From 287947ac71827ce816f137c2a2c0db8ef110e722 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 14:43:40 -0700 Subject: [PATCH 176/232] Update community.rs --- crates/db_schema/src/source/community.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/source/community.rs b/crates/db_schema/src/source/community.rs index 0f0d078f0..e79e8c5b1 100644 --- a/crates/db_schema/src/source/community.rs +++ b/crates/db_schema/src/source/community.rs @@ -8,7 +8,7 @@ use crate::{ }; use chrono::{DateTime, Utc}; #[cfg(feature = "full")] -use diesel::{dsl, expression_methods::NullableExplessionMethods}; +use diesel::{dsl, expression_methods::NullableExpressionMethods}; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; #[cfg(feature = "full")] From 4e89913cebed0d9b7400037797820f15fb9bd237 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 14:45:36 -0700 Subject: [PATCH 177/232] Update comment.rs --- crates/db_schema/src/impls/comment.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index 67d9ecedf..9690e6e4b 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -13,7 +13,6 @@ use crate::{ }, traits::{Crud, Likeable, Saveable}, utils::{ - expression::SelectableHelper, functions::coalesce, get_conn, naive_now, @@ -25,7 +24,8 @@ use crate::{ }; use chrono::{DateTime, Utc}; use diesel::{ - dsl::{self, insert_into}, + dsl::insert_into, + expression::SelectableHelper, result::Error, ExpressionMethods, NullableExpressionMethods, From 7ed70806ae287ce4d6eae1283912b6d914ba8c48 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 14:47:56 -0700 Subject: [PATCH 178/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index e9d5d4e4e..a262d5ec8 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -2,13 +2,7 @@ use diesel::{ associations::HasTable, dsl, pg::Pg, - query_builder::{ - AsQuery, - AstPass, - Query, - QueryFragment, - QueryId, - }, + query_builder::{AsQuery, AstPass, Query, QueryFragment, QueryId}, query_dsl::methods::{FilterDsl, SelectDsl}, result::Error, sql_types, @@ -74,7 +68,11 @@ where // the modifications takes place, but it is not easy (and sometimes not possible) to reliably // predict which one. This also applies to deleting a row that was already updated in the same // statement: only the update is performed." - update_subquery: Box::new(subquery.clone().filter(dsl::not(AllNull(other_columns.clone())))), + update_subquery: Box::new( + subquery + .clone() + .filter(dsl::not(AllNull(other_columns.clone()))), + ), delete_subquery: Box::new(subquery.filter(AllNull(other_columns))), table: Box::new(Q::Table::default()), primary_key: Box::new(primary_key), From bc941a2981e992c39bf1c27fc0364a2a40735617 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 15:44:15 -0700 Subject: [PATCH 179/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index a262d5ec8..5db84bc58 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -36,13 +36,14 @@ impl UpleteBuilder { impl AsQuery for UpleteBuilder where Q::Table: Default + Table, - Q::Table::AllColumns: IntoArray, + Q::Table::AllColumns: IntoArray, + : IntoIterator, Q::Query: SelectDsl<(K0, K1)>, dsl::Select: Clone + FilterDsl + FilterDsl>, { type Query = UpleteQuery; - type SqlType = CountSqlType; + type SqlType = (sql_types::BigInt, sql_types::BigInt); fn as_query(self) -> Self::Query { let primary_key = Q::Table::default().primary_key(); @@ -163,9 +164,9 @@ impl QueryFragment for AllNull { } } -pub struct DynColumn(Box>); +pub struct DynColumn(Box + 'static>); -impl> From for DynColumn { +impl + 'static> From for DynColumn { fn from(value: T) -> Self { DynColumn(Box::new(value)) } From 19c4ba165dc3aa9c9342a59dee885b9279744ef1 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 18:40:11 -0700 Subject: [PATCH 180/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 5db84bc58..859f35b91 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -37,7 +37,7 @@ impl AsQuery for UpleteBuilder< where Q::Table: Default + Table, Q::Table::AllColumns: IntoArray, - : IntoIterator, + ::Output IntoIterator, Q::Query: SelectDsl<(K0, K1)>, dsl::Select: Clone + FilterDsl + FilterDsl>, { From 60af6eddc82f6b15574ac5ab7b4f4e0e39ab0bf1 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 18:43:08 -0700 Subject: [PATCH 181/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 859f35b91..e8a021278 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -37,7 +37,7 @@ impl AsQuery for UpleteBuilder< where Q::Table: Default + Table, Q::Table::AllColumns: IntoArray, - ::Output IntoIterator, + ::Output: IntoIterator, Q::Query: SelectDsl<(K0, K1)>, dsl::Select: Clone + FilterDsl + FilterDsl>, { From 0e441c89ab2b51d0279412921f0e878fd14a7d10 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 18:44:50 -0700 Subject: [PATCH 182/232] something is wrong with me --- crates/db_schema/src/utils/uplete.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index e8a021278..38d350273 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -37,7 +37,7 @@ impl AsQuery for UpleteBuilder< where Q::Table: Default + Table, Q::Table::AllColumns: IntoArray, - ::Output: IntoIterator, + >::Output: IntoIterator, Q::Query: SelectDsl<(K0, K1)>, dsl::Select: Clone + FilterDsl + FilterDsl>, { From 4751d28b7b37bbccb9e3fd3e053297104f041c88 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 28 May 2024 19:22:58 -0700 Subject: [PATCH 183/232] use new uplete function everywhere --- .../src/aggregates/person_post_aggregates.rs | 1 - crates/db_schema/src/impls/community.rs | 50 ++++++------------- crates/db_schema/src/impls/community_block.rs | 9 ++-- crates/db_schema/src/impls/instance.rs | 9 ---- crates/db_schema/src/impls/instance_block.rs | 9 ++-- crates/db_schema/src/impls/person.rs | 23 ++------- crates/db_schema/src/impls/person_block.rs | 8 ++- crates/db_schema/src/impls/post.rs | 42 ++++------------ crates/db_schema/src/source/person.rs | 2 + 9 files changed, 43 insertions(+), 110 deletions(-) diff --git a/crates/db_schema/src/aggregates/person_post_aggregates.rs b/crates/db_schema/src/aggregates/person_post_aggregates.rs index 6140a7706..63a50af9c 100644 --- a/crates/db_schema/src/aggregates/person_post_aggregates.rs +++ b/crates/db_schema/src/aggregates/person_post_aggregates.rs @@ -6,7 +6,6 @@ use crate::{ utils::{find_action, get_conn, now, DbPool}, }; use diesel::{ - dsl, expression::SelectableHelper, insert_into, result::Error, diff --git a/crates/db_schema/src/impls/community.rs b/crates/db_schema/src/impls/community.rs index a270f393d..c346df5bb 100644 --- a/crates/db_schema/src/impls/community.rs +++ b/crates/db_schema/src/impls/community.rs @@ -20,12 +20,11 @@ use crate::{ traits::{ApubActor, Bannable, Crud, Followable, Joinable}, utils::{ action_query, - expression::SelectableHelper, find_action, functions::{coalesce, lower}, get_conn, now, - uplete::{OrDelete, UpleteCount, UpleteTable}, + uplete::{uplete, UpleteCount}, DbPool, }, SubscribedType, @@ -35,6 +34,7 @@ use diesel::{ deserialize, dsl, dsl::{exists, insert_into}, + expression::SelectableHelper, pg::Pg, result::Error, select, @@ -48,19 +48,6 @@ use diesel::{ }; use diesel_async::RunQueryDsl; -impl UpleteTable for community_actions::table { - type EmptyRow = ( - community_actions::community_id, - community_actions::person_id, - Option>, - Option, - Option>, - Option>, - Option>, - Option>, - ); -} - #[async_trait] impl Crud for Community { type InsertForm = CommunityInsertForm; @@ -124,12 +111,11 @@ impl Joinable for CommunityModerator { community_moderator_form: &CommunityModeratorForm, ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::update(community_actions::table.find(( + uplete(community_actions::table.find(( community_moderator_form.person_id, community_moderator_form.community_id, ))) - .set(community_actions::became_moderator.eq(None::>)) - .or_delete() + .set_null(community_actions::became_moderator) .get_result(conn) .await } @@ -231,11 +217,10 @@ impl CommunityModerator { ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::update( + uplete( community_actions::table.filter(community_actions::community_id.eq(for_community_id)), ) - .set(community_actions::became_moderator.eq(None::>)) - .or_delete() + .set_null(community_actions::became_moderator) .get_result(conn) .await } @@ -245,9 +230,8 @@ impl CommunityModerator { for_person_id: PersonId, ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::update(community_actions::table.filter(community_actions::person_id.eq(for_person_id))) - .set(community_actions::became_moderator.eq(None::>)) - .or_delete() + uplete(community_actions::table.filter(community_actions::person_id.eq(for_person_id))) + .set_null(community_actions::became_moderator) .get_result(conn) .await } @@ -295,15 +279,12 @@ impl Bannable for CommunityPersonBan { community_person_ban_form: &CommunityPersonBanForm, ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::update(community_actions::table.find(( + uplete(community_actions::table.find(( community_person_ban_form.person_id, community_person_ban_form.community_id, ))) - .set(( - community_actions::received_ban.eq(None::>), - community_actions::ban_expires.eq(None::>), - )) - .or_delete() + .set_null(community_actions::received_ban) + .set_null(community_actions::ban_expires) .get_result(conn) .await } @@ -393,12 +374,9 @@ impl Followable for CommunityFollower { form: &CommunityFollowerForm, ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::update(community_actions::table.find((form.person_id, form.community_id))) - .set(( - community_actions::followed.eq(None::>), - community_actions::follow_pending.eq(None::), - )) - .or_delete() + uplete(community_actions::table.find((form.person_id, form.community_id))) + .set_null(community_actions::followed) + .set_null(community_actions::follow_pending) .get_result(conn) .await } diff --git a/crates/db_schema/src/impls/community_block.rs b/crates/db_schema/src/impls/community_block.rs index 72eacb85d..5e9382644 100644 --- a/crates/db_schema/src/impls/community_block.rs +++ b/crates/db_schema/src/impls/community_block.rs @@ -7,13 +7,13 @@ use crate::{ find_action, get_conn, now, - uplete::{OrDelete, UpleteCount}, + uplete::{uplete, UpleteCount}, DbPool, }, }; use chrono::{DateTime, Utc}; use diesel::{ - dsl::{self, exists, insert_into}, + dsl::{exists, insert_into}, expression::SelectableHelper, result::Error, select, @@ -65,12 +65,11 @@ impl Blockable for CommunityBlock { community_block_form: &Self::Form, ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::update(community_actions::table.find(( + uplete(community_actions::table.find(( community_block_form.person_id, community_block_form.community_id, ))) - .set(community_actions::blocked.eq(None::>)) - .or_delete() + .set_null(community_actions::blocked) .get_result(conn) .await } diff --git a/crates/db_schema/src/impls/instance.rs b/crates/db_schema/src/impls/instance.rs index 5b21a5515..1a8e829e2 100644 --- a/crates/db_schema/src/impls/instance.rs +++ b/crates/db_schema/src/impls/instance.rs @@ -19,7 +19,6 @@ use crate::{ get_conn, naive_now, now, - uplete::UpleteTable, DbPool, }, }; @@ -35,14 +34,6 @@ use diesel::{ }; use diesel_async::RunQueryDsl; -impl UpleteTable for instance_actions::table { - type EmptyRow = ( - instance_actions::person_id, - instance_actions::instance_id, - Option>, - ); -} - impl Instance { /// Attempt to read Instance column for the given domain. If it doesn't exist, insert a new one. /// There is no need for update as the domain of an existing instance cant change. diff --git a/crates/db_schema/src/impls/instance_block.rs b/crates/db_schema/src/impls/instance_block.rs index f82452f1f..54e938f57 100644 --- a/crates/db_schema/src/impls/instance_block.rs +++ b/crates/db_schema/src/impls/instance_block.rs @@ -7,13 +7,13 @@ use crate::{ find_action, get_conn, now, - uplete::{OrDelete, UpleteCount}, + uplete::{uplete, UpleteCount}, DbPool, }, }; use chrono::{DateTime, Utc}; use diesel::{ - dsl::{self, exists, insert_into}, + dsl::{exists, insert_into}, expression::SelectableHelper, result::Error, select, @@ -62,12 +62,11 @@ impl Blockable for InstanceBlock { instance_block_form: &Self::Form, ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::update(instance_actions::table.find(( + uplete(instance_actions::table.find(( instance_block_form.person_id, instance_block_form.instance_id, ))) - .set(instance_actions::blocked.eq(None::>)) - .or_delete() + .set_null(instance_actions::blocked) .get_result(conn) .await } diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs index 1c7dbc7e5..4b4212d91 100644 --- a/crates/db_schema/src/impls/person.rs +++ b/crates/db_schema/src/impls/person.rs @@ -16,13 +16,13 @@ use crate::{ get_conn, naive_now, now, - uplete::{OrDelete, UpleteCount, UpleteTable}, + uplete::{uplete, UpleteCount}, DbPool, }, }; use chrono::{DateTime, Utc}; use diesel::{ - dsl::{self, insert_into}, + dsl::insert_into, expression::SelectableHelper, result::Error, CombineDsl, @@ -33,16 +33,6 @@ use diesel::{ }; use diesel_async::RunQueryDsl; -impl UpleteTable for person_actions::table { - type EmptyRow = ( - person_actions::target_id, - person_actions::person_id, - Option>, - Option, - Option>, - ); -} - #[async_trait] impl Crud for Person { type InsertForm = PersonInsertForm; @@ -224,12 +214,9 @@ impl Followable for PersonFollower { form: &PersonFollowerForm, ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::update(person_actions::table.find((form.follower_id, form.person_id))) - .set(( - person_actions::followed.eq(None::>), - person_actions::follow_pending.eq(None::), - )) - .or_delete() + uplete(person_actions::table.find((form.follower_id, form.person_id))) + .set_null(person_actions::followed) + .set_null(person_actions::follow_pending) .get_result(conn) .await } diff --git a/crates/db_schema/src/impls/person_block.rs b/crates/db_schema/src/impls/person_block.rs index b1c17cfbc..7a2b5a845 100644 --- a/crates/db_schema/src/impls/person_block.rs +++ b/crates/db_schema/src/impls/person_block.rs @@ -7,13 +7,12 @@ use crate::{ find_action, get_conn, now, - uplete::{OrDelete, UpleteCount}, + uplete::{uplete, UpleteCount}, DbPool, }, }; use chrono::{DateTime, Utc}; use diesel::{ - dsl, dsl::{exists, insert_into}, expression::SelectableHelper, result::Error, @@ -66,11 +65,10 @@ impl Blockable for PersonBlock { person_block_form: &Self::Form, ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::update( + uplete( person_actions::table.find((person_block_form.person_id, person_block_form.target_id)), ) - .set(person_actions::blocked.eq(None::>)) - .or_delete() + .set_null(person_actions::blocked) .get_result(conn) .await } diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index 06a979f83..20a46b9f4 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -21,7 +21,7 @@ use crate::{ get_conn, naive_now, now, - uplete::{OrDelete, UpleteCount, UpleteTable}, + uplete::{uplete, UpleteCount}, DbPool, DELETED_REPLACEMENT_TEXT, FETCH_LIMIT_MAX, @@ -32,7 +32,7 @@ use crate::{ use ::url::Url; use chrono::{DateTime, Utc}; use diesel::{ - dsl::{self, insert_into}, + dsl::insert_into, expression::SelectableHelper, result::Error, DecoratableTarget, @@ -44,20 +44,6 @@ use diesel::{ use diesel_async::RunQueryDsl; use std::collections::HashSet; -impl UpleteTable for post_actions::table { - type EmptyRow = ( - post_actions::post_id, - post_actions::person_id, - Option>, - Option>, - Option, - Option>, - Option>, - Option, - Option>, - ); -} - #[async_trait] impl Crud for Post { type InsertForm = PostInsertForm; @@ -284,12 +270,9 @@ impl Likeable for PostLike { post_id: PostId, ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::update(post_actions::table.find((person_id, post_id))) - .set(( - post_actions::like_score.eq(None::), - post_actions::liked.eq(None::>), - )) - .or_delete() + uplete(post_actions::table.find((person_id, post_id))) + .set_null(post_actions::like_score) + .set_null(post_actions::liked) .get_result(conn) .await } @@ -315,9 +298,8 @@ impl Saveable for PostSaved { post_saved_form: &PostSavedForm, ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::update(post_actions::table.find((post_saved_form.person_id, post_saved_form.post_id))) - .set(post_actions::saved.eq(None::>)) - .or_delete() + uplete(post_actions::table.find((post_saved_form.person_id, post_saved_form.post_id))) + .set_null(post_actions::saved) .get_result(conn) .await } @@ -356,13 +338,12 @@ impl PostRead { ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::update( + uplete( post_actions::table .filter(post_actions::post_id.eq_any(post_id_)) .filter(post_actions::person_id.eq(person_id_)), ) - .set(post_actions::read.eq(None::>)) - .or_delete() + .set_null(post_actions::read) .get_result(conn) .await } @@ -401,13 +382,12 @@ impl PostHide { ) -> Result { let conn = &mut get_conn(pool).await?; - diesel::update( + uplete( post_actions::table .filter(post_actions::post_id.eq_any(post_id_)) .filter(post_actions::person_id.eq(person_id_)), ) - .set(post_actions::hidden.eq(None::>)) - .or_delete() + .set_null(post_actions::hidden) .get_result(conn) .await } diff --git a/crates/db_schema/src/source/person.rs b/crates/db_schema/src/source/person.rs index 6dd792f1a..2c7008b05 100644 --- a/crates/db_schema/src/source/person.rs +++ b/crates/db_schema/src/source/person.rs @@ -125,7 +125,9 @@ pub struct PersonUpdateForm { #[cfg_attr(feature = "full", diesel(primary_key(follower_id, person_id)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] pub struct PersonFollower { + #[cfg_attr(feature = "full", diesel(column_name = target_id))] pub person_id: PersonId, + #[cfg_attr(feature = "full", diesel(column_name = person_id))] pub follower_id: PersonId, #[cfg_attr(feature = "full", diesel(select_expression = person_actions::followed.assume_not_null()))] #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] From 591895ee384d0046127c02bea6552adbd203debf Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 09:41:46 -0700 Subject: [PATCH 184/232] fmt --- crates/db_schema/src/impls/community.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/db_schema/src/impls/community.rs b/crates/db_schema/src/impls/community.rs index c346df5bb..1832e817c 100644 --- a/crates/db_schema/src/impls/community.rs +++ b/crates/db_schema/src/impls/community.rs @@ -217,12 +217,10 @@ impl CommunityModerator { ) -> Result { let conn = &mut get_conn(pool).await?; - uplete( - community_actions::table.filter(community_actions::community_id.eq(for_community_id)), - ) - .set_null(community_actions::became_moderator) - .get_result(conn) - .await + uplete(community_actions::table.filter(community_actions::community_id.eq(for_community_id))) + .set_null(community_actions::became_moderator) + .get_result(conn) + .await } pub async fn leave_all_communities( From eb720a9d88f78888c557af79a32b9ba6bfbd5b5e Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 09:43:41 -0700 Subject: [PATCH 185/232] fmt --- crates/db_schema/src/impls/person_block.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/db_schema/src/impls/person_block.rs b/crates/db_schema/src/impls/person_block.rs index 7a2b5a845..944b83977 100644 --- a/crates/db_schema/src/impls/person_block.rs +++ b/crates/db_schema/src/impls/person_block.rs @@ -65,11 +65,9 @@ impl Blockable for PersonBlock { person_block_form: &Self::Form, ) -> Result { let conn = &mut get_conn(pool).await?; - uplete( - person_actions::table.find((person_block_form.person_id, person_block_form.target_id)), - ) - .set_null(person_actions::blocked) - .get_result(conn) - .await + uplete(person_actions::table.find((person_block_form.person_id, person_block_form.target_id))) + .set_null(person_actions::blocked) + .get_result(conn) + .await } } From 6ce8f67ebffdbfade592572a1b760e4eacec1272 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 11:10:40 -0700 Subject: [PATCH 186/232] Keep post_id when comment_actions::liked is not null --- crates/api/src/comment/like.rs | 1 + crates/api_crud/src/comment/create.rs | 1 + .../src/activities/create_or_update/comment.rs | 1 + crates/apub/src/activities/voting/mod.rs | 1 + .../src/aggregates/comment_aggregates.rs | 2 ++ .../src/aggregates/person_aggregates.rs | 2 ++ crates/db_schema/src/impls/comment.rs | 6 ++++++ crates/db_schema/src/source/comment.rs | 4 ++++ crates/db_views/src/comment_view.rs | 2 ++ crates/db_views/src/vote_view.rs | 6 ++++-- .../down.sql | 18 ++---------------- .../up.sql | 6 ++++-- 12 files changed, 30 insertions(+), 20 deletions(-) diff --git a/crates/api/src/comment/like.rs b/crates/api/src/comment/like.rs index aa76b91e6..d0aa4a6c2 100644 --- a/crates/api/src/comment/like.rs +++ b/crates/api/src/comment/like.rs @@ -59,6 +59,7 @@ pub async fn like_comment( let like_form = CommentLikeForm { comment_id: data.comment_id, + post_id: orig_comment.post.id, person_id: local_user_view.person.id, score: data.score, }; diff --git a/crates/api_crud/src/comment/create.rs b/crates/api_crud/src/comment/create.rs index 48d3787c7..2efd46964 100644 --- a/crates/api_crud/src/comment/create.rs +++ b/crates/api_crud/src/comment/create.rs @@ -160,6 +160,7 @@ pub async fn create_comment( // You like your own comment by default let like_form = CommentLikeForm { comment_id: inserted_comment.id, + post_id: post.id, person_id: local_user_view.person.id, score: 1, }; diff --git a/crates/apub/src/activities/create_or_update/comment.rs b/crates/apub/src/activities/create_or_update/comment.rs index e068b5621..2406d2eb3 100644 --- a/crates/apub/src/activities/create_or_update/comment.rs +++ b/crates/apub/src/activities/create_or_update/comment.rs @@ -160,6 +160,7 @@ impl ActivityHandler for CreateOrUpdateNote { // author likes their own comment by default let like_form = CommentLikeForm { comment_id: comment.id, + post_id: comment.post_id, person_id: comment.creator_id, score: 1, }; diff --git a/crates/apub/src/activities/voting/mod.rs b/crates/apub/src/activities/voting/mod.rs index 7c39b2246..3e59cb7d0 100644 --- a/crates/apub/src/activities/voting/mod.rs +++ b/crates/apub/src/activities/voting/mod.rs @@ -62,6 +62,7 @@ async fn vote_comment( let comment_id = comment.id; let like_form = CommentLikeForm { comment_id, + post_id: comment.post_id, person_id: actor.id, score: vote_type.into(), }; diff --git a/crates/db_schema/src/aggregates/comment_aggregates.rs b/crates/db_schema/src/aggregates/comment_aggregates.rs index 1baa48881..915d17b1d 100644 --- a/crates/db_schema/src/aggregates/comment_aggregates.rs +++ b/crates/db_schema/src/aggregates/comment_aggregates.rs @@ -118,6 +118,7 @@ mod tests { let comment_like = CommentLikeForm { comment_id: inserted_comment.id, + post_id: inserted_post.id, person_id: inserted_person.id, score: 1, }; @@ -136,6 +137,7 @@ mod tests { // Add a post dislike from the other person let comment_dislike = CommentLikeForm { comment_id: inserted_comment.id, + post_id: inserted_post.id, person_id: another_inserted_person.id, score: -1, }; diff --git a/crates/db_schema/src/aggregates/person_aggregates.rs b/crates/db_schema/src/aggregates/person_aggregates.rs index 8315b5afc..e96795e8c 100644 --- a/crates/db_schema/src/aggregates/person_aggregates.rs +++ b/crates/db_schema/src/aggregates/person_aggregates.rs @@ -100,6 +100,7 @@ mod tests { let mut comment_like = CommentLikeForm { comment_id: inserted_comment.id, + post_id: inserted_post.id, person_id: inserted_person.id, score: 1, }; @@ -119,6 +120,7 @@ mod tests { let child_comment_like = CommentLikeForm { comment_id: inserted_child_comment.id, + post_id: inserted_post.id, person_id: another_inserted_person.id, score: 1, }; diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index 9690e6e4b..ce24662f8 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -178,6 +178,9 @@ impl Likeable for CommentLike { uplete(comment_actions::table.find((person_id, comment_id))) .set_null(comment_actions::like_score) .set_null(comment_actions::liked) + // Deleting empty `comment_actions` rows would not work without setting `post_id` to + // null, because it's not part of the primary key + .set_null(comment_actions::post_id) .get_result(conn) .await } @@ -320,6 +323,7 @@ mod tests { // Comment Like let comment_like_form = CommentLikeForm { comment_id: inserted_comment.id, + post_id: inserted_post.id, person_id: inserted_person.id, score: 1, }; @@ -328,6 +332,7 @@ mod tests { let expected_comment_like = CommentLike { comment_id: inserted_comment.id, + post_id: inserted_post.id, person_id: inserted_person.id, published: inserted_comment_like.published, score: 1, @@ -343,6 +348,7 @@ mod tests { let expected_comment_saved = CommentSaved { comment_id: inserted_comment.id, + post_id: inserted_post.id, person_id: inserted_person.id, published: inserted_comment_saved.published, }; diff --git a/crates/db_schema/src/source/comment.rs b/crates/db_schema/src/source/comment.rs index 14b2bd20b..57155f83e 100644 --- a/crates/db_schema/src/source/comment.rs +++ b/crates/db_schema/src/source/comment.rs @@ -101,6 +101,9 @@ pub struct CommentUpdateForm { pub struct CommentLike { pub person_id: PersonId, pub comment_id: CommentId, + #[cfg_attr(feature = "full", diesel(select_expression = comment_actions::post_id.assume_not_null()))] + #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] + pub post_id: PostId, // TODO this is redundant #[cfg_attr(feature = "full", diesel(select_expression = comment_actions::like_score.assume_not_null()))] #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub score: i16, @@ -115,6 +118,7 @@ pub struct CommentLike { pub struct CommentLikeForm { pub person_id: PersonId, pub comment_id: CommentId, + pub post_id: PostId, // TODO this is redundant #[cfg_attr(feature = "full", diesel(column_name = like_score))] pub score: i16, } diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs index 6ea2374bf..c2b171778 100644 --- a/crates/db_views/src/comment_view.rs +++ b/crates/db_views/src/comment_view.rs @@ -533,6 +533,7 @@ mod tests { let comment_like_form = CommentLikeForm { comment_id: inserted_comment_0.id, + post_id: inserted_post.id, person_id: inserted_timmy_person.id, score: 1, }; @@ -632,6 +633,7 @@ mod tests { // Like a new comment let comment_like_form = CommentLikeForm { comment_id: data.inserted_comment_1.id, + post_id: data.inserted_post.id, person_id: data.timmy_local_user_view.person.id, score: 1, }; diff --git a/crates/db_views/src/vote_view.rs b/crates/db_views/src/vote_view.rs index 647f152a4..6cb4c8c87 100644 --- a/crates/db_views/src/vote_view.rs +++ b/crates/db_views/src/vote_view.rs @@ -4,7 +4,7 @@ use diesel_async::RunQueryDsl; use lemmy_db_schema::{ aliases::creator_community_actions, newtypes::{CommentId, PostId}, - schema::{comment, comment_actions, community_actions, person, post, post_actions}, + schema::{comment_actions, community_actions, person, post, post_actions}, utils::{action_query, actions_alias, get_conn, limit_and_offset, DbPool}, }; @@ -53,7 +53,7 @@ impl VoteView { action_query(comment_actions::like_score) .inner_join(person::table) - .inner_join(comment::table.inner_join(post::table)) + .inner_join(post::table) .left_join(actions_alias( creator_community_actions, comment_actions::person_id, @@ -184,6 +184,7 @@ mod tests { // Timothy votes down his own comment let timmy_comment_vote_form = CommentLikeForm { comment_id: inserted_comment.id, + post_id: inserted_post.id, person_id: inserted_timmy.id, score: -1, }; @@ -194,6 +195,7 @@ mod tests { // Sara upvotes timmy's comment let sara_comment_vote_form = CommentLikeForm { comment_id: inserted_comment.id, + post_id: inserted_post.id, person_id: inserted_sara.id, score: 1, }; diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/down.sql b/migrations/2024-03-17-134311_smoosh-tables-together/down.sql index 68b9d9070..4a1d4d9e4 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/down.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/down.sql @@ -35,22 +35,8 @@ ALTER TABLE comment_like ALTER COLUMN published SET NOT NULL, ALTER COLUMN published SET DEFAULT now(), ALTER COLUMN score SET NOT NULL, - DROP COLUMN saved, - ADD COLUMN post_id int REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE; - -UPDATE - comment_like -SET - post_id = ( - SELECT - post_id - FROM - comment - WHERE - comment.id = comment_like.comment_id); - -ALTER TABLE comment_like - ALTER COLUMN post_id SET NOT NULL; + ALTER COLUMN post_id SET NOT NULL, + DROP COLUMN saved; -- Create community_follower from community_actions CREATE TABLE community_block ( diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql index 90111b9c1..829d86470 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql @@ -11,12 +11,14 @@ ALTER TABLE comment_actions RENAME COLUMN published TO liked; ALTER TABLE comment_actions RENAME COLUMN score TO like_score; ALTER TABLE comment_actions - DROP COLUMN post_id, + ALTER COLUMN post_id DROP NOT NULL, ALTER COLUMN liked DROP NOT NULL, ALTER COLUMN liked DROP DEFAULT, ALTER COLUMN like_score DROP NOT NULL, ADD COLUMN saved timestamptz, - ADD CONSTRAINT comment_actions_check_liked CHECK ((liked IS NULL) = (like_score IS NULL)); + -- `post_id` was only in the `comment_liked` table, and removing it entirely or making it not null + -- for the `saved` action would make this PR too complicated + ADD CONSTRAINT comment_actions_check_liked CHECK ((liked IS NULL) = (like_score IS NULL) = (post_id IS NULL)); WITH old_comment_saved AS ( DELETE FROM comment_saved From 3c56d1b038c9bc421fd84fba743e51630260e186 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 11:28:33 -0700 Subject: [PATCH 187/232] Update up.sql --- migrations/2024-03-17-134311_smoosh-tables-together/up.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql index 829d86470..eede02f62 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql @@ -18,7 +18,7 @@ ALTER TABLE comment_actions ADD COLUMN saved timestamptz, -- `post_id` was only in the `comment_liked` table, and removing it entirely or making it not null -- for the `saved` action would make this PR too complicated - ADD CONSTRAINT comment_actions_check_liked CHECK ((liked IS NULL) = (like_score IS NULL) = (post_id IS NULL)); + ADD CONSTRAINT comment_actions_check_liked CHECK ((liked IS NULL) = ALL (ARRAY[like_score IS NULL, post_id IS NULL]); WITH old_comment_saved AS ( DELETE FROM comment_saved From 13a63e6d24bfe5edf3ab50fc8e5b192beeda01fa Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 11:39:30 -0700 Subject: [PATCH 188/232] Update up.sql --- migrations/2024-03-17-134311_smoosh-tables-together/up.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql index eede02f62..a194b3664 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql @@ -18,7 +18,7 @@ ALTER TABLE comment_actions ADD COLUMN saved timestamptz, -- `post_id` was only in the `comment_liked` table, and removing it entirely or making it not null -- for the `saved` action would make this PR too complicated - ADD CONSTRAINT comment_actions_check_liked CHECK ((liked IS NULL) = ALL (ARRAY[like_score IS NULL, post_id IS NULL]); + ADD CONSTRAINT comment_actions_check_liked CHECK ((liked IS NULL) = ALL (ARRAY[like_score IS NULL, post_id IS NULL])); WITH old_comment_saved AS ( DELETE FROM comment_saved From d2f8710c7b558f144dc434d5c774fdd91200e6dd Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 12:04:28 -0700 Subject: [PATCH 189/232] clean up up.sql --- .../up.sql | 336 ++++++++---------- 1 file changed, 147 insertions(+), 189 deletions(-) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql index a194b3664..daeabaa28 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql @@ -1,15 +1,36 @@ --- For each new actions table: --- * Transform the table previously used for the most common action type into the new actions table, --- which should only change the table's metadata instead of rewriting the rows --- * Add actions from other old tables to the new table --- --- Create comment_actions from comment_like +-- For each new actions table, transform the table previously used for the most common action type +-- into the new actions table, which should only change the table's metadata instead of rewriting the +-- rows ALTER TABLE comment_like RENAME TO comment_actions; +ALTER TABLE community_follower RENAME TO community_actions; + +ALTER TABLE instance_block RENAME TO instance_actions; + +ALTER TABLE person_follower RENAME TO person_actions; + +ALTER TABLE post_read RENAME TO post_actions; + ALTER TABLE comment_actions RENAME COLUMN published TO liked; ALTER TABLE comment_actions RENAME COLUMN score TO like_score; +ALTER TABLE community_actions RENAME COLUMN published TO followed; + +ALTER TABLE community_actions RENAME COLUMN pending TO follow_pending; + +ALTER TABLE instance_actions RENAME COLUMN published TO blocked; + +ALTER TABLE person_actions RENAME COLUMN person_id TO target_id; + +ALTER TABLE person_actions RENAME COLUMN follower_id TO person_id; + +ALTER TABLE person_actions RENAME COLUMN published TO followed; + +ALTER TABLE person_actions RENAME COLUMN pending TO follow_pending; + +ALTER TABLE post_actions RENAME COLUMN published TO read; + ALTER TABLE comment_actions ALTER COLUMN post_id DROP NOT NULL, ALTER COLUMN liked DROP NOT NULL, @@ -20,29 +41,6 @@ ALTER TABLE comment_actions -- for the `saved` action would make this PR too complicated ADD CONSTRAINT comment_actions_check_liked CHECK ((liked IS NULL) = ALL (ARRAY[like_score IS NULL, post_id IS NULL])); -WITH old_comment_saved AS ( - DELETE FROM comment_saved -RETURNING - *) - INSERT INTO comment_actions (person_id, comment_id, saved) - SELECT - person_id, - comment_id, - published - FROM - old_comment_saved - ON CONFLICT (person_id, - comment_id) - DO UPDATE SET - saved = excluded.saved; - --- Create community_actions from community_follower -ALTER TABLE community_follower RENAME TO community_actions; - -ALTER TABLE community_actions RENAME COLUMN published TO followed; - -ALTER TABLE community_actions RENAME pending TO follow_pending; - ALTER TABLE community_actions ALTER COLUMN followed DROP NOT NULL, ALTER COLUMN followed DROP DEFAULT, @@ -57,82 +55,10 @@ ALTER TABLE community_actions ADD CONSTRAINT community_actions_check_followed CHECK ((followed IS NULL) = (follow_pending IS NULL)), ADD CONSTRAINT community_actions_check_received_ban CHECK ((received_ban IS NULL, ban_expires IS NULL) != (FALSE, TRUE)); -WITH old_community_block AS ( - DELETE FROM community_block -RETURNING - *) - INSERT INTO community_actions (person_id, community_id, blocked) - SELECT - person_id, - community_id, - published - FROM - old_community_block - ON CONFLICT (person_id, - community_id) - DO UPDATE SET - person_id = excluded.person_id, - community_id = excluded.community_id, - blocked = excluded.blocked; - -WITH old_community_moderator AS ( - DELETE FROM community_moderator -RETURNING - *) - INSERT INTO community_actions (person_id, community_id, became_moderator) - SELECT - person_id, - community_id, - published - FROM - old_community_moderator - ON CONFLICT (person_id, - community_id) - DO UPDATE SET - person_id = excluded.person_id, - community_id = excluded.community_id, - became_moderator = excluded.became_moderator; - -WITH old_community_person_ban AS ( - DELETE FROM community_person_ban -RETURNING - *) - INSERT INTO community_actions (person_id, community_id, received_ban, ban_expires) - SELECT - person_id, - community_id, - published, - expires - FROM - old_community_person_ban - ON CONFLICT (person_id, - community_id) - DO UPDATE SET - person_id = excluded.person_id, - community_id = excluded.community_id, - received_ban = excluded.received_ban, - ban_expires = excluded.ban_expires; - --- Create instance_actions from instance_block -ALTER TABLE instance_block RENAME TO instance_actions; - -ALTER TABLE instance_actions RENAME COLUMN published TO blocked; - ALTER TABLE instance_actions ALTER COLUMN blocked DROP NOT NULL, ALTER COLUMN blocked DROP DEFAULT; --- Create person_actions from person_follower -ALTER TABLE person_follower RENAME TO person_actions; - -ALTER TABLE person_actions RENAME COLUMN person_id TO target_id; - -ALTER TABLE person_actions RENAME COLUMN follower_id TO person_id; - -ALTER TABLE person_actions RENAME COLUMN published TO followed; - -ALTER TABLE person_actions RENAME COLUMN pending TO follow_pending; - ALTER TABLE person_actions ALTER COLUMN followed DROP NOT NULL, ALTER COLUMN followed DROP DEFAULT, @@ -140,29 +66,6 @@ ALTER TABLE person_actions ADD COLUMN blocked timestamptz, ADD CONSTRAINT person_actions_check_followed CHECK ((followed IS NULL) = (follow_pending IS NULL)); -WITH old_person_block AS ( - DELETE FROM person_block -RETURNING - *) - INSERT INTO person_actions (person_id, target_id, blocked) - SELECT - person_id, - target_id, - published - FROM - old_person_block - ON CONFLICT (person_id, - target_id) - DO UPDATE SET - person_id = excluded.person_id, - target_id = excluded.target_id, - blocked = excluded.blocked; - --- Create post_actions from post_read -ALTER TABLE post_read RENAME TO post_actions; - -ALTER TABLE post_actions RENAME COLUMN published TO read; - ALTER TABLE post_actions ALTER COLUMN read DROP NOT NULL, ALTER COLUMN read DROP DEFAULT, @@ -175,73 +78,128 @@ ALTER TABLE post_actions ADD CONSTRAINT post_actions_check_read_comments CHECK ((read_comments IS NULL) = (read_comments_amount IS NULL)), ADD CONSTRAINT post_actions_check_liked CHECK ((liked IS NULL) = (like_score IS NULL)); -WITH old_person_post_aggregates AS ( - DELETE FROM person_post_aggregates -RETURNING - *) - INSERT INTO post_actions (person_id, post_id, read_comments, read_comments_amount) - SELECT - person_id, - post_id, - published, - read_comments - FROM - old_person_post_aggregates - ON CONFLICT (person_id, - post_id) - DO UPDATE SET - read_comments = excluded.read_comments, - read_comments_amount = excluded.read_comments_amount; +-- Add actions from other old tables to the new tables +INSERT INTO comment_actions (person_id, comment_id, saved) +SELECT + person_id, + comment_id, + published +FROM + comment_saved +ON CONFLICT (person_id, + comment_id) + DO UPDATE SET + saved = excluded.saved; -WITH old_post_hide AS ( - DELETE FROM post_hide -RETURNING - *) - INSERT INTO post_actions (person_id, post_id, hidden) - SELECT - person_id, - post_id, - published - FROM - old_post_hide - ON CONFLICT (person_id, - post_id) - DO UPDATE SET - hidden = excluded.hidden; +INSERT INTO community_actions (person_id, community_id, blocked) +SELECT + person_id, + community_id, + published +FROM + community_block +ON CONFLICT (person_id, + community_id) + DO UPDATE SET + person_id = excluded.person_id, + community_id = excluded.community_id, + blocked = excluded.blocked; -WITH old_post_like AS ( - DELETE FROM post_like -RETURNING - *) - INSERT INTO post_actions (person_id, post_id, liked, like_score) - SELECT - person_id, - post_id, - published, - score - FROM - old_post_like - ON CONFLICT (person_id, - post_id) - DO UPDATE SET - liked = excluded.liked, - like_score = excluded.like_score; +INSERT INTO community_actions (person_id, community_id, became_moderator) +SELECT + person_id, + community_id, + published +FROM + community_moderator +ON CONFLICT (person_id, + community_id) + DO UPDATE SET + person_id = excluded.person_id, + community_id = excluded.community_id, + became_moderator = excluded.became_moderator; -WITH old_post_saved AS ( - DELETE FROM post_saved -RETURNING - *) - INSERT INTO post_actions (person_id, post_id, saved) - SELECT - person_id, - post_id, - published - FROM - old_post_saved - ON CONFLICT (person_id, - post_id) - DO UPDATE SET - saved = excluded.saved; +INSERT INTO community_actions (person_id, community_id, received_ban, ban_expires) +SELECT + person_id, + community_id, + published, + expires +FROM + community_person_ban +ON CONFLICT (person_id, + community_id) + DO UPDATE SET + person_id = excluded.person_id, + community_id = excluded.community_id, + received_ban = excluded.received_ban, + ban_expires = excluded.ban_expires; + +INSERT INTO person_actions (person_id, target_id, blocked) +SELECT + person_id, + target_id, + published +FROM + person_block +ON CONFLICT (person_id, + target_id) + DO UPDATE SET + person_id = excluded.person_id, + target_id = excluded.target_id, + blocked = excluded.blocked; + +INSERT INTO post_actions (person_id, post_id, read_comments, read_comments_amount) +SELECT + person_id, + post_id, + published, + read_comments +FROM + person_post_aggregates +ON CONFLICT (person_id, + post_id) + DO UPDATE SET + read_comments = excluded.read_comments, + read_comments_amount = excluded.read_comments_amount; + +INSERT INTO post_actions (person_id, post_id, hidden) +SELECT + person_id, + post_id, + published +FROM + post_hide +ON CONFLICT (person_id, + post_id) + DO UPDATE SET + hidden = excluded.hidden; + +INSERT INTO post_actions (person_id, post_id, liked, like_score) +SELECT + person_id, + post_id, + published, + score +FROM + post_like +ON CONFLICT (person_id, + post_id) + DO UPDATE SET + liked = excluded.liked, + like_score = excluded.like_score; + +INSERT INTO post_actions (person_id, post_id, saved) +SELECT + person_id, + post_id, + published +FROM + post_saved +ON CONFLICT (person_id, + post_id) + DO UPDATE SET + saved = excluded.saved; -- Drop old tables DROP TABLE comment_saved, community_block, community_moderator, community_person_ban, person_block, person_post_aggregates, post_hide, post_like, post_saved; @@ -377,6 +335,6 @@ FROM person_actions; CREATE statistics post_actions_read_comments_stat ON (read_comments IS NULL), (read_comments_amount IS NULL) FROM post_actions; -CREATE statistics post_actions_liked_stat ON (liked IS NULL), (like_score IS NULL) +CREATE statistics post_actions_liked_stat ON (liked IS NULL), (like_score IS NULL), (post_id IS NULL) FROM post_actions; From fdb7bceac00109b3a5ad5da8317e6cc119cd1eff Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 12:21:07 -0700 Subject: [PATCH 190/232] clean up down.sql --- .../down.sql | 188 +++++++++--------- 1 file changed, 89 insertions(+), 99 deletions(-) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/down.sql b/migrations/2024-03-17-134311_smoosh-tables-together/down.sql index 4a1d4d9e4..3524a9845 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/down.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/down.sql @@ -1,9 +1,4 @@ --- For each new actions table: --- * Create tables that are dropped in up.sql, and insert into them --- * Do the opposite of the `ALTER TABLE` commands in up.sql, with `DELETE` being used to --- only keep rows where the preserved action is not null --- --- Create comment_like from comment_actions +-- For each new actions table, create tables that are dropped in up.sql, and insert into them CREATE TABLE comment_saved ( person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, comment_id int REFERENCES COMMENT ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, @@ -21,24 +16,6 @@ FROM WHERE saved IS NOT NULL; -DELETE FROM comment_actions -WHERE liked IS NULL; - -ALTER TABLE comment_actions RENAME TO comment_like; - -ALTER TABLE comment_like RENAME COLUMN liked TO published; - -ALTER TABLE comment_like RENAME COLUMN like_score TO score; - -ALTER TABLE comment_like - DROP CONSTRAINT comment_actions_check_liked, - ALTER COLUMN published SET NOT NULL, - ALTER COLUMN published SET DEFAULT now(), - ALTER COLUMN score SET NOT NULL, - ALTER COLUMN post_id SET NOT NULL, - DROP COLUMN saved; - --- Create community_follower from community_actions CREATE TABLE community_block ( person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, community_id int REFERENCES community ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, @@ -56,23 +33,6 @@ FROM WHERE blocked IS NOT NULL; -CREATE TABLE community_moderator ( - community_id int REFERENCES community ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, - person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, - published timestamptz DEFAULT now() NOT NULL, - PRIMARY KEY (person_id, community_id) -); - -INSERT INTO community_moderator (community_id, person_id, published) -SELECT - community_id, - person_id, - became_moderator -FROM - community_actions -WHERE - became_moderator IS NOT NULL; - CREATE TABLE community_person_ban ( community_id int REFERENCES community ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, @@ -92,42 +52,23 @@ FROM WHERE received_ban IS NOT NULL; -DELETE FROM community_actions -WHERE followed IS NULL; +CREATE TABLE community_moderator ( + community_id int REFERENCES community ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + published timestamptz DEFAULT now() NOT NULL, + PRIMARY KEY (person_id, community_id) +); -ALTER TABLE community_actions RENAME TO community_follower; +INSERT INTO community_moderator (community_id, person_id, published) +SELECT + community_id, + person_id, + became_moderator +FROM + community_actions +WHERE + became_moderator IS NOT NULL; -ALTER TABLE community_follower RENAME COLUMN followed TO published; - -ALTER TABLE community_follower RENAME follow_pending TO pending; - -ALTER TABLE community_follower - DROP CONSTRAINT community_actions_check_followed, - DROP CONSTRAINT community_actions_check_received_ban, - ALTER COLUMN published SET NOT NULL, - ALTER COLUMN published SET DEFAULT now(), - ALTER COLUMN pending SET NOT NULL, - -- This `SET DEFAULT` is done for community follow, but not person follow. It's not a mistake - -- in this migration. Believe it or not, `pending` only had a default value in community follow. - ALTER COLUMN pending SET DEFAULT FALSE, - DROP COLUMN blocked, - DROP COLUMN became_moderator, - DROP COLUMN received_ban, - DROP COLUMN ban_expires; - --- Create instance_block from instance_actions -DELETE FROM instance_actions -WHERE blocked IS NULL; - -ALTER TABLE instance_actions RENAME TO instance_block; - -ALTER TABLE instance_block RENAME COLUMN blocked TO published; - -ALTER TABLE instance_block - ALTER COLUMN published SET NOT NULL, - ALTER COLUMN published SET DEFAULT now(); - --- Create person_follower from person_actions CREATE TABLE person_block ( person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, target_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, @@ -145,27 +86,6 @@ FROM WHERE blocked IS NOT NULL; -DELETE FROM person_actions -WHERE followed IS NULL; - -ALTER TABLE person_actions RENAME TO person_follower; - -ALTER TABLE person_follower RENAME COLUMN person_id TO follower_id; - -ALTER TABLE person_follower RENAME COLUMN target_id TO person_id; - -ALTER TABLE person_follower RENAME COLUMN followed TO published; - -ALTER TABLE person_follower RENAME COLUMN follow_pending TO pending; - -ALTER TABLE person_follower - DROP CONSTRAINT person_actions_check_followed, - ALTER COLUMN published SET NOT NULL, - ALTER COLUMN published SET DEFAULT now(), - ALTER COLUMN pending SET NOT NULL, - DROP COLUMN blocked; - --- Create post_read from post_actions CREATE TABLE person_post_aggregates ( person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, post_id int REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, @@ -238,13 +158,86 @@ FROM WHERE saved IS NOT NULL; + +-- Do the opposite of the `ALTER TABLE` commands in up.sql +DELETE FROM comment_actions +WHERE liked IS NULL; + +DELETE FROM community_actions +WHERE followed IS NULL; + +DELETE FROM instance_actions +WHERE blocked IS NULL; + +DELETE FROM person_actions +WHERE followed IS NULL; + DELETE FROM post_actions WHERE read IS NULL; +ALTER TABLE comment_actions RENAME TO comment_like; + +ALTER TABLE community_actions RENAME TO community_follower; + +ALTER TABLE instance_actions RENAME TO instance_block; + +ALTER TABLE person_actions RENAME TO person_follower; + ALTER TABLE post_actions RENAME TO post_read; +ALTER TABLE comment_like RENAME COLUMN liked TO published; + +ALTER TABLE comment_like RENAME COLUMN like_score TO score; + +ALTER TABLE community_follower RENAME COLUMN followed TO published; + +ALTER TABLE community_follower RENAME COLUMN follow_pending TO pending; + +ALTER TABLE instance_block RENAME COLUMN blocked TO published; + +ALTER TABLE person_follower RENAME COLUMN person_id TO follower_id; + +ALTER TABLE person_follower RENAME COLUMN target_id TO person_id; + +ALTER TABLE person_follower RENAME COLUMN followed TO published; + +ALTER TABLE person_follower RENAME COLUMN follow_pending TO pending; + ALTER TABLE post_read RENAME COLUMN read TO published; +ALTER TABLE comment_like + DROP CONSTRAINT comment_actions_check_liked, + ALTER COLUMN published SET NOT NULL, + ALTER COLUMN published SET DEFAULT now(), + ALTER COLUMN score SET NOT NULL, + ALTER COLUMN post_id SET NOT NULL, + DROP COLUMN saved; + +ALTER TABLE community_follower + DROP CONSTRAINT community_actions_check_followed, + DROP CONSTRAINT community_actions_check_received_ban, + ALTER COLUMN published SET NOT NULL, + ALTER COLUMN published SET DEFAULT now(), + ALTER COLUMN pending SET NOT NULL, + -- This `SET DEFAULT` is done for community follow, but not person follow. It's not a mistake + -- in this migration. Believe it or not, `pending` only had a default value in community follow. + ALTER COLUMN pending SET DEFAULT FALSE, + DROP COLUMN blocked, + DROP COLUMN became_moderator, + DROP COLUMN received_ban, + DROP COLUMN ban_expires; + +ALTER TABLE instance_block + ALTER COLUMN published SET NOT NULL, + ALTER COLUMN published SET DEFAULT now(); + +ALTER TABLE person_follower + DROP CONSTRAINT person_actions_check_followed, + ALTER COLUMN published SET NOT NULL, + ALTER COLUMN published SET DEFAULT now(), + ALTER COLUMN pending SET NOT NULL, + DROP COLUMN blocked; + ALTER TABLE post_read DROP CONSTRAINT post_actions_check_read_comments, DROP CONSTRAINT post_actions_check_liked, @@ -332,6 +325,3 @@ DROP INDEX idx_comment_actions_liked_not_null, idx_community_actions_followed_no -- Drop statistics of columns that still exist DROP statistics comment_actions_liked_stat, community_actions_followed_stat, person_actions_followed_stat; -ALTER TABLE comment_actions - ALTER COLUMN post_id SET NOT NULL; - From 64eb9304c71b9f4f763fc741b2103fe42c819db0 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 12:42:20 -0700 Subject: [PATCH 191/232] fix --- crates/db_schema/src/impls/community_block.rs | 1 - crates/db_schema/src/impls/instance.rs | 2 -- crates/db_schema/src/impls/instance_block.rs | 1 - crates/db_schema/src/impls/person.rs | 1 - crates/db_schema/src/impls/person_block.rs | 1 - crates/db_schema/src/source/person.rs | 2 +- crates/db_schema/src/utils/uplete.rs | 6 +++--- 7 files changed, 4 insertions(+), 10 deletions(-) diff --git a/crates/db_schema/src/impls/community_block.rs b/crates/db_schema/src/impls/community_block.rs index 5e9382644..d8e3618f7 100644 --- a/crates/db_schema/src/impls/community_block.rs +++ b/crates/db_schema/src/impls/community_block.rs @@ -11,7 +11,6 @@ use crate::{ DbPool, }, }; -use chrono::{DateTime, Utc}; use diesel::{ dsl::{exists, insert_into}, expression::SelectableHelper, diff --git a/crates/db_schema/src/impls/instance.rs b/crates/db_schema/src/impls/instance.rs index 1a8e829e2..94bf909a3 100644 --- a/crates/db_schema/src/impls/instance.rs +++ b/crates/db_schema/src/impls/instance.rs @@ -6,7 +6,6 @@ use crate::{ federation_blocklist, federation_queue_state, instance, - instance_actions, local_site, site, }, @@ -22,7 +21,6 @@ use crate::{ DbPool, }, }; -use chrono::{DateTime, Utc}; use diesel::{ dsl::{count_star, insert_into}, result::Error, diff --git a/crates/db_schema/src/impls/instance_block.rs b/crates/db_schema/src/impls/instance_block.rs index 54e938f57..68668d953 100644 --- a/crates/db_schema/src/impls/instance_block.rs +++ b/crates/db_schema/src/impls/instance_block.rs @@ -11,7 +11,6 @@ use crate::{ DbPool, }, }; -use chrono::{DateTime, Utc}; use diesel::{ dsl::{exists, insert_into}, expression::SelectableHelper, diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs index 4b4212d91..3b4ed6956 100644 --- a/crates/db_schema/src/impls/person.rs +++ b/crates/db_schema/src/impls/person.rs @@ -20,7 +20,6 @@ use crate::{ DbPool, }, }; -use chrono::{DateTime, Utc}; use diesel::{ dsl::insert_into, expression::SelectableHelper, diff --git a/crates/db_schema/src/impls/person_block.rs b/crates/db_schema/src/impls/person_block.rs index 944b83977..c38c49402 100644 --- a/crates/db_schema/src/impls/person_block.rs +++ b/crates/db_schema/src/impls/person_block.rs @@ -11,7 +11,6 @@ use crate::{ DbPool, }, }; -use chrono::{DateTime, Utc}; use diesel::{ dsl::{exists, insert_into}, expression::SelectableHelper, diff --git a/crates/db_schema/src/source/person.rs b/crates/db_schema/src/source/person.rs index 2c7008b05..e42c98022 100644 --- a/crates/db_schema/src/source/person.rs +++ b/crates/db_schema/src/source/person.rs @@ -122,7 +122,7 @@ pub struct PersonUpdateForm { )] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::person::Person)))] #[cfg_attr(feature = "full", diesel(table_name = person_actions))] -#[cfg_attr(feature = "full", diesel(primary_key(follower_id, person_id)))] +#[cfg_attr(feature = "full", diesel(primary_key(person_id, target_id)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] pub struct PersonFollower { #[cfg_attr(feature = "full", diesel(column_name = target_id))] diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 38d350273..6f336be4a 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -36,8 +36,8 @@ impl UpleteBuilder { impl AsQuery for UpleteBuilder where Q::Table: Default + Table, - Q::Table::AllColumns: IntoArray, - >::Output: IntoIterator, + ::AllColumns: IntoArray, + <::AllColumns as IntoArray>::Output: IntoIterator, Q::Query: SelectDsl<(K0, K1)>, dsl::Select: Clone + FilterDsl + FilterDsl>, { @@ -149,7 +149,7 @@ impl Expression for AllNull { type SqlType = sql_types::Bool; } -impl QueryFragment for AllNull { +impl QueryFragment for AllNull { fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> Result<(), Error> { let mut item_prefix = "("; for column in &self.0 { From 4cd46ed6fc26710894a507ff76a34ecedc66c6e4 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 12:44:43 -0700 Subject: [PATCH 192/232] Update person_aggregates.rs --- crates/db_schema/src/aggregates/person_aggregates.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/db_schema/src/aggregates/person_aggregates.rs b/crates/db_schema/src/aggregates/person_aggregates.rs index e96795e8c..03295173f 100644 --- a/crates/db_schema/src/aggregates/person_aggregates.rs +++ b/crates/db_schema/src/aggregates/person_aggregates.rs @@ -100,8 +100,8 @@ mod tests { let mut comment_like = CommentLikeForm { comment_id: inserted_comment.id, - post_id: inserted_post.id, person_id: inserted_person.id, + post_id: inserted_post.id, score: 1, }; @@ -120,8 +120,8 @@ mod tests { let child_comment_like = CommentLikeForm { comment_id: inserted_child_comment.id, - post_id: inserted_post.id, person_id: another_inserted_person.id, + post_id: inserted_post.id, score: 1, }; From a0b0566485174490da4fe9daaefa4e734ff9ad0a Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 12:46:54 -0700 Subject: [PATCH 193/232] fmt --- migrations/2024-03-17-134311_smoosh-tables-together/down.sql | 1 - 1 file changed, 1 deletion(-) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/down.sql b/migrations/2024-03-17-134311_smoosh-tables-together/down.sql index 3524a9845..38a273747 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/down.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/down.sql @@ -158,7 +158,6 @@ FROM WHERE saved IS NOT NULL; - -- Do the opposite of the `ALTER TABLE` commands in up.sql DELETE FROM comment_actions WHERE liked IS NULL; From 5ba61c43b5c592c2a7c617e2826ff7bc0105ff17 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 13:21:50 -0700 Subject: [PATCH 194/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 48 +++++++++++++++++----------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 6f336be4a..2ac67b081 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -14,9 +14,14 @@ use std::any::Any; use tuplex::{IntoArray, Len}; /// Set columns to null and delete the row if all columns not in the primary key are null -pub fn uplete(query: Q) -> UpleteBuilder { +pub fn uplete(query: Q) -> UpleteBuilder +where + Q: AsQuery + Table, + Q::Table: Default, + Q::Query: SelectDsl<::PrimaryKey>, +{ UpleteBuilder { - query, + query: query.as_query().select(Q::Table::default().primary_key()), set_null_columns: Vec::new(), } } @@ -33,32 +38,37 @@ impl UpleteBuilder { } } -impl AsQuery for UpleteBuilder +impl AsQuery for UpleteBuilder where - Q::Table: Default + Table, + K0: 'static, + K1: 'static, + (K0, K1): Expression + QueryFragment + Send, + Q: HasTable, + Q::Table: Default + Table + QueryFragment + Send + 'static, ::AllColumns: IntoArray, <::AllColumns as IntoArray>::Output: IntoIterator, - Q::Query: SelectDsl<(K0, K1)>, - dsl::Select: Clone + FilterDsl + FilterDsl>, + Q: Clone + FilterDsl + FilterDsl>, + dsl::Filter: QueryFragment + Send + 'static, + dsl::Filter>: QueryFragment + Send + 'static, { type Query = UpleteQuery; type SqlType = (sql_types::BigInt, sql_types::BigInt); fn as_query(self) -> Self::Query { - let primary_key = Q::Table::default().primary_key(); - let primary_key_type_ids = [primary_key.0.type_id(), primary_key.1.type_id()]; + let table = Q::Table::default(); + let pk = table.primary_key(); + let pk_type_ids = [pk.0.type_id(), pk.1.type_id()]; let other_columns = Q::Table::all_columns() .into_array() .into_iter() .filter(|c: DynColumn| { - primary_key_type_ids + pk_type_ids .iter() .chain(self.set_null_columns.iter().map(|c| c.type_id())) .all(|other| other != c.type_id()) }) .collect::>(); - let subquery = self.query.select(primary_key.clone()); UpleteQuery { // Updated rows and deleted rows must not overlap, so updating all rows and using the returned // new rows to determine which ones to delete is not an option. @@ -70,23 +80,23 @@ where // predict which one. This also applies to deleting a row that was already updated in the same // statement: only the update is performed." update_subquery: Box::new( - subquery + self.query .clone() .filter(dsl::not(AllNull(other_columns.clone()))), ), - delete_subquery: Box::new(subquery.filter(AllNull(other_columns))), - table: Box::new(Q::Table::default()), - primary_key: Box::new(primary_key), + delete_subquery: Box::new(self.query.filter(AllNull(other_columns))), + table: Box::new(table), + primary_key: Box::new(pk), set_null_columns: self.set_null_columns, } } } pub struct UpleteQuery { - update_subquery: Box>, - delete_subquery: Box>, - table: Box>, - primary_key: Box>, + update_subquery: Box + Send + 'static>, + delete_subquery: Box + Send + 'static>, + table: Box + Send + 'static>, + primary_key: Box + Send + 'static>, set_null_columns: Vec, } @@ -164,7 +174,7 @@ impl QueryFragment for AllNull { } } -pub struct DynColumn(Box + 'static>); +pub struct DynColumn(Box + Send + 'static>); impl + 'static> From for DynColumn { fn from(value: T) -> Self { From 85053e51c216a42111e99abdcc28d5647e949db6 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 13:23:35 -0700 Subject: [PATCH 195/232] fmt --- crates/db_schema/src/utils/uplete.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 2ac67b081..c39670589 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -80,7 +80,8 @@ where // predict which one. This also applies to deleting a row that was already updated in the same // statement: only the update is performed." update_subquery: Box::new( - self.query + self + .query .clone() .filter(dsl::not(AllNull(other_columns.clone()))), ), From 83901d16386fc53895f91582ad1fe2cd007e447c Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 13:39:21 -0700 Subject: [PATCH 196/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index c39670589..90f998d2d 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -16,7 +16,7 @@ use tuplex::{IntoArray, Len}; /// Set columns to null and delete the row if all columns not in the primary key are null pub fn uplete(query: Q) -> UpleteBuilder where - Q: AsQuery + Table, + Q: AsQuery + HasTable, Q::Table: Default, Q::Query: SelectDsl<::PrimaryKey>, { From 00642277e74aacf71e9e6cfa6c6817a6e7f3dbc8 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 13:54:29 -0700 Subject: [PATCH 197/232] Update community.rs --- crates/db_schema/src/source/community.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/db_schema/src/source/community.rs b/crates/db_schema/src/source/community.rs index e79e8c5b1..46f0b7a80 100644 --- a/crates/db_schema/src/source/community.rs +++ b/crates/db_schema/src/source/community.rs @@ -181,8 +181,6 @@ pub struct CommunityPersonBan { #[cfg_attr(feature = "full", diesel(select_expression = community_actions::received_ban.assume_not_null()))] #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub published: DateTime, - #[cfg_attr(feature = "full", diesel(select_expression = community_actions::ban_expires.assume_not_null()))] - #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub expires: Option>, } From b9492135ac4cf61ea9a33a7f51e9cf60f9bc50f7 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 17:11:51 -0700 Subject: [PATCH 198/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 67 +++++++++++++++------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 90f998d2d..8b65eeabc 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -19,6 +19,9 @@ where Q: AsQuery + HasTable, Q::Table: Default, Q::Query: SelectDsl<::PrimaryKey>, + + // For better error messages + UpleteBuilder: AsQuery, { UpleteBuilder { query: query.as_query().select(Q::Table::default().primary_key()), @@ -38,14 +41,13 @@ impl UpleteBuilder { } } -impl AsQuery for UpleteBuilder +impl AsQuery for UpleteBuilder where - K0: 'static, - K1: 'static, - (K0, K1): Expression + QueryFragment + Send, Q: HasTable, - Q::Table: Default + Table + QueryFragment + Send + 'static, + Q::Table: Default + QueryFragment + Send + 'static, + ::PrimaryKey: IntoArray + QueryFragment + Send + 'static, ::AllColumns: IntoArray, + <::PrimaryKey as IntoArray>::Output: IntoIterator, <::AllColumns as IntoArray>::Output: IntoIterator, Q: Clone + FilterDsl + FilterDsl>, dsl::Filter: QueryFragment + Send + 'static, @@ -57,18 +59,19 @@ where fn as_query(self) -> Self::Query { let table = Q::Table::default(); - let pk = table.primary_key(); - let pk_type_ids = [pk.0.type_id(), pk.1.type_id()]; - let other_columns = Q::Table::all_columns() - .into_array() - .into_iter() - .filter(|c: DynColumn| { - pk_type_ids - .iter() - .chain(self.set_null_columns.iter().map(|c| c.type_id())) - .all(|other| other != c.type_id()) - }) - .collect::>(); + let primary_key_columns = table.primary_key().into_array(); + let deletion_condition = AllNull( + Q::Table::all_columns() + .into_array() + .into_iter() + .filter(|c: DynColumn| { + primary_key_columns + .iter() + .chain(&self.set_null_columns) + .all(|excluded_column| excluded_column.type_id() != c.type_id()) + }) + .collect::>() + ); UpleteQuery { // Updated rows and deleted rows must not overlap, so updating all rows and using the returned // new rows to determine which ones to delete is not an option. @@ -83,11 +86,11 @@ where self .query .clone() - .filter(dsl::not(AllNull(other_columns.clone()))), + .filter(dsl::not(deletion_condition.clone())), ), - delete_subquery: Box::new(self.query.filter(AllNull(other_columns))), + delete_subquery: Box::new(self.query.filter(deletion_condition)), table: Box::new(table), - primary_key: Box::new(pk), + primary_key: Box::new(table.primary_key()), set_null_columns: self.set_null_columns, } } @@ -115,17 +118,18 @@ impl QueryFragment for UpleteQuery { fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> Result<(), Error> { assert_ne!(self.set_null_columns.len(), 0, "`set_null` was not called"); - // Which rows to update - out.push_sql("WITH update_keys AS ("); - self.update_subquery.walk_ast(out.reborrow())?; - out.push_sql(" FOR UPDATE)"); + // Declare `update_keys` and `delete_keys` CTEs, which select primary keys + for (prefix, subquery) in [ + ("WITH update_keys", &self.update_subquery), + (", delete_keys", &self.delete_subquery), + ] { + out.push_sql(prefix); + out.push_sql(" AS ("); + subquery.walk_ast(out.reborrow())?; + out.push_sql(" FOR UPDATE)"); + } - // Which rows to delete - out.push_sql(", delete_keys AS ("); - self.delete_subquery.walk_ast(out.reborrow())?; - out.push_sql(" FOR UPDATE)"); - - // Update rows + // Update rows that are referenced in `update_keys` out.push_sql(", update_result AS (UPDATE "); self.table.walk_ast(out.reborrow())?; let mut item_prefix = " SET "; @@ -139,7 +143,7 @@ impl QueryFragment for UpleteQuery { self.primary_key.walk_ast(out.reborrow())?; out.push_sql(") = ANY (SELECT * FROM update_keys) RETURNING 1)"); - // Delete rows + // Delete rows that are referenced in `delete_keys` out.push_sql(", delete_result AS (DELETE FROM "); self.table.walk_ast(out.reborrow())?; out.push_sql(" WHERE ("); @@ -154,6 +158,7 @@ impl QueryFragment for UpleteQuery { } } +#[derive(Clone)] pub struct AllNull(Vec); impl Expression for AllNull { From 1761eb533540cfe8e002cb297102f86aa2fbf763 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 17:40:00 -0700 Subject: [PATCH 199/232] Update local_user.rs --- crates/db_schema/src/impls/local_user.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/db_schema/src/impls/local_user.rs b/crates/db_schema/src/impls/local_user.rs index cad0a37c0..fef2cec78 100644 --- a/crates/db_schema/src/impls/local_user.rs +++ b/crates/db_schema/src/impls/local_user.rs @@ -163,21 +163,21 @@ impl LocalUser { let followed_communities = action_query(community_actions::followed) .filter(community_actions::person_id.eq(person_id_)) - .inner_join(community::table.on(community_actions::community_id.eq(community::id))) + .inner_join(community::table) .select(community::actor_id) .get_results(conn) .await?; let saved_posts = action_query(post_actions::saved) .filter(post_actions::person_id.eq(person_id_)) - .inner_join(post::table.on(post_actions::post_id.eq(post::id))) + .inner_join(post::table) .select(post::ap_id) .get_results(conn) .await?; let saved_comments = action_query(comment_actions::saved) .filter(comment_actions::person_id.eq(person_id_)) - .inner_join(comment::table.on(comment_actions::comment_id.eq(comment::id))) + .inner_join(comment::table) .select(comment::ap_id) .get_results(conn) .await?; @@ -191,7 +191,7 @@ impl LocalUser { let blocked_users = action_query(person_actions::blocked) .filter(person_actions::person_id.eq(person_id_)) - .inner_join(person::table.on(person_actions::target_id.eq(person::id))) + .inner_join(person::table) .select(person::actor_id) .get_results(conn) .await?; From 37ed6515d4e2acaf787ea9ecbb5b0da130a91cbf Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 17:44:06 -0700 Subject: [PATCH 200/232] fmt --- crates/db_schema/src/utils/uplete.rs | 2 +- crates/db_views_actor/src/comment_reply_view.rs | 5 +---- crates/db_views_actor/src/person_mention_view.rs | 5 +---- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 8b65eeabc..f285bf6e0 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -70,7 +70,7 @@ where .chain(&self.set_null_columns) .all(|excluded_column| excluded_column.type_id() != c.type_id()) }) - .collect::>() + .collect::>(), ); UpleteQuery { // Updated rows and deleted rows must not overlap, so updating all rows and using the returned diff --git a/crates/db_views_actor/src/comment_reply_view.rs b/crates/db_views_actor/src/comment_reply_view.rs index 15ba6c426..1c8b576e9 100644 --- a/crates/db_views_actor/src/comment_reply_view.rs +++ b/crates/db_views_actor/src/comment_reply_view.rs @@ -23,10 +23,7 @@ use lemmy_db_schema::{ person_actions, post, }, - source::{ - community::CommunityFollower, - local_user::LocalUser, - }, + source::{community::CommunityFollower, local_user::LocalUser}, utils::{ actions, actions_alias, diff --git a/crates/db_views_actor/src/person_mention_view.rs b/crates/db_views_actor/src/person_mention_view.rs index ba46e3cef..cbd513f73 100644 --- a/crates/db_views_actor/src/person_mention_view.rs +++ b/crates/db_views_actor/src/person_mention_view.rs @@ -23,10 +23,7 @@ use lemmy_db_schema::{ person_mention, post, }, - source::{ - community::CommunityFollower, - local_user::LocalUser, - }, + source::{community::CommunityFollower, local_user::LocalUser}, utils::{ actions, actions_alias, From c95f0b05e3e2bbc998c76533f44735036ed7b746 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 18:08:43 -0700 Subject: [PATCH 201/232] fix --- crates/db_schema/src/impls/local_user.rs | 2 +- crates/db_schema/src/source/community.rs | 1 + crates/db_schema/src/utils/uplete.rs | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/db_schema/src/impls/local_user.rs b/crates/db_schema/src/impls/local_user.rs index fef2cec78..cc96a0bdf 100644 --- a/crates/db_schema/src/impls/local_user.rs +++ b/crates/db_schema/src/impls/local_user.rs @@ -191,7 +191,7 @@ impl LocalUser { let blocked_users = action_query(person_actions::blocked) .filter(person_actions::person_id.eq(person_id_)) - .inner_join(person::table) + .inner_join(person::table.on(person_actions::target_id.eq(person::id))) .select(person::actor_id) .get_results(conn) .await?; diff --git a/crates/db_schema/src/source/community.rs b/crates/db_schema/src/source/community.rs index 46f0b7a80..0f96280de 100644 --- a/crates/db_schema/src/source/community.rs +++ b/crates/db_schema/src/source/community.rs @@ -181,6 +181,7 @@ pub struct CommunityPersonBan { #[cfg_attr(feature = "full", diesel(select_expression = community_actions::received_ban.assume_not_null()))] #[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull))] pub published: DateTime, + #[cfg_attr(feature = "full", diesel(column_name = ban_expires))] pub expires: Option>, } diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index f285bf6e0..ab1b09a2d 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -1,6 +1,7 @@ use diesel::{ associations::HasTable, dsl, + expression::{is_aggregate, ValidGrouping}, pg::Pg, query_builder::{AsQuery, AstPass, Query, QueryFragment, QueryId}, query_dsl::methods::{FilterDsl, SelectDsl}, @@ -165,6 +166,10 @@ impl Expression for AllNull { type SqlType = sql_types::Bool; } +impl ValidGrouping<()> for AllNull { + type IsAggregate = is_aggregate::No; +} + impl QueryFragment for AllNull { fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> Result<(), Error> { let mut item_prefix = "("; From 561e0434686af3541f61b3c7d1a9219932029603 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 18:58:01 -0700 Subject: [PATCH 202/232] fix --- crates/db_schema/src/source/person.rs | 2 +- crates/db_schema/src/utils/uplete.rs | 50 +++++++++++++-------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/crates/db_schema/src/source/person.rs b/crates/db_schema/src/source/person.rs index e42c98022..d8238340e 100644 --- a/crates/db_schema/src/source/person.rs +++ b/crates/db_schema/src/source/person.rs @@ -7,7 +7,7 @@ use crate::{ }; use chrono::{DateTime, Utc}; #[cfg(feature = "full")] -use diesel::{dsl, expression_methods::ExpressionMethods}; +use diesel::{dsl, expression_methods::NullableExpressionMethods}; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; #[cfg(feature = "full")] diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index ab1b09a2d..17c53e5f5 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -12,10 +12,10 @@ use diesel::{ Table, }; use std::any::Any; -use tuplex::{IntoArray, Len}; +use tuplex::IntoArray; /// Set columns to null and delete the row if all columns not in the primary key are null -pub fn uplete(query: Q) -> UpleteBuilder +pub fn uplete(query: Q) -> UpleteBuilder::PrimaryKey>> where Q: AsQuery + HasTable, Q::Table: Default, @@ -48,8 +48,8 @@ where Q::Table: Default + QueryFragment + Send + 'static, ::PrimaryKey: IntoArray + QueryFragment + Send + 'static, ::AllColumns: IntoArray, - <::PrimaryKey as IntoArray>::Output: IntoIterator, - <::AllColumns as IntoArray>::Output: IntoIterator, + <::PrimaryKey as IntoArray>::Output: AsRef<[DynColumn]>, + <::AllColumns as IntoArray>::Output: AsRef<[DynColumn]>, Q: Clone + FilterDsl + FilterDsl>, dsl::Filter: QueryFragment + Send + 'static, dsl::Filter>: QueryFragment + Send + 'static, @@ -61,18 +61,22 @@ where fn as_query(self) -> Self::Query { let table = Q::Table::default(); let primary_key_columns = table.primary_key().into_array(); - let deletion_condition = AllNull( - Q::Table::all_columns() - .into_array() - .into_iter() - .filter(|c: DynColumn| { - primary_key_columns - .iter() - .chain(&self.set_null_columns) - .all(|excluded_column| excluded_column.type_id() != c.type_id()) - }) - .collect::>(), - ); + let all_columns = Q::Table::all_columns().into_array(); + let deletion_condition = || { + AllNull( + all_columns + .as_ref() + .iter() + .filter(|c: DynColumn| { + primary_key_columns + .as_ref() + .iter() + .chain(&self.set_null_columns) + .all(|excluded_column| excluded_column.type_id() != c.type_id()) + }) + .collect::>(), + ) + }; UpleteQuery { // Updated rows and deleted rows must not overlap, so updating all rows and using the returned // new rows to determine which ones to delete is not an option. @@ -84,12 +88,9 @@ where // predict which one. This also applies to deleting a row that was already updated in the same // statement: only the update is performed." update_subquery: Box::new( - self - .query - .clone() - .filter(dsl::not(deletion_condition.clone())), + self.query.clone().filter(dsl::not(deletion_condition())), ), - delete_subquery: Box::new(self.query.filter(deletion_condition)), + delete_subquery: Box::new(self.query.filter(deletion_condition())), table: Box::new(table), primary_key: Box::new(table.primary_key()), set_null_columns: self.set_null_columns, @@ -136,7 +137,7 @@ impl QueryFragment for UpleteQuery { let mut item_prefix = " SET "; for column in &self.set_null_columns { out.push_sql(item_prefix); - column.walk_ast(out.reborrow())?; + column.0.walk_ast(out.reborrow())?; out.push_sql(" = NULL"); item_prefix = ","; } @@ -159,7 +160,6 @@ impl QueryFragment for UpleteQuery { } } -#[derive(Clone)] pub struct AllNull(Vec); impl Expression for AllNull { @@ -175,7 +175,7 @@ impl QueryFragment for AllNull { let mut item_prefix = "("; for column in &self.0 { out.push_sql(item_prefix); - column.walk_ast(out.reborrow())?; + column.0.walk_ast(out.reborrow())?; out.push_sql(" IS NOT NULL"); item_prefix = " AND "; } @@ -187,7 +187,7 @@ impl QueryFragment for AllNull { pub struct DynColumn(Box + Send + 'static>); -impl + 'static> From for DynColumn { +impl + Send + 'static> From for DynColumn { fn from(value: T) -> Self { DynColumn(Box::new(value)) } From d9890f198c3c9fc38a333a70c01312678835c53e Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 19:05:44 -0700 Subject: [PATCH 203/232] fmt --- crates/db_schema/src/utils/uplete.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 17c53e5f5..ea6d88829 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -87,9 +87,7 @@ where // the modifications takes place, but it is not easy (and sometimes not possible) to reliably // predict which one. This also applies to deleting a row that was already updated in the same // statement: only the update is performed." - update_subquery: Box::new( - self.query.clone().filter(dsl::not(deletion_condition())), - ), + update_subquery: Box::new(self.query.clone().filter(dsl::not(deletion_condition()))), delete_subquery: Box::new(self.query.filter(deletion_condition())), table: Box::new(table), primary_key: Box::new(table.primary_key()), From 266edf47f9cfe5f4d6328b592ef304636ae107f0 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 19:56:13 -0700 Subject: [PATCH 204/232] improve uplete api --- crates/db_schema/src/impls/comment.rs | 16 +++++----- crates/db_schema/src/impls/community.rs | 30 ++++++++--------- crates/db_schema/src/impls/community_block.rs | 6 ++-- crates/db_schema/src/impls/instance_block.rs | 6 ++-- crates/db_schema/src/impls/person.rs | 10 +++--- crates/db_schema/src/impls/person_block.rs | 6 ++-- crates/db_schema/src/impls/post.rs | 26 +++++++-------- crates/db_schema/src/traits.rs | 14 ++++---- crates/db_schema/src/utils/uplete.rs | 32 +++++++++---------- 9 files changed, 73 insertions(+), 73 deletions(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index ce24662f8..c9afaffc0 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -17,7 +17,7 @@ use crate::{ get_conn, naive_now, now, - uplete::{uplete, UpleteCount}, + uplete, DbPool, DELETED_REPLACEMENT_TEXT, }, @@ -173,9 +173,9 @@ impl Likeable for CommentLike { pool: &mut DbPool<'_>, person_id: PersonId, comment_id: CommentId, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; - uplete(comment_actions::table.find((person_id, comment_id))) + uplete::new(comment_actions::table.find((person_id, comment_id))) .set_null(comment_actions::like_score) .set_null(comment_actions::liked) // Deleting empty `comment_actions` rows would not work without setting `post_id` to @@ -210,9 +210,9 @@ impl Saveable for CommentSaved { async fn unsave( pool: &mut DbPool<'_>, comment_saved_form: &CommentSavedForm, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; - uplete( + uplete::new( comment_actions::table.find((comment_saved_form.person_id, comment_saved_form.comment_id)), ) .set_null(comment_actions::saved) @@ -244,7 +244,7 @@ mod tests { post::{Post, PostInsertForm}, }, traits::{Crud, Likeable, Saveable}, - utils::{build_db_pool_for_tests, uplete::UpleteCount}, + utils::{build_db_pool_for_tests, uplete::uplete::Count}, }; use diesel_ltree::Ltree; use pretty_assertions::assert_eq; @@ -392,8 +392,8 @@ mod tests { format!("0.{}.{}", expected_comment.id, inserted_child_comment.id), inserted_child_comment.path.0, ); - assert_eq!(UpleteCount::only_updated(1), like_removed); - assert_eq!(UpleteCount::only_deleted(1), saved_removed); + assert_eq!(uplete::Count::only_updated(1), like_removed); + assert_eq!(uplete::Count::only_deleted(1), saved_removed); assert_eq!(1, num_deleted); } } diff --git a/crates/db_schema/src/impls/community.rs b/crates/db_schema/src/impls/community.rs index 1832e817c..cc4865afe 100644 --- a/crates/db_schema/src/impls/community.rs +++ b/crates/db_schema/src/impls/community.rs @@ -24,7 +24,7 @@ use crate::{ functions::{coalesce, lower}, get_conn, now, - uplete::{uplete, UpleteCount}, + uplete, DbPool, }, SubscribedType, @@ -109,9 +109,9 @@ impl Joinable for CommunityModerator { async fn leave( pool: &mut DbPool<'_>, community_moderator_form: &CommunityModeratorForm, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; - uplete(community_actions::table.find(( + uplete::new(community_actions::table.find(( community_moderator_form.person_id, community_moderator_form.community_id, ))) @@ -214,10 +214,10 @@ impl CommunityModerator { pub async fn delete_for_community( pool: &mut DbPool<'_>, for_community_id: CommunityId, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; - uplete(community_actions::table.filter(community_actions::community_id.eq(for_community_id))) + uplete::new(community_actions::table.filter(community_actions::community_id.eq(for_community_id))) .set_null(community_actions::became_moderator) .get_result(conn) .await @@ -226,9 +226,9 @@ impl CommunityModerator { pub async fn leave_all_communities( pool: &mut DbPool<'_>, for_person_id: PersonId, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; - uplete(community_actions::table.filter(community_actions::person_id.eq(for_person_id))) + uplete::new(community_actions::table.filter(community_actions::person_id.eq(for_person_id))) .set_null(community_actions::became_moderator) .get_result(conn) .await @@ -275,9 +275,9 @@ impl Bannable for CommunityPersonBan { async fn unban( pool: &mut DbPool<'_>, community_person_ban_form: &CommunityPersonBanForm, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; - uplete(community_actions::table.find(( + uplete::new(community_actions::table.find(( community_person_ban_form.person_id, community_person_ban_form.community_id, ))) @@ -370,9 +370,9 @@ impl Followable for CommunityFollower { async fn unfollow( pool: &mut DbPool<'_>, form: &CommunityFollowerForm, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; - uplete(community_actions::table.find((form.person_id, form.community_id))) + uplete::new(community_actions::table.find((form.person_id, form.community_id))) .set_null(community_actions::followed) .set_null(community_actions::follow_pending) .get_result(conn) @@ -451,7 +451,7 @@ mod tests { person::{Person, PersonInsertForm}, }, traits::{Bannable, Crud, Followable, Joinable}, - utils::{build_db_pool_for_tests, uplete::UpleteCount}, + utils::{build_db_pool_for_tests, uplete::uplete::Count}, CommunityVisibility, }; use pretty_assertions::assert_eq; @@ -595,9 +595,9 @@ mod tests { assert_eq!(expected_community_follower, inserted_community_follower); assert_eq!(expected_community_moderator, inserted_community_moderator); assert_eq!(expected_community_person_ban, inserted_community_person_ban); - assert_eq!(UpleteCount::only_updated(1), ignored_community); - assert_eq!(UpleteCount::only_updated(1), left_community); - assert_eq!(UpleteCount::only_deleted(1), unban); + assert_eq!(uplete::Count::only_updated(1), ignored_community); + assert_eq!(uplete::Count::only_updated(1), left_community); + assert_eq!(uplete::Count::only_deleted(1), unban); // assert_eq!(2, loaded_count); assert_eq!(1, num_deleted); } diff --git a/crates/db_schema/src/impls/community_block.rs b/crates/db_schema/src/impls/community_block.rs index d8e3618f7..428df331f 100644 --- a/crates/db_schema/src/impls/community_block.rs +++ b/crates/db_schema/src/impls/community_block.rs @@ -7,7 +7,7 @@ use crate::{ find_action, get_conn, now, - uplete::{uplete, UpleteCount}, + uplete, DbPool, }, }; @@ -62,9 +62,9 @@ impl Blockable for CommunityBlock { async fn unblock( pool: &mut DbPool<'_>, community_block_form: &Self::Form, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; - uplete(community_actions::table.find(( + uplete::new(community_actions::table.find(( community_block_form.person_id, community_block_form.community_id, ))) diff --git a/crates/db_schema/src/impls/instance_block.rs b/crates/db_schema/src/impls/instance_block.rs index 68668d953..735824008 100644 --- a/crates/db_schema/src/impls/instance_block.rs +++ b/crates/db_schema/src/impls/instance_block.rs @@ -7,7 +7,7 @@ use crate::{ find_action, get_conn, now, - uplete::{uplete, UpleteCount}, + uplete, DbPool, }, }; @@ -59,9 +59,9 @@ impl Blockable for InstanceBlock { async fn unblock( pool: &mut DbPool<'_>, instance_block_form: &Self::Form, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; - uplete(instance_actions::table.find(( + uplete::new(instance_actions::table.find(( instance_block_form.person_id, instance_block_form.instance_id, ))) diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs index 3b4ed6956..446e75056 100644 --- a/crates/db_schema/src/impls/person.rs +++ b/crates/db_schema/src/impls/person.rs @@ -16,7 +16,7 @@ use crate::{ get_conn, naive_now, now, - uplete::{uplete, UpleteCount}, + uplete, DbPool, }, }; @@ -211,9 +211,9 @@ impl Followable for PersonFollower { async fn unfollow( pool: &mut DbPool<'_>, form: &PersonFollowerForm, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; - uplete(person_actions::table.find((form.follower_id, form.person_id))) + uplete::new(person_actions::table.find((form.follower_id, form.person_id))) .set_null(person_actions::followed) .set_null(person_actions::follow_pending) .get_result(conn) @@ -247,7 +247,7 @@ mod tests { person::{Person, PersonFollower, PersonFollowerForm, PersonInsertForm, PersonUpdateForm}, }, traits::{Crud, Followable}, - utils::{build_db_pool_for_tests, uplete::UpleteCount}, + utils::{build_db_pool_for_tests, uplete::uplete::Count}, }; use pretty_assertions::assert_eq; use serial_test::serial; @@ -354,6 +354,6 @@ mod tests { assert_eq!(vec![person_2], followers); let unfollow = PersonFollower::unfollow(pool, &follow_form).await.unwrap(); - assert_eq!(UpleteCount::only_deleted(1), unfollow); + assert_eq!(uplete::Count::only_deleted(1), unfollow); } } diff --git a/crates/db_schema/src/impls/person_block.rs b/crates/db_schema/src/impls/person_block.rs index c38c49402..4ca0f682e 100644 --- a/crates/db_schema/src/impls/person_block.rs +++ b/crates/db_schema/src/impls/person_block.rs @@ -7,7 +7,7 @@ use crate::{ find_action, get_conn, now, - uplete::{uplete, UpleteCount}, + uplete, DbPool, }, }; @@ -62,9 +62,9 @@ impl Blockable for PersonBlock { async fn unblock( pool: &mut DbPool<'_>, person_block_form: &Self::Form, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; - uplete(person_actions::table.find((person_block_form.person_id, person_block_form.target_id))) + uplete::new(person_actions::table.find((person_block_form.person_id, person_block_form.target_id))) .set_null(person_actions::blocked) .get_result(conn) .await diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index 20a46b9f4..46e2e870e 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -21,7 +21,7 @@ use crate::{ get_conn, naive_now, now, - uplete::{uplete, UpleteCount}, + uplete, DbPool, DELETED_REPLACEMENT_TEXT, FETCH_LIMIT_MAX, @@ -268,9 +268,9 @@ impl Likeable for PostLike { pool: &mut DbPool<'_>, person_id: PersonId, post_id: PostId, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; - uplete(post_actions::table.find((person_id, post_id))) + uplete::new(post_actions::table.find((person_id, post_id))) .set_null(post_actions::like_score) .set_null(post_actions::liked) .get_result(conn) @@ -296,9 +296,9 @@ impl Saveable for PostSaved { async fn unsave( pool: &mut DbPool<'_>, post_saved_form: &PostSavedForm, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; - uplete(post_actions::table.find((post_saved_form.person_id, post_saved_form.post_id))) + uplete::new(post_actions::table.find((post_saved_form.person_id, post_saved_form.post_id))) .set_null(post_actions::saved) .get_result(conn) .await @@ -335,10 +335,10 @@ impl PostRead { pool: &mut DbPool<'_>, post_id_: HashSet, person_id_: PersonId, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; - uplete( + uplete::new( post_actions::table .filter(post_actions::post_id.eq_any(post_id_)) .filter(post_actions::person_id.eq(person_id_)), @@ -379,10 +379,10 @@ impl PostHide { pool: &mut DbPool<'_>, post_id_: HashSet, person_id_: PersonId, - ) -> Result { + ) -> Result { let conn = &mut get_conn(pool).await?; - uplete( + uplete::new( post_actions::table .filter(post_actions::post_id.eq_any(post_id_)) .filter(post_actions::person_id.eq(person_id_)), @@ -415,7 +415,7 @@ mod tests { }, }, traits::{Crud, Likeable, Saveable}, - utils::{build_db_pool_for_tests, uplete::UpleteCount}, + utils::{build_db_pool_for_tests, uplete::uplete::Count}, }; use pretty_assertions::assert_eq; use serial_test::serial; @@ -542,9 +542,9 @@ mod tests { let like_removed = PostLike::remove(pool, inserted_person.id, inserted_post.id) .await .unwrap(); - assert_eq!(UpleteCount::only_updated(1), like_removed); + assert_eq!(uplete::Count::only_updated(1), like_removed); let saved_removed = PostSaved::unsave(pool, &post_saved_form).await.unwrap(); - assert_eq!(UpleteCount::only_updated(1), saved_removed); + assert_eq!(uplete::Count::only_updated(1), saved_removed); let read_removed = PostRead::mark_as_unread( pool, HashSet::from([inserted_post.id, inserted_post2.id]), @@ -552,7 +552,7 @@ mod tests { ) .await .unwrap(); - assert_eq!(UpleteCount::only_deleted(2), read_removed); + assert_eq!(uplete::Count::only_deleted(2), read_removed); let num_deleted = Post::delete(pool, inserted_post.id).await.unwrap() + Post::delete(pool, inserted_post2.id).await.unwrap(); diff --git a/crates/db_schema/src/traits.rs b/crates/db_schema/src/traits.rs index 4779c0a83..d9b64114a 100644 --- a/crates/db_schema/src/traits.rs +++ b/crates/db_schema/src/traits.rs @@ -1,7 +1,7 @@ use crate::{ diesel::OptionalExtension, newtypes::{CommunityId, DbUrl, PersonId}, - utils::{get_conn, uplete::UpleteCount, DbPool}, + utils::{get_conn, uplete::uplete::Count, DbPool}, }; use diesel::{ associations::HasTable, @@ -77,7 +77,7 @@ pub trait Followable { ) -> Result where Self: Sized; - async fn unfollow(pool: &mut DbPool<'_>, form: &Self::Form) -> Result + async fn unfollow(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; } @@ -88,7 +88,7 @@ pub trait Joinable { async fn join(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; - async fn leave(pool: &mut DbPool<'_>, form: &Self::Form) -> Result + async fn leave(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; } @@ -104,7 +104,7 @@ pub trait Likeable { pool: &mut DbPool<'_>, person_id: PersonId, item_id: Self::IdType, - ) -> Result + ) -> Result where Self: Sized; } @@ -115,7 +115,7 @@ pub trait Bannable { async fn ban(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; - async fn unban(pool: &mut DbPool<'_>, form: &Self::Form) -> Result + async fn unban(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; } @@ -126,7 +126,7 @@ pub trait Saveable { async fn save(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; - async fn unsave(pool: &mut DbPool<'_>, form: &Self::Form) -> Result + async fn unsave(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; } @@ -137,7 +137,7 @@ pub trait Blockable { async fn block(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; - async fn unblock(pool: &mut DbPool<'_>, form: &Self::Form) -> Result + async fn unblock(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; } diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index ea6d88829..b716fe70d 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -14,8 +14,9 @@ use diesel::{ use std::any::Any; use tuplex::IntoArray; -/// Set columns to null and delete the row if all columns not in the primary key are null -pub fn uplete(query: Q) -> UpleteBuilder::PrimaryKey>> +/// Set columns (each specified with `UpleteBuilder::set_null`) to null in the rows found by +/// `query`, and delete rows that have no remaining non-null values outside of the primary key +pub fn new(query: Q) -> UpleteBuilder::PrimaryKey>> where Q: AsQuery + HasTable, Q::Table: Default, @@ -48,8 +49,8 @@ where Q::Table: Default + QueryFragment + Send + 'static, ::PrimaryKey: IntoArray + QueryFragment + Send + 'static, ::AllColumns: IntoArray, - <::PrimaryKey as IntoArray>::Output: AsRef<[DynColumn]>, - <::AllColumns as IntoArray>::Output: AsRef<[DynColumn]>, + <::PrimaryKey as IntoArray>::Output: IntoIterator, + <::AllColumns as IntoArray>::Output: IntoIterator, Q: Clone + FilterDsl + FilterDsl>, dsl::Filter: QueryFragment + Send + 'static, dsl::Filter>: QueryFragment + Send + 'static, @@ -60,17 +61,16 @@ where fn as_query(self) -> Self::Query { let table = Q::Table::default(); - let primary_key_columns = table.primary_key().into_array(); - let all_columns = Q::Table::all_columns().into_array(); let deletion_condition = || { AllNull( - all_columns - .as_ref() - .iter() + Q::Table::all_columns() + .into_array() + .into_iter() .filter(|c: DynColumn| { - primary_key_columns - .as_ref() - .iter() + table + .primary_key() + .into_array(); + .into_iter() .chain(&self.set_null_columns) .all(|excluded_column| excluded_column.type_id() != c.type_id()) }) @@ -192,21 +192,21 @@ impl + Send + 'static> From for DynColumn { } #[derive(Queryable, PartialEq, Eq, Debug)] -pub struct UpleteCount { +pub struct Count { pub updated: i64, pub deleted: i64, } -impl UpleteCount { +impl Count { pub fn only_updated(n: i64) -> Self { - UpleteCount { + Count { updated: n, deleted: 0, } } pub fn only_deleted(n: i64) -> Self { - UpleteCount { + Count { updated: 0, deleted: n, } From 85b52c679804dda8daaa15dc39177c99a1ebc78d Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 19:58:16 -0700 Subject: [PATCH 205/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index b716fe70d..f02bc59e0 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -69,7 +69,7 @@ where .filter(|c: DynColumn| { table .primary_key() - .into_array(); + .into_array() .into_iter() .chain(&self.set_null_columns) .all(|excluded_column| excluded_column.type_id() != c.type_id()) From ce7569720e9ea71cb4411e85de65094079c1527b Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 20:18:58 -0700 Subject: [PATCH 206/232] fix --- crates/db_schema/src/impls/comment.rs | 2 +- crates/db_schema/src/impls/community.rs | 12 +++++++----- crates/db_schema/src/impls/community_block.rs | 8 +------- crates/db_schema/src/impls/instance_block.rs | 8 +------- crates/db_schema/src/impls/person.rs | 12 ++---------- crates/db_schema/src/impls/person_block.rs | 18 +++++++----------- crates/db_schema/src/impls/post.rs | 2 +- crates/db_schema/src/traits.rs | 2 +- 8 files changed, 21 insertions(+), 43 deletions(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index c9afaffc0..d7a0aa10f 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -244,7 +244,7 @@ mod tests { post::{Post, PostInsertForm}, }, traits::{Crud, Likeable, Saveable}, - utils::{build_db_pool_for_tests, uplete::uplete::Count}, + utils::{build_db_pool_for_tests, uplete::Count}, }; use diesel_ltree::Ltree; use pretty_assertions::assert_eq; diff --git a/crates/db_schema/src/impls/community.rs b/crates/db_schema/src/impls/community.rs index cc4865afe..a6c1d76bb 100644 --- a/crates/db_schema/src/impls/community.rs +++ b/crates/db_schema/src/impls/community.rs @@ -217,10 +217,12 @@ impl CommunityModerator { ) -> Result { let conn = &mut get_conn(pool).await?; - uplete::new(community_actions::table.filter(community_actions::community_id.eq(for_community_id))) - .set_null(community_actions::became_moderator) - .get_result(conn) - .await + uplete::new( + community_actions::table.filter(community_actions::community_id.eq(for_community_id)), + ) + .set_null(community_actions::became_moderator) + .get_result(conn) + .await } pub async fn leave_all_communities( @@ -451,7 +453,7 @@ mod tests { person::{Person, PersonInsertForm}, }, traits::{Bannable, Crud, Followable, Joinable}, - utils::{build_db_pool_for_tests, uplete::uplete::Count}, + utils::{build_db_pool_for_tests, uplete::Count}, CommunityVisibility, }; use pretty_assertions::assert_eq; diff --git a/crates/db_schema/src/impls/community_block.rs b/crates/db_schema/src/impls/community_block.rs index 428df331f..874eff5f2 100644 --- a/crates/db_schema/src/impls/community_block.rs +++ b/crates/db_schema/src/impls/community_block.rs @@ -3,13 +3,7 @@ use crate::{ schema::community_actions, source::community_block::{CommunityBlock, CommunityBlockForm}, traits::Blockable, - utils::{ - find_action, - get_conn, - now, - uplete, - DbPool, - }, + utils::{find_action, get_conn, now, uplete, DbPool}, }; use diesel::{ dsl::{exists, insert_into}, diff --git a/crates/db_schema/src/impls/instance_block.rs b/crates/db_schema/src/impls/instance_block.rs index 735824008..9d53cec96 100644 --- a/crates/db_schema/src/impls/instance_block.rs +++ b/crates/db_schema/src/impls/instance_block.rs @@ -3,13 +3,7 @@ use crate::{ schema::instance_actions, source::instance_block::{InstanceBlock, InstanceBlockForm}, traits::Blockable, - utils::{ - find_action, - get_conn, - now, - uplete, - DbPool, - }, + utils::{find_action, get_conn, now, uplete, DbPool}, }; use diesel::{ dsl::{exists, insert_into}, diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs index 446e75056..d6d252f30 100644 --- a/crates/db_schema/src/impls/person.rs +++ b/crates/db_schema/src/impls/person.rs @@ -10,15 +10,7 @@ use crate::{ PersonUpdateForm, }, traits::{ApubActor, Crud, Followable}, - utils::{ - action_query, - functions::lower, - get_conn, - naive_now, - now, - uplete, - DbPool, - }, + utils::{action_query, functions::lower, get_conn, naive_now, now, uplete, DbPool}, }; use diesel::{ dsl::insert_into, @@ -247,7 +239,7 @@ mod tests { person::{Person, PersonFollower, PersonFollowerForm, PersonInsertForm, PersonUpdateForm}, }, traits::{Crud, Followable}, - utils::{build_db_pool_for_tests, uplete::uplete::Count}, + utils::{build_db_pool_for_tests, uplete::Count}, }; use pretty_assertions::assert_eq; use serial_test::serial; diff --git a/crates/db_schema/src/impls/person_block.rs b/crates/db_schema/src/impls/person_block.rs index 4ca0f682e..12c484f06 100644 --- a/crates/db_schema/src/impls/person_block.rs +++ b/crates/db_schema/src/impls/person_block.rs @@ -3,13 +3,7 @@ use crate::{ schema::person_actions, source::person_block::{PersonBlock, PersonBlockForm}, traits::Blockable, - utils::{ - find_action, - get_conn, - now, - uplete, - DbPool, - }, + utils::{find_action, get_conn, now, uplete, DbPool}, }; use diesel::{ dsl::{exists, insert_into}, @@ -64,9 +58,11 @@ impl Blockable for PersonBlock { person_block_form: &Self::Form, ) -> Result { let conn = &mut get_conn(pool).await?; - uplete::new(person_actions::table.find((person_block_form.person_id, person_block_form.target_id))) - .set_null(person_actions::blocked) - .get_result(conn) - .await + uplete::new( + person_actions::table.find((person_block_form.person_id, person_block_form.target_id)), + ) + .set_null(person_actions::blocked) + .get_result(conn) + .await } } diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index 46e2e870e..fe6637935 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -415,7 +415,7 @@ mod tests { }, }, traits::{Crud, Likeable, Saveable}, - utils::{build_db_pool_for_tests, uplete::uplete::Count}, + utils::{build_db_pool_for_tests, uplete::Count}, }; use pretty_assertions::assert_eq; use serial_test::serial; diff --git a/crates/db_schema/src/traits.rs b/crates/db_schema/src/traits.rs index d9b64114a..c6f70cb72 100644 --- a/crates/db_schema/src/traits.rs +++ b/crates/db_schema/src/traits.rs @@ -1,7 +1,7 @@ use crate::{ diesel::OptionalExtension, newtypes::{CommunityId, DbUrl, PersonId}, - utils::{get_conn, uplete::uplete::Count, DbPool}, + utils::{get_conn, uplete::Count, DbPool}, }; use diesel::{ associations::HasTable, From d124a58b6f046a3f3b60c8115f91f68d9189f879 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 20:42:06 -0700 Subject: [PATCH 207/232] fix --- crates/db_schema/src/impls/comment.rs | 2 +- crates/db_schema/src/impls/community.rs | 2 +- crates/db_schema/src/impls/person.rs | 2 +- crates/db_schema/src/impls/post.rs | 2 +- crates/db_schema/src/traits.rs | 2 +- crates/db_views/src/vote_view.rs | 4 ++-- crates/db_views_actor/src/comment_reply_view.rs | 2 +- crates/db_views_actor/src/person_mention_view.rs | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index d7a0aa10f..280f8ae85 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -244,7 +244,7 @@ mod tests { post::{Post, PostInsertForm}, }, traits::{Crud, Likeable, Saveable}, - utils::{build_db_pool_for_tests, uplete::Count}, + utils::{build_db_pool_for_tests, uplete}, }; use diesel_ltree::Ltree; use pretty_assertions::assert_eq; diff --git a/crates/db_schema/src/impls/community.rs b/crates/db_schema/src/impls/community.rs index a6c1d76bb..2d49a01f6 100644 --- a/crates/db_schema/src/impls/community.rs +++ b/crates/db_schema/src/impls/community.rs @@ -453,7 +453,7 @@ mod tests { person::{Person, PersonInsertForm}, }, traits::{Bannable, Crud, Followable, Joinable}, - utils::{build_db_pool_for_tests, uplete::Count}, + utils::{build_db_pool_for_tests, uplete}, CommunityVisibility, }; use pretty_assertions::assert_eq; diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs index d6d252f30..cdf183cb0 100644 --- a/crates/db_schema/src/impls/person.rs +++ b/crates/db_schema/src/impls/person.rs @@ -239,7 +239,7 @@ mod tests { person::{Person, PersonFollower, PersonFollowerForm, PersonInsertForm, PersonUpdateForm}, }, traits::{Crud, Followable}, - utils::{build_db_pool_for_tests, uplete::Count}, + utils::{build_db_pool_for_tests, uplete}, }; use pretty_assertions::assert_eq; use serial_test::serial; diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index fe6637935..bebdd57fe 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -415,7 +415,7 @@ mod tests { }, }, traits::{Crud, Likeable, Saveable}, - utils::{build_db_pool_for_tests, uplete::Count}, + utils::{build_db_pool_for_tests, uplete}, }; use pretty_assertions::assert_eq; use serial_test::serial; diff --git a/crates/db_schema/src/traits.rs b/crates/db_schema/src/traits.rs index c6f70cb72..300e2e2bc 100644 --- a/crates/db_schema/src/traits.rs +++ b/crates/db_schema/src/traits.rs @@ -1,7 +1,7 @@ use crate::{ diesel::OptionalExtension, newtypes::{CommunityId, DbUrl, PersonId}, - utils::{get_conn, uplete::Count, DbPool}, + utils::{get_conn, uplete, DbPool}, }; use diesel::{ associations::HasTable, diff --git a/crates/db_views/src/vote_view.rs b/crates/db_views/src/vote_view.rs index 6cb4c8c87..0a0748df8 100644 --- a/crates/db_views/src/vote_view.rs +++ b/crates/db_views/src/vote_view.rs @@ -183,8 +183,8 @@ mod tests { // Timothy votes down his own comment let timmy_comment_vote_form = CommentLikeForm { - comment_id: inserted_comment.id, post_id: inserted_post.id, + comment_id: inserted_comment.id, person_id: inserted_timmy.id, score: -1, }; @@ -194,8 +194,8 @@ mod tests { // Sara upvotes timmy's comment let sara_comment_vote_form = CommentLikeForm { - comment_id: inserted_comment.id, post_id: inserted_post.id, + comment_id: inserted_comment.id, person_id: inserted_sara.id, score: 1, }; diff --git a/crates/db_views_actor/src/comment_reply_view.rs b/crates/db_views_actor/src/comment_reply_view.rs index 1c8b576e9..a20c72f6c 100644 --- a/crates/db_views_actor/src/comment_reply_view.rs +++ b/crates/db_views_actor/src/comment_reply_view.rs @@ -188,7 +188,7 @@ impl CommentReplyView { } query - // Dont count replies from blocked users + // Don't count replies from blocked users .filter(person_actions::blocked.is_null()) .filter(comment_reply::recipient_id.eq(local_user.person_id)) .filter(comment_reply::read.eq(false)) diff --git a/crates/db_views_actor/src/person_mention_view.rs b/crates/db_views_actor/src/person_mention_view.rs index cbd513f73..3e25bbf7d 100644 --- a/crates/db_views_actor/src/person_mention_view.rs +++ b/crates/db_views_actor/src/person_mention_view.rs @@ -189,7 +189,7 @@ impl PersonMentionView { } query - // Dont count replies from blocked users + // Don't count replies from blocked users .filter(person_actions::blocked.is_null()) .filter(person_mention::recipient_id.eq(local_user.person_id)) .filter(person_mention::read.eq(false)) From c72ec047daddf96d7c4439ac38c34d9df3a5c3d4 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 20:52:00 -0700 Subject: [PATCH 208/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index f02bc59e0..2ab2173dd 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -61,16 +61,15 @@ where fn as_query(self) -> Self::Query { let table = Q::Table::default(); + let primary_key_columns = table.primary_key().into_array(); let deletion_condition = || { AllNull( Q::Table::all_columns() .into_array() .into_iter() .filter(|c: DynColumn| { - table - .primary_key() - .into_array() - .into_iter() + primary_key_columns + .iter() .chain(&self.set_null_columns) .all(|excluded_column| excluded_column.type_id() != c.type_id()) }) From 2aaddb1b8def49e9b9553413f637d5da53777284 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 20:59:41 -0700 Subject: [PATCH 209/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 2ab2173dd..4f3b415bb 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -49,7 +49,7 @@ where Q::Table: Default + QueryFragment + Send + 'static, ::PrimaryKey: IntoArray + QueryFragment + Send + 'static, ::AllColumns: IntoArray, - <::PrimaryKey as IntoArray>::Output: IntoIterator, + <::PrimaryKey as IntoArray>::Output: AsRef<[DynColumn]>, <::AllColumns as IntoArray>::Output: IntoIterator, Q: Clone + FilterDsl + FilterDsl>, dsl::Filter: QueryFragment + Send + 'static, @@ -69,6 +69,7 @@ where .into_iter() .filter(|c: DynColumn| { primary_key_columns + .as_ref() .iter() .chain(&self.set_null_columns) .all(|excluded_column| excluded_column.type_id() != c.type_id()) From fa312c2b1dcd98667c501551a4e028bd3dbb8512 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 29 May 2024 21:11:42 -0700 Subject: [PATCH 210/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 4f3b415bb..83057370e 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -67,7 +67,7 @@ where Q::Table::all_columns() .into_array() .into_iter() - .filter(|c: DynColumn| { + .filter(|c: &DynColumn| { primary_key_columns .as_ref() .iter() From 4b0c0598c674702de01382b8ff45113c2ca28c8d Mon Sep 17 00:00:00 2001 From: dullbananas Date: Thu, 30 May 2024 05:59:18 -0700 Subject: [PATCH 211/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 83057370e..472380d08 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -60,8 +60,8 @@ where type SqlType = (sql_types::BigInt, sql_types::BigInt); fn as_query(self) -> Self::Query { - let table = Q::Table::default(); - let primary_key_columns = table.primary_key().into_array(); + let table = Q::Table::default; + let primary_key_columns = table().primary_key().into_array(); let deletion_condition = || { AllNull( Q::Table::all_columns() @@ -89,8 +89,8 @@ where // statement: only the update is performed." update_subquery: Box::new(self.query.clone().filter(dsl::not(deletion_condition()))), delete_subquery: Box::new(self.query.filter(deletion_condition())), - table: Box::new(table), - primary_key: Box::new(table.primary_key()), + table: Box::new(table()), + primary_key: Box::new(table().primary_key()), set_null_columns: self.set_null_columns, } } From 102f4b35660c2856b133a59cf49e9a9e133765d7 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Thu, 30 May 2024 10:29:33 -0700 Subject: [PATCH 212/232] fix --- crates/db_views/src/comment_view.rs | 1 - crates/db_views/src/post_view.rs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs index c2b171778..8d81f1ec2 100644 --- a/crates/db_views/src/comment_view.rs +++ b/crates/db_views/src/comment_view.rs @@ -32,7 +32,6 @@ use lemmy_db_schema::{ utils::{ actions, actions_alias, - functions::coalesce, fuzzy_search, limit_and_offset, DbConn, diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index ec3bfd01c..9f7d66962 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -60,8 +60,8 @@ fn queries<'a>() -> Queries< impl ListFn<'a, PostView, (PostQuery<'a>, &'a Site)>, > { let creator_is_admin = exists( - post::table.filter( - comment::creator_id + local_user::table.filter( + post_aggregates::creator_id .eq(local_user::person_id) .and(local_user::admin.eq(true)), ), From 3ee0beca3dcdb00a318c375df9c33847b84cfcea Mon Sep 17 00:00:00 2001 From: dullbananas Date: Thu, 30 May 2024 10:48:09 -0700 Subject: [PATCH 213/232] fix test --- crates/db_schema/src/impls/comment.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index 280f8ae85..426e11ca9 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -348,7 +348,6 @@ mod tests { let expected_comment_saved = CommentSaved { comment_id: inserted_comment.id, - post_id: inserted_post.id, person_id: inserted_person.id, published: inserted_comment_saved.published, }; From ba13257618f8a75129aa4e4f249a72e8e7b0ad3c Mon Sep 17 00:00:00 2001 From: dullbananas Date: Thu, 30 May 2024 11:52:54 -0700 Subject: [PATCH 214/232] fix db_views_actor imports --- crates/db_views_actor/src/comment_reply_view.rs | 5 +++-- crates/db_views_actor/src/person_mention_view.rs | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/db_views_actor/src/comment_reply_view.rs b/crates/db_views_actor/src/comment_reply_view.rs index a20c72f6c..398c32ae8 100644 --- a/crates/db_views_actor/src/comment_reply_view.rs +++ b/crates/db_views_actor/src/comment_reply_view.rs @@ -1,9 +1,11 @@ use crate::structs::CommentReplyView; use diesel::{ - dsl::exists, + dsl::{exists, not}, pg::Pg, result::Error, + BoolExpressionMethods, ExpressionMethods, + JoinOnDsl, NullableExpressionMethods, QueryDsl, }; @@ -27,7 +29,6 @@ use lemmy_db_schema::{ utils::{ actions, actions_alias, - functions::coalesce, get_conn, limit_and_offset, DbConn, diff --git a/crates/db_views_actor/src/person_mention_view.rs b/crates/db_views_actor/src/person_mention_view.rs index 3e25bbf7d..69ad2b281 100644 --- a/crates/db_views_actor/src/person_mention_view.rs +++ b/crates/db_views_actor/src/person_mention_view.rs @@ -1,9 +1,11 @@ use crate::structs::PersonMentionView; use diesel::{ - dsl::exists, + dsl::{exists, not}, pg::Pg, result::Error, + BoolExpressionMethods, ExpressionMethods, + JoinOnDsl, NullableExpressionMethods, QueryDsl, }; @@ -27,7 +29,6 @@ use lemmy_db_schema::{ utils::{ actions, actions_alias, - functions::coalesce, get_conn, limit_and_offset, DbConn, From 37f34063d21812f52d09e2558603dc84a19d49ff Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Thu, 30 May 2024 19:13:02 +0000 Subject: [PATCH 215/232] fix uplete import in post_view test --- crates/db_views/src/post_view.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 9f7d66962..2e9107922 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -613,7 +613,7 @@ mod tests { site::Site, }, traits::{Bannable, Blockable, Crud, Joinable, Likeable}, - utils::{build_db_pool, build_db_pool_for_tests, uplete::UpleteCount, DbPool, RANK_DEFAULT}, + utils::{build_db_pool, build_db_pool_for_tests, uplete, DbPool, RANK_DEFAULT}, CommunityVisibility, SortType, SubscribedType, @@ -953,7 +953,7 @@ mod tests { let like_removed = PostLike::remove(pool, data.local_user_view.person.id, data.inserted_post.id).await?; - assert_eq!(UpleteCount::only_deleted(1), like_removed); + assert_eq!(uplete::Count::only_deleted(1), like_removed); cleanup(data, pool).await } From ae7838e78be7baefa41cada13947689b32501678 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Thu, 30 May 2024 12:30:57 -0700 Subject: [PATCH 216/232] rerun ci --- crates/db_schema/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/Cargo.toml b/crates/db_schema/Cargo.toml index 79e15dba3..f8f35517f 100644 --- a/crates/db_schema/Cargo.toml +++ b/crates/db_schema/Cargo.toml @@ -38,8 +38,8 @@ full = [ "tokio-postgres-rustls", "rustls", "i-love-jesus", - "diesel-bind-if-some", "tuplex", + "diesel-bind-if-some", ] [dependencies] From 334c0f612e72b859f7e02ecdd0245e5287b9f900 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Thu, 30 May 2024 14:00:24 -0700 Subject: [PATCH 217/232] fix AllNull syntax error --- crates/db_schema/src/utils/uplete.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 472380d08..639f76c10 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -170,12 +170,12 @@ impl ValidGrouping<()> for AllNull { impl QueryFragment for AllNull { fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> Result<(), Error> { - let mut item_prefix = "("; + // Must produce a valid expression even if `self.0` is empty + out.push_sql("(TRUE"); for column in &self.0 { - out.push_sql(item_prefix); + out.push_sql(" AND "); column.0.walk_ast(out.reborrow())?; out.push_sql(" IS NOT NULL"); - item_prefix = " AND "; } out.push_sql(")"); From acfc3a02a1c7fe0cc85f9e8b5666c2875673e31c Mon Sep 17 00:00:00 2001 From: dullbananas Date: Thu, 30 May 2024 16:57:24 -0700 Subject: [PATCH 218/232] fix DynColumn --- crates/db_schema/src/utils/uplete.rs | 58 +++++++++++++++------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 639f76c10..383ee7d4c 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -11,7 +11,7 @@ use diesel::{ Expression, Table, }; -use std::any::Any; +use std::any::TypeId; use tuplex::IntoArray; /// Set columns (each specified with `UpleteBuilder::set_null`) to null in the rows found by @@ -49,7 +49,7 @@ where Q::Table: Default + QueryFragment + Send + 'static, ::PrimaryKey: IntoArray + QueryFragment + Send + 'static, ::AllColumns: IntoArray, - <::PrimaryKey as IntoArray>::Output: AsRef<[DynColumn]>, + <::PrimaryKey as IntoArray>::Output: IntoIterator, <::AllColumns as IntoArray>::Output: IntoIterator, Q: Clone + FilterDsl + FilterDsl>, dsl::Filter: QueryFragment + Send + 'static, @@ -61,22 +61,20 @@ where fn as_query(self) -> Self::Query { let table = Q::Table::default; - let primary_key_columns = table().primary_key().into_array(); - let deletion_condition = || { - AllNull( - Q::Table::all_columns() - .into_array() - .into_iter() - .filter(|c: &DynColumn| { - primary_key_columns - .as_ref() - .iter() - .chain(&self.set_null_columns) - .all(|excluded_column| excluded_column.type_id() != c.type_id()) - }) - .collect::>(), - ) - }; + let deletion_condition = AllNull( + Q::Table::all_columns() + .into_array() + .into_iter() + .filter(|c: DynColumn| { + table() + .primary_key() + .into_array(); + .into_iter() + .chain(self.set_null_columns.iter().copied()) + .all(|excluded_column| excluded_column.type_id != c.type_id) + }) + .collect::>(), + ); UpleteQuery { // Updated rows and deleted rows must not overlap, so updating all rows and using the returned // new rows to determine which ones to delete is not an option. @@ -87,8 +85,8 @@ where // the modifications takes place, but it is not easy (and sometimes not possible) to reliably // predict which one. This also applies to deleting a row that was already updated in the same // statement: only the update is performed." - update_subquery: Box::new(self.query.clone().filter(dsl::not(deletion_condition()))), - delete_subquery: Box::new(self.query.filter(deletion_condition())), + update_subquery: Box::new(self.query.clone().filter(dsl::not(deletion_condition.clone()))), + delete_subquery: Box::new(self.query.filter(deletion_condition)), table: Box::new(table()), primary_key: Box::new(table().primary_key()), set_null_columns: self.set_null_columns, @@ -135,7 +133,7 @@ impl QueryFragment for UpleteQuery { let mut item_prefix = " SET "; for column in &self.set_null_columns { out.push_sql(item_prefix); - column.0.walk_ast(out.reborrow())?; + out.push_identifier(column.name)?; out.push_sql(" = NULL"); item_prefix = ","; } @@ -158,6 +156,7 @@ impl QueryFragment for UpleteQuery { } } +#[derive(Clone)] pub struct AllNull(Vec); impl Expression for AllNull { @@ -174,7 +173,7 @@ impl QueryFragment for AllNull { out.push_sql("(TRUE"); for column in &self.0 { out.push_sql(" AND "); - column.0.walk_ast(out.reborrow())?; + out.push_identifier(column.name)?; out.push_sql(" IS NOT NULL"); } out.push_sql(")"); @@ -183,11 +182,18 @@ impl QueryFragment for AllNull { } } -pub struct DynColumn(Box + Send + 'static>); +#[derive(Clone)] +pub struct DynColumn { + type_id: TypeId, + name: &'static str, +}; -impl + Send + 'static> From for DynColumn { - fn from(value: T) -> Self { - DynColumn(Box::new(value)) +impl From for DynColumn { + fn from(_value: T) -> Self { + DynColumn { + type_id: TypeId::of::(), + name: T::NAME, + } } } From 314f336e67831c7aecf9de9123ff23e2bfd48ab1 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Thu, 30 May 2024 17:08:59 -0700 Subject: [PATCH 219/232] Fix rust syntax --- crates/db_schema/src/utils/uplete.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 383ee7d4c..5fe466fdb 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -68,7 +68,7 @@ where .filter(|c: DynColumn| { table() .primary_key() - .into_array(); + .into_array() .into_iter() .chain(self.set_null_columns.iter().copied()) .all(|excluded_column| excluded_column.type_id != c.type_id) @@ -186,7 +186,7 @@ impl QueryFragment for AllNull { pub struct DynColumn { type_id: TypeId, name: &'static str, -}; +} impl From for DynColumn { fn from(_value: T) -> Self { From 542ad8e6804f6f23c1bfa7054b321fad6d97b3e5 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Thu, 30 May 2024 17:14:17 -0700 Subject: [PATCH 220/232] fmt --- crates/db_schema/src/utils/uplete.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 5fe466fdb..9be89a8b0 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -85,7 +85,12 @@ where // the modifications takes place, but it is not easy (and sometimes not possible) to reliably // predict which one. This also applies to deleting a row that was already updated in the same // statement: only the update is performed." - update_subquery: Box::new(self.query.clone().filter(dsl::not(deletion_condition.clone()))), + update_subquery: Box::new( + self + .query + .clone() + .filter(dsl::not(deletion_condition.clone())), + ), delete_subquery: Box::new(self.query.filter(deletion_condition)), table: Box::new(table()), primary_key: Box::new(table().primary_key()), From d469e9ad82784579fd6660b423f63544103a8445 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Thu, 30 May 2024 17:27:41 -0700 Subject: [PATCH 221/232] fix iter --- crates/db_schema/src/utils/uplete.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 9be89a8b0..ea9bc41c2 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -70,7 +70,7 @@ where .primary_key() .into_array() .into_iter() - .chain(self.set_null_columns.iter().copied()) + .chain(self.set_null_columns.iter().cloned()) .all(|excluded_column| excluded_column.type_id != c.type_id) }) .collect::>(), From 82cae91d72e2fc739f910746c1d8dc7af562bbe5 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Fri, 31 May 2024 16:56:04 +0000 Subject: [PATCH 222/232] pain --- Cargo.lock | 9 +++++++++ .../apub/src/collections/community_moderators.rs | 14 +++++++++++++- crates/db_schema/src/schema.rs | 1 + crates/db_schema/src/utils/uplete.rs | 14 ++++++++------ .../db_views_actor/src/community_moderator_view.rs | 2 ++ .../up.sql | 2 +- 6 files changed, 34 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 716525950..42bcf79ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1548,6 +1548,8 @@ dependencies = [ [[package]] name = "diesel-bind-if-some" version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ed8ce9db476124d2eaf4c9db45dc6581b8e8c4c4d47d5e0f39de1fb55dfb2a7" dependencies = [ "diesel", ] @@ -2919,6 +2921,7 @@ dependencies = [ "tokio-postgres-rustls", "tracing", "ts-rs", + "tuplex", "typed-builder", "url", "uuid", @@ -6262,6 +6265,12 @@ dependencies = [ "termcolor", ] +[[package]] +name = "tuplex" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "676ac81d5454c4dcf37955d34fa8626ede3490f744b86ca14a7b90168d2a08aa" + [[package]] name = "typed-builder" version = "0.18.2" diff --git a/crates/apub/src/collections/community_moderators.rs b/crates/apub/src/collections/community_moderators.rs index 02b912f44..4a55a3173 100644 --- a/crates/apub/src/collections/community_moderators.rs +++ b/crates/apub/src/collections/community_moderators.rs @@ -69,7 +69,19 @@ impl Collection for ApubCommunityModerators { community_id: mod_user.community.id, person_id: mod_user.moderator.id, }; - CommunityModerator::leave(&mut data.pool(), &community_moderator_form).await?; + let c = CommunityModerator::leave(&mut data.pool(), &community_moderator_form).await?; + assert_eq!(c.deleted + c.updated, 1); + } + } + for mod_user in ¤t_moderators { + let mod_id = ObjectId::from(mod_user.moderator.actor_id.clone()); + if !apub.ordered_items.contains(&mod_id) { + let community_moderator_form = CommunityModeratorForm { + community_id: mod_user.community.id, + person_id: mod_user.moderator.id, + }; + let c = CommunityModerator::leave(&mut data.pool(), &community_moderator_form).await?; + panic!("pain"); } } diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 2ed170b0e..1c6652ee6 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -102,6 +102,7 @@ diesel::table! { comment_actions (person_id, comment_id) { person_id -> Int4, comment_id -> Int4, + post_id -> Nullable, like_score -> Nullable, liked -> Nullable, saved -> Nullable, diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index ea9bc41c2..015068fc6 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -65,7 +65,7 @@ where Q::Table::all_columns() .into_array() .into_iter() - .filter(|c: DynColumn| { + .filter(|c: &DynColumn| { table() .primary_key() .into_array() @@ -129,7 +129,7 @@ impl QueryFragment for UpleteQuery { out.push_sql(prefix); out.push_sql(" AS ("); subquery.walk_ast(out.reborrow())?; - out.push_sql(" FOR UPDATE)"); + out.push_sql(" )"); } // Update rows that are referenced in `update_keys` @@ -154,8 +154,10 @@ impl QueryFragment for UpleteQuery { out.push_sql(") = ANY (SELECT * FROM update_keys) RETURNING 1)"); // Count updated rows and deleted rows (`RETURNING 1` makes this possible) - out.push_sql(" SELECT (SELECT count(*) FROM update_result)"); - out.push_sql(", (SELECT count(*) FROM delete_result)"); + //out.push_sql(" SELECT (SELECT count(*) FROM update_result)"); + //out.push_sql(", (SELECT count(*) FROM delete_result)"); + out.push_sql(" SELECT (SELECT count(*) FROM update_keys)"); + out.push_sql(", (SELECT count(*) FROM delete_keys)"); Ok(()) } @@ -177,9 +179,9 @@ impl QueryFragment for AllNull { // Must produce a valid expression even if `self.0` is empty out.push_sql("(TRUE"); for column in &self.0 { - out.push_sql(" AND "); + out.push_sql(" AND ("); out.push_identifier(column.name)?; - out.push_sql(" IS NOT NULL"); + out.push_sql(" IS NULL)"); } out.push_sql(")"); diff --git a/crates/db_views_actor/src/community_moderator_view.rs b/crates/db_views_actor/src/community_moderator_view.rs index e145394d4..0c1b81508 100644 --- a/crates/db_views_actor/src/community_moderator_view.rs +++ b/crates/db_views_actor/src/community_moderator_view.rs @@ -40,11 +40,13 @@ impl CommunityModeratorView { pool: &mut DbPool<'_>, community_id: CommunityId, ) -> Result, Error> { + use diesel::NullableExpressionMethods; let conn = &mut get_conn(pool).await?; action_query(community_actions::became_moderator) .inner_join(community::table) .inner_join(person::table) .filter(community_actions::community_id.eq(community_id)) + .filter(community_actions::became_moderator.is_not_null()) .select((community::all_columns, person::all_columns)) .order_by(community_actions::became_moderator) .load::(conn) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql index daeabaa28..e9127d11a 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql +++ b/migrations/2024-03-17-134311_smoosh-tables-together/up.sql @@ -53,7 +53,7 @@ ALTER TABLE community_actions ADD COLUMN received_ban timestamptz, ADD COLUMN ban_expires timestamptz, ADD CONSTRAINT community_actions_check_followed CHECK ((followed IS NULL) = (follow_pending IS NULL)), - ADD CONSTRAINT community_actions_check_received_ban CHECK ((received_ban IS NULL, ban_expires IS NULL) != (FALSE, TRUE)); + ADD CONSTRAINT community_actions_check_received_ban CHECK ((received_ban IS NULL, ban_expires IS NULL) != (TRUE, FALSE)); ALTER TABLE instance_actions ALTER COLUMN blocked DROP NOT NULL, From c9482401a94d4dd7c2d0b5d48525fbce36af680b Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 31 May 2024 10:32:30 -0700 Subject: [PATCH 223/232] Update community_moderators.rs --- crates/apub/src/collections/community_moderators.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/apub/src/collections/community_moderators.rs b/crates/apub/src/collections/community_moderators.rs index 4a55a3173..1845b4f42 100644 --- a/crates/apub/src/collections/community_moderators.rs +++ b/crates/apub/src/collections/community_moderators.rs @@ -73,14 +73,11 @@ impl Collection for ApubCommunityModerators { assert_eq!(c.deleted + c.updated, 1); } } + let current_moderators = + CommunityModeratorView::for_community(&mut data.pool(), community_id).await?; for mod_user in ¤t_moderators { let mod_id = ObjectId::from(mod_user.moderator.actor_id.clone()); if !apub.ordered_items.contains(&mod_id) { - let community_moderator_form = CommunityModeratorForm { - community_id: mod_user.community.id, - person_id: mod_user.moderator.id, - }; - let c = CommunityModerator::leave(&mut data.pool(), &community_moderator_form).await?; panic!("pain"); } } From ee1de0e20f9d8900d2fc948b56ff19a1b9c63e78 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 31 May 2024 10:46:06 -0700 Subject: [PATCH 224/232] Update community_moderator_view.rs --- crates/db_views_actor/src/community_moderator_view.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/db_views_actor/src/community_moderator_view.rs b/crates/db_views_actor/src/community_moderator_view.rs index 0c1b81508..a1a01c5d3 100644 --- a/crates/db_views_actor/src/community_moderator_view.rs +++ b/crates/db_views_actor/src/community_moderator_view.rs @@ -40,7 +40,6 @@ impl CommunityModeratorView { pool: &mut DbPool<'_>, community_id: CommunityId, ) -> Result, Error> { - use diesel::NullableExpressionMethods; let conn = &mut get_conn(pool).await?; action_query(community_actions::became_moderator) .inner_join(community::table) From 7fc191322a93504ae2cec44d278d459220a65c89 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 31 May 2024 11:21:21 -0700 Subject: [PATCH 225/232] Update uplete.rs --- crates/db_schema/src/utils/uplete.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index 015068fc6..c2964686b 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -154,10 +154,10 @@ impl QueryFragment for UpleteQuery { out.push_sql(") = ANY (SELECT * FROM update_keys) RETURNING 1)"); // Count updated rows and deleted rows (`RETURNING 1` makes this possible) - //out.push_sql(" SELECT (SELECT count(*) FROM update_result)"); - //out.push_sql(", (SELECT count(*) FROM delete_result)"); - out.push_sql(" SELECT (SELECT count(*) FROM update_keys)"); - out.push_sql(", (SELECT count(*) FROM delete_keys)"); + out.push_sql(" SELECT (SELECT count(*) FROM update_result)"); + out.push_sql(", (SELECT count(*) FROM delete_result)"); + //out.push_sql(" SELECT (SELECT count(*) FROM update_keys)"); + //out.push_sql(", (SELECT count(*) FROM delete_keys)"); Ok(()) } From 383dc4ae0089dc27e6929f4ddd520ed58f806b7f Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 31 May 2024 11:28:07 -0700 Subject: [PATCH 226/232] Fix mistake found by chatgpt --- crates/db_schema/src/utils/uplete.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index c2964686b..db321db1d 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -151,7 +151,7 @@ impl QueryFragment for UpleteQuery { self.table.walk_ast(out.reborrow())?; out.push_sql(" WHERE ("); self.primary_key.walk_ast(out.reborrow())?; - out.push_sql(") = ANY (SELECT * FROM update_keys) RETURNING 1)"); + out.push_sql(") = ANY (SELECT * FROM delete_keys) RETURNING 1)"); // Count updated rows and deleted rows (`RETURNING 1` makes this possible) out.push_sql(" SELECT (SELECT count(*) FROM update_result)"); From a47106170294348cd91867e23c7a1a718bb97421 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 31 May 2024 14:35:11 -0700 Subject: [PATCH 227/232] revert debugging stuff, change migration date, refactor constraint --- crates/apub/src/collections/community_moderators.rs | 11 +---------- crates/db_schema/src/utils/uplete.rs | 4 +--- crates/db_views_actor/src/community_moderator_view.rs | 1 - .../down.sql | 0 .../up.sql | 2 +- 5 files changed, 3 insertions(+), 15 deletions(-) rename migrations/{2024-03-17-134311_smoosh-tables-together => 2024-05-31-134311_smoosh-tables-together}/down.sql (100%) rename migrations/{2024-03-17-134311_smoosh-tables-together => 2024-05-31-134311_smoosh-tables-together}/up.sql (99%) diff --git a/crates/apub/src/collections/community_moderators.rs b/crates/apub/src/collections/community_moderators.rs index 1845b4f42..02b912f44 100644 --- a/crates/apub/src/collections/community_moderators.rs +++ b/crates/apub/src/collections/community_moderators.rs @@ -69,16 +69,7 @@ impl Collection for ApubCommunityModerators { community_id: mod_user.community.id, person_id: mod_user.moderator.id, }; - let c = CommunityModerator::leave(&mut data.pool(), &community_moderator_form).await?; - assert_eq!(c.deleted + c.updated, 1); - } - } - let current_moderators = - CommunityModeratorView::for_community(&mut data.pool(), community_id).await?; - for mod_user in ¤t_moderators { - let mod_id = ObjectId::from(mod_user.moderator.actor_id.clone()); - if !apub.ordered_items.contains(&mod_id) { - panic!("pain"); + CommunityModerator::leave(&mut data.pool(), &community_moderator_form).await?; } } diff --git a/crates/db_schema/src/utils/uplete.rs b/crates/db_schema/src/utils/uplete.rs index db321db1d..14f52eece 100644 --- a/crates/db_schema/src/utils/uplete.rs +++ b/crates/db_schema/src/utils/uplete.rs @@ -129,7 +129,7 @@ impl QueryFragment for UpleteQuery { out.push_sql(prefix); out.push_sql(" AS ("); subquery.walk_ast(out.reborrow())?; - out.push_sql(" )"); + out.push_sql(" FOR UPDATE)"); } // Update rows that are referenced in `update_keys` @@ -156,8 +156,6 @@ impl QueryFragment for UpleteQuery { // Count updated rows and deleted rows (`RETURNING 1` makes this possible) out.push_sql(" SELECT (SELECT count(*) FROM update_result)"); out.push_sql(", (SELECT count(*) FROM delete_result)"); - //out.push_sql(" SELECT (SELECT count(*) FROM update_keys)"); - //out.push_sql(", (SELECT count(*) FROM delete_keys)"); Ok(()) } diff --git a/crates/db_views_actor/src/community_moderator_view.rs b/crates/db_views_actor/src/community_moderator_view.rs index a1a01c5d3..e145394d4 100644 --- a/crates/db_views_actor/src/community_moderator_view.rs +++ b/crates/db_views_actor/src/community_moderator_view.rs @@ -45,7 +45,6 @@ impl CommunityModeratorView { .inner_join(community::table) .inner_join(person::table) .filter(community_actions::community_id.eq(community_id)) - .filter(community_actions::became_moderator.is_not_null()) .select((community::all_columns, person::all_columns)) .order_by(community_actions::became_moderator) .load::(conn) diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/down.sql b/migrations/2024-05-31-134311_smoosh-tables-together/down.sql similarity index 100% rename from migrations/2024-03-17-134311_smoosh-tables-together/down.sql rename to migrations/2024-05-31-134311_smoosh-tables-together/down.sql diff --git a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql b/migrations/2024-05-31-134311_smoosh-tables-together/up.sql similarity index 99% rename from migrations/2024-03-17-134311_smoosh-tables-together/up.sql rename to migrations/2024-05-31-134311_smoosh-tables-together/up.sql index e9127d11a..ac1b66a20 100644 --- a/migrations/2024-03-17-134311_smoosh-tables-together/up.sql +++ b/migrations/2024-05-31-134311_smoosh-tables-together/up.sql @@ -53,7 +53,7 @@ ALTER TABLE community_actions ADD COLUMN received_ban timestamptz, ADD COLUMN ban_expires timestamptz, ADD CONSTRAINT community_actions_check_followed CHECK ((followed IS NULL) = (follow_pending IS NULL)), - ADD CONSTRAINT community_actions_check_received_ban CHECK ((received_ban IS NULL, ban_expires IS NULL) != (TRUE, FALSE)); + ADD CONSTRAINT community_actions_check_received_ban CHECK (NOT (received_ban IS NULL AND ban_expires IS NOT NULL)); ALTER TABLE instance_actions ALTER COLUMN blocked DROP NOT NULL, From 590542b7f7092ceff15dc1fb024ccfcbe1449c0e Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 31 May 2024 16:38:32 -0700 Subject: [PATCH 228/232] Update down.sql --- migrations/2024-05-31-134311_smoosh-tables-together/down.sql | 4 ---- 1 file changed, 4 deletions(-) diff --git a/migrations/2024-05-31-134311_smoosh-tables-together/down.sql b/migrations/2024-05-31-134311_smoosh-tables-together/down.sql index 38a273747..f7ea48c6f 100644 --- a/migrations/2024-05-31-134311_smoosh-tables-together/down.sql +++ b/migrations/2024-05-31-134311_smoosh-tables-together/down.sql @@ -254,8 +254,6 @@ ALTER INDEX comment_actions_pkey RENAME TO comment_like_pkey; ALTER INDEX idx_comment_actions_comment RENAME TO idx_comment_like_comment; -ALTER INDEX idx_comment_actions_post RENAME TO idx_comment_like_post; - ALTER TABLE comment_like RENAME CONSTRAINT comment_actions_comment_id_fkey TO comment_like_comment_id_fkey; ALTER TABLE comment_like RENAME CONSTRAINT comment_actions_person_id_fkey TO comment_like_person_id_fkey; @@ -298,8 +296,6 @@ CREATE INDEX idx_comment_saved_comment ON comment_saved (comment_id); CREATE INDEX idx_comment_saved_person ON comment_saved (person_id); -CREATE INDEX idx_comment_like_post ON comment_like (post_id); - CREATE INDEX idx_community_block_community ON community_block (community_id); CREATE INDEX idx_community_moderator_community ON community_moderator (community_id); From e1b0e1de3ac9357d5e14ecca496e5ae464ab124e Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 31 May 2024 17:10:03 -0700 Subject: [PATCH 229/232] Update down.sql --- migrations/2024-05-31-134311_smoosh-tables-together/down.sql | 2 -- 1 file changed, 2 deletions(-) diff --git a/migrations/2024-05-31-134311_smoosh-tables-together/down.sql b/migrations/2024-05-31-134311_smoosh-tables-together/down.sql index f7ea48c6f..01cf9ef7e 100644 --- a/migrations/2024-05-31-134311_smoosh-tables-together/down.sql +++ b/migrations/2024-05-31-134311_smoosh-tables-together/down.sql @@ -258,8 +258,6 @@ ALTER TABLE comment_like RENAME CONSTRAINT comment_actions_comment_id_fkey TO co ALTER TABLE comment_like RENAME CONSTRAINT comment_actions_person_id_fkey TO comment_like_person_id_fkey; -ALTER TABLE comment_like RENAME CONSTRAINT comment_actions_post_id_fkey TO comment_like_post_id_fkey; - ALTER INDEX community_actions_pkey RENAME TO community_follower_pkey; ALTER INDEX idx_community_actions_community RENAME TO idx_community_follower_community; From 076262317bc4c548f390d28b704fb03751ac4237 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Tue, 25 Jun 2024 19:37:55 +0000 Subject: [PATCH 230/232] fmt --- crates/db_views_actor/src/community_view.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_views_actor/src/community_view.rs b/crates/db_views_actor/src/community_view.rs index 19c83208f..069fa2215 100644 --- a/crates/db_views_actor/src/community_view.rs +++ b/crates/db_views_actor/src/community_view.rs @@ -15,7 +15,7 @@ use lemmy_db_schema::{ schema::{community, community_actions, community_aggregates, instance_actions}, source::{community::CommunityFollower, local_user::LocalUser, site::Site}, utils::{ - actions, + actions, fuzzy_search, limit_and_offset, visible_communities_only, From f51764327de1f205664084da07c5ae95b0bb27b0 Mon Sep 17 00:00:00 2001 From: Dull Bananas Date: Tue, 2 Jul 2024 17:04:05 +0000 Subject: [PATCH 231/232] make things added to db_schema::utils more understandable --- crates/db_schema/src/utils.rs | 41 +++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index 75c3ecb77..5fe88c885 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -541,8 +541,7 @@ pub fn now() -> AsExprOf { diesel::dsl::now.into_sql::() } -pub type AsRecordOutput = dsl::AsExprOf::SqlType>>; - +/// Trait alias for a type that can be converted to an SQL tuple using `IntoSql::into_sql` pub trait AsRecord: Expression + AsExpression> where Self::SqlType: 'static, @@ -554,8 +553,25 @@ impl>> AsRecord for T { } +/// Output of `IntoSql::into_sql` for a type that implements `AsRecord` +pub type AsRecordOutput = dsl::AsExprOf::SqlType>>; + +/// Output of `t.on((l0, l1).into_sql().eq((r0, r1)))` type OnTupleEq = dsl::On, (R0, R1)>>; +/// Creates an `ON` clause for a table where a person ID and another column are used as the +/// primary key. Use with the `QueryDsl::left_join` method. +/// +/// This example modifies a query to make columns in `community_actions` available: +/// +/// ``` +/// community::table +/// .left_join(actions( +/// community_actions::table, +/// my_person_id, +/// community::id, +/// )) +/// ``` pub fn actions( actions_table: T, person_id: Option

, @@ -585,8 +601,7 @@ pub fn actions_alias( ) -> OnTupleEq, AliasedField, AliasedField, P, C> where Alias: QuerySource + Copy, - T: AliasSource + Default, - T::Target: Table, + T: AliasSource> + Default, K0: Column

, K1: Column
, (AliasedField, AliasedField): AsRecord, @@ -606,34 +621,32 @@ where /// `table_name::table.filter(table_name::action_name.is_not_null())`. pub fn action_query(column: C) -> dsl::Filter> where - C: Column, - C::Table: Default + FilterDsl>, - C::SqlType: SingleValue, + C: Column>, SqlType: SingleValue>, { action_query_with_fn(column, |t| t) } +/// `find_action(table_name::action_name, key)` is the same as +/// `table_name::table.find(key).filter(table_name::action_name.is_not_null())`. pub fn find_action( column: C, key: K, ) -> dsl::Filter, dsl::IsNotNull> where - C: Column, - C::Table: Default + FindDsl, - dsl::Find: FilterDsl>, - C::SqlType: SingleValue, + C: + Column>>, SqlType: SingleValue>, { action_query_with_fn(column, |t| t.find(key)) } +/// `action_query_with_fn(table_name::action_name, f)` is the same as +/// `f(table_name::table).filter(table_name::action_name.is_not_null())`. fn action_query_with_fn( column: C, f: impl FnOnce(C::Table) -> Q, ) -> dsl::Filter> where - C: Column, - C::Table: Default, - C::SqlType: SingleValue, + C: Column, Q: FilterDsl>, { f(C::Table::default()).filter(column.is_not_null()) From 02f0513389761389c69a866a4804e8d6203caeeb Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 2 Jul 2024 16:06:44 -0700 Subject: [PATCH 232/232] update rust version for woodpecker --- .woodpecker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index b77fd6615..744daa173 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -2,7 +2,7 @@ # See https://github.com/woodpecker-ci/woodpecker/issues/1677 variables: - - &rust_image "rust:1.78" + - &rust_image "rust:1.79" - &rust_nightly_image "rustlang/rust:nightly" - &install_pnpm "corepack enable pnpm" - &slow_check_paths