Shrink things that are rewritten in slow migrations (#5874)

* update schema.rs

* Require indexes for all foreign keys (#5872)

* add test

* add migration with missing indexes

* Fix foreign key indexes migration (#5875)

* Allow remote groups to follow Lemmy communities (fixes #5354) (#5864)

* Allow remote groups to follow Lemmy communities (fixes #5354)

* index

* rename columns

* review changes

* primary key

* Prevent stack overflow when fetching nested comment (#5787)

* attempt future wrapper

* Revert "attempt future wrapper"

This reverts commit ce95422228.

* use spawn

* remove `lazy` and change comment

* temporary change for test

* change 5000 back to 50

* fix comment about async laziness

* make columns nullable

* more shrinking

* update utils.sql

* update remove-aggregate-tables migration, and change indexed ranks back to non-null

* rename columns in remove-aggregate-tables migration, and fix later migrations

* remove comment

* optimize rank functions

* stuff

* more migration fixes

* other changes to migrations

* make schema setup tests pass

* stuff

* make tests pass

* crud trait is back

* add todo

* change immutable to stable

* use minutes for age

* clean up

* start cursor refactor

* finish cursor refactor

* remove "get_" prefix

* clean up

* import style consistency

* revert change to translations commit

* use i-love-jesus from crates.io

* remove some non_0_ and non_1_

* revert most changes in the crates folder

* fix column order in structs

* stuff

* fix migrations

* stuff (rust tests now pass)

* rename some vote-related fields

* fix some rust errors to make ts bindings generation work, and rename voteview field

* lint

* change stuff in api_tests to match changes to types

* change translations commit to prevent merge conflict

* rename "is_positive"

* remove like score range check test from post.spec.ts

* uncomment restrict-key thing

* prettier

* rerun ci

* add cfg_attr

* fix "A required parameter cannot follow an optional parameter"

* person_liked_combined: RENAME COLUMN liked_at TO voted_at

* for "newest comment" times: remove "after_published" prefix and don't convert to non-null

* move "voted_at" rename to "rename_timestamp_add_at" migration

* remove added uses of as_select

* fix sql code referencing "liked_at"

* clippy

* restore as_select uses that were already present

* change lemmy-js-client version

---------

Co-authored-by: Nutomic <me@nutomic.com>
Co-authored-by: Dessalines <dessalines@users.noreply.github.com>
Co-authored-by: Dessalines <tyhou13@gmx.com>
This commit is contained in:
dullbananas
2025-10-16 12:22:34 -07:00
committed by GitHub
parent e882f8ca54
commit 64c75868e6
59 changed files with 514 additions and 972 deletions

View File

@@ -31,7 +31,7 @@
"eslint-plugin-prettier": "^5.5.0",
"jest": "^30.0.0",
"joi": "^17.13.3",
"lemmy-js-client": "1.0.0-enum-variants-snake-case.3",
"lemmy-js-client": "1.0.0-bool-vote.2",
"prettier": "^3.5.3",
"ts-jest": "^29.4.0",
"tsoa": "^6.6.0",

View File

@@ -36,8 +36,8 @@ importers:
specifier: ^17.13.3
version: 17.13.3
lemmy-js-client:
specifier: 1.0.0-enum-variants-snake-case.3
version: 1.0.0-enum-variants-snake-case.3
specifier: 1.0.0-bool-vote.2
version: 1.0.0-bool-vote.2
prettier:
specifier: ^3.5.3
version: 3.6.2
@@ -1656,8 +1656,8 @@ packages:
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
lemmy-js-client@1.0.0-enum-variants-snake-case.3:
resolution: {integrity: sha512-IFdDO9KZ7JKfuVJVpb9xqCVZEmZZVnAATFxDiG94RMp0dPAu8wOyD9OcT/nVn7sXmjbuex+3BFwjC2M6TlWj9A==}
lemmy-js-client@1.0.0-bool-vote.2:
resolution: {integrity: sha512-RqePoajuK7WNv63W6FzH4cf+Q5ahNCo6kxriFLS21BsJok9olap4AitgyN6p+swLVFkjIeSj11dCT1Bf8wqt3Q==}
leven@3.1.0:
resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
@@ -4399,7 +4399,7 @@ snapshots:
dependencies:
json-buffer: 3.0.1
lemmy-js-client@1.0.0-enum-variants-snake-case.3:
lemmy-js-client@1.0.0-bool-vote.2:
dependencies:
'@tsoa/runtime': 6.6.0
transitivePeerDependencies:

View File

@@ -292,7 +292,11 @@ test("Unlike a comment", async () => {
expect(gammaComment1?.creator.local).toBe(false);
expect(gammaComment1?.comment.score).toBe(1);
let unlike = await likeComment(alpha, 0, commentRes.comment_view.comment);
let unlike = await likeComment(
alpha,
undefined,
commentRes.comment_view.comment,
);
expect(unlike.comment_view.comment.score).toBe(0);
// Make sure that comment is unliked on beta
@@ -330,7 +334,7 @@ test("Federated comment like", async () => {
throw "Missing beta comment";
}
let like = await likeComment(beta, 1, betaComment.comment);
let like = await likeComment(beta, true, betaComment.comment);
expect(like.comment_view.comment.score).toBe(2);
// Get the post from alpha, check the likes

View File

@@ -169,11 +169,11 @@ test("Unlike a post", async () => {
throw "Missing beta community";
}
let postRes = await createPost(alpha, betaCommunity.community.id);
let unlike = await likePost(alpha, 0, postRes.post_view.post);
let unlike = await likePost(alpha, undefined, postRes.post_view.post);
expect(unlike.post_view.post.score).toBe(0);
// Try to unlike it again, make sure it stays at 0
let unlike2 = await likePost(alpha, 0, postRes.post_view.post);
let unlike2 = await likePost(alpha, undefined, postRes.post_view.post);
expect(unlike2.post_view.post.score).toBe(0);
// Make sure that post is unliked on beta
@@ -190,40 +190,6 @@ test("Unlike a post", async () => {
await assertPostFederation(betaPost, postRes.post_view);
});
test("Make sure like is within range", async () => {
if (!betaCommunity) {
throw "Missing beta community";
}
let postRes = await createPost(alpha, betaCommunity.community.id);
// Try a like with score 2
await expect(
likePost(alpha, 2, postRes.post_view.post),
).rejects.toStrictEqual(
new LemmyError("couldnt_like_post", statusBadRequest),
);
// Try a like with score -2
await expect(
likePost(alpha, -2, postRes.post_view.post),
).rejects.toStrictEqual(
new LemmyError("couldnt_like_post", statusBadRequest),
);
// Make sure that post stayed at 1
const betaPost = await waitForPost(
beta,
postRes.post_view.post,
post => post?.post.score === 1,
);
expect(betaPost).toBeDefined();
expect(betaPost?.community.local).toBe(true);
expect(betaPost?.creator.local).toBe(false);
expect(betaPost?.post.score).toBe(1);
await assertPostFederation(betaPost, postRes.post_view);
});
test("Update a post", async () => {
if (!betaCommunity) {
throw "Missing beta community";

View File

@@ -164,8 +164,8 @@ test("Only followers can view and interact with private community content", asyn
const post1 = await createPost(user, betaCommunity!.id);
expect(post1.post_view).toBeDefined();
const like = await likeComment(user, 1, resolvedComment!.comment);
expect(like.comment_view.comment_actions?.like_score).toBe(1);
const like = await likeComment(user, true, resolvedComment!.comment);
expect(like.comment_view.comment_actions?.vote_is_upvote).toBe(true);
});
test("Reject follower", async () => {

View File

@@ -524,12 +524,12 @@ export async function followCommunity(
export async function likePost(
api: LemmyHttp,
score: number,
is_upvote: boolean | undefined,
post: Post,
): Promise<PostResponse> {
let form: CreatePostLike = {
post_id: post.id,
score: score,
is_upvote: is_upvote,
};
return api.likePost(form);
@@ -588,12 +588,12 @@ export async function removeComment(
export async function likeComment(
api: LemmyHttp,
score: number,
is_upvote: boolean | undefined,
comment: Comment,
): Promise<CommentResponse> {
let form: CreateCommentLike = {
comment_id: comment.id,
score,
is_upvote,
};
return api.likeComment(form);
}

View File

@@ -41,7 +41,7 @@ pub async fn like_comment(
let my_person_id = local_user_view.person.id;
check_local_vote_mode(
data.score,
data.is_upvote,
PostOrCommentId::Comment(comment_id),
&local_site,
my_person_id,
@@ -57,7 +57,7 @@ pub async fn like_comment(
local_instance_id,
)
.await?;
let previous_score = orig_comment.comment_actions.and_then(|p| p.like_score);
let previous_is_upvote = orig_comment.comment_actions.and_then(|p| p.vote_is_upvote);
check_community_user_action(
&local_user_view,
@@ -66,30 +66,29 @@ pub async fn like_comment(
)
.await?;
let mut like_form = CommentLikeForm::new(my_person_id, data.comment_id, data.score);
// Remove any likes first
CommentActions::remove_like(&mut context.pool(), my_person_id, comment_id).await?;
if let Some(previous_score) = previous_score {
if let Some(previous_is_upvote) = previous_is_upvote {
PersonActions::remove_like(
&mut context.pool(),
my_person_id,
orig_comment.creator.id,
previous_score,
previous_is_upvote,
)
.await
// Ignore errors, since a previous_like of zero throws an error
.ok();
}
if like_form.like_score != 0 {
if let Some(is_upvote) = data.is_upvote {
let mut like_form = CommentLikeForm::new(my_person_id, data.comment_id, is_upvote);
like_form = plugin_hook_before("before_comment_vote", like_form).await?;
let like = CommentActions::like(&mut context.pool(), &like_form).await?;
PersonActions::like(
&mut context.pool(),
my_person_id,
orig_comment.creator.id,
like_form.like_score,
like_form.vote_is_upvote,
)
.await?;
@@ -101,8 +100,8 @@ pub async fn like_comment(
object_id: orig_comment.comment.ap_id,
actor: local_user_view.person.clone(),
community: orig_comment.community,
previous_score,
new_score: data.score,
previous_is_upvote,
new_is_upvote: data.is_upvote,
},
&context,
)?;

View File

@@ -41,7 +41,7 @@ pub async fn like_post(
let my_person_id = local_user_view.person.id;
check_local_vote_mode(
data.score,
data.is_upvote,
PostOrCommentId::Post(post_id),
&local_site,
my_person_id,
@@ -59,34 +59,33 @@ pub async fn like_post(
false,
)
.await?;
let previous_score = orig_post.post_actions.and_then(|p| p.like_score);
let previous_is_upvote = orig_post.post_actions.and_then(|p| p.vote_is_upvote);
check_community_user_action(&local_user_view, &orig_post.community, &mut context.pool()).await?;
let mut like_form = PostLikeForm::new(data.post_id, my_person_id, data.score);
// Remove any likes first
PostActions::remove_like(&mut context.pool(), my_person_id, post_id).await?;
if let Some(previous_score) = previous_score {
if let Some(previous_is_upvote) = previous_is_upvote {
PersonActions::remove_like(
&mut context.pool(),
my_person_id,
orig_post.creator.id,
previous_score,
previous_is_upvote,
)
.await
// Ignore errors, since a previous_like of zero throws an error
.ok();
}
if like_form.like_score != 0 {
if let Some(is_upvote) = data.is_upvote {
let mut like_form = PostLikeForm::new(data.post_id, my_person_id, is_upvote);
like_form = plugin_hook_before("before_post_vote", like_form).await?;
let like = PostActions::like(&mut context.pool(), &like_form).await?;
PersonActions::like(
&mut context.pool(),
my_person_id,
orig_post.creator.id,
like_form.like_score,
like_form.vote_is_upvote,
)
.await?;
@@ -102,8 +101,8 @@ pub async fn like_post(
object_id: orig_post.post.ap_id,
actor: local_user_view.person.clone(),
community: orig_post.community.clone(),
previous_score,
new_score: data.score,
previous_is_upvote,
new_is_upvote: data.is_upvote,
},
&context,
)?;

View File

@@ -138,7 +138,7 @@ mod tests {
let post_form_1 = PostInsertForm::new("A test post tubular".into(), sara.id, community.id);
let post_1 = Post::create(pool, &post_form_1).await?;
let post_like_form_1 = PostLikeForm::new(post_1.id, sara.id, 1);
let post_like_form_1 = PostLikeForm::new(post_1.id, sara.id, true);
let _post_like_1 = PostActions::like(pool, &post_like_form_1).await?;
let post_form_2 = PostInsertForm::new("A test post radical".into(), sara.id, community.id);
@@ -148,7 +148,7 @@ mod tests {
CommentInsertForm::new(sara.id, post_1.id, "A test comment tubular".into());
let comment_1 = Comment::create(pool, &comment_form_1, None).await?;
let comment_like_form_1 = CommentLikeForm::new(sara.id, comment_1.id, 1);
let comment_like_form_1 = CommentLikeForm::new(sara.id, comment_1.id, true);
let _comment_like_1 = CommentActions::like(pool, &comment_like_form_1).await?;
let comment_form_2 =
@@ -160,8 +160,8 @@ mod tests {
PostView::read(pool, post_1.id, Some(&sara_local_user), instance.id, false).await?;
assert_eq!(1, post_view_1.post.score);
assert_eq!(
Some(1),
post_view_1.post_actions.and_then(|pa| pa.like_score)
Some(true),
post_view_1.post_actions.and_then(|pa| pa.vote_is_upvote)
);
// Read saras comment to make sure it has a like
@@ -169,8 +169,10 @@ mod tests {
CommentView::read(pool, comment_1.id, Some(&sara_local_user), instance.id).await?;
assert_eq!(1, comment_view_1.post.score);
assert_eq!(
Some(1),
comment_view_1.comment_actions.and_then(|ca| ca.like_score)
Some(true),
comment_view_1
.comment_actions
.and_then(|ca| ca.vote_is_upvote)
);
// Remove the user data
@@ -232,7 +234,10 @@ mod tests {
let post_view_1 =
PostView::read(pool, post_1.id, Some(&sara_local_user), instance.id, false).await?;
assert_eq!(0, post_view_1.post.score);
assert_eq!(None, post_view_1.post_actions.and_then(|pa| pa.like_score));
assert_eq!(
None,
post_view_1.post_actions.and_then(|pa| pa.vote_is_upvote)
);
// comment
let comment_view_1 =
@@ -240,7 +245,9 @@ mod tests {
assert_eq!(0, comment_view_1.post.score);
assert_eq!(
None,
comment_view_1.comment_actions.and_then(|ca| ca.like_score)
comment_view_1
.comment_actions
.and_then(|ca| ca.vote_is_upvote)
);
// Now restore the content, and make sure it got appended

View File

@@ -125,7 +125,7 @@ pub async fn create_comment(
.send(&context);
// You like your own comment by default
let like_form = CommentLikeForm::new(local_user_view.person.id, inserted_comment.id, 1);
let like_form = CommentLikeForm::new(local_user_view.person.id, inserted_comment.id, true);
CommentActions::like(&mut context.pool(), &like_form).await?;

View File

@@ -161,7 +161,7 @@ pub async fn create_post(
// They like their own post by default
let person_id = local_user_view.person.id;
let post_id = inserted_post.id;
let like_form = PostLikeForm::new(post_id, person_id, 1);
let like_form = PostLikeForm::new(post_id, person_id, true);
PostActions::like(&mut context.pool(), &like_form).await?;

View File

@@ -62,8 +62,8 @@ pub enum SendActivityData {
object_id: DbUrl,
actor: Person,
community: Community,
previous_score: Option<i16>,
new_score: i16,
previous_is_upvote: Option<bool>,
new_is_upvote: Option<bool>,
},
FollowCommunity(Community, Person, bool),
FollowMultiCommunity(MultiCommunity, Person, bool),

View File

@@ -311,7 +311,7 @@ pub fn check_comment_deleted_or_removed(comment: &Comment) -> LemmyResult<()> {
}
pub async fn check_local_vote_mode(
score: i16,
is_upvote: Option<bool>,
post_or_comment_id: PostOrCommentId,
local_site: &LocalSite,
person_id: PersonId,
@@ -322,8 +322,8 @@ pub async fn check_local_vote_mode(
PostOrCommentId::Comment(_) => (local_site.comment_downvotes, local_site.comment_upvotes),
};
let downvote_fail = score == -1 && downvote_setting == FederationMode::Disable;
let upvote_fail = score == 1 && upvote_setting == FederationMode::Disable;
let downvote_fail = is_upvote == Some(false) && downvote_setting == FederationMode::Disable;
let upvote_fail = is_upvote == Some(true) && upvote_setting == FederationMode::Disable;
// Undo previous vote for item if new vote fails
if downvote_fail || upvote_fail {

View File

@@ -144,7 +144,7 @@ impl Activity for CreateOrUpdateNote {
let comment = ApubComment::from_json(self.object, context).await?;
// author likes their own comment by default
let like_form = CommentLikeForm::new(comment.creator_id, comment.id, 1);
let like_form = CommentLikeForm::new(comment.creator_id, comment.id, true);
CommentActions::like(&mut context.pool(), &like_form).await?;
// Calculate initial hot_rank

View File

@@ -144,7 +144,7 @@ impl Activity for CreateOrUpdatePage {
let post = ApubPost::from_json(self.object, context).await?;
// author likes their own post by default
let like_form = PostLikeForm::new(post.id, post.creator_id, 1);
let like_form = PostLikeForm::new(post.id, post.creator_id, true);
PostActions::like(&mut context.pool(), &like_form).await?;
// Calculate initial hot_rank for post

View File

@@ -253,15 +253,15 @@ pub async fn match_outgoing_activities(
object_id,
actor,
community,
previous_score,
new_score,
previous_is_upvote,
new_is_upvote,
} => {
send_like_activity(
object_id,
actor,
community,
previous_score,
new_score,
previous_is_upvote,
new_is_upvote,
context,
)
.await

View File

@@ -5,7 +5,7 @@ use lemmy_apub_objects::{
objects::{community::ApubCommunity, person::ApubPerson, PostOrComment},
utils::protocol::InCommunity,
};
use lemmy_utils::error::{LemmyError, LemmyResult, UntranslatedError};
use lemmy_utils::error::LemmyResult;
use serde::{Deserialize, Serialize};
use strum::Display;
use url::Url;
@@ -26,24 +26,19 @@ pub enum VoteType {
Dislike,
}
impl TryFrom<i16> for VoteType {
type Error = LemmyError;
fn try_from(value: i16) -> Result<Self, Self::Error> {
match value {
1 => Ok(VoteType::Like),
-1 => Ok(VoteType::Dislike),
_ => Err(UntranslatedError::InvalidVoteValue.into()),
impl From<bool> for VoteType {
fn from(value: bool) -> Self {
if value {
VoteType::Like
} else {
VoteType::Dislike
}
}
}
impl From<&VoteType> for i16 {
fn from(value: &VoteType) -> i16 {
match value {
VoteType::Like => 1,
VoteType::Dislike => -1,
}
impl From<&VoteType> for bool {
fn from(value: &VoteType) -> Self {
value == &VoteType::Like
}
}

View File

@@ -38,8 +38,8 @@ pub(crate) async fn send_like_activity(
object_id: DbUrl,
actor: Person,
community: Community,
previous_score: Option<i16>,
new_score: i16,
previous_is_upvote: Option<bool>,
new_is_upvote: Option<bool>,
context: Data<LemmyContext>,
) -> LemmyResult<()> {
let object_id: ObjectId<PostOrComment> = object_id.into();
@@ -47,13 +47,13 @@ pub(crate) async fn send_like_activity(
let community: ApubCommunity = community.into();
let empty = ActivitySendTargets::empty();
// score of 1 means upvote, -1 downvote, 0 undo a previous vote
if new_score != 0 {
let vote = Vote::new(object_id, &actor, new_score.try_into()?, &context)?;
if let Some(s) = new_is_upvote {
let vote = Vote::new(object_id, &actor, s.into(), &context)?;
let activity = AnnouncableActivities::Vote(vote);
send_activity_in_community(activity, &actor, &community, empty, false, &context).await
} else {
let previous_vote_type = if previous_score.unwrap_or_default() > 0 {
// undo a previous vote
let previous_vote_type = if previous_is_upvote == Some(true) {
VoteType::Like
} else {
VoteType::Dislike

View File

@@ -13,7 +13,6 @@ use crate::{
utils::{
functions::{coalesce, hot_rank},
get_conn,
validate_like,
DbPool,
DELETED_REPLACEMENT_TEXT,
},
@@ -32,7 +31,7 @@ use diesel_ltree::{dsl::LtreeExtensions, Ltree};
use diesel_uplete::{uplete, UpleteCount};
use lemmy_db_schema_file::schema::{comment, comment_actions, community, post};
use lemmy_utils::{
error::{LemmyErrorExt, LemmyErrorExt2, LemmyErrorType, LemmyResult},
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
settings::structs::Settings,
};
use url::Url;
@@ -316,8 +315,6 @@ impl Likeable for CommentActions {
async fn like(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
let conn = &mut get_conn(pool).await?;
validate_like(form.like_score).with_lemmy_type(LemmyErrorType::CouldntCreate)?;
insert_into(comment_actions::table)
.values(form)
.on_conflict((comment_actions::comment_id, comment_actions::person_id))
@@ -335,8 +332,8 @@ impl Likeable for CommentActions {
) -> LemmyResult<UpleteCount> {
let conn = &mut get_conn(pool).await?;
uplete(comment_actions::table.find((person_id, comment_id)))
.set_null(comment_actions::like_score)
.set_null(comment_actions::liked_at)
.set_null(comment_actions::vote_is_upvote)
.set_null(comment_actions::voted_at)
.get_result(conn)
.await
.with_lemmy_type(LemmyErrorType::CouldntCreate)
@@ -349,8 +346,8 @@ impl Likeable for CommentActions {
let conn = &mut get_conn(pool).await?;
uplete(comment_actions::table.filter(comment_actions::person_id.eq(creator_id)))
.set_null(comment_actions::like_score)
.set_null(comment_actions::liked_at)
.set_null(comment_actions::vote_is_upvote)
.set_null(comment_actions::voted_at)
.get_result(conn)
.await
.with_lemmy_type(LemmyErrorType::CouldntUpdate)
@@ -367,8 +364,8 @@ impl Likeable for CommentActions {
let conn = &mut get_conn(pool).await?;
uplete(comment_actions::table.filter(comment_actions::comment_id.eq_any(comment_ids.clone())))
.set_null(comment_actions::like_score)
.set_null(comment_actions::liked_at)
.set_null(comment_actions::vote_is_upvote)
.set_null(comment_actions::voted_at)
.get_result(conn)
.await
.with_lemmy_type(LemmyErrorType::CouldntUpdate)
@@ -509,10 +506,10 @@ mod tests {
Comment::create(pool, &child_comment_form, Some(&inserted_comment.path)).await?;
// Comment Like
let comment_like_form = CommentLikeForm::new(inserted_person.id, inserted_comment.id, 1);
let comment_like_form = CommentLikeForm::new(inserted_person.id, inserted_comment.id, true);
let inserted_comment_like = CommentActions::like(pool, &comment_like_form).await?;
assert_eq!(Some(1), inserted_comment_like.like_score);
assert_eq!(Some(true), inserted_comment_like.vote_is_upvote);
// Comment Saved
let comment_saved_form = CommentSavedForm::new(inserted_person.id, inserted_comment.id);
@@ -596,7 +593,7 @@ mod tests {
let _inserted_child_comment =
Comment::create(pool, &child_comment_form, Some(&inserted_comment.path)).await?;
let comment_like = CommentLikeForm::new(inserted_person.id, inserted_comment.id, 1);
let comment_like = CommentLikeForm::new(inserted_person.id, inserted_comment.id, true);
CommentActions::like(pool, &comment_like).await?;
@@ -607,7 +604,8 @@ mod tests {
assert_eq!(0, comment_aggs_before_delete.downvotes);
// Add a post dislike from the other person
let comment_dislike = CommentLikeForm::new(another_inserted_person.id, inserted_comment.id, -1);
let comment_dislike =
CommentLikeForm::new(another_inserted_person.id, inserted_comment.id, false);
CommentActions::like(pool, &comment_dislike).await?;

View File

@@ -365,15 +365,11 @@ impl PersonActions {
pool: &mut DbPool<'_>,
person_id: PersonId,
target_id: PersonId,
like_score: i16,
vote_is_upvote: bool,
) -> LemmyResult<Self> {
let conn = &mut get_conn(pool).await?;
let (upvotes_inc, downvotes_inc) = match like_score {
1 => (1, 0),
-1 => (0, 1),
_ => return Err(LemmyErrorType::NotFound.into()),
};
let (upvotes_inc, downvotes_inc) = if vote_is_upvote { (1, 0) } else { (0, 1) };
let voted_at = Utc::now();
@@ -400,20 +396,16 @@ impl PersonActions {
.with_lemmy_type(LemmyErrorType::NotFound)
}
/// Removes a person like. A previous_score of zero throws an error.
/// Removes a person like.
pub async fn remove_like(
pool: &mut DbPool<'_>,
person_id: PersonId,
target_id: PersonId,
previous_score: i16,
previous_is_upvote: bool,
) -> LemmyResult<Self> {
let conn = &mut get_conn(pool).await?;
let (upvotes_inc, downvotes_inc) = match previous_score {
1 => (-1, 0),
-1 => (0, -1),
_ => return Err(LemmyErrorType::NotFound.into()),
};
let (upvotes_inc, downvotes_inc) = if previous_is_upvote { (-1, 0) } else { (0, -1) };
let voted_at = Utc::now();
insert_into(person_actions::table)
@@ -575,7 +567,7 @@ mod tests {
);
let inserted_post = Post::create(pool, &new_post).await?;
let post_like = PostLikeForm::new(inserted_post.id, inserted_person.id, 1);
let post_like = PostLikeForm::new(inserted_post.id, inserted_person.id, true);
let _inserted_post_like = PostActions::like(pool, &post_like).await?;
let comment_form = CommentInsertForm::new(
@@ -585,7 +577,7 @@ mod tests {
);
let inserted_comment = Comment::create(pool, &comment_form, None).await?;
let mut comment_like = CommentLikeForm::new(inserted_person.id, inserted_comment.id, 1);
let mut comment_like = CommentLikeForm::new(inserted_person.id, inserted_comment.id, true);
let _inserted_comment_like = CommentActions::like(pool, &comment_like).await?;
@@ -598,7 +590,7 @@ mod tests {
Comment::create(pool, &child_comment_form, Some(&inserted_comment.path)).await?;
let child_comment_like =
CommentLikeForm::new(another_inserted_person.id, inserted_child_comment.id, 1);
CommentLikeForm::new(another_inserted_person.id, inserted_child_comment.id, true);
let _inserted_child_comment_like = CommentActions::like(pool, &child_comment_like).await?;

View File

@@ -16,7 +16,6 @@ use crate::{
functions::{coalesce, hot_rank, scaled_rank},
get_conn,
now,
validate_like,
DbPool,
DELETED_REPLACEMENT_TEXT,
FETCH_LIMIT_MAX,
@@ -43,7 +42,7 @@ use lemmy_db_schema_file::{
schema::{community, local_user, person, post, post_actions},
};
use lemmy_utils::{
error::{LemmyErrorExt, LemmyErrorExt2, LemmyErrorType, LemmyResult},
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
settings::structs::Settings,
};
use url::Url;
@@ -313,7 +312,10 @@ impl Post {
diesel::update(post::table.find(post_id))
.set((
post::hot_rank.eq(hot_rank(post::score, post::published_at)),
post::hot_rank_active.eq(hot_rank(post::score, post::newest_comment_time_necro_at)),
post::hot_rank_active.eq(hot_rank(
post::score,
coalesce(post::newest_comment_time_necro_at, post::published_at),
)),
post::scaled_rank.eq(scaled_rank(
post::score,
post::published_at,
@@ -349,8 +351,6 @@ impl Likeable for PostActions {
async fn like(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
let conn = &mut get_conn(pool).await?;
validate_like(form.like_score).with_lemmy_type(LemmyErrorType::CouldntCreate)?;
insert_into(post_actions::table)
.values(form)
.on_conflict((post_actions::post_id, post_actions::person_id))
@@ -369,8 +369,8 @@ impl Likeable for PostActions {
) -> LemmyResult<UpleteCount> {
let conn = &mut get_conn(pool).await?;
uplete(post_actions::table.find((person_id, post_id)))
.set_null(post_actions::like_score)
.set_null(post_actions::liked_at)
.set_null(post_actions::vote_is_upvote)
.set_null(post_actions::voted_at)
.get_result(conn)
.await
.with_lemmy_type(LemmyErrorType::CouldntUpdate)
@@ -383,8 +383,8 @@ impl Likeable for PostActions {
let conn = &mut get_conn(pool).await?;
uplete(post_actions::table.filter(post_actions::person_id.eq(person_id)))
.set_null(post_actions::like_score)
.set_null(post_actions::liked_at)
.set_null(post_actions::vote_is_upvote)
.set_null(post_actions::voted_at)
.get_result(conn)
.await
.with_lemmy_type(LemmyErrorType::CouldntUpdate)
@@ -400,8 +400,8 @@ impl Likeable for PostActions {
let conn = &mut get_conn(pool).await?;
uplete(post_actions::table.filter(post_actions::post_id.eq_any(post_ids.clone())))
.set_null(post_actions::like_score)
.set_null(post_actions::liked_at)
.set_null(post_actions::vote_is_upvote)
.set_null(post_actions::voted_at)
.get_result(conn)
.await
.with_lemmy_type(LemmyErrorType::CouldntUpdate)
@@ -533,7 +533,10 @@ impl PostActions {
.with_lemmy_type(LemmyErrorType::NotFound)
}
pub async fn from_cursor(cursor: &PaginationCursor, pool: &mut DbPool<'_>) -> LemmyResult<Self> {
pub async fn from_cursor(
cursor: &PaginationCursor,
pool: &mut DbPool<'_>,
) -> LemmyResult<PostActions> {
let [(_, person_id), (_, post_id)] = cursor.prefixes_and_ids()?;
Self::read(pool, PostId(post_id), PersonId(person_id)).await
}
@@ -688,8 +691,8 @@ mod tests {
score: 1,
hot_rank: RANK_DEFAULT,
hot_rank_active: RANK_DEFAULT,
newest_comment_time_at: inserted_post.published_at,
newest_comment_time_necro_at: inserted_post.published_at,
newest_comment_time_at: None,
newest_comment_time_necro_at: None,
report_count: 0,
scaled_rank: RANK_DEFAULT,
unresolved_report_count: 0,
@@ -697,10 +700,10 @@ mod tests {
};
// Post Like
let post_like_form = PostLikeForm::new(inserted_post.id, inserted_person.id, 1);
let post_like_form = PostLikeForm::new(inserted_post.id, inserted_person.id, true);
let inserted_post_like = PostActions::like(pool, &post_like_form).await?;
assert_eq!(Some(1), inserted_post_like.like_score);
assert_eq!(Some(true), inserted_post_like.vote_is_upvote);
// Post Save
let post_saved_form = PostSavedForm::new(inserted_post.id, inserted_person.id);
@@ -800,7 +803,7 @@ mod tests {
let inserted_child_comment =
Comment::create(pool, &child_comment_form, Some(&inserted_comment.path)).await?;
let post_like = PostLikeForm::new(inserted_post.id, inserted_person.id, 1);
let post_like = PostLikeForm::new(inserted_post.id, inserted_person.id, true);
PostActions::like(pool, &post_like).await?;
@@ -812,7 +815,7 @@ mod tests {
assert_eq!(0, post_aggs_before_delete.downvotes);
// Add a post dislike from the other person
let post_dislike = PostLikeForm::new(inserted_post.id, another_inserted_person.id, -1);
let post_dislike = PostLikeForm::new(inserted_post.id, another_inserted_person.id, false);
PostActions::like(pool, &post_dislike).await?;

View File

@@ -251,9 +251,9 @@ pub type Person2AliasAllColumnsTuple = (
#[cfg(feature = "full")]
/// A helper tuple for more my instance persons actions
pub type MyInstancePersonsActionsAllColumnsTuple = (
AliasedField<aliases::MyInstancePersonsActions, instance_actions::blocked_communities_at>,
AliasedField<aliases::MyInstancePersonsActions, instance_actions::person_id>,
AliasedField<aliases::MyInstancePersonsActions, instance_actions::instance_id>,
AliasedField<aliases::MyInstancePersonsActions, instance_actions::blocked_communities_at>,
AliasedField<aliases::MyInstancePersonsActions, instance_actions::received_ban_at>,
AliasedField<aliases::MyInstancePersonsActions, instance_actions::ban_expires_at>,
AliasedField<aliases::MyInstancePersonsActions, instance_actions::blocked_persons_at>,

View File

@@ -18,10 +18,10 @@ use serde_with::skip_serializing_none;
#[cfg_attr(feature = "full", cursor_keys_module(name = person_liked_combined_keys))]
/// A combined person_liked table.
pub struct PersonLikedCombined {
pub liked_at: DateTime<Utc>,
pub like_score: i16,
pub voted_at: DateTime<Utc>,
pub id: PersonLikedCombinedId,
pub person_id: PersonId,
pub post_id: Option<PostId>,
pub comment_id: Option<CommentId>,
pub id: PersonLikedCombinedId,
pub vote_is_upvote: bool,
}

View File

@@ -34,35 +34,3 @@ pub struct SearchCombined {
pub id: SearchCombinedId,
pub multi_community_id: Option<MultiCommunityId>,
}
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
#[cfg_attr(feature = "full", diesel(table_name = search_combined))]
pub struct SearchCombinedPostInsertForm {
pub published_at: DateTime<Utc>,
pub score: i32,
pub post_id: PostId,
}
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
#[cfg_attr(feature = "full", diesel(table_name = search_combined))]
pub struct SearchCombinedCommentInsertForm {
pub published_at: DateTime<Utc>,
pub score: i32,
pub comment_id: CommentId,
}
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
#[cfg_attr(feature = "full", diesel(table_name = search_combined))]
pub struct SearchCombinedCommunityInsertForm {
pub published_at: DateTime<Utc>,
pub score: i32,
pub community_id: CommunityId,
}
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
#[cfg_attr(feature = "full", diesel(table_name = search_combined))]
pub struct SearchCombinedPersonInsertForm {
pub published_at: DateTime<Utc>,
pub score: i32,
pub person_id: PersonId,
}

View File

@@ -55,9 +55,9 @@ pub struct Comment {
/// The total number of children in this comment branch.
pub child_count: i32,
#[serde(skip)]
pub hot_rank: f64,
pub hot_rank: f32,
#[serde(skip)]
pub controversy_rank: f64,
pub controversy_rank: f32,
pub report_count: i16,
pub unresolved_report_count: i16,
/// If a local user comments in a remote community, the comment is hidden until it is confirmed
@@ -130,16 +130,16 @@ pub struct CommentUpdateForm {
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
#[cfg_attr(feature = "ts-rs", ts(optional_fields, export))]
pub struct CommentActions {
/// When the comment was upvoted or downvoted.
pub voted_at: Option<DateTime<Utc>>,
/// When the comment was saved.
pub saved_at: Option<DateTime<Utc>>,
#[serde(skip)]
pub person_id: PersonId,
#[serde(skip)]
pub comment_id: CommentId,
/// The like / score for the comment.
pub like_score: Option<i16>,
/// When the comment was liked.
pub liked_at: Option<DateTime<Utc>>,
/// When the comment was saved.
pub saved_at: Option<DateTime<Utc>>,
/// True if upvoted, false if downvoted. Upvote is greater than downvote.
pub vote_is_upvote: Option<bool>,
}
#[derive(Clone, derive_new::new)]
@@ -151,9 +151,9 @@ pub struct CommentActions {
pub struct CommentLikeForm {
pub person_id: PersonId,
pub comment_id: CommentId,
pub like_score: i16,
pub vote_is_upvote: bool,
#[new(value = "Utc::now()")]
pub liked_at: DateTime<Utc>,
pub voted_at: DateTime<Utc>,
}
#[derive(derive_new::new)]

View File

@@ -90,13 +90,13 @@ pub struct Community {
/// The number of users with any activity in the last year.
pub users_active_half_year: i32,
#[serde(skip)]
pub hot_rank: f64,
pub hot_rank: f32,
pub subscribers_local: i32,
pub report_count: i16,
pub unresolved_report_count: i16,
/// Number of any interactions over the last month.
#[serde(skip)]
pub interactions_month: i32,
pub report_count: i16,
pub unresolved_report_count: i16,
pub local_removed: bool,
}
@@ -195,17 +195,8 @@ pub struct CommunityUpdateForm {
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
#[cfg_attr(feature = "ts-rs", ts(optional_fields, export))]
pub struct CommunityActions {
#[serde(skip)]
pub person_id: PersonId,
#[serde(skip)]
pub community_id: CommunityId,
/// When the community was followed.
pub followed_at: Option<DateTime<Utc>>,
/// The state of the community follow.
pub follow_state: Option<CommunityFollowerState>,
/// The approver of the community follow.
#[serde(skip)]
pub follow_approver_id: Option<PersonId>,
/// When the community was blocked.
pub blocked_at: Option<DateTime<Utc>>,
/// When this user became a moderator.
@@ -214,6 +205,15 @@ pub struct CommunityActions {
pub received_ban_at: Option<DateTime<Utc>>,
/// When their ban expires.
pub ban_expires_at: Option<DateTime<Utc>>,
#[serde(skip)]
pub person_id: PersonId,
#[serde(skip)]
pub community_id: CommunityId,
/// The state of the community follow.
pub follow_state: Option<CommunityFollowerState>,
/// The approver of the community follow.
#[serde(skip)]
pub follow_approver_id: Option<PersonId>,
pub notifications: Option<CommunityNotificationsMode>,
}

View File

@@ -55,12 +55,12 @@ pub struct InstanceForm {
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
#[cfg_attr(feature = "ts-rs", ts(optional_fields, export))]
pub struct InstanceActions {
/// When the instance's communities were blocked.
pub blocked_communities_at: Option<DateTime<Utc>>,
#[serde(skip)]
pub person_id: PersonId,
#[serde(skip)]
pub instance_id: InstanceId,
/// When the instance's communities were blocked.
pub blocked_communities_at: Option<DateTime<Utc>>,
/// When this user received a site ban.
pub received_ban_at: Option<DateTime<Utc>>,
/// When their ban expires.

View File

@@ -134,16 +134,16 @@ pub struct PersonUpdateForm {
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
#[cfg_attr(feature = "ts-rs", ts(optional_fields, export))]
pub struct PersonActions {
#[serde(skip)]
pub followed_at: Option<DateTime<Utc>>,
/// When the person was blocked.
pub blocked_at: Option<DateTime<Utc>>,
#[serde(skip)]
pub person_id: PersonId,
#[serde(skip)]
pub target_id: PersonId,
#[serde(skip)]
pub followed_at: Option<DateTime<Utc>>,
#[serde(skip)]
pub follow_pending: Option<bool>,
/// When the person was blocked.
pub blocked_at: Option<DateTime<Utc>>,
/// When the person was noted.
pub noted_at: Option<DateTime<Utc>>,
/// A note about the person.

View File

@@ -62,24 +62,24 @@ pub struct Post {
pub alt_text: Option<String>,
/// Time at which the post will be published. None means publish immediately.
pub scheduled_publish_time_at: Option<DateTime<Utc>>,
#[serde(skip)]
/// A newest comment time, limited to 2 days, to prevent necrobumping
pub newest_comment_time_necro_at: Option<DateTime<Utc>>,
/// The time of the newest comment in the post, if the post has any comments.
pub newest_comment_time_at: Option<DateTime<Utc>>,
pub comments: i32,
pub score: i32,
pub upvotes: i32,
pub downvotes: i32,
#[serde(skip)]
/// A newest comment time, limited to 2 days, to prevent necrobumping
pub newest_comment_time_necro_at: DateTime<Utc>,
/// The time of the newest comment in the post.
pub newest_comment_time_at: DateTime<Utc>,
pub hot_rank: f32,
#[serde(skip)]
pub hot_rank: f64,
pub hot_rank_active: f32,
#[serde(skip)]
pub hot_rank_active: f64,
#[serde(skip)]
pub controversy_rank: f64,
pub controversy_rank: f32,
/// A rank that amplifies smaller communities
#[serde(skip)]
pub scaled_rank: f64,
pub scaled_rank: f32,
pub report_count: i16,
pub unresolved_report_count: i16,
/// If a local user posts in a remote community, the comment is hidden until it is confirmed
@@ -191,25 +191,25 @@ pub struct PostUpdateForm {
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
#[cfg_attr(feature = "ts-rs", ts(optional_fields, export))]
pub struct PostActions {
#[serde(skip)]
pub person_id: PersonId,
#[serde(skip)]
pub post_id: PostId,
/// When the post was read.
pub read_at: Option<DateTime<Utc>>,
/// When was the last time you read the comments.
pub read_comments_at: Option<DateTime<Utc>>,
/// When the post was saved.
pub saved_at: Option<DateTime<Utc>>,
/// When the post was upvoted or downvoted.
pub voted_at: Option<DateTime<Utc>>,
/// When the post was hidden.
pub hidden_at: Option<DateTime<Utc>>,
#[serde(skip)]
pub person_id: PersonId,
#[serde(skip)]
pub post_id: PostId,
/// The number of comments you read last. Subtract this from total comments to get an unread
/// count.
pub read_comments_amount: Option<i32>,
/// When the post was saved.
pub saved_at: Option<DateTime<Utc>>,
/// When the post was liked.
pub liked_at: Option<DateTime<Utc>>,
/// The like / score of the post.
pub like_score: Option<i16>,
/// When the post was hidden.
pub hidden_at: Option<DateTime<Utc>>,
/// True if upvoted, false if downvoted. Upvote is greater than downvote.
pub vote_is_upvote: Option<bool>,
pub notifications: Option<PostNotificationsMode>,
}
@@ -222,9 +222,9 @@ pub struct PostActions {
pub struct PostLikeForm {
pub post_id: PostId,
pub person_id: PersonId,
pub like_score: i16,
pub vote_is_upvote: bool,
#[new(value = "Utc::now()")]
pub liked_at: DateTime<Utc>,
pub voted_at: DateTime<Utc>,
}
#[derive(derive_new::new)]

View File

@@ -7,8 +7,11 @@ use crate::{
use diesel::{
associations::HasTable,
dsl,
expression::{Expression, Selectable},
pg::Pg,
query_builder::{DeleteStatement, IntoUpdateTarget},
query_dsl::methods::{FindDsl, LimitDsl},
query_dsl::methods::{FindDsl, LimitDsl, SelectDsl},
SelectableHelper,
Table,
};
use diesel_async::{
@@ -34,14 +37,17 @@ pub type PrimaryKey<T> = <<T as HasTable>::Table as Table>::PrimaryKey;
// Trying to create default implementations for `create` and `update` results in a lifetime mess and
// weird compile errors. https://github.com/rust-lang/rust/issues/102211
pub trait Crud: HasTable + Sized
pub trait Crud: HasTable + Sized + Selectable<Pg>
where
Self::Table: FindDsl<Self::IdType>,
Find<Self>: LimitDsl + IntoUpdateTarget + Send,
Find<Self>: LimitDsl + IntoUpdateTarget + SelectDsl<dsl::AsSelect<Self, Pg>> + Send,
Delete<Find<Self>>: ExecuteDsl<AsyncPgConnection> + Send + 'static,
dsl::Select<Find<Self>, dsl::AsSelect<Self, Pg>>: LimitDsl + Send,
dsl::AsSelect<Self, Pg>: Expression,
// Used by `RunQueryDsl::first`
dsl::Limit<Find<Self>>: LoadQuery<'static, AsyncPgConnection, Self> + Send + 'static,
dsl::Limit<dsl::Select<Find<Self>, dsl::AsSelect<Self, Pg>>>:
LoadQuery<'static, AsyncPgConnection, Self> + Send + 'static,
{
type InsertForm;
type UpdateForm;
@@ -57,7 +63,8 @@ where
Self: Send,
{
async {
let query: Find<Self> = Self::table().find(id);
let query: dsl::Select<Find<Self>, dsl::AsSelect<Self, Pg>> =
Self::table().find(id).select(Self::as_select());
let conn = &mut *get_conn(pool).await?;
query
.first(conn)

View File

@@ -60,7 +60,7 @@ const FETCH_LIMIT_DEFAULT: i64 = 20;
pub const FETCH_LIMIT_MAX: usize = 50;
pub const SITEMAP_LIMIT: i64 = 50000;
pub const SITEMAP_DAYS: TimeDelta = TimeDelta::days(31);
pub const RANK_DEFAULT: f64 = 0.0001;
pub const RANK_DEFAULT: f32 = 0.0001;
pub type ActualDbPool = Pool<AsyncPgConnection>;
@@ -218,6 +218,28 @@ where
}
}
pub struct CoalesceKey<A, B>(pub A, pub B);
impl<A, B, C> CursorKey<C> for CoalesceKey<A, B>
where
A: CursorKey<C, SqlType = sql_types::Nullable<B::SqlType>>,
B: CursorKey<C, SqlType: Send>,
{
type SqlType = B::SqlType;
type CursorValue = functions::coalesce<B::SqlType, A::CursorValue, B::CursorValue>;
type SqlValue = functions::coalesce<B::SqlType, A::SqlValue, B::SqlValue>;
fn get_cursor_value(cursor: &C) -> Self::CursorValue {
// TODO: for slight optimization, use unwrap_or_else here (this requires the CursorKey trait to
// be changed to allow non-binded CursorValue)
functions::coalesce(A::get_cursor_value(cursor), B::get_cursor_value(cursor))
}
fn get_sql_value() -> Self::SqlValue {
functions::coalesce(A::get_sql_value(), B::get_sql_value())
}
}
/// Includes an SQL comment before `T`, which can be used to label auto_explain output
#[derive(QueryId)]
pub struct Commented<T> {
@@ -490,12 +512,12 @@ pub mod functions {
define_sql_function! {
#[sql_name = "r.hot_rank"]
fn hot_rank(score: Int4, time: Timestamptz) -> Double;
fn hot_rank(score: Int4, time: Timestamptz) -> Float;
}
define_sql_function! {
#[sql_name = "r.scaled_rank"]
fn scaled_rank(score: Int4, time: Timestamptz, interactions_month: Int4) -> Double;
fn scaled_rank(score: Int4, time: Timestamptz, interactions_month: Int4) -> Float;
}
define_sql_function!(fn lower(x: Text) -> Text);
@@ -572,18 +594,6 @@ pub(crate) fn format_actor_url(
Ok(Url::parse(&url)?)
}
/// Make sure the like score is 1, or -1
///
/// Uses a default NotFound error, that you should map to
/// CouldntLikeComment/CouldntLikePost.
pub(crate) fn validate_like(like_score: i16) -> LemmyResult<()> {
if [-1, 1].contains(&like_score) {
Ok(())
} else {
Err(LemmyErrorType::NotFound.into())
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -315,12 +315,12 @@ pub fn post_select_remove_deletes() -> _ {
post::url_content_type,
post::alt_text,
post::scheduled_publish_time_at,
post::newest_comment_time_necro_at,
post::newest_comment_time_at,
post::comments,
post::score,
post::upvotes,
post::downvotes,
post::newest_comment_time_necro_at,
post::newest_comment_time_at,
post::hot_rank,
post::hot_rank_active,
post::controversy_rank,

View File

@@ -184,8 +184,8 @@ diesel::table! {
upvotes -> Int4,
downvotes -> Int4,
child_count -> Int4,
hot_rank -> Float8,
controversy_rank -> Float8,
hot_rank -> Float4,
controversy_rank -> Float4,
report_count -> Int2,
unresolved_report_count -> Int2,
federation_pending -> Bool,
@@ -195,11 +195,11 @@ diesel::table! {
diesel::table! {
comment_actions (person_id, comment_id) {
voted_at -> Nullable<Timestamptz>,
saved_at -> Nullable<Timestamptz>,
person_id -> Int4,
comment_id -> Int4,
like_score -> Nullable<Int2>,
liked_at -> Nullable<Timestamptz>,
saved_at -> Nullable<Timestamptz>,
vote_is_upvote -> Nullable<Bool>,
}
}
@@ -263,11 +263,11 @@ diesel::table! {
users_active_week -> Int4,
users_active_month -> Int4,
users_active_half_year -> Int4,
hot_rank -> Float8,
hot_rank -> Float4,
subscribers_local -> Int4,
interactions_month -> Int4,
report_count -> Int2,
unresolved_report_count -> Int2,
interactions_month -> Int4,
local_removed -> Bool,
}
}
@@ -278,15 +278,15 @@ diesel::table! {
use super::sql_types::CommunityNotificationsModeEnum;
community_actions (person_id, community_id) {
person_id -> Int4,
community_id -> Int4,
followed_at -> Nullable<Timestamptz>,
follow_state -> Nullable<CommunityFollowerState>,
follow_approver_id -> Nullable<Int4>,
blocked_at -> Nullable<Timestamptz>,
became_moderator_at -> Nullable<Timestamptz>,
received_ban_at -> Nullable<Timestamptz>,
ban_expires_at -> Nullable<Timestamptz>,
person_id -> Int4,
community_id -> Int4,
follow_state -> Nullable<CommunityFollowerState>,
follow_approver_id -> Nullable<Int4>,
notifications -> Nullable<CommunityNotificationsModeEnum>,
}
}
@@ -410,9 +410,9 @@ diesel::table! {
diesel::table! {
instance_actions (person_id, instance_id) {
blocked_communities_at -> Nullable<Timestamptz>,
person_id -> Int4,
instance_id -> Int4,
blocked_communities_at -> Nullable<Timestamptz>,
received_ban_at -> Nullable<Timestamptz>,
ban_expires_at -> Nullable<Timestamptz>,
blocked_persons_at -> Nullable<Timestamptz>,
@@ -866,11 +866,11 @@ diesel::table! {
diesel::table! {
person_actions (person_id, target_id) {
followed_at -> Nullable<Timestamptz>,
blocked_at -> Nullable<Timestamptz>,
person_id -> Int4,
target_id -> Int4,
followed_at -> Nullable<Timestamptz>,
follow_pending -> Nullable<Bool>,
blocked_at -> Nullable<Timestamptz>,
noted_at -> Nullable<Timestamptz>,
note -> Nullable<Text>,
voted_at -> Nullable<Timestamptz>,
@@ -890,12 +890,12 @@ diesel::table! {
diesel::table! {
person_liked_combined (id) {
liked_at -> Timestamptz,
like_score -> Int2,
voted_at -> Timestamptz,
id -> Int4,
person_id -> Int4,
post_id -> Nullable<Int4>,
comment_id -> Nullable<Int4>,
id -> Int4,
vote_is_upvote -> Bool,
}
}
@@ -938,16 +938,16 @@ diesel::table! {
url_content_type -> Nullable<Text>,
alt_text -> Nullable<Text>,
scheduled_publish_time_at -> Nullable<Timestamptz>,
newest_comment_time_necro_at -> Nullable<Timestamptz>,
newest_comment_time_at -> Nullable<Timestamptz>,
comments -> Int4,
score -> Int4,
upvotes -> Int4,
downvotes -> Int4,
newest_comment_time_necro_at -> Timestamptz,
newest_comment_time_at -> Timestamptz,
hot_rank -> Float8,
hot_rank_active -> Float8,
controversy_rank -> Float8,
scaled_rank -> Float8,
hot_rank -> Float4,
hot_rank_active -> Float4,
controversy_rank -> Float4,
scaled_rank -> Float4,
report_count -> Int2,
unresolved_report_count -> Int2,
federation_pending -> Bool,
@@ -961,15 +961,15 @@ diesel::table! {
use super::sql_types::PostNotificationsModeEnum;
post_actions (person_id, post_id) {
person_id -> Int4,
post_id -> Int4,
read_at -> Nullable<Timestamptz>,
read_comments_at -> Nullable<Timestamptz>,
read_comments_amount -> Nullable<Int4>,
saved_at -> Nullable<Timestamptz>,
liked_at -> Nullable<Timestamptz>,
like_score -> Nullable<Int2>,
voted_at -> Nullable<Timestamptz>,
hidden_at -> Nullable<Timestamptz>,
person_id -> Int4,
post_id -> Int4,
read_comments_amount -> Nullable<Int4>,
vote_is_upvote -> Nullable<Bool>,
notifications -> Nullable<PostNotificationsModeEnum>,
}
}

View File

@@ -29,8 +29,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).vote_is_upvote), 0) AS upvotes, coalesce(sum(count_diff) FILTER (WHERE NOT (thing_actions).vote_is_upvote), 0) AS downvotes FROM select_old_and_new_rows AS old_and_new_rows
WHERE (thing_actions).vote_is_upvote IS NOT NULL GROUP BY (thing_actions).thing_id) AS diff
WHERE
a.id = diff.thing_id
AND (diff.upvotes, diff.downvotes) != (0, 0)
@@ -370,9 +370,6 @@ BEGIN
IF NEW.local THEN
NEW.ap_id = coalesce(NEW.ap_id, r.local_url ('/post/' || NEW.id::text));
END IF;
-- Set aggregates
NEW.newest_comment_time_at = NEW.published_at;
NEW.newest_comment_time_necro_at = NEW.published_at;
RETURN NEW;
END
$$;
@@ -516,26 +513,26 @@ BEGIN
WHERE p.person_id = OLD.person_id
AND p.thing_id = OLD.thing_id;
ELSIF (TG_OP = 'INSERT') THEN
IF NEW.liked_at IS NOT NULL AND (
IF NEW.voted_at IS NOT NULL AND (
SELECT
local
FROM
person
WHERE
id = NEW.person_id) = TRUE THEN
INSERT INTO person_liked_combined (liked_at, like_score, person_id, thing_id)
VALUES (NEW.liked_at, NEW.like_score, NEW.person_id, NEW.thing_id);
INSERT INTO person_liked_combined (voted_at, vote_is_upvote, person_id, thing_id)
VALUES (NEW.voted_at, NEW.vote_is_upvote, NEW.person_id, NEW.thing_id);
END IF;
ELSIF (TG_OP = 'UPDATE') THEN
IF NEW.liked_at IS NOT NULL AND (
IF NEW.voted_at IS NOT NULL AND (
SELECT
local
FROM
person
WHERE
id = NEW.person_id) = TRUE THEN
INSERT INTO person_liked_combined (liked_at, like_score, person_id, thing_id)
VALUES (NEW.liked_at, NEW.like_score, NEW.person_id, NEW.thing_id);
INSERT INTO person_liked_combined (voted_at, vote_is_upvote, person_id, thing_id)
VALUES (NEW.voted_at, NEW.vote_is_upvote, NEW.person_id, NEW.thing_id);
-- If liked gets set as null, delete the row
ELSE
DELETE FROM person_liked_combined AS p
@@ -546,7 +543,7 @@ BEGIN
RETURN NULL;
END $$;
CREATE TRIGGER person_liked_combined
AFTER INSERT OR DELETE OR UPDATE OF liked_at ON thing_actions
AFTER INSERT OR DELETE OR UPDATE OF voted_at ON thing_actions
FOR EACH ROW
EXECUTE FUNCTION r.person_liked_combined_change_values_thing ( );
$b$,

View File

@@ -1,7 +1,7 @@
-- Each calculation used in triggers should be a single SQL language
-- expression so it can be inlined in migrations.
CREATE FUNCTION r.controversy_rank (upvotes numeric, downvotes numeric)
RETURNS float
RETURNS real
LANGUAGE sql
IMMUTABLE PARALLEL SAFE RETURN CASE WHEN downvotes <= 0
OR upvotes <= 0 THEN
@@ -16,7 +16,7 @@ CREATE FUNCTION r.controversy_rank (upvotes numeric, downvotes numeric)
END;
CREATE FUNCTION r.hot_rank (score numeric, published_at timestamp with time zone)
RETURNS double precision
RETURNS real
LANGUAGE sql
IMMUTABLE PARALLEL SAFE RETURN
-- after a week, it will default to 0.
@@ -34,7 +34,7 @@ now() - published_at) < '7 days' THEN
END;
CREATE FUNCTION r.scaled_rank (score numeric, published_at timestamp with time zone, interactions_month numeric)
RETURNS double precision
RETURNS real
LANGUAGE sql
IMMUTABLE PARALLEL SAFE
-- Add 2 to avoid divide by zero errors
@@ -154,14 +154,14 @@ $a$;
-- Edit community aggregates to include voters as active users
CREATE OR REPLACE FUNCTION r.community_aggregates_activity (i text)
RETURNS TABLE (
count_ bigint,
count_ integer,
community_id_ integer)
LANGUAGE plpgsql
AS $$
BEGIN
RETURN query
SELECT
count(*),
count(*)::integer,
community_id
FROM (
SELECT
@@ -193,7 +193,7 @@ BEGIN
INNER JOIN post p ON pa.post_id = p.id
INNER JOIN person pe ON pa.person_id = pe.id
WHERE
pa.liked_at > ('now'::timestamp - i::interval)
pa.voted_at > ('now'::timestamp - i::interval)
AND pe.bot_account = FALSE
UNION
SELECT
@@ -205,7 +205,7 @@ BEGIN
INNER JOIN post p ON c.post_id = p.id
INNER JOIN person pe ON ca.person_id = pe.id
WHERE
ca.liked_at > ('now'::timestamp - i::interval)
ca.voted_at > ('now'::timestamp - i::interval)
AND pe.bot_account = FALSE) a
GROUP BY
community_id;
@@ -215,14 +215,14 @@ $$;
-- Community aggregate function for adding up total number of interactions
CREATE OR REPLACE FUNCTION r.community_aggregates_interactions (i text)
RETURNS TABLE (
count_ bigint,
count_ integer,
community_id_ integer)
LANGUAGE plpgsql
AS $$
BEGIN
RETURN query
SELECT
COALESCE(sum(comments + upvotes + downvotes)::bigint, 0) AS count_,
COALESCE(sum(comments + upvotes + downvotes)::integer, 0) AS count_,
community_id AS community_id_
FROM
post
@@ -270,7 +270,7 @@ BEGIN
post_actions pa
INNER JOIN person pe ON pa.person_id = pe.id
WHERE
pa.liked_at > ('now'::timestamp - i::interval)
pa.voted_at > ('now'::timestamp - i::interval)
AND pe.local = TRUE
AND pe.bot_account = FALSE
UNION
@@ -280,7 +280,7 @@ BEGIN
comment_actions ca
INNER JOIN person pe ON ca.person_id = pe.id
WHERE
ca.liked_at > ('now'::timestamp - i::interval)
ca.voted_at > ('now'::timestamp - i::interval)
AND pe.local = TRUE
AND pe.bot_account = FALSE) a;
RETURN count_;

View File

@@ -32,8 +32,7 @@ pub struct CreateComment {
/// Like a comment.
pub struct CreateCommentLike {
pub comment_id: CommentId,
/// Must be -1, 0, or 1 .
pub score: i16,
pub is_upvote: Option<bool>,
}
#[skip_serializing_none]

View File

@@ -457,7 +457,7 @@ mod tests {
)
);
let comment_like_form = CommentLikeForm::new(inserted_timmy_person.id, comment_0.id, 1);
let comment_like_form = CommentLikeForm::new(inserted_timmy_person.id, comment_0.id, true);
CommentActions::like(pool, &comment_like_form).await?;
@@ -513,7 +513,7 @@ mod tests {
assert!(read_comment_views_with_person[0]
.comment_actions
.as_ref()
.is_some_and(|x| x.like_score == Some(1)));
.is_some_and(|x| x.vote_is_upvote == Some(true)));
assert!(read_comment_views_with_person[0].can_mod);
// Make sure its 1, not showing the blocked comment

View File

@@ -6,6 +6,7 @@ use crate::{
PostView,
};
use diesel::{
dsl::not,
BoolExpressionMethods,
ExpressionMethods,
JoinOnDsl,
@@ -179,8 +180,8 @@ impl PersonLikedCombinedQuery {
if let Some(like_type) = self.like_type {
query = match like_type {
LikeType::All => query,
LikeType::LikedOnly => query.filter(person_liked_combined::like_score.eq(1)),
LikeType::DislikedOnly => query.filter(person_liked_combined::like_score.eq(-1)),
LikeType::LikedOnly => query.filter(person_liked_combined::vote_is_upvote),
LikeType::DislikedOnly => query.filter(not(person_liked_combined::vote_is_upvote)),
}
}
@@ -192,7 +193,7 @@ impl PersonLikedCombinedQuery {
None,
self.page_back,
)
.then_order_by(key::liked_at)
.then_order_by(key::voted_at)
// Tie breaker
.then_order_by(key::id);
@@ -366,13 +367,13 @@ mod tests {
assert_eq!(0, timmy_liked.len());
// Like a few things
let like_sara_comment_2 = CommentLikeForm::new(data.timmy.id, data.sara_comment_2.id, 1);
let like_sara_comment_2 = CommentLikeForm::new(data.timmy.id, data.sara_comment_2.id, true);
CommentActions::like(pool, &like_sara_comment_2).await?;
let dislike_sara_comment = CommentLikeForm::new(data.timmy.id, data.sara_comment.id, -1);
let dislike_sara_comment = CommentLikeForm::new(data.timmy.id, data.sara_comment.id, false);
CommentActions::like(pool, &dislike_sara_comment).await?;
let post_like_form = PostLikeForm::new(data.timmy_post.id, data.timmy.id, 1);
let post_like_form = PostLikeForm::new(data.timmy_post.id, data.timmy.id, true);
PostActions::like(pool, &post_like_form).await?;
let timmy_liked_all = PersonLikedCombinedQuery::default()
@@ -384,7 +385,10 @@ mod tests {
if let PersonLikedCombinedView::Post(v) = &timmy_liked_all[0] {
assert_eq!(data.timmy_post.id, v.post.id);
assert_eq!(data.timmy.id, v.post.creator_id);
assert_eq!(Some(1), v.post_actions.as_ref().and_then(|l| l.like_score));
assert_eq!(
Some(true),
v.post_actions.as_ref().and_then(|l| l.vote_is_upvote)
);
} else {
panic!("wrong type");
}
@@ -392,8 +396,8 @@ mod tests {
assert_eq!(data.sara_comment.id, v.comment.id);
assert_eq!(data.sara.id, v.comment.creator_id);
assert_eq!(
Some(-1),
v.comment_actions.as_ref().and_then(|l| l.like_score)
Some(false),
v.comment_actions.as_ref().and_then(|l| l.vote_is_upvote)
);
} else {
panic!("wrong type");
@@ -402,8 +406,8 @@ mod tests {
assert_eq!(data.sara_comment_2.id, v.comment.id);
assert_eq!(data.sara.id, v.comment.creator_id);
assert_eq!(
Some(1),
v.comment_actions.as_ref().and_then(|l| l.like_score)
Some(true),
v.comment_actions.as_ref().and_then(|l| l.vote_is_upvote)
);
} else {
panic!("wrong type");
@@ -421,8 +425,8 @@ mod tests {
assert_eq!(data.sara_comment.id, v.comment.id);
assert_eq!(data.sara.id, v.comment.creator_id);
assert_eq!(
Some(-1),
v.comment_actions.as_ref().and_then(|l| l.like_score)
Some(false),
v.comment_actions.as_ref().and_then(|l| l.vote_is_upvote)
);
} else {
panic!("wrong type");

View File

@@ -38,8 +38,7 @@ pub struct CreatePost {
/// Like a post.
pub struct CreatePostLike {
pub post_id: PostId,
/// Score must be -1, 0, or 1.
pub score: i16,
pub is_upvote: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize, Clone, Copy, Default, PartialEq, Eq, Hash)]

View File

@@ -53,6 +53,7 @@ use lemmy_db_schema::{
},
},
seconds_to_pg_interval,
CoalesceKey,
Commented,
DbPool,
},
@@ -529,7 +530,7 @@ impl PostQuery<'_> {
Scaled => pq.then_order_by(key::scaled_rank),
Controversial => pq.then_order_by(key::controversy_rank),
New | Old => pq.then_order_by(key::published_at),
NewComments => pq.then_order_by(key::newest_comment_time_at),
NewComments => pq.then_order_by(CoalesceKey(key::newest_comment_time_at, key::published_at)),
MostComments => pq.then_order_by(key::comments),
Top => pq.then_order_by(key::score),
};
@@ -971,16 +972,16 @@ mod tests {
let pool = &data.pool();
let pool = &mut pool.into();
let post_like_form = PostLikeForm::new(data.post.id, data.tegan.person.id, 1);
let post_like_form = PostLikeForm::new(data.post.id, data.tegan.person.id, true);
let inserted_post_like = PostActions::like(pool, &post_like_form).await?;
assert_eq!(
(data.post.id, data.tegan.person.id, Some(1)),
(data.post.id, data.tegan.person.id, Some(true)),
(
inserted_post_like.post_id,
inserted_post_like.person_id,
inserted_post_like.like_score,
inserted_post_like.vote_is_upvote,
)
);
@@ -998,7 +999,7 @@ mod tests {
(
post_listing_single_with_person
.post_actions
.is_some_and(|t| t.like_score == Some(1)),
.is_some_and(|t| t.vote_is_upvote == Some(true)),
// Make sure person actions is none so you don't get a voted_at for your own user
post_listing_single_with_person.person_actions.is_none(),
post_listing_single_with_person.post.score,
@@ -1094,20 +1095,20 @@ mod tests {
);
let bot_post_2 = Post::create(pool, &bot_post_2).await?;
let post_like_form = PostLikeForm::new(data.bot_post.id, data.tegan.person.id, 1);
let post_like_form = PostLikeForm::new(data.bot_post.id, data.tegan.person.id, true);
let inserted_post_like = PostActions::like(pool, &post_like_form).await?;
assert_eq!(
(data.bot_post.id, data.tegan.person.id, Some(1)),
(data.bot_post.id, data.tegan.person.id, Some(true)),
(
inserted_post_like.post_id,
inserted_post_like.person_id,
inserted_post_like.like_score,
inserted_post_like.vote_is_upvote,
)
);
let inserted_person_like =
PersonActions::like(pool, data.tegan.person.id, data.bot.person.id, 1).await?;
PersonActions::like(pool, data.tegan.person.id, data.bot.person.id, true).await?;
assert_eq!(
(data.tegan.person.id, data.bot.person.id, Some(1), Some(0),),
@@ -1133,7 +1134,7 @@ mod tests {
(
post_listing
.post_actions
.is_some_and(|t| t.like_score == Some(1)),
.is_some_and(|t| t.vote_is_upvote == Some(true)),
post_listing
.person_actions
.as_ref()
@@ -1149,10 +1150,10 @@ mod tests {
);
// Do a 2nd like to another post
let post_2_like_form = PostLikeForm::new(bot_post_2.id, data.tegan.person.id, 1);
let post_2_like_form = PostLikeForm::new(bot_post_2.id, data.tegan.person.id, true);
let _inserted_post_2_like = PostActions::like(pool, &post_2_like_form).await?;
let inserted_person_like_2 =
PersonActions::like(pool, data.tegan.person.id, data.bot.person.id, 1).await?;
PersonActions::like(pool, data.tegan.person.id, data.bot.person.id, true).await?;
assert_eq!(
(data.tegan.person.id, data.bot.person.id, Some(2), Some(0),),
(
@@ -1169,7 +1170,7 @@ mod tests {
assert_eq!(UpleteCount::only_deleted(1), like_removed);
let person_like_removed =
PersonActions::remove_like(pool, data.tegan.person.id, data.bot.person.id, 1).await?;
PersonActions::remove_like(pool, data.tegan.person.id, data.bot.person.id, true).await?;
assert_eq!(
(data.tegan.person.id, data.bot.person.id, Some(1), Some(0),),
(
@@ -1181,10 +1182,10 @@ mod tests {
);
// Now do a downvote
let post_like_form = PostLikeForm::new(data.bot_post.id, data.tegan.person.id, -1);
let post_like_form = PostLikeForm::new(data.bot_post.id, data.tegan.person.id, false);
let _inserted_post_dislike = PostActions::like(pool, &post_like_form).await?;
let inserted_person_dislike =
PersonActions::like(pool, data.tegan.person.id, data.bot.person.id, -1).await?;
PersonActions::like(pool, data.tegan.person.id, data.bot.person.id, false).await?;
assert_eq!(
(data.tegan.person.id, data.bot.person.id, Some(1), Some(1),),
(
@@ -1209,7 +1210,7 @@ mod tests {
(
post_listing
.post_actions
.is_some_and(|t| t.like_score == Some(-1)),
.is_some_and(|t| t.vote_is_upvote == Some(false)),
post_listing
.person_actions
.as_ref()

View File

@@ -290,25 +290,25 @@ impl SearchCombinedQuery {
// Liked / disliked filter
if let Some(my_id) = my_person_id {
let not_creator_filter = item_creator.ne(my_id);
let liked_disliked_filter = |score: i16| {
let liked_disliked_filter = |should_be_upvote: bool| {
search_combined::post_id
.is_not_null()
.and(post_actions::like_score.eq(score))
.and(post_actions::vote_is_upvote.eq(should_be_upvote))
.or(
search_combined::comment_id
.is_not_null()
.and(comment_actions::like_score.eq(score)),
.and(comment_actions::vote_is_upvote.eq(should_be_upvote)),
)
};
if self.liked_only.unwrap_or_default() {
query = query
.filter(not_creator_filter)
.filter(liked_disliked_filter(1));
.filter(liked_disliked_filter(true));
} else if self.disliked_only.unwrap_or_default() {
query = query
.filter(not_creator_filter)
.filter(liked_disliked_filter(-1));
.filter(liked_disliked_filter(false));
}
};
@@ -609,22 +609,22 @@ mod tests {
let comment_in_nsfw_post = Comment::create(pool, &comment_in_nsfw_post_form, None).await?;
// Timmy likes and dislikes a few things
let timmy_like_post_form = PostLikeForm::new(timmy_post.id, timmy.id, 1);
let timmy_like_post_form = PostLikeForm::new(timmy_post.id, timmy.id, true);
PostActions::like(pool, &timmy_like_post_form).await?;
let timmy_like_sara_post_form = PostLikeForm::new(sara_post.id, timmy.id, 1);
let timmy_like_sara_post_form = PostLikeForm::new(sara_post.id, timmy.id, true);
PostActions::like(pool, &timmy_like_sara_post_form).await?;
let timmy_dislike_post_form = PostLikeForm::new(timmy_post_2.id, timmy.id, -1);
let timmy_dislike_post_form = PostLikeForm::new(timmy_post_2.id, timmy.id, false);
PostActions::like(pool, &timmy_dislike_post_form).await?;
let timmy_like_comment_form = CommentLikeForm::new(timmy.id, timmy_comment.id, 1);
let timmy_like_comment_form = CommentLikeForm::new(timmy.id, timmy_comment.id, true);
CommentActions::like(pool, &timmy_like_comment_form).await?;
let timmy_like_sara_comment_form = CommentLikeForm::new(timmy.id, sara_comment.id, 1);
let timmy_like_sara_comment_form = CommentLikeForm::new(timmy.id, sara_comment.id, true);
CommentActions::like(pool, &timmy_like_sara_comment_form).await?;
let timmy_dislike_sara_comment_form = CommentLikeForm::new(timmy.id, sara_comment_2.id, -1);
let timmy_dislike_sara_comment_form = CommentLikeForm::new(timmy.id, sara_comment_2.id, false);
CommentActions::like(pool, &timmy_dislike_sara_comment_form).await?;
Ok(Data {

View File

@@ -85,7 +85,7 @@ impl VoteView {
.left_join(creator_home_instance_actions_join())
.left_join(creator_local_instance_actions_join)
.filter(post_actions::post_id.eq(post_id))
.filter(post_actions::like_score.is_not_null())
.filter(post_actions::vote_is_upvote.is_not_null())
.select((
person::all_columns,
creator_local_home_banned(),
@@ -93,16 +93,16 @@ impl VoteView {
.field(community_actions::received_ban_at)
.nullable()
.is_not_null(),
post_actions::like_score.assume_not_null(),
post_actions::vote_is_upvote.assume_not_null(),
))
.limit(limit)
.into_boxed();
// Sorting by like score
let paginated_query = paginate(query, SortDirection::Asc, cursor_data, None, page_back)
.then_order_by(key::like_score)
.then_order_by(key::vote_is_upvote)
// Tie breaker
.then_order_by(key::liked_at);
.then_order_by(key::voted_at);
paginated_query
.load::<Self>(conn)
@@ -159,7 +159,7 @@ impl VoteView {
.left_join(creator_home_instance_actions_join())
.left_join(creator_local_instance_actions_join)
.filter(comment_actions::comment_id.eq(comment_id))
.filter(comment_actions::like_score.is_not_null())
.filter(comment_actions::vote_is_upvote.is_not_null())
.select((
person::all_columns,
creator_local_home_banned(),
@@ -167,16 +167,16 @@ impl VoteView {
.field(community_actions::received_ban_at)
.nullable()
.is_not_null(),
comment_actions::like_score.assume_not_null(),
comment_actions::vote_is_upvote.assume_not_null(),
))
.limit(limit)
.into_boxed();
// Sorting by like score
let paginated_query = paginate(query, SortDirection::Asc, cursor_data, None, page_back)
.then_order_by(key::like_score)
.then_order_by(key::vote_is_upvote)
// Tie breaker
.then_order_by(key::liked_at);
.then_order_by(key::voted_at);
paginated_query
.load::<Self>(conn)
@@ -243,11 +243,11 @@ mod tests {
let inserted_comment = Comment::create(pool, &comment_form, None).await?;
// Timmy upvotes his own post
let timmy_post_vote_form = PostLikeForm::new(inserted_post.id, inserted_timmy.id, 1);
let timmy_post_vote_form = PostLikeForm::new(inserted_post.id, inserted_timmy.id, true);
PostActions::like(pool, &timmy_post_vote_form).await?;
// Sara downvotes timmy's post
let sara_post_vote_form = PostLikeForm::new(inserted_post.id, inserted_sara.id, -1);
let sara_post_vote_form = PostLikeForm::new(inserted_post.id, inserted_sara.id, false);
PostActions::like(pool, &sara_post_vote_form).await?;
let mut expected_post_vote_views = [
@@ -255,13 +255,13 @@ mod tests {
creator: inserted_sara.clone(),
creator_banned: false,
creator_banned_from_community: false,
score: -1,
is_upvote: false,
},
VoteView {
creator: inserted_timmy.clone(),
creator_banned: false,
creator_banned_from_community: false,
score: 1,
is_upvote: true,
},
];
expected_post_vote_views[1].creator.post_count = 1;
@@ -272,11 +272,12 @@ mod tests {
assert_eq!(read_post_vote_views, expected_post_vote_views);
// Timothy votes down his own comment
let timmy_comment_vote_form = CommentLikeForm::new(inserted_timmy.id, inserted_comment.id, -1);
let timmy_comment_vote_form =
CommentLikeForm::new(inserted_timmy.id, inserted_comment.id, false);
CommentActions::like(pool, &timmy_comment_vote_form).await?;
// Sara upvotes timmy's comment
let sara_comment_vote_form = CommentLikeForm::new(inserted_sara.id, inserted_comment.id, 1);
let sara_comment_vote_form = CommentLikeForm::new(inserted_sara.id, inserted_comment.id, true);
CommentActions::like(pool, &sara_comment_vote_form).await?;
let mut expected_comment_vote_views = [
@@ -284,13 +285,13 @@ mod tests {
creator: inserted_timmy.clone(),
creator_banned: false,
creator_banned_from_community: false,
score: -1,
is_upvote: false,
},
VoteView {
creator: inserted_sara.clone(),
creator_banned: false,
creator_banned_from_community: false,
score: 1,
is_upvote: true,
},
];
expected_comment_vote_views[0].creator.post_count = 1;

View File

@@ -18,5 +18,5 @@ pub struct VoteView {
pub creator: Person,
pub creator_banned: bool,
pub creator_banned_from_community: bool,
pub score: i16,
pub is_upvote: bool,
}

View File

@@ -12,6 +12,7 @@ use diesel::{
NullableExpressionMethods,
QueryDsl,
QueryableByName,
SelectableHelper,
};
use diesel_async::{AsyncPgConnection, RunQueryDsl};
use diesel_uplete::uplete;
@@ -250,7 +251,7 @@ async fn process_post_aggregates_ranks_in_batches(conn: &mut AsyncPgConnection)
FOR UPDATE SKIP LOCKED)
UPDATE post pa
SET hot_rank = r.hot_rank(pa.score, pa.published_at),
hot_rank_active = r.hot_rank(pa.score, pa.newest_comment_time_necro_at),
hot_rank_active = r.hot_rank(pa.score, coalesce(pa.newest_comment_time_necro_at, pa.published_at)),
scaled_rank = r.scaled_rank(pa.score, pa.published_at, ca.interactions_month)
FROM batch, community ca
WHERE pa.id = batch.id
@@ -593,7 +594,7 @@ async fn publish_scheduled_posts(context: &Data<LemmyContext>) -> LemmyResult<()
.filter(not(exists(not_community_banned_action)))
// ensure that user isnt banned from local
.filter(not(exists(not_local_banned_action)))
.select((post::all_columns, community::all_columns))
.select((Post::as_select(), Community::as_select()))
.get_results::<(Post, Community)>(conn)
.await?;
@@ -771,7 +772,7 @@ mod tests {
&PostInsertForm::new("i am grrreat".to_owned(), person.id, community.id),
)
.await?;
PostActions::like(pool, &PostLikeForm::new(post.id, person.id, 1)).await?;
PostActions::like(pool, &PostLikeForm::new(post.id, person.id, true)).await?;
active_counts(pool, ONE_DAY).await?;
all_active_counts(pool).await?;

View File

@@ -134,7 +134,11 @@ INSERT INTO post_like (post_id, person_id, score, published)
SELECT
post_id,
person_id,
like_score,
CASE WHEN vote_is_upvote THEN
1
ELSE
-1
END,
liked
FROM
post_actions
@@ -186,7 +190,11 @@ INSERT INTO comment_like (comment_id, person_id, score, published)
SELECT
comment_id,
person_id,
like_score,
CASE WHEN vote_is_upvote THEN
1
ELSE
-1
END,
liked
FROM
comment_actions

View File

@@ -5,11 +5,11 @@
-- comment_actions
CREATE TABLE comment_actions AS
SELECT
max(liked) AS liked,
max(saved) AS saved,
person_id,
comment_id,
cast(max(like_score) AS smallint) AS like_score,
max(liked) AS liked,
max(saved) AS saved
max(like_score) = 1 AS vote_is_upvote -- `null = 1` returns null
FROM (
SELECT
person_id,
@@ -42,17 +42,17 @@ ALTER TABLE comment_actions
ADD PRIMARY KEY (person_id, comment_id),
ADD CONSTRAINT comment_actions_person_id_fkey FOREIGN KEY (person_id) REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE,
ADD CONSTRAINT comment_actions_comment_id_fkey FOREIGN KEY (comment_id) REFERENCES COMMENT ON UPDATE CASCADE ON DELETE CASCADE,
ADD CONSTRAINT comment_actions_check_liked CHECK (((liked IS NULL) = (like_score IS NULL)));
ADD CONSTRAINT comment_actions_check_liked CHECK (((liked IS NULL) = (vote_is_upvote IS NULL)));
-- 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)
-- a group (e.g. `liked IS NOT NULL` and `vote_is_upvote IS NOT NULL` both work)
CREATE INDEX idx_comment_actions_person ON comment_actions (person_id);
CREATE INDEX idx_comment_actions_comment ON comment_actions (comment_id);
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;
liked IS NOT NULL OR vote_is_upvote IS NOT NULL;
CREATE INDEX idx_comment_actions_saved_not_null ON comment_actions (person_id, comment_id)
WHERE
@@ -63,15 +63,15 @@ WHERE
-- SO link on merges: https://stackoverflow.com/a/74066614/1655478
CREATE TABLE post_actions AS
SELECT
person_id,
post_id,
max(read) AS read,
max(read_comments) AS read_comments,
cast(max(read_comments_amount) AS int) AS read_comments_amount,
max(saved) AS saved,
max(liked) AS liked,
cast(max(like_score) AS smallint) AS like_score,
max(hidden) AS hidden
max(hidden) AS hidden,
person_id,
post_id,
cast(max(read_comments_amount) AS int) AS read_comments_amount,
max(like_score) = 1 AS vote_is_upvote -- `null = 1` returns null
FROM (
SELECT
person_id,
@@ -151,7 +151,7 @@ ALTER TABLE post_actions
ADD PRIMARY KEY (person_id, post_id),
ADD CONSTRAINT post_actions_person_id_fkey FOREIGN KEY (person_id) REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE,
ADD CONSTRAINT post_actions_post_id_fkey FOREIGN KEY (post_id) REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE,
ADD CONSTRAINT post_actions_check_liked CHECK (((liked IS NULL) = (like_score IS NULL))),
ADD CONSTRAINT post_actions_check_liked CHECK (((liked IS NULL) = (vote_is_upvote IS NULL))),
ADD CONSTRAINT post_actions_check_read_comments CHECK (((read_comments IS NULL) = (read_comments_amount IS NULL)));
-- Create indexes
@@ -173,7 +173,7 @@ WHERE
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;
liked IS NOT NULL OR vote_is_upvote IS NOT NULL;
CREATE INDEX idx_post_actions_hidden_not_null ON post_actions (person_id, post_id)
WHERE
@@ -182,15 +182,15 @@ WHERE
-- community_actions
CREATE TABLE community_actions AS
SELECT
person_id,
community_id,
max(followed) AS followed,
max(follow_state) AS follow_state,
max(follow_approver_id) AS follow_approver_id,
max(blocked) AS blocked,
max(became_moderator) AS became_moderator,
max(received_ban) AS received_ban,
max(ban_expires) AS ban_expires
max(ban_expires) AS ban_expires,
person_id,
community_id,
max(follow_state) AS follow_state,
max(follow_approver_id) AS follow_approver_id
FROM (
SELECT
person_id,
@@ -293,9 +293,9 @@ WHERE
-- instance_actions
CREATE TABLE instance_actions AS
SELECT
published AS blocked,
person_id,
instance_id,
published AS blocked
instance_id
FROM
instance_block;
@@ -322,11 +322,11 @@ WHERE
-- person_actions
CREATE TABLE person_actions AS
SELECT
max(followed) AS followed,
max(blocked) AS blocked,
person_id,
target_id,
max(followed) AS followed,
cast(max(follow_pending) AS boolean) AS follow_pending,
max(blocked) AS blocked
cast(max(follow_pending) AS boolean) AS follow_pending
FROM (
SELECT
follower_id AS person_id,
@@ -376,7 +376,7 @@ WHERE
-- `(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)
CREATE statistics comment_actions_liked_stat ON (liked IS NULL), (vote_is_upvote IS NULL)
FROM comment_actions;
CREATE statistics community_actions_followed_stat ON (followed IS NULL), (follow_state IS NULL)
@@ -388,6 +388,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), (post_id IS NULL)
CREATE statistics post_actions_liked_stat ON (liked IS NULL), (vote_is_upvote IS NULL), (post_id IS NULL)
FROM post_actions;

View File

@@ -93,8 +93,8 @@ SELECT
upvotes,
downvotes,
published,
newest_comment_time_necro,
newest_comment_time,
coalesce(newest_comment_time_necro, published),
coalesce(newest_comment_time, published),
featured_community,
featured_local,
hot_rank,
@@ -102,7 +102,13 @@ SELECT
community_id,
creator_id,
controversy_rank,
instance_id,
(
SELECT
community.instance_id
FROM
community
WHERE
community.id = post.community_id) AS instance_id,
scaled_rank,
report_count,
unresolved_report_count
@@ -139,7 +145,6 @@ ALTER TABLE post
DROP COLUMN hot_rank,
DROP COLUMN hot_rank_active,
DROP COLUMN controversy_rank,
DROP COLUMN instance_id,
DROP COLUMN scaled_rank,
DROP COLUMN report_count,
DROP COLUMN unresolved_report_count;

View File

@@ -1,14 +1,20 @@
-- Merge comment_aggregates into comment table
ALTER TABLE comment
ADD COLUMN score int NOT NULL DEFAULT 0,
ADD COLUMN upvotes int NOT NULL DEFAULT 0,
ADD COLUMN score int NOT NULL DEFAULT 1, -- Default value only for previous rows, to match the similar thing done with `upvotes`
ADD COLUMN upvotes int NOT NULL DEFAULT 1, -- Default value only for previous rows, so the update below can filter out more rows by using `upvotes != 1` instead of `upvotes != 0`
ADD COLUMN downvotes int NOT NULL DEFAULT 0,
ADD COLUMN child_count int NOT NULL DEFAULT 0,
ADD COLUMN hot_rank double precision NOT NULL DEFAULT 0.0001,
ADD COLUMN controversy_rank double precision NOT NULL DEFAULT 0,
ADD COLUMN hot_rank real NOT NULL DEFAULT 0, -- Default value only for previous rows, so the update below can filter out more rows by using `hot_rank != 0` instead of `hot_rank != 0.0001`
ADD COLUMN controversy_rank real NOT NULL DEFAULT 0,
ADD COLUMN report_count smallint NOT NULL DEFAULT 0,
ADD COLUMN unresolved_report_count smallint NOT NULL DEFAULT 0;
-- Default values only for future rows
ALTER TABLE comment
ALTER COLUMN score SET DEFAULT 0,
ALTER COLUMN upvotes SET DEFAULT 0,
ALTER COLUMN hot_rank SET DEFAULT 0.0001;
-- Disable the triggers temporarily
ALTER TABLE comment DISABLE TRIGGER ALL;
@@ -40,7 +46,14 @@ SET
FROM
comment_aggregates AS ca
WHERE
comment.id = ca.comment_id;
comment.id = ca.comment_id
-- If `(upvotes, downvotes) = (1, 0)`, then `(score, controversy_rank) = (1, 0)`, so it would be redundant to check `score` and `controversy_rank` in this filter.
AND (ca.upvotes != 1
OR ca.downvotes != 0
OR ca.child_count != 0
OR ca.hot_rank != 0
OR ca.report_count != 0
OR ca.unresolved_report_count != 0);
DROP TABLE comment_aggregates;
@@ -77,20 +90,27 @@ CREATE INDEX idx_comment_score ON comment USING btree (score DESC);
-- merge post_aggregates into post table
ALTER TABLE post
ADD COLUMN newest_comment_time_necro timestamp with time zone,
ADD COLUMN newest_comment_time timestamp with time zone,
ADD COLUMN comments int NOT NULL DEFAULT 0,
ADD COLUMN score int NOT NULL DEFAULT 0,
ADD COLUMN upvotes int NOT NULL DEFAULT 0,
ADD COLUMN score int NOT NULL DEFAULT 1, -- Default value only for previous rows, to match the similar thing done with `upvotes`
ADD COLUMN upvotes int NOT NULL DEFAULT 1, -- Default value only for previous rows, so the update below can filter out more rows by using `upvotes != 1` instead of `upvotes != 0`
ADD COLUMN downvotes int NOT NULL DEFAULT 0,
ADD COLUMN newest_comment_time_necro timestamp with time zone NOT NULL DEFAULT now(),
ADD COLUMN newest_comment_time timestamp with time zone NOT NULL DEFAULT now(),
ADD COLUMN hot_rank double precision NOT NULL DEFAULT 0.0001,
ADD COLUMN hot_rank_active double precision NOT NULL DEFAULT 0.0001,
ADD COLUMN controversy_rank double precision NOT NULL DEFAULT 0,
ADD COLUMN instance_id int REFERENCES instance (id) ON UPDATE CASCADE ON DELETE CASCADE,
ADD COLUMN scaled_rank double precision NOT NULL DEFAULT 0.0001,
ADD COLUMN hot_rank real NOT NULL DEFAULT 0, -- Default value only for previous rows, so the update below can filter out more rows by using `hot_rank != 0` instead of `hot_rank != 0.0001`
ADD COLUMN hot_rank_active real NOT NULL DEFAULT 0, -- Default value only for previous rows, so the update below can filter out more rows by using `hot_rank_active != 0` instead of `hot_rank_active != 0.0001`
ADD COLUMN controversy_rank real NOT NULL DEFAULT 0,
ADD COLUMN scaled_rank real NOT NULL DEFAULT 0, -- Default value only for previous rows, so the update below can filter out more rows by using `scaled_rank != 0` instead of `scaled_rank != 0.0001`
ADD COLUMN report_count smallint NOT NULL DEFAULT 0,
ADD COLUMN unresolved_report_count smallint NOT NULL DEFAULT 0;
-- Default values only for future rows
ALTER TABLE post
ALTER COLUMN score SET DEFAULT 0,
ALTER COLUMN upvotes SET DEFAULT 0,
ALTER COLUMN hot_rank SET DEFAULT 0.0001,
ALTER COLUMN hot_rank_active SET DEFAULT 0.0001,
ALTER COLUMN scaled_rank SET DEFAULT 0.0001;
-- Disable the triggers temporarily
ALTER TABLE post DISABLE TRIGGER ALL;
@@ -111,23 +131,33 @@ WHERE
UPDATE
post
SET
newest_comment_time_necro = nullif (pa.newest_comment_time_necro, pa.published),
newest_comment_time = nullif (pa.newest_comment_time, pa.published),
comments = pa.comments,
score = pa.score,
upvotes = pa.upvotes,
downvotes = pa.downvotes,
newest_comment_time_necro = pa.newest_comment_time_necro,
newest_comment_time = pa.newest_comment_time,
hot_rank = pa.hot_rank,
hot_rank_active = pa.hot_rank_active,
controversy_rank = pa.controversy_rank,
instance_id = pa.instance_id,
scaled_rank = pa.scaled_rank,
report_count = pa.report_count,
unresolved_report_count = pa.unresolved_report_count
FROM
post_aggregates AS pa
WHERE
post.id = pa.post_id;
post.id = pa.post_id
-- If `(upvotes, downvotes) = (1, 0)`, then `(score, controversy_rank) = (1, 0)`, so it would be redundant to check `score` and `controversy_rank` in this filter.
AND (pa.newest_comment_time_necro != pa.published
OR pa.newest_comment_time != pa.published
OR pa.comments != 0
OR pa.upvotes != 1
OR pa.downvotes != 0
OR pa.hot_rank != 0
OR pa.hot_rank_active != 0
OR pa.scaled_rank != 0
OR pa.report_count != 0
OR pa.unresolved_report_count != 0);
-- Delete that data
DROP TABLE post_aggregates;
@@ -160,9 +190,9 @@ CREATE INDEX idx_post_community_hot ON post USING btree (community_id, featured_
CREATE INDEX idx_post_community_most_comments ON post USING btree (community_id, featured_local DESC, comments DESC, published DESC, id DESC);
CREATE INDEX idx_post_community_newest_comment_time ON post USING btree (community_id, featured_local DESC, newest_comment_time DESC, id DESC);
CREATE INDEX idx_post_community_newest_comment_time ON post USING btree (community_id, featured_local DESC, coalesce(newest_comment_time, published) DESC, id DESC);
CREATE INDEX idx_post_community_newest_comment_time_necro ON post USING btree (community_id, featured_local DESC, newest_comment_time_necro DESC, id DESC);
CREATE INDEX idx_post_community_newest_comment_time_necro ON post USING btree (community_id, featured_local DESC, coalesce(newest_comment_time_necro, published) DESC, id DESC);
-- INDEX idx_post_community_published ON post USING btree (community_id, featured_local DESC, published DESC);
--CREATE INDEX idx_post_community_published_asc ON post USING btree (community_id, featured_local DESC, reverse_timestamp_sort (published) DESC);
@@ -178,9 +208,9 @@ CREATE INDEX idx_post_featured_community_hot ON post USING btree (community_id,
CREATE INDEX idx_post_featured_community_most_comments ON post USING btree (community_id, featured_community DESC, comments DESC, published DESC, id DESC);
CREATE INDEX idx_post_featured_community_newest_comment_time ON post USING btree (community_id, featured_community DESC, newest_comment_time DESC, id DESC);
CREATE INDEX idx_post_featured_community_newest_comment_time ON post USING btree (community_id, featured_community DESC, coalesce(newest_comment_time, published) DESC, id DESC);
CREATE INDEX idx_post_featured_community_newest_comment_time_necr ON post USING btree (community_id, featured_community DESC, newest_comment_time_necro DESC, id DESC);
CREATE INDEX idx_post_featured_community_newest_comment_time_necr ON post USING btree (community_id, featured_community DESC, coalesce(newest_comment_time_necro, published) DESC, id DESC);
--CREATE INDEX idx_post_featured_community_published ON post USING btree (community_id, featured_community DESC, published DESC);
CREATE INDEX idx_post_featured_community_published_asc ON post USING btree (community_id, featured_community DESC, reverse_timestamp_sort (published) DESC, id DESC);
@@ -197,9 +227,9 @@ CREATE INDEX idx_post_featured_local_hot ON post USING btree (featured_local DES
CREATE INDEX idx_post_featured_local_most_comments ON post USING btree (featured_local DESC, comments DESC, published DESC, id DESC);
CREATE INDEX idx_post_featured_local_newest_comment_time ON post USING btree (featured_local DESC, newest_comment_time DESC, id DESC);
CREATE INDEX idx_post_featured_local_newest_comment_time ON post USING btree (featured_local DESC, coalesce(newest_comment_time, published) DESC, id DESC);
CREATE INDEX idx_post_featured_local_newest_comment_time_necro ON post USING btree (featured_local DESC, newest_comment_time_necro DESC, id DESC);
CREATE INDEX idx_post_featured_local_newest_comment_time_necro ON post USING btree (featured_local DESC, coalesce(newest_comment_time_necro, published) DESC, id DESC);
CREATE INDEX idx_post_featured_local_published ON post USING btree (featured_local DESC, published DESC, id DESC);
@@ -216,18 +246,23 @@ CREATE INDEX idx_post_published_asc ON post USING btree (reverse_timestamp_sort
-- merge community_aggregates into community table
ALTER TABLE community
ADD COLUMN subscribers int NOT NULL DEFAULT 0,
ADD COLUMN subscribers int NOT NULL DEFAULT 1, -- Default value only for previous rows, so the update below can filter out more rows by using `subscribers != 1` instead of `subscribers != 0`
ADD COLUMN posts int NOT NULL DEFAULT 0,
ADD COLUMN comments int NOT NULL DEFAULT 0,
ADD COLUMN users_active_day int NOT NULL DEFAULT 0,
ADD COLUMN users_active_week int NOT NULL DEFAULT 0,
ADD COLUMN users_active_month int NOT NULL DEFAULT 0,
ADD COLUMN users_active_half_year int NOT NULL DEFAULT 0,
ADD COLUMN hot_rank double precision NOT NULL DEFAULT 0.0001,
ADD COLUMN hot_rank real NOT NULL DEFAULT 0, -- Default value only for previous rows, so the update below can filter out more rows by using `hot_rank != 0` instead of `hot_rank != 0.0001`
ADD COLUMN subscribers_local int NOT NULL DEFAULT 0,
ADD COLUMN interactions_month int NOT NULL DEFAULT 0,
ADD COLUMN report_count smallint NOT NULL DEFAULT 0,
ADD COLUMN unresolved_report_count smallint NOT NULL DEFAULT 0,
ADD COLUMN interactions_month int NOT NULL DEFAULT 0;
ADD COLUMN unresolved_report_count smallint NOT NULL DEFAULT 0;
-- Default values only for future rows
ALTER TABLE community
ALTER COLUMN subscribers SET DEFAULT 0,
ALTER COLUMN hot_rank SET DEFAULT 0.0001;
-- Disable the triggers temporarily
ALTER TABLE community DISABLE TRIGGER ALL;
@@ -258,13 +293,25 @@ SET
users_active_half_year = ca.users_active_half_year,
hot_rank = ca.hot_rank,
subscribers_local = ca.subscribers_local,
interactions_month = ca.interactions_month,
report_count = ca.report_count,
unresolved_report_count = ca.unresolved_report_count,
interactions_month = ca.interactions_month
unresolved_report_count = ca.unresolved_report_count
FROM
community_aggregates AS ca
WHERE
community.id = ca.community_id;
community.id = ca.community_id
AND (ca.subscribers != 1
OR ca.posts != 0
OR ca.comments != 0
OR ca.users_active_day != 0
OR ca.users_active_week != 0
OR ca.users_active_month != 0
OR ca.users_active_half_year != 0
OR ca.hot_rank != 0
OR ca.subscribers_local != 0
OR ca.interactions_month != 0
OR ca.report_count != 0
OR ca.unresolved_report_count != 0);
DROP TABLE community_aggregates;
@@ -290,7 +337,7 @@ REINDEX TABLE community;
CREATE INDEX idx_community_hot ON public.community USING btree (hot_rank DESC);
CREATE INDEX idx_community_nonzero_hotrank ON public.community USING btree (published)
CREATE INDEX idx_community_nonzero_hotrank ON community USING btree (published)
WHERE (hot_rank <> (0)::double precision);
CREATE INDEX idx_community_subscribers ON public.community USING btree (subscribers DESC);
@@ -331,7 +378,11 @@ SET
FROM
person_aggregates AS pa
WHERE
person.id = pa.person_id;
person.id = pa.person_id
AND (pa.post_count != 0
OR pa.post_score != 0
OR pa.comment_count != 0
OR pa.comment_score != 0);
DROP TABLE person_aggregates;
@@ -455,7 +506,11 @@ SET
FROM
local_user_vote_display_mode AS v
WHERE
local_user.id = v.local_user_id;
local_user.id = v.local_user_id
AND (v.score
OR NOT v.upvotes
OR NOT v.downvotes
OR v.upvote_percentage);
DROP TABLE local_user_vote_display_mode;

View File

@@ -1,132 +1,18 @@
-- recreate columns in the original order
ALTER TABLE community
ADD COLUMN hidden bool DEFAULT FALSE NOT NULL,
ADD COLUMN posting_restricted_to_mods_new bool NOT NULL DEFAULT FALSE,
ADD COLUMN instance_id_new int,
ADD COLUMN moderators_url_new varchar(255),
ADD COLUMN featured_url_new varchar(255),
ADD COLUMN visibility_new community_visibility NOT NULL DEFAULT 'Public',
ADD COLUMN description_new varchar(150),
ADD COLUMN random_number_new smallint NOT NULL DEFAULT random_smallint (),
ADD COLUMN subscribers_new int NOT NULL DEFAULT 0,
ADD COLUMN posts_new int NOT NULL DEFAULT 0,
ADD COLUMN comments_new int NOT NULL DEFAULT 0,
ADD COLUMN users_active_day_new int NOT NULL DEFAULT 0,
ADD COLUMN users_active_week_new int NOT NULL DEFAULT 0,
ADD COLUMN users_active_month_new int NOT NULL DEFAULT 0,
ADD COLUMN users_active_half_year_new int NOT NULL DEFAULT 0,
ADD COLUMN hot_rank_new double precision NOT NULL DEFAULT 0.0001,
ADD COLUMN subscribers_local_new int NOT NULL DEFAULT 0,
ADD COLUMN report_count_new smallint NOT NULL DEFAULT 0,
ADD COLUMN unresolved_report_count_new smallint NOT NULL DEFAULT 0,
ADD COLUMN interactions_month_new int NOT NULL DEFAULT 0;
ADD COLUMN visibility_new community_visibility NOT NULL DEFAULT 'Public';
UPDATE
community
SET
(posting_restricted_to_mods_new,
instance_id_new,
moderators_url_new,
featured_url_new,
visibility_new,
description_new,
random_number_new,
subscribers_new,
posts_new,
comments_new,
users_active_day_new,
users_active_week_new,
users_active_month_new,
users_active_half_year_new,
hot_rank_new,
subscribers_local_new,
report_count_new,
unresolved_report_count_new,
interactions_month_new) = (posting_restricted_to_mods,
instance_id,
moderators_url,
featured_url,
visibility,
description,
random_number,
subscribers,
posts,
comments,
users_active_day,
users_active_week,
users_active_month,
users_active_half_year,
hot_rank,
subscribers_local,
report_count,
unresolved_report_count,
interactions_month);
visibility_new = visibility;
ALTER TABLE community
ALTER COLUMN instance_id_new SET NOT NULL,
DROP COLUMN posting_restricted_to_mods,
DROP COLUMN instance_id,
DROP COLUMN moderators_url,
DROP COLUMN featured_url,
DROP COLUMN visibility,
DROP COLUMN description,
DROP COLUMN random_number,
DROP COLUMN subscribers,
DROP COLUMN posts,
DROP COLUMN comments,
DROP COLUMN users_active_day,
DROP COLUMN users_active_week,
DROP COLUMN users_active_month,
DROP COLUMN users_active_half_year,
DROP COLUMN hot_rank,
DROP COLUMN subscribers_local,
DROP COLUMN report_count,
DROP COLUMN unresolved_report_count,
DROP COLUMN interactions_month;
ALTER TABLE community RENAME COLUMN posting_restricted_to_mods_new TO posting_restricted_to_mods;
ALTER TABLE community RENAME COLUMN instance_id_new TO instance_id;
ALTER TABLE community RENAME COLUMN moderators_url_new TO moderators_url;
ALTER TABLE community RENAME COLUMN featured_url_new TO featured_url;
DROP COLUMN visibility;
ALTER TABLE community RENAME COLUMN visibility_new TO visibility;
ALTER TABLE community RENAME COLUMN description_new TO description;
ALTER TABLE community RENAME COLUMN random_number_new TO random_number;
ALTER TABLE community RENAME COLUMN subscribers_new TO subscribers;
ALTER TABLE community RENAME COLUMN posts_new TO posts;
ALTER TABLE community RENAME COLUMN comments_new TO comments;
ALTER TABLE community RENAME COLUMN users_active_day_new TO users_active_day;
ALTER TABLE community RENAME COLUMN users_active_week_new TO users_active_week;
ALTER TABLE community RENAME COLUMN users_active_month_new TO users_active_month;
ALTER TABLE community RENAME COLUMN users_active_half_year_new TO users_active_half_year;
ALTER TABLE community RENAME COLUMN hot_rank_new TO hot_rank;
ALTER TABLE community RENAME COLUMN subscribers_local_new TO subscribers_local;
ALTER TABLE community RENAME COLUMN report_count_new TO report_count;
ALTER TABLE community RENAME COLUMN unresolved_report_count_new TO unresolved_report_count;
ALTER TABLE community RENAME COLUMN interactions_month_new TO interactions_month;
ALTER TABLE community
ADD CONSTRAINT community_featured_url_key UNIQUE (featured_url),
ADD CONSTRAINT community_moderators_url_key UNIQUE (moderators_url),
ADD CONSTRAINT community_instance_id_fkey FOREIGN KEY (instance_id) REFERENCES instance (id) ON UPDATE CASCADE ON DELETE CASCADE;
-- same changes as up.sql, but the other way round
UPDATE
community
@@ -161,15 +47,6 @@ CREATE INDEX idx_community_random_number ON community (random_number) INCLUDE (l
WHERE
NOT (deleted OR removed OR visibility = 'Private');
CREATE INDEX idx_community_nonzero_hotrank ON community USING btree (published)
WHERE (hot_rank <> (0)::double precision);
CREATE INDEX idx_community_subscribers ON community USING btree (subscribers DESC);
CREATE INDEX idx_community_users_active_month ON community USING btree (users_active_month DESC);
CREATE INDEX idx_community_hot ON public.community USING btree (hot_rank DESC);
REINDEX TABLE community;
-- revert modlog table changes

View File

@@ -17,11 +17,7 @@ ALTER TABLE person
ADD COLUMN matrix_user_id_new text,
ADD COLUMN bot_account_new boolean DEFAULT FALSE NOT NULL,
ADD COLUMN ban_expires timestamptz,
ADD COLUMN instance_id_new int,
ADD COLUMN post_count_new int DEFAULT 0 NOT NULL,
ADD COLUMN post_score_new int DEFAULT 0 NOT NULL,
ADD COLUMN comment_count_new int DEFAULT 0 NOT NULL,
ADD COLUMN comment_score_new int DEFAULT 0 NOT NULL;
ADD COLUMN instance_id_new int;
UPDATE
person
@@ -39,11 +35,7 @@ SET
inbox_url_new,
matrix_user_id_new,
bot_account_new,
instance_id_new,
post_count_new,
post_score_new,
comment_count_new,
comment_score_new) = (published,
instance_id_new) = (published,
updated,
ap_id,
bio,
@@ -56,11 +48,7 @@ SET
inbox_url,
matrix_user_id,
bot_account,
instance_id,
post_count,
post_score,
comment_count,
comment_score);
instance_id);
ALTER TABLE person
DROP COLUMN published,
@@ -76,11 +64,7 @@ ALTER TABLE person
DROP COLUMN inbox_url,
DROP COLUMN matrix_user_id,
DROP COLUMN bot_account,
DROP COLUMN instance_id,
DROP COLUMN post_count,
DROP COLUMN post_score,
DROP COLUMN comment_count,
DROP COLUMN comment_score;
DROP COLUMN instance_id;
ALTER TABLE person RENAME COLUMN published_new TO published;
@@ -110,14 +94,6 @@ ALTER TABLE person RENAME COLUMN bot_account_new TO bot_account;
ALTER TABLE person RENAME COLUMN instance_id_new TO instance_id;
ALTER TABLE person RENAME COLUMN post_count_new TO post_count;
ALTER TABLE person RENAME COLUMN post_score_new TO post_score;
ALTER TABLE person RENAME COLUMN comment_count_new TO comment_count;
ALTER TABLE person RENAME COLUMN comment_score_new TO comment_score;
ALTER TABLE person
ALTER public_key SET NOT NULL,
ALTER instance_id SET NOT NULL,

View File

@@ -1,339 +0,0 @@
ALTER TABLE post
ADD COLUMN name_new character varying(200),
ADD COLUMN url_new character varying(2000),
ADD COLUMN body_new text,
ADD COLUMN creator_id_new integer,
ADD COLUMN community_id_new integer,
ADD COLUMN removed_new boolean DEFAULT FALSE NOT NULL,
ADD COLUMN locked_new boolean DEFAULT FALSE NOT NULL,
ADD COLUMN published_new timestamp with time zone DEFAULT now() NOT NULL,
ADD COLUMN updated_new timestamp with time zone,
ADD COLUMN deleted_new boolean DEFAULT FALSE NOT NULL,
ADD COLUMN nsfw_new boolean DEFAULT FALSE NOT NULL,
ADD COLUMN embed_title_new text,
ADD COLUMN embed_description_new text,
ADD COLUMN thumbnail_url_new text,
ADD COLUMN ap_id_new character varying(255),
ADD COLUMN local_new boolean DEFAULT TRUE NOT NULL,
ADD COLUMN embed_video_url_new text,
ADD COLUMN language_id_new integer DEFAULT 0 NOT NULL,
ADD COLUMN featured_community_new boolean DEFAULT FALSE NOT NULL,
ADD COLUMN featured_local_new boolean DEFAULT FALSE NOT NULL,
ADD COLUMN url_content_type_new text,
ADD COLUMN alt_text_new text,
ADD COLUMN scheduled_publish_time_new timestamp with time zone,
ADD COLUMN comments_new int DEFAULT 0 NOT NULL,
ADD COLUMN score_new int DEFAULT 0 NOT NULL,
ADD COLUMN upvotes_new int DEFAULT 0 NOT NULL,
ADD COLUMN downvotes_new int DEFAULT 0 NOT NULL,
ADD COLUMN newest_comment_time_necro_new timestamp with time zone DEFAULT now() NOT NULL,
ADD COLUMN newest_comment_time_new timestamp with time zone DEFAULT now() NOT NULL,
ADD COLUMN hot_rank_new double precision DEFAULT 0.0001 NOT NULL,
ADD COLUMN hot_rank_active_new double precision DEFAULT 0.0001 NOT NULL,
ADD COLUMN controversy_rank_new double precision DEFAULT 0 NOT NULL,
-- Old column here
ADD COLUMN instance_id integer,
ADD COLUMN scaled_rank_new double precision DEFAULT 0.0001 NOT NULL,
ADD COLUMN report_count_new smallint DEFAULT 0 NOT NULL,
ADD COLUMN unresolved_report_count_new smallint DEFAULT 0 NOT NULL,
ADD COLUMN federation_pending_new boolean DEFAULT FALSE NOT NULL;
UPDATE
post
SET
(instance_id,
name_new,
url_new,
body_new,
creator_id_new,
community_id_new,
removed_new,
locked_new,
published_new,
updated_new,
deleted_new,
nsfw_new,
embed_title_new,
embed_description_new,
thumbnail_url_new,
ap_id_new,
local_new,
embed_video_url_new,
language_id_new,
featured_community_new,
featured_local_new,
url_content_type_new,
alt_text_new,
scheduled_publish_time_new,
comments_new,
score_new,
upvotes_new,
downvotes_new,
newest_comment_time_necro_new,
newest_comment_time_new,
hot_rank_new,
hot_rank_active_new,
controversy_rank_new,
scaled_rank_new,
report_count_new,
unresolved_report_count_new,
federation_pending_new) = (0,
name,
url,
body,
creator_id,
community_id,
removed,
LOCKED,
published,
updated,
deleted,
nsfw,
embed_title,
embed_description,
thumbnail_url,
ap_id,
local,
embed_video_url,
language_id,
featured_community,
featured_local,
url_content_type,
alt_text,
scheduled_publish_time,
comments,
score,
upvotes,
downvotes,
newest_comment_time_necro,
newest_comment_time,
hot_rank,
hot_rank_active,
controversy_rank,
scaled_rank,
report_count,
unresolved_report_count,
federation_pending);
ALTER TABLE post
DROP COLUMN name,
DROP COLUMN url,
DROP COLUMN body,
DROP COLUMN creator_id,
DROP COLUMN community_id,
DROP COLUMN removed,
DROP COLUMN LOCKED,
DROP COLUMN published,
DROP COLUMN updated,
DROP COLUMN deleted,
DROP COLUMN nsfw,
DROP COLUMN embed_title,
DROP COLUMN embed_description,
DROP COLUMN thumbnail_url,
DROP COLUMN ap_id,
DROP COLUMN local,
DROP COLUMN embed_video_url,
DROP COLUMN language_id,
DROP COLUMN featured_community,
DROP COLUMN featured_local,
DROP COLUMN url_content_type,
DROP COLUMN alt_text,
DROP COLUMN scheduled_publish_time,
DROP COLUMN comments,
DROP COLUMN score,
DROP COLUMN upvotes,
DROP COLUMN downvotes,
DROP COLUMN newest_comment_time_necro,
DROP COLUMN newest_comment_time,
DROP COLUMN hot_rank,
DROP COLUMN hot_rank_active,
DROP COLUMN controversy_rank,
DROP COLUMN scaled_rank,
DROP COLUMN report_count,
DROP COLUMN unresolved_report_count,
DROP COLUMN federation_pending;
ALTER TABLE post RENAME COLUMN name_new TO name;
ALTER TABLE post RENAME COLUMN url_new TO url;
ALTER TABLE post RENAME COLUMN body_new TO body;
ALTER TABLE post RENAME COLUMN creator_id_new TO creator_id;
ALTER TABLE post RENAME COLUMN community_id_new TO community_id;
ALTER TABLE post RENAME COLUMN removed_new TO removed;
ALTER TABLE post RENAME COLUMN locked_new TO LOCKED;
ALTER TABLE post RENAME COLUMN published_new TO published;
ALTER TABLE post RENAME COLUMN updated_new TO updated;
ALTER TABLE post RENAME COLUMN deleted_new TO deleted;
ALTER TABLE post RENAME COLUMN nsfw_new TO nsfw;
ALTER TABLE post RENAME COLUMN embed_title_new TO embed_title;
ALTER TABLE post RENAME COLUMN embed_description_new TO embed_description;
ALTER TABLE post RENAME COLUMN thumbnail_url_new TO thumbnail_url;
ALTER TABLE post RENAME COLUMN ap_id_new TO ap_id;
ALTER TABLE post RENAME COLUMN local_new TO local;
ALTER TABLE post RENAME COLUMN embed_video_url_new TO embed_video_url;
ALTER TABLE post RENAME COLUMN language_id_new TO language_id;
ALTER TABLE post RENAME COLUMN featured_community_new TO featured_community;
ALTER TABLE post RENAME COLUMN featured_local_new TO featured_local;
ALTER TABLE post RENAME COLUMN url_content_type_new TO url_content_type;
ALTER TABLE post RENAME COLUMN alt_text_new TO alt_text;
ALTER TABLE post RENAME COLUMN scheduled_publish_time_new TO scheduled_publish_time;
ALTER TABLE post RENAME COLUMN comments_new TO comments;
ALTER TABLE post RENAME COLUMN score_new TO score;
ALTER TABLE post RENAME COLUMN upvotes_new TO upvotes;
ALTER TABLE post RENAME COLUMN downvotes_new TO downvotes;
ALTER TABLE post RENAME COLUMN newest_comment_time_necro_new TO newest_comment_time_necro;
ALTER TABLE post RENAME COLUMN newest_comment_time_new TO newest_comment_time;
ALTER TABLE post RENAME COLUMN hot_rank_new TO hot_rank;
ALTER TABLE post RENAME COLUMN hot_rank_active_new TO hot_rank_active;
ALTER TABLE post RENAME COLUMN controversy_rank_new TO controversy_rank;
ALTER TABLE post RENAME COLUMN scaled_rank_new TO scaled_rank;
ALTER TABLE post RENAME COLUMN report_count_new TO report_count;
ALTER TABLE post RENAME COLUMN unresolved_report_count_new TO unresolved_report_count;
ALTER TABLE post RENAME COLUMN federation_pending_new TO federation_pending;
-- Update the historical instance_id rows
UPDATE
post AS p
SET
instance_id = c.instance_id
FROM
community AS c
WHERE
p.community_id = c.id;
ALTER TABLE ONLY post
ADD CONSTRAINT idx_post_ap_id UNIQUE (ap_id);
CREATE INDEX idx_post_community ON post USING btree (community_id);
CREATE INDEX idx_post_community_active ON post USING btree (community_id, featured_local DESC, hot_rank_active DESC, published DESC, id DESC);
CREATE INDEX idx_post_community_controversy ON post USING btree (community_id, featured_local DESC, controversy_rank DESC, id DESC);
CREATE INDEX idx_post_community_hot ON post USING btree (community_id, featured_local DESC, hot_rank DESC, published DESC, id DESC);
CREATE INDEX idx_post_community_most_comments ON post USING btree (community_id, featured_local DESC, comments DESC, published DESC, id DESC);
CREATE INDEX idx_post_community_newest_comment_time ON post USING btree (community_id, featured_local DESC, newest_comment_time DESC, id DESC);
CREATE INDEX idx_post_community_newest_comment_time_necro ON post USING btree (community_id, featured_local DESC, newest_comment_time_necro DESC, id DESC);
CREATE INDEX idx_post_community_scaled ON post USING btree (community_id, featured_local DESC, scaled_rank DESC, published DESC, id DESC);
CREATE INDEX idx_post_community_score ON post USING btree (community_id, featured_local DESC, score DESC, published DESC, id DESC);
CREATE INDEX idx_post_creator ON post USING btree (creator_id);
CREATE INDEX idx_post_featured_community_active ON post USING btree (community_id, featured_community DESC, hot_rank_active DESC, published DESC, id DESC);
CREATE INDEX idx_post_featured_community_controversy ON post USING btree (community_id, featured_community DESC, controversy_rank DESC, id DESC);
CREATE INDEX idx_post_featured_community_hot ON post USING btree (community_id, featured_community DESC, hot_rank DESC, published DESC, id DESC);
CREATE INDEX idx_post_featured_community_most_comments ON post USING btree (community_id, featured_community DESC, comments DESC, published DESC, id DESC);
CREATE INDEX idx_post_featured_community_newest_comment_time ON post USING btree (community_id, featured_community DESC, newest_comment_time DESC, id DESC);
CREATE INDEX idx_post_featured_community_newest_comment_time_necr ON post USING btree (community_id, featured_community DESC, newest_comment_time_necro DESC, id DESC);
CREATE INDEX idx_post_featured_community_published_asc ON post USING btree (community_id, featured_community DESC, reverse_timestamp_sort (published) DESC, id DESC);
CREATE INDEX idx_post_featured_community_scaled ON post USING btree (community_id, featured_community DESC, scaled_rank DESC, published DESC, id DESC);
CREATE INDEX idx_post_featured_community_score ON post USING btree (community_id, featured_community DESC, score DESC, published DESC, id DESC);
CREATE INDEX idx_post_featured_local_active ON post USING btree (featured_local DESC, hot_rank_active DESC, published DESC, id DESC);
CREATE INDEX idx_post_featured_local_controversy ON post USING btree (featured_local DESC, controversy_rank DESC, id DESC);
CREATE INDEX idx_post_featured_local_hot ON post USING btree (featured_local DESC, hot_rank DESC, published DESC, id DESC);
CREATE INDEX idx_post_featured_local_most_comments ON post USING btree (featured_local DESC, comments DESC, published DESC, id DESC);
CREATE INDEX idx_post_featured_local_newest_comment_time ON post USING btree (featured_local DESC, newest_comment_time DESC, id DESC);
CREATE INDEX idx_post_featured_local_newest_comment_time_necro ON post USING btree (featured_local DESC, newest_comment_time_necro DESC, id DESC);
CREATE INDEX idx_post_featured_local_published ON post USING btree (featured_local DESC, published DESC, id DESC);
CREATE INDEX idx_post_featured_local_published_asc ON post USING btree (featured_local DESC, reverse_timestamp_sort (published) DESC, id DESC);
CREATE INDEX idx_post_featured_local_scaled ON post USING btree (featured_local DESC, scaled_rank DESC, published DESC, id DESC);
CREATE INDEX idx_post_featured_local_score ON post USING btree (featured_local DESC, score DESC, published DESC, id DESC);
CREATE INDEX idx_post_language ON post USING btree (language_id);
CREATE INDEX idx_post_nonzero_hotrank ON post USING btree (published DESC)
WHERE ((hot_rank <> (0)::double precision) OR (hot_rank_active <> (0)::double precision));
CREATE INDEX idx_post_published ON post USING btree (published);
CREATE INDEX idx_post_published_asc ON post USING btree (reverse_timestamp_sort (published) DESC);
CREATE INDEX idx_post_scheduled_publish_time ON post USING btree (scheduled_publish_time);
CREATE INDEX idx_post_trigram ON post USING gin (name gin_trgm_ops, body gin_trgm_ops, alt_text gin_trgm_ops);
CREATE INDEX idx_post_url ON post USING btree (url);
CREATE INDEX idx_post_url_content_type ON post USING gin (url_content_type gin_trgm_ops);
ALTER TABLE ONLY post
ADD CONSTRAINT post_community_id_fkey FOREIGN KEY (community_id) REFERENCES community (id) ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE ONLY post
ADD CONSTRAINT post_creator_id_fkey FOREIGN KEY (creator_id) REFERENCES person (id) ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE ONLY post
ADD CONSTRAINT post_language_id_fkey FOREIGN KEY (language_id) REFERENCES LANGUAGE (id);
ALTER TABLE ONLY post
ADD CONSTRAINT post_instance_id_fkey FOREIGN KEY (instance_id) REFERENCES instance (id) ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE post
ALTER COLUMN name SET NOT NULL;
ALTER TABLE post
ALTER COLUMN creator_id SET NOT NULL;
ALTER TABLE post
ALTER COLUMN community_id SET NOT NULL;
ALTER TABLE post
ALTER COLUMN ap_id SET NOT NULL;

View File

@@ -1,3 +0,0 @@
ALTER TABLE post
DROP COLUMN instance_id;

View File

@@ -2,13 +2,13 @@
CREATE INDEX idx_tagline_published_id ON tagline (published DESC, id DESC);
-- Some for the vote views
CREATE INDEX idx_comment_actions_like_score ON comment_actions (comment_id, like_score, person_id)
CREATE INDEX idx_comment_actions_like_score ON comment_actions (comment_id, vote_is_upvote, person_id)
WHERE
like_score IS NOT NULL;
vote_is_upvote IS NOT NULL;
CREATE INDEX idx_post_actions_like_score ON post_actions (post_id, like_score, person_id)
CREATE INDEX idx_post_actions_like_score ON post_actions (post_id, vote_is_upvote, person_id)
WHERE
like_score IS NOT NULL;
vote_is_upvote IS NOT NULL;
-- Fixing the community sorts for an id tie-breaker
DROP INDEX idx_community_lower_name;

View File

@@ -2,13 +2,22 @@
-- person_liked: (comment, post)
-- This one is special, because you use the liked date, not the ordinary published
-- Updating the history
CREATE SEQUENCE person_liked_combined_id_seq
AS integer START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
CREATE TABLE person_liked_combined AS
SELECT
pa.liked,
pa.like_score,
-- `ADD COLUMN id serial` is not used for this because it would require either putting the column at the end (might increase the amount of padding bytes) or using an `INSERT` statement (not parallelizable).
nextval('person_liked_combined_id_seq'::regclass)::int AS id,
pa.person_id,
pa.post_id,
NULL::int AS comment_id
NULL::int AS comment_id,
pa.vote_is_upvote
FROM
post_actions pa
INNER JOIN person p ON pa.person_id = p.id
@@ -18,10 +27,11 @@ WHERE
UNION ALL
SELECT
ca.liked,
ca.like_score,
nextval('person_liked_combined_id_seq'::regclass)::int,
ca.person_id,
NULL::int,
ca.comment_id
ca.comment_id,
ca.vote_is_upvote
FROM
comment_actions ca
INNER JOIN person p ON ca.person_id = p.id
@@ -30,16 +40,19 @@ WHERE
AND p.local = TRUE;
ALTER TABLE person_liked_combined
ADD COLUMN id int PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
ALTER COLUMN id SET DEFAULT nextval('person_liked_combined_id_seq'::regclass),
ALTER COLUMN liked SET NOT NULL,
ALTER COLUMN like_score SET NOT NULL,
ALTER COLUMN vote_is_upvote SET NOT NULL,
ALTER COLUMN person_id SET NOT NULL,
ADD CONSTRAINT person_liked_combined_person_id_fkey FOREIGN KEY (person_id) REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE,
ADD CONSTRAINT person_liked_combined_post_id_fkey FOREIGN KEY (post_id) REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE,
ADD CONSTRAINT person_liked_combined_comment_id_fkey FOREIGN KEY (comment_id) REFERENCES COMMENT ON UPDATE CASCADE ON DELETE CASCADE,
ADD UNIQUE (person_id, post_id),
ADD UNIQUE (person_id, comment_id),
ADD PRIMARY KEY (id),
ADD CONSTRAINT person_liked_combined_check CHECK (num_nonnulls (post_id, comment_id) = 1);
ALTER SEQUENCE person_liked_combined_id_seq OWNED BY person_liked_combined.id;
CREATE INDEX idx_person_liked_combined ON person_liked_combined (person_id);

View File

@@ -18,7 +18,7 @@ ALTER TABLE comment RENAME COLUMN published_at TO published;
ALTER TABLE comment RENAME COLUMN updated_at TO updated;
ALTER TABLE comment_actions RENAME COLUMN liked_at TO liked;
ALTER TABLE comment_actions RENAME COLUMN voted_at TO liked;
ALTER TABLE comment_actions RENAME COLUMN saved_at TO saved;
@@ -148,7 +148,7 @@ ALTER TABLE person_comment_mention RENAME COLUMN published_at TO published;
ALTER TABLE person_content_combined RENAME COLUMN published_at TO published;
ALTER TABLE person_liked_combined RENAME COLUMN liked_at TO liked;
ALTER TABLE person_liked_combined RENAME COLUMN voted_at TO liked;
ALTER TABLE person_post_mention RENAME COLUMN published_at TO published;
@@ -170,7 +170,7 @@ ALTER TABLE post_actions RENAME COLUMN read_comments_at TO read_comments;
ALTER TABLE post_actions RENAME COLUMN saved_at TO saved;
ALTER TABLE post_actions RENAME COLUMN liked_at TO liked;
ALTER TABLE post_actions RENAME COLUMN voted_at TO liked;
ALTER TABLE post_actions RENAME COLUMN hidden_at TO hidden;

View File

@@ -18,7 +18,7 @@ ALTER TABLE comment RENAME COLUMN published TO published_at;
ALTER TABLE comment RENAME COLUMN updated TO updated_at;
ALTER TABLE comment_actions RENAME COLUMN liked TO liked_at;
ALTER TABLE comment_actions RENAME COLUMN liked TO voted_at;
ALTER TABLE comment_actions RENAME COLUMN saved TO saved_at;
@@ -148,7 +148,7 @@ ALTER TABLE person_comment_mention RENAME COLUMN published TO published_at;
ALTER TABLE person_content_combined RENAME COLUMN published TO published_at;
ALTER TABLE person_liked_combined RENAME COLUMN liked TO liked_at;
ALTER TABLE person_liked_combined RENAME COLUMN liked TO voted_at;
ALTER TABLE person_post_mention RENAME COLUMN published TO published_at;
@@ -170,7 +170,7 @@ ALTER TABLE post_actions RENAME COLUMN read_comments TO read_comments_at;
ALTER TABLE post_actions RENAME COLUMN saved TO saved_at;
ALTER TABLE post_actions RENAME COLUMN liked TO liked_at;
ALTER TABLE post_actions RENAME COLUMN liked TO voted_at;
ALTER TABLE post_actions RENAME COLUMN hidden TO hidden_at;

View File

@@ -20,13 +20,13 @@ SELECT
votes.person_id,
votes.creator_id,
now(),
count(*) FILTER (WHERE votes.like_score = 1) AS upvotes,
count(*) FILTER (WHERE votes.like_score != 1) AS downvotes
count(*) FILTER (WHERE votes.vote_is_upvote) AS upvotes,
count(*) FILTER (WHERE NOT votes.vote_is_upvote) AS downvotes
FROM (
SELECT
pa.person_id,
p.creator_id,
like_score
vote_is_upvote
FROM
post_actions pa
INNER JOIN post p ON pa.post_id = p.id
@@ -35,7 +35,7 @@ FROM (
SELECT
ca.person_id,
c.creator_id,
like_score
vote_is_upvote
FROM
comment_actions ca
INNER JOIN comment c ON ca.comment_id = c.id

View File

@@ -1,2 +1,2 @@
DROP INDEX idx_post_actions_liked_at, idx_comment_actions_liked_at;
DROP INDEX idx_post_actions_voted_at, idx_comment_actions_voted_at;

View File

@@ -1,8 +1,8 @@
CREATE INDEX idx_post_actions_liked_at ON post_actions (liked_at)
CREATE INDEX idx_post_actions_voted_at ON post_actions (voted_at)
WHERE
liked_at IS NOT NULL;
voted_at IS NOT NULL;
CREATE INDEX idx_comment_actions_liked_at ON comment_actions (liked_at)
CREATE INDEX idx_comment_actions_voted_at ON comment_actions (voted_at)
WHERE
liked_at IS NOT NULL;
voted_at IS NOT NULL;