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:
link2xt
2024-12-22 18:50:40 +00:00
committed by l
parent 3af4ea1d00
commit 3d5e442145
5 changed files with 75 additions and 80 deletions

View File

@@ -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);

View File

@@ -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(())
} }

View File

@@ -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(())

View File

@@ -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")?;
} }
} }

View File

@@ -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 => {