Remove usages of FIND_IN_SET
FIND_IN_SET doesn't make use of indexes
This commit is contained in:
		@@ -72,55 +72,60 @@ pub async fn get_reminders(
 | 
			
		||||
 | 
			
		||||
    match channels_res {
 | 
			
		||||
        Ok(channels) => {
 | 
			
		||||
            let channels = channels
 | 
			
		||||
                .keys()
 | 
			
		||||
                .into_iter()
 | 
			
		||||
                .map(|k| k.get().to_string())
 | 
			
		||||
                .collect::<Vec<String>>()
 | 
			
		||||
                .join(",");
 | 
			
		||||
            let channels =
 | 
			
		||||
                channels.keys().into_iter().map(|k| k.get().to_string()).collect::<Vec<String>>();
 | 
			
		||||
 | 
			
		||||
            sqlx::query_as_unchecked!(
 | 
			
		||||
                GetReminder,
 | 
			
		||||
            let placeholder = vec!["?"; channels.len()].join(",");
 | 
			
		||||
            let sql = format!(
 | 
			
		||||
                "
 | 
			
		||||
                SELECT
 | 
			
		||||
                 reminders.attachment_name,
 | 
			
		||||
                 reminders.avatar,
 | 
			
		||||
                 channels.channel,
 | 
			
		||||
                 reminders.content,
 | 
			
		||||
                 reminders.embed_author,
 | 
			
		||||
                 reminders.embed_author_url,
 | 
			
		||||
                 reminders.embed_color,
 | 
			
		||||
                 reminders.embed_description,
 | 
			
		||||
                 reminders.embed_footer,
 | 
			
		||||
                 reminders.embed_footer_url,
 | 
			
		||||
                 reminders.embed_image_url,
 | 
			
		||||
                 reminders.embed_thumbnail_url,
 | 
			
		||||
                 reminders.embed_title,
 | 
			
		||||
                 IFNULL(reminders.embed_fields, '[]') AS embed_fields,
 | 
			
		||||
                 reminders.enabled,
 | 
			
		||||
                 reminders.expires,
 | 
			
		||||
                 reminders.interval_seconds,
 | 
			
		||||
                 reminders.interval_days,
 | 
			
		||||
                 reminders.interval_months,
 | 
			
		||||
                 reminders.name,
 | 
			
		||||
                 reminders.restartable,
 | 
			
		||||
                 reminders.tts,
 | 
			
		||||
                 reminders.uid,
 | 
			
		||||
                 reminders.username,
 | 
			
		||||
                 reminders.utc_time
 | 
			
		||||
                    reminders.attachment_name,
 | 
			
		||||
                    reminders.avatar,
 | 
			
		||||
                    channels.channel,
 | 
			
		||||
                    reminders.content,
 | 
			
		||||
                    reminders.embed_author,
 | 
			
		||||
                    reminders.embed_author_url,
 | 
			
		||||
                    reminders.embed_color,
 | 
			
		||||
                    reminders.embed_description,
 | 
			
		||||
                    reminders.embed_footer,
 | 
			
		||||
                    reminders.embed_footer_url,
 | 
			
		||||
                    reminders.embed_image_url,
 | 
			
		||||
                    reminders.embed_thumbnail_url,
 | 
			
		||||
                    reminders.embed_title,
 | 
			
		||||
                    IFNULL(reminders.embed_fields, '[]') AS embed_fields,
 | 
			
		||||
                    reminders.enabled,
 | 
			
		||||
                    reminders.expires,
 | 
			
		||||
                    reminders.interval_seconds,
 | 
			
		||||
                    reminders.interval_days,
 | 
			
		||||
                    reminders.interval_months,
 | 
			
		||||
                    reminders.name,
 | 
			
		||||
                    reminders.restartable,
 | 
			
		||||
                    reminders.tts,
 | 
			
		||||
                    reminders.uid,
 | 
			
		||||
                    reminders.username,
 | 
			
		||||
                    reminders.utc_time
 | 
			
		||||
                FROM reminders
 | 
			
		||||
                INNER JOIN channels ON channels.id = reminders.channel_id
 | 
			
		||||
                WHERE `status` = 'pending' AND FIND_IN_SET(channels.channel, ?)",
 | 
			
		||||
                channels
 | 
			
		||||
            )
 | 
			
		||||
            .fetch_all(pool.inner())
 | 
			
		||||
            .await
 | 
			
		||||
            .map(|r| Ok(json!(r)))
 | 
			
		||||
            .unwrap_or_else(|e| {
 | 
			
		||||
                warn!("Failed to complete SQL query: {:?}", e);
 | 
			
		||||
                INNER JOIN channels
 | 
			
		||||
                    ON channels.id = reminders.channel_id
 | 
			
		||||
                WHERE `status` = 'pending'
 | 
			
		||||
                    AND channels.channel IN ({placeholder})
 | 
			
		||||
                "
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
                json_err!("Could not load reminders")
 | 
			
		||||
            })
 | 
			
		||||
            let mut query = sqlx::query_as::<Database, GetReminder>(&sql);
 | 
			
		||||
            for channel in channels {
 | 
			
		||||
                query = query.bind(channel);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            query
 | 
			
		||||
                .fetch_all(pool.inner())
 | 
			
		||||
                .await
 | 
			
		||||
                .map(|reminders| Ok(json!(reminders)))
 | 
			
		||||
                .unwrap_or_else(|e| {
 | 
			
		||||
                    warn!("Failed to complete SQL query: {:?}", e);
 | 
			
		||||
 | 
			
		||||
                    json_err!("Could not load reminders")
 | 
			
		||||
                })
 | 
			
		||||
        }
 | 
			
		||||
        Err(e) => {
 | 
			
		||||
            warn!("Could not fetch channels from {}: {:?}", id, e);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,14 @@
 | 
			
		||||
use crate::web::{
 | 
			
		||||
    check_authorization,
 | 
			
		||||
    guards::transaction::Transaction,
 | 
			
		||||
    routes::{
 | 
			
		||||
        dashboard::{
 | 
			
		||||
            create_reminder, CreateReminder, ImportBody, ReminderCsv, ReminderTemplateCsv, TodoCsv,
 | 
			
		||||
        },
 | 
			
		||||
        JsonResult,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
use crate::Database;
 | 
			
		||||
use base64::{prelude::BASE64_STANDARD, Engine};
 | 
			
		||||
use csv::{QuoteStyle, WriterBuilder};
 | 
			
		||||
use log::warn;
 | 
			
		||||
@@ -14,17 +25,6 @@ use serenity::{
 | 
			
		||||
};
 | 
			
		||||
use sqlx::{MySql, Pool};
 | 
			
		||||
 | 
			
		||||
use crate::web::{
 | 
			
		||||
    check_authorization,
 | 
			
		||||
    guards::transaction::Transaction,
 | 
			
		||||
    routes::{
 | 
			
		||||
        dashboard::{
 | 
			
		||||
            create_reminder, CreateReminder, ImportBody, ReminderCsv, ReminderTemplateCsv, TodoCsv,
 | 
			
		||||
        },
 | 
			
		||||
        JsonResult,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#[get("/api/guild/<id>/export/reminders")]
 | 
			
		||||
pub async fn export_reminders(
 | 
			
		||||
    id: u64,
 | 
			
		||||
@@ -40,48 +40,47 @@ pub async fn export_reminders(
 | 
			
		||||
 | 
			
		||||
    match channels_res {
 | 
			
		||||
        Ok(channels) => {
 | 
			
		||||
            let channels = channels
 | 
			
		||||
                .keys()
 | 
			
		||||
                .into_iter()
 | 
			
		||||
                .map(|k| k.get().to_string())
 | 
			
		||||
                .collect::<Vec<String>>()
 | 
			
		||||
                .join(",");
 | 
			
		||||
 | 
			
		||||
            let result = sqlx::query_as_unchecked!(
 | 
			
		||||
                ReminderCsv,
 | 
			
		||||
                "SELECT
 | 
			
		||||
                 reminders.attachment,
 | 
			
		||||
                 reminders.attachment_name,
 | 
			
		||||
                 reminders.avatar,
 | 
			
		||||
                 CONCAT('#', channels.channel) AS channel,
 | 
			
		||||
                 reminders.content,
 | 
			
		||||
                 reminders.embed_author,
 | 
			
		||||
                 reminders.embed_author_url,
 | 
			
		||||
                 reminders.embed_color,
 | 
			
		||||
                 reminders.embed_description,
 | 
			
		||||
                 reminders.embed_footer,
 | 
			
		||||
                 reminders.embed_footer_url,
 | 
			
		||||
                 reminders.embed_image_url,
 | 
			
		||||
                 reminders.embed_thumbnail_url,
 | 
			
		||||
                 reminders.embed_title,
 | 
			
		||||
                 reminders.embed_fields,
 | 
			
		||||
                 reminders.enabled,
 | 
			
		||||
                 reminders.expires,
 | 
			
		||||
                 reminders.interval_seconds,
 | 
			
		||||
                 reminders.interval_days,
 | 
			
		||||
                 reminders.interval_months,
 | 
			
		||||
                 reminders.name,
 | 
			
		||||
                 reminders.restartable,
 | 
			
		||||
                 reminders.tts,
 | 
			
		||||
                 reminders.username,
 | 
			
		||||
                 reminders.utc_time
 | 
			
		||||
            let channels =
 | 
			
		||||
                channels.keys().into_iter().map(|k| k.get().to_string()).collect::<Vec<String>>();
 | 
			
		||||
            let placeholder = vec!["?"; channels.len()].join(",");
 | 
			
		||||
            let sql = format!(
 | 
			
		||||
                "
 | 
			
		||||
                SELECT
 | 
			
		||||
                    reminders.attachment,
 | 
			
		||||
                    reminders.attachment_name,
 | 
			
		||||
                    reminders.avatar,
 | 
			
		||||
                    CONCAT('#', channels.channel) AS channel,
 | 
			
		||||
                    reminders.content,
 | 
			
		||||
                    reminders.embed_author,
 | 
			
		||||
                    reminders.embed_author_url,
 | 
			
		||||
                    reminders.embed_color,
 | 
			
		||||
                    reminders.embed_description,
 | 
			
		||||
                    reminders.embed_footer,
 | 
			
		||||
                    reminders.embed_footer_url,
 | 
			
		||||
                    reminders.embed_image_url,
 | 
			
		||||
                    reminders.embed_thumbnail_url,
 | 
			
		||||
                    reminders.embed_title,
 | 
			
		||||
                    reminders.embed_fields,
 | 
			
		||||
                    reminders.enabled,
 | 
			
		||||
                    reminders.expires,
 | 
			
		||||
                    reminders.interval_seconds,
 | 
			
		||||
                    reminders.interval_days,
 | 
			
		||||
                    reminders.interval_months,
 | 
			
		||||
                    reminders.name,
 | 
			
		||||
                    reminders.restartable,
 | 
			
		||||
                    reminders.tts,
 | 
			
		||||
                    reminders.username,
 | 
			
		||||
                    reminders.utc_time
 | 
			
		||||
                FROM reminders
 | 
			
		||||
                LEFT JOIN channels ON channels.id = reminders.channel_id
 | 
			
		||||
                WHERE FIND_IN_SET(channels.channel, ?) AND status = 'pending'",
 | 
			
		||||
                channels
 | 
			
		||||
            )
 | 
			
		||||
            .fetch_all(pool.inner())
 | 
			
		||||
            .await;
 | 
			
		||||
                LEFT JOIN channels
 | 
			
		||||
                    ON channels.id = reminders.channel_id
 | 
			
		||||
                WHERE status = 'pending'
 | 
			
		||||
                    AND channels.channel IN ({placeholder})
 | 
			
		||||
                "
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            let result =
 | 
			
		||||
                sqlx::query_as::<Database, ReminderCsv>(&sql).fetch_all(pool.inner()).await;
 | 
			
		||||
 | 
			
		||||
            match result {
 | 
			
		||||
                Ok(reminders) => {
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@ use serenity::{
 | 
			
		||||
    model::id::{ChannelId, GuildId, UserId},
 | 
			
		||||
};
 | 
			
		||||
use sqlx::types::Json;
 | 
			
		||||
use sqlx::FromRow;
 | 
			
		||||
 | 
			
		||||
use crate::web::{
 | 
			
		||||
    catchers::internal_server_error,
 | 
			
		||||
@@ -177,7 +178,7 @@ pub struct CreateReminder {
 | 
			
		||||
    utc_time: NaiveDateTime,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize)]
 | 
			
		||||
#[derive(Serialize, FromRow)]
 | 
			
		||||
pub struct GetReminder {
 | 
			
		||||
    attachment_name: Option<String>,
 | 
			
		||||
    avatar: Option<String>,
 | 
			
		||||
@@ -209,7 +210,7 @@ pub struct GetReminder {
 | 
			
		||||
    utc_time: NaiveDateTime,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize)]
 | 
			
		||||
#[derive(Serialize, Deserialize, FromRow)]
 | 
			
		||||
pub struct ReminderCsv {
 | 
			
		||||
    attachment: Option<Attachment>,
 | 
			
		||||
    attachment_name: Option<String>,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user