improve admin and mod check to not do seq scans and return unnecessary data (#3483)
authorphiresky <phireskyde+git@gmail.com>
Thu, 6 Jul 2023 12:44:26 +0000 (14:44 +0200)
committerGitHub <noreply@github.com>
Thu, 6 Jul 2023 12:44:26 +0000 (14:44 +0200)
* improve admin and mod check

* fix clippy

* move admin index to existing code

* Revert "move admin index to existing code"

This reverts commit d0c58d5f4021e1775d0c1d30d8df6c7df87557c4.

* third attempt at the migration

* fix formatting

* rebuild

---------

Co-authored-by: Dessalines <dessalines@users.noreply.github.com>
crates/db_views_actor/src/community_moderator_view.rs
crates/db_views_actor/src/community_view.rs
crates/db_views_actor/src/person_view.rs
migrations/2023-07-04-153335_add_optimized_indexes/up.sql
migrations/2023-07-05-000058_person-admin/down.sql [new file with mode: 0644]
migrations/2023-07-05-000058_person-admin/up.sql [new file with mode: 0644]

index 63b4a5a5f9bab1d83752e65376740cf1fd2c89cc..113efe4b7fcb4df30abd8073815793a88384202c 100644 (file)
@@ -1,5 +1,5 @@
 use crate::structs::CommunityModeratorView;
-use diesel::{result::Error, ExpressionMethods, QueryDsl};
+use diesel::{dsl::exists, result::Error, select, ExpressionMethods, QueryDsl};
 use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::{CommunityId, PersonId},
@@ -12,6 +12,25 @@ use lemmy_db_schema::{
 type CommunityModeratorViewTuple = (Community, Person);
 
 impl CommunityModeratorView {
+  pub async fn is_community_moderator(
+    pool: &DbPool,
+    find_community_id: CommunityId,
+    find_person_id: PersonId,
+  ) -> Result<bool, Error> {
+    use lemmy_db_schema::schema::community_moderator::dsl::{
+      community_id,
+      community_moderator,
+      person_id,
+    };
+    let conn = &mut get_conn(pool).await?;
+    select(exists(
+      community_moderator
+        .filter(community_id.eq(find_community_id))
+        .filter(person_id.eq(find_person_id)),
+    ))
+    .get_result::<bool>(conn)
+    .await
+  }
   pub async fn for_community(pool: &DbPool, community_id: CommunityId) -> Result<Vec<Self>, Error> {
     let conn = &mut get_conn(pool).await?;
     let res = community_moderator::table
index 899931c4f4a1da5d8d99e0cbe92293e9280e3862..991c4cdd5df11dad4510ca5672b2d0d90dd13d6e 100644 (file)
@@ -90,29 +90,13 @@ impl CommunityView {
     person_id: PersonId,
     community_id: CommunityId,
   ) -> Result<bool, Error> {
-    let is_mod = CommunityModeratorView::for_community(pool, community_id)
-      .await
-      .map(|v| {
-        v.into_iter()
-          .map(|m| m.moderator.id)
-          .collect::<Vec<PersonId>>()
-      })
-      .unwrap_or_default()
-      .contains(&person_id);
+    let is_mod =
+      CommunityModeratorView::is_community_moderator(pool, community_id, person_id).await?;
     if is_mod {
       return Ok(true);
     }
 
-    let is_admin = PersonView::admins(pool)
-      .await
-      .map(|v| {
-        v.into_iter()
-          .map(|a| a.person.id)
-          .collect::<Vec<PersonId>>()
-      })
-      .unwrap_or_default()
-      .contains(&person_id);
-    Ok(is_admin)
+    PersonView::is_admin(pool, person_id).await
   }
 }
 
index 2a7a2ce79466a935f731026337c592e4f368e615..06215123b080038107e1e36a57175ac6f506f4c4 100644 (file)
@@ -11,6 +11,7 @@ use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   aggregates::structs::PersonAggregates,
   newtypes::PersonId,
+  schema,
   schema::{person, person_aggregates},
   source::person::Person,
   traits::JoinView,
@@ -34,6 +35,16 @@ impl PersonView {
     Ok(Self::from_tuple(res))
   }
 
+  pub async fn is_admin(pool: &DbPool, person_id: PersonId) -> Result<bool, Error> {
+    use schema::person::dsl::{admin, id, person};
+    let conn = &mut get_conn(pool).await?;
+    let is_admin = person
+      .filter(id.eq(person_id))
+      .select(admin)
+      .first::<bool>(conn)
+      .await?;
+    Ok(is_admin)
+  }
   pub async fn admins(pool: &DbPool) -> Result<Vec<Self>, Error> {
     let conn = &mut get_conn(pool).await?;
     let admins = person::table
index c2911df79c9c4813c2169bf1ad141f37dd6041f4..c55ecee9d34b484924c2c908e5e71e8752081aab 100644 (file)
@@ -1,5 +1,5 @@
 -- Create an admin person index
-create index idx_person_admin on person (admin);
+create index if not exists idx_person_admin on person (admin);
 
 -- Compound indexes, using featured_, then the other sorts, proved to be much faster
 -- Drop the old indexes
diff --git a/migrations/2023-07-05-000058_person-admin/down.sql b/migrations/2023-07-05-000058_person-admin/down.sql
new file mode 100644 (file)
index 0000000..b77e174
--- /dev/null
@@ -0,0 +1,2 @@
+drop index idx_person_admin;
+create index idx_person_admin on person(admin);
\ No newline at end of file
diff --git a/migrations/2023-07-05-000058_person-admin/up.sql b/migrations/2023-07-05-000058_person-admin/up.sql
new file mode 100644 (file)
index 0000000..c71052e
--- /dev/null
@@ -0,0 +1,2 @@
+drop index if exists idx_person_admin;
+create index idx_person_admin on person(admin) where admin; -- allow quickly finding all admins (PersonView::admins)
\ No newline at end of file