mirror of
https://github.com/chatmail/core.git
synced 2026-05-20 23:36:30 +03:00
fix: reduce number of repeat_vars() calls
SQL statements fail if the number of variables exceeds `SQLITE_LIMIT_VARIABLE_NUMBER`. Remaining repeat_vars() calls are difficult to replace and use arrays passed from the UI, e.g. forwarded message IDs or marked as seen IDs.
This commit is contained in:
17
src/chat.rs
17
src/chat.rs
@@ -3267,14 +3267,17 @@ pub async fn marknoticed_chat(context: &Context, chat_id: ChatId) -> Result<()>
|
|||||||
|
|
||||||
context
|
context
|
||||||
.sql
|
.sql
|
||||||
.execute(
|
.transaction(|transaction| {
|
||||||
&format!(
|
let mut stmt = transaction.prepare(
|
||||||
"UPDATE msgs SET state=13 WHERE state=10 AND hidden=0 AND chat_id IN ({});",
|
"UPDATE msgs SET state=13 WHERE state=10 AND hidden=0 AND chat_id = ?",
|
||||||
sql::repeat_vars(chat_ids_in_archive.len())
|
)?;
|
||||||
),
|
for chat_id_in_archive in &chat_ids_in_archive {
|
||||||
rusqlite::params_from_iter(&chat_ids_in_archive),
|
stmt.execute((chat_id_in_archive,))?;
|
||||||
)
|
}
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
for chat_id_in_archive in chat_ids_in_archive {
|
for chat_id_in_archive in chat_ids_in_archive {
|
||||||
context.emit_event(EventType::MsgsNoticed(chat_id_in_archive));
|
context.emit_event(EventType::MsgsNoticed(chat_id_in_archive));
|
||||||
chatlist_events::emit_chatlist_item_changed(context, chat_id_in_archive);
|
chatlist_events::emit_chatlist_item_changed(context, chat_id_in_archive);
|
||||||
|
|||||||
@@ -129,17 +129,14 @@ impl ContactId {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
context
|
context
|
||||||
.sql
|
.sql
|
||||||
.execute(
|
.transaction(|transaction| {
|
||||||
&format!(
|
let mut stmt = transaction
|
||||||
"UPDATE contacts SET origin=? WHERE id IN ({}) AND origin<?",
|
.prepare("UPDATE contacts SET origin=?1 WHERE id = ?2 AND origin < ?1")?;
|
||||||
sql::repeat_vars(ids.len())
|
for id in ids {
|
||||||
),
|
stmt.execute((origin, id))?;
|
||||||
rusqlite::params_from_iter(
|
}
|
||||||
params_iter(&[origin])
|
Ok(())
|
||||||
.chain(params_iter(ids))
|
})
|
||||||
.chain(params_iter(&[origin])),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,6 @@ use crate::location;
|
|||||||
use crate::log::LogExt;
|
use crate::log::LogExt;
|
||||||
use crate::message::{Message, MessageState, MsgId, Viewtype};
|
use crate::message::{Message, MessageState, MsgId, Viewtype};
|
||||||
use crate::mimeparser::SystemMessage;
|
use crate::mimeparser::SystemMessage;
|
||||||
use crate::sql::{self, params_iter};
|
|
||||||
use crate::stock_str;
|
use crate::stock_str;
|
||||||
use crate::tools::{duration_to_str, time, SystemTime};
|
use crate::tools::{duration_to_str, time, SystemTime};
|
||||||
|
|
||||||
@@ -329,23 +328,22 @@ pub(crate) async fn start_ephemeral_timers_msgids(
|
|||||||
msg_ids: &[MsgId],
|
msg_ids: &[MsgId],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let now = time();
|
let now = time();
|
||||||
let count = context
|
let should_interrupt =
|
||||||
|
context
|
||||||
.sql
|
.sql
|
||||||
.execute(
|
.transaction(move |transaction| {
|
||||||
&format!(
|
let mut should_interrupt = false;
|
||||||
"UPDATE msgs SET ephemeral_timestamp = ? + ephemeral_timer
|
let mut stmt =
|
||||||
WHERE (ephemeral_timestamp == 0 OR ephemeral_timestamp > ? + ephemeral_timer) AND ephemeral_timer > 0
|
transaction.prepare(
|
||||||
AND id IN ({})",
|
"UPDATE msgs SET ephemeral_timestamp = ?1 + ephemeral_timer
|
||||||
sql::repeat_vars(msg_ids.len())
|
WHERE (ephemeral_timestamp == 0 OR ephemeral_timestamp > ?1 + ephemeral_timer) AND ephemeral_timer > 0
|
||||||
),
|
AND id=?2")?;
|
||||||
rusqlite::params_from_iter(
|
for msg_id in msg_ids {
|
||||||
std::iter::once(&now as &dyn crate::sql::ToSql)
|
should_interrupt |= stmt.execute((now, msg_id))? > 0;
|
||||||
.chain(std::iter::once(&now as &dyn crate::sql::ToSql))
|
}
|
||||||
.chain(params_iter(msg_ids)),
|
Ok(should_interrupt)
|
||||||
),
|
}).await?;
|
||||||
)
|
if should_interrupt {
|
||||||
.await?;
|
|
||||||
if count > 0 {
|
|
||||||
context.scheduler.interrupt_ephemeral_task().await;
|
context.scheduler.interrupt_ephemeral_task().await;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
66
src/imap.rs
66
src/imap.rs
@@ -46,7 +46,6 @@ use crate::receive_imf::{
|
|||||||
from_field_to_contact_id, get_prefetch_parent_message, receive_imf_inner, ReceivedMsg,
|
from_field_to_contact_id, get_prefetch_parent_message, receive_imf_inner, ReceivedMsg,
|
||||||
};
|
};
|
||||||
use crate::scheduler::connectivity::ConnectivityStore;
|
use crate::scheduler::connectivity::ConnectivityStore;
|
||||||
use crate::sql;
|
|
||||||
use crate::stock_str;
|
use crate::stock_str;
|
||||||
use crate::tools::{self, create_id, duration_to_str};
|
use crate::tools::{self, create_id, duration_to_str};
|
||||||
|
|
||||||
@@ -911,15 +910,15 @@ impl Session {
|
|||||||
.await?;
|
.await?;
|
||||||
context
|
context
|
||||||
.sql
|
.sql
|
||||||
.execute(
|
.transaction(|transaction| {
|
||||||
&format!(
|
let mut stmt = transaction.prepare("DELETE FROM imap WHERE id = ?")?;
|
||||||
"DELETE FROM imap WHERE id IN ({})",
|
for row_id in row_ids {
|
||||||
sql::repeat_vars(row_ids.len())
|
stmt.execute((row_id,))?;
|
||||||
),
|
}
|
||||||
rusqlite::params_from_iter(row_ids),
|
Ok(())
|
||||||
)
|
})
|
||||||
.await
|
.await
|
||||||
.context("cannot remove deleted messages from imap table")?;
|
.context("Cannot remove deleted messages from imap table")?;
|
||||||
|
|
||||||
context.emit_event(EventType::ImapMessageDeleted(format!(
|
context.emit_event(EventType::ImapMessageDeleted(format!(
|
||||||
"IMAP messages {uid_set} marked as deleted"
|
"IMAP messages {uid_set} marked as deleted"
|
||||||
@@ -942,15 +941,15 @@ impl Session {
|
|||||||
// Messages are moved or don't exist, IMAP returns OK response in both cases.
|
// Messages are moved or don't exist, IMAP returns OK response in both cases.
|
||||||
context
|
context
|
||||||
.sql
|
.sql
|
||||||
.execute(
|
.transaction(|transaction| {
|
||||||
&format!(
|
let mut stmt = transaction.prepare("DELETE FROM imap WHERE id = ?")?;
|
||||||
"DELETE FROM imap WHERE id IN ({})",
|
for row_id in row_ids {
|
||||||
sql::repeat_vars(row_ids.len())
|
stmt.execute((row_id,))?;
|
||||||
),
|
}
|
||||||
rusqlite::params_from_iter(row_ids),
|
Ok(())
|
||||||
)
|
})
|
||||||
.await
|
.await
|
||||||
.context("cannot delete moved messages from imap table")?;
|
.context("Cannot delete moved messages from imap table")?;
|
||||||
context.emit_event(EventType::ImapMessageMoved(format!(
|
context.emit_event(EventType::ImapMessageMoved(format!(
|
||||||
"IMAP messages {set} moved to {target}"
|
"IMAP messages {set} moved to {target}"
|
||||||
)));
|
)));
|
||||||
@@ -996,15 +995,15 @@ impl Session {
|
|||||||
}
|
}
|
||||||
context
|
context
|
||||||
.sql
|
.sql
|
||||||
.execute(
|
.transaction(|transaction| {
|
||||||
&format!(
|
let mut stmt = transaction.prepare("UPDATE imap SET target='' WHERE id = ?")?;
|
||||||
"UPDATE imap SET target='' WHERE id IN ({})",
|
for row_id in row_ids {
|
||||||
sql::repeat_vars(row_ids.len())
|
stmt.execute((row_id,))?;
|
||||||
),
|
}
|
||||||
rusqlite::params_from_iter(row_ids),
|
Ok(())
|
||||||
)
|
})
|
||||||
.await
|
.await
|
||||||
.context("cannot plan deletion of messages")?;
|
.context("Cannot plan deletion of messages")?;
|
||||||
if copy {
|
if copy {
|
||||||
context.emit_event(EventType::ImapMessageMoved(format!(
|
context.emit_event(EventType::ImapMessageMoved(format!(
|
||||||
"IMAP messages {set} copied to {target}"
|
"IMAP messages {set} copied to {target}"
|
||||||
@@ -1147,15 +1146,16 @@ impl Session {
|
|||||||
);
|
);
|
||||||
context
|
context
|
||||||
.sql
|
.sql
|
||||||
.execute(
|
.transaction(|transaction| {
|
||||||
&format!(
|
let mut stmt =
|
||||||
"DELETE FROM imap_markseen WHERE id IN ({})",
|
transaction.prepare("DELETE FROM imap_markseen WHERE id = ?")?;
|
||||||
sql::repeat_vars(rowid_set.len())
|
for rowid in rowid_set {
|
||||||
),
|
stmt.execute((rowid,))?;
|
||||||
rusqlite::params_from_iter(rowid_set),
|
}
|
||||||
)
|
Ok(())
|
||||||
|
})
|
||||||
.await
|
.await
|
||||||
.context("cannot remove messages marked as seen from imap_markseen table")?;
|
.context("Cannot remove messages marked as seen from imap_markseen table")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
21
src/smtp.rs
21
src/smtp.rs
@@ -21,7 +21,6 @@ use crate::mimefactory::MimeFactory;
|
|||||||
use crate::net::proxy::ProxyConfig;
|
use crate::net::proxy::ProxyConfig;
|
||||||
use crate::net::session::SessionBufStream;
|
use crate::net::session::SessionBufStream;
|
||||||
use crate::scheduler::connectivity::ConnectivityStore;
|
use crate::scheduler::connectivity::ConnectivityStore;
|
||||||
use crate::sql;
|
|
||||||
use crate::stock_str::unencrypted_email;
|
use crate::stock_str::unencrypted_email;
|
||||||
use crate::tools::{self, time_elapsed};
|
use crate::tools::{self, time_elapsed};
|
||||||
|
|
||||||
@@ -585,18 +584,16 @@ async fn send_mdn_rfc724_mid(
|
|||||||
info!(context, "Successfully sent MDN for {rfc724_mid}.");
|
info!(context, "Successfully sent MDN for {rfc724_mid}.");
|
||||||
context
|
context
|
||||||
.sql
|
.sql
|
||||||
.execute("DELETE FROM smtp_mdns WHERE rfc724_mid = ?", (rfc724_mid,))
|
.transaction(|transaction| {
|
||||||
|
let mut stmt =
|
||||||
|
transaction.prepare("DELETE FROM smtp_mdns WHERE rfc724_mid = ?")?;
|
||||||
|
stmt.execute((rfc724_mid,))?;
|
||||||
|
for additional_rfc724_mid in additional_rfc724_mids {
|
||||||
|
stmt.execute((additional_rfc724_mid,))?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
.await?;
|
.await?;
|
||||||
if !additional_rfc724_mids.is_empty() {
|
|
||||||
let q = format!(
|
|
||||||
"DELETE FROM smtp_mdns WHERE rfc724_mid IN({})",
|
|
||||||
sql::repeat_vars(additional_rfc724_mids.len())
|
|
||||||
);
|
|
||||||
context
|
|
||||||
.sql
|
|
||||||
.execute(&q, rusqlite::params_from_iter(additional_rfc724_mids))
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
SendResult::Retry => {
|
SendResult::Retry => {
|
||||||
|
|||||||
Reference in New Issue
Block a user