Skip to content

Commit 3d5e442

Browse files
committed
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.
1 parent 3af4ea1 commit 3d5e442

File tree

5 files changed

+75
-80
lines changed

5 files changed

+75
-80
lines changed

src/chat.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3267,14 +3267,17 @@ pub async fn marknoticed_chat(context: &Context, chat_id: ChatId) -> Result<()>
32673267

32683268
context
32693269
.sql
3270-
.execute(
3271-
&format!(
3272-
"UPDATE msgs SET state=13 WHERE state=10 AND hidden=0 AND chat_id IN ({});",
3273-
sql::repeat_vars(chat_ids_in_archive.len())
3274-
),
3275-
rusqlite::params_from_iter(&chat_ids_in_archive),
3276-
)
3270+
.transaction(|transaction| {
3271+
let mut stmt = transaction.prepare(
3272+
"UPDATE msgs SET state=13 WHERE state=10 AND hidden=0 AND chat_id = ?",
3273+
)?;
3274+
for chat_id_in_archive in &chat_ids_in_archive {
3275+
stmt.execute((chat_id_in_archive,))?;
3276+
}
3277+
Ok(())
3278+
})
32773279
.await?;
3280+
32783281
for chat_id_in_archive in chat_ids_in_archive {
32793282
context.emit_event(EventType::MsgsNoticed(chat_id_in_archive));
32803283
chatlist_events::emit_chatlist_item_changed(context, chat_id_in_archive);

src/contact.rs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -129,17 +129,14 @@ impl ContactId {
129129
) -> Result<()> {
130130
context
131131
.sql
132-
.execute(
133-
&format!(
134-
"UPDATE contacts SET origin=? WHERE id IN ({}) AND origin<?",
135-
sql::repeat_vars(ids.len())
136-
),
137-
rusqlite::params_from_iter(
138-
params_iter(&[origin])
139-
.chain(params_iter(ids))
140-
.chain(params_iter(&[origin])),
141-
),
142-
)
132+
.transaction(|transaction| {
133+
let mut stmt = transaction
134+
.prepare("UPDATE contacts SET origin=?1 WHERE id = ?2 AND origin < ?1")?;
135+
for id in ids {
136+
stmt.execute((origin, id))?;
137+
}
138+
Ok(())
139+
})
143140
.await?;
144141
Ok(())
145142
}

src/ephemeral.rs

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ use crate::location;
8484
use crate::log::LogExt;
8585
use crate::message::{Message, MessageState, MsgId, Viewtype};
8686
use crate::mimeparser::SystemMessage;
87-
use crate::sql::{self, params_iter};
8887
use crate::stock_str;
8988
use crate::tools::{duration_to_str, time, SystemTime};
9089

@@ -329,23 +328,22 @@ pub(crate) async fn start_ephemeral_timers_msgids(
329328
msg_ids: &[MsgId],
330329
) -> Result<()> {
331330
let now = time();
332-
let count = context
331+
let should_interrupt =
332+
context
333333
.sql
334-
.execute(
335-
&format!(
336-
"UPDATE msgs SET ephemeral_timestamp = ? + ephemeral_timer
337-
WHERE (ephemeral_timestamp == 0 OR ephemeral_timestamp > ? + ephemeral_timer) AND ephemeral_timer > 0
338-
AND id IN ({})",
339-
sql::repeat_vars(msg_ids.len())
340-
),
341-
rusqlite::params_from_iter(
342-
std::iter::once(&now as &dyn crate::sql::ToSql)
343-
.chain(std::iter::once(&now as &dyn crate::sql::ToSql))
344-
.chain(params_iter(msg_ids)),
345-
),
346-
)
347-
.await?;
348-
if count > 0 {
334+
.transaction(move |transaction| {
335+
let mut should_interrupt = false;
336+
let mut stmt =
337+
transaction.prepare(
338+
"UPDATE msgs SET ephemeral_timestamp = ?1 + ephemeral_timer
339+
WHERE (ephemeral_timestamp == 0 OR ephemeral_timestamp > ?1 + ephemeral_timer) AND ephemeral_timer > 0
340+
AND id=?2")?;
341+
for msg_id in msg_ids {
342+
should_interrupt |= stmt.execute((now, msg_id))? > 0;
343+
}
344+
Ok(should_interrupt)
345+
}).await?;
346+
if should_interrupt {
349347
context.scheduler.interrupt_ephemeral_task().await;
350348
}
351349
Ok(())

src/imap.rs

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ use crate::receive_imf::{
4646
from_field_to_contact_id, get_prefetch_parent_message, receive_imf_inner, ReceivedMsg,
4747
};
4848
use crate::scheduler::connectivity::ConnectivityStore;
49-
use crate::sql;
5049
use crate::stock_str;
5150
use crate::tools::{self, create_id, duration_to_str};
5251

@@ -911,15 +910,15 @@ impl Session {
911910
.await?;
912911
context
913912
.sql
914-
.execute(
915-
&format!(
916-
"DELETE FROM imap WHERE id IN ({})",
917-
sql::repeat_vars(row_ids.len())
918-
),
919-
rusqlite::params_from_iter(row_ids),
920-
)
913+
.transaction(|transaction| {
914+
let mut stmt = transaction.prepare("DELETE FROM imap WHERE id = ?")?;
915+
for row_id in row_ids {
916+
stmt.execute((row_id,))?;
917+
}
918+
Ok(())
919+
})
921920
.await
922-
.context("cannot remove deleted messages from imap table")?;
921+
.context("Cannot remove deleted messages from imap table")?;
923922

924923
context.emit_event(EventType::ImapMessageDeleted(format!(
925924
"IMAP messages {uid_set} marked as deleted"
@@ -942,15 +941,15 @@ impl Session {
942941
// Messages are moved or don't exist, IMAP returns OK response in both cases.
943942
context
944943
.sql
945-
.execute(
946-
&format!(
947-
"DELETE FROM imap WHERE id IN ({})",
948-
sql::repeat_vars(row_ids.len())
949-
),
950-
rusqlite::params_from_iter(row_ids),
951-
)
944+
.transaction(|transaction| {
945+
let mut stmt = transaction.prepare("DELETE FROM imap WHERE id = ?")?;
946+
for row_id in row_ids {
947+
stmt.execute((row_id,))?;
948+
}
949+
Ok(())
950+
})
952951
.await
953-
.context("cannot delete moved messages from imap table")?;
952+
.context("Cannot delete moved messages from imap table")?;
954953
context.emit_event(EventType::ImapMessageMoved(format!(
955954
"IMAP messages {set} moved to {target}"
956955
)));
@@ -996,15 +995,15 @@ impl Session {
996995
}
997996
context
998997
.sql
999-
.execute(
1000-
&format!(
1001-
"UPDATE imap SET target='' WHERE id IN ({})",
1002-
sql::repeat_vars(row_ids.len())
1003-
),
1004-
rusqlite::params_from_iter(row_ids),
1005-
)
998+
.transaction(|transaction| {
999+
let mut stmt = transaction.prepare("UPDATE imap SET target='' WHERE id = ?")?;
1000+
for row_id in row_ids {
1001+
stmt.execute((row_id,))?;
1002+
}
1003+
Ok(())
1004+
})
10061005
.await
1007-
.context("cannot plan deletion of messages")?;
1006+
.context("Cannot plan deletion of messages")?;
10081007
if copy {
10091008
context.emit_event(EventType::ImapMessageMoved(format!(
10101009
"IMAP messages {set} copied to {target}"
@@ -1147,15 +1146,16 @@ impl Session {
11471146
);
11481147
context
11491148
.sql
1150-
.execute(
1151-
&format!(
1152-
"DELETE FROM imap_markseen WHERE id IN ({})",
1153-
sql::repeat_vars(rowid_set.len())
1154-
),
1155-
rusqlite::params_from_iter(rowid_set),
1156-
)
1149+
.transaction(|transaction| {
1150+
let mut stmt =
1151+
transaction.prepare("DELETE FROM imap_markseen WHERE id = ?")?;
1152+
for rowid in rowid_set {
1153+
stmt.execute((rowid,))?;
1154+
}
1155+
Ok(())
1156+
})
11571157
.await
1158-
.context("cannot remove messages marked as seen from imap_markseen table")?;
1158+
.context("Cannot remove messages marked as seen from imap_markseen table")?;
11591159
}
11601160
}
11611161

src/smtp.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use crate::mimefactory::MimeFactory;
2121
use crate::net::proxy::ProxyConfig;
2222
use crate::net::session::SessionBufStream;
2323
use crate::scheduler::connectivity::ConnectivityStore;
24-
use crate::sql;
2524
use crate::stock_str::unencrypted_email;
2625
use crate::tools::{self, time_elapsed};
2726

@@ -585,18 +584,16 @@ async fn send_mdn_rfc724_mid(
585584
info!(context, "Successfully sent MDN for {rfc724_mid}.");
586585
context
587586
.sql
588-
.execute("DELETE FROM smtp_mdns WHERE rfc724_mid = ?", (rfc724_mid,))
587+
.transaction(|transaction| {
588+
let mut stmt =
589+
transaction.prepare("DELETE FROM smtp_mdns WHERE rfc724_mid = ?")?;
590+
stmt.execute((rfc724_mid,))?;
591+
for additional_rfc724_mid in additional_rfc724_mids {
592+
stmt.execute((additional_rfc724_mid,))?;
593+
}
594+
Ok(())
595+
})
589596
.await?;
590-
if !additional_rfc724_mids.is_empty() {
591-
let q = format!(
592-
"DELETE FROM smtp_mdns WHERE rfc724_mid IN({})",
593-
sql::repeat_vars(additional_rfc724_mids.len())
594-
);
595-
context
596-
.sql
597-
.execute(&q, rusqlite::params_from_iter(additional_rfc724_mids))
598-
.await?;
599-
}
600597
Ok(true)
601598
}
602599
SendResult::Retry => {

0 commit comments

Comments
 (0)